введение
1
НИЗАМУТДИНОВ ИЛЬЯС
ИЖЕВСК 2022 ГОД
© Ноябрь 2022 года. Все права защищены
Предисловие Введение Глава 1. Вводная информация Глава 2. Примитивные типы и переменные Глава 3. Основные операторы Глава 4. Основы конфигурации Глава 5. Работа с формами Глава 6. Объектные типы Глава 7. Универсальные коллекции значений Глава 8. Таблицы Глава 9. Получение данных Глава 10. Регистры сведений и накоплений Глава 11. Вывод информации Заключение |
Приветствую, уважаемый читатель!
Книга, которую Вы сейчас читаете, предназначена для людей, которые находятся в самой начальной стадии изучения языка программирования 1С. Это может быть простой бухгалтер, который хочет вносить небольшие правки в программу, чтобы не ждать специалиста. Или студент, который хочет понять, что такое 1С, как написать на языке программирования 1С и стоит ли связывать свою будущую жизнь с этой отраслью. А возможно, это системный администратор – фрилансер, который решил получить дополнительный заработок, обслуживая незначительные задачи своих клиентов в «1С: Предприятии».
Так или иначе эта книга будет полезна всем, кто желает получить базовые знания в работе с языком программирования 1С.
Мой труд рассчитан на тех, кто в принципе никогда не изучал никакие языки программирования. В этом его уникальность. Всё идёт с самых основ: переменные, циклы, условия. И заканчивается более сложными вещами, такими как язык запросов, работа с регистрами сведений и накоплений, СКД. Поэтому после изучения этой книги Вы сможете писать элементарные программы на языке 1С, читать имеющийся несложный код и выполнять другие базовые и элементарные задачи в среде 1С. Не исключаю, что этой информации Вам хватит с избытком, а возможно, Вы захотите идти дальше и изучать программирование в 1С на более глубоком и профессиональном уровне. В любом случае с этой книгой у Вас есть шанс на великолепный старт в изучении языка программирования 1С.
Книга разделена на одиннадцать глав, каждая глава также разделена на несколько частей. Каждая часть – это кусочек тех или иных знаний и умений по программированию (конфигурированию) в платформе 1С. В каждой части даётся минимум теоретических знаний и огромное количество различных практических примеров. Рекомендую прорешать все примеры, которые приведены в этой книге, тогда Вы очень хорошо закрепите свой навык программирования. Запомните: научиться программировать – можно только программируя.
Удачи в изучении языка программирования в 1С!
Дорогой друг, я начал программировать в 1С в 2008 году, когда пришёл работать в фирму, входящую в сеть «1С: Франчайзинг». Когда я начал работать, никто особо не занимался моим обучением, благо я уже перед этим умел программировать в Pascal и успел проработать 1,5 года на одном из предприятий моего города, поэтому какой-то базис у меня был. В той фирме не было какого-то отдела по обучению учеников или каких-то специально разработанных программ и методик. Шеф просто дал мне одну методичку от фирмы 1С и одну толстенную книгу, где объяснялось всё, всё, всё, вплоть до значения каждого мелкого свойства. И я начал постигать программирование в 1С путём изучения этой литературы и методичек.
Проработав какое-то время, я ушёл из фирмы и начал работать на себя – фрилансить. Это был послекризисный 2009 год. Многое из программирования в 1С мне пришлось изучить самостоятельно по различным разрозненным статьям в интернете. И в один момент я осознал, что в том обучении, которое я прошёл в 1С-франчайзи, не было никакой структуры, не было системы. Многих вещей я не знал в принципе, когда там работал, – а должен был!
Все эти знания я получил уже тогда, когда работал на себя, методом проб и ошибок. Поэтому в один прекрасный момент у меня родилась идея создать методичку, учебник, курс, который поможет начинающим как можно быстрее «въехать» в профессию программиста 1С. И который собрал бы в себя все те знания, которые необходимы именно начинающим разработчикам, тем, кто только хочет прикоснуться к этой профессии.
И прежде чем начать изучать материал этой книги, рекомендую Вам ознакомиться с основными положениями, соблюдение которых поможет легче его усвоить.
Как читать эту книгу?
«Программировать в 1С за 11 шагов» – это не просто книга, где даётся сухая теория. В каждой главе приведены различные практические примеры. Вы должны прорешать их все!
Причём не просто скопировать код из листинга и посмотреть, как он работает, а именно решить ту задачу, что была перед этим поставлена. Это не значит, что нужно тупо набирать код с книги. Нет! Вы должны осмыслить приведённый в книге код и сделать то же самое, не заглядывая в книгу. Да, поначалу это будет трудно, но в процессе таких тренировок Вы гораздо быстрее запомните весь материал, который изложен в моём труде.
Структура книги
Если Вы впервые столкнулись с программой 1С, то начать изучение нужно с самой первой главы, в которой даются самые базовые значения о платформе 1С. Изучив первую главу, Вы научитесь самостоятельно устанавливать учебную версию платформы 1С, создавать пустую базу (для разработки и учёбы), пользоваться справкой и работать в отладке. Эти знания самые базовые, и без них Вы не сможете идти дальше.
Во второй и третьей главе даются основы программирования в 1С: мы познакомимся с примитивными типами, научимся задавать переменный и узнаем основные конструкции языка программирования в 1С (условия, циклы, процедуры и т.д.) Четвёртая глава очень
объёмная, в ней мы изучим основные объекты конфигурации (метаданные), которые часто применимы при разработке. В пятой главе мы научимся работать с управляемыми формами. Сама по себе тема управляемых форм очень объёмна, мы же освоим тот минимум, который необходим для начальной работы. В шестой главе узнаем все об объектных типах. Узнаем, что такое Объект, Ссылка и многие другие интересные понятия. В седьмой и восьмой главе мы будем изучать универсальные коллекции значений: массивы, структуры, таблицы значений и многое другое. В девятой главе мы изучим различные способы получения данных. При помощи выборок и запросов. Язык запросов в этой книге дан в том минимуме, который позволит Вам двигаться успешно дальше в изучении этого интересного инструмента. В десятой главе научимся работать с регистрами сведений и накоплений. А в одиннадцатой, заключительной главе мы научимся работать с печатными формами, отчётами, динамическими списками, то есть со всем тем, что выводит пользователю конечную информацию.
Информация во всех главах структурирована, и в дальнейшем Вы сможете эту книгу использовать в качестве справочника.
Успехов в изучении языка программирования в 1С!
В первой главе Вы узнаете, где скачать учебную версию платформы 1С и как её установить. Также мы изучим основную информацию о среде программирования 1С, о языке программирования 1С, создадим информационную базу и заполним основные свойства этой базы, научимся создавать внешние обработки (этот навык нам в дальнейшем пригодится) и работать с отладкой.
Если Вы ещё ни разу не имели дело с программой 1С, то Вам нужно скачать и установить платформу 1С (в противном случае сразу переходите ко второй части этой главы, изучив только создание пустой базы). Фирма 1С предоставляет возможность скачать бесплатную учебную версию платформы по этой ссылке:
http://online.1c.ru/catalog/free/28765768/
На форме регистрации Вам необходимо будет ввести свое ФИО и e-mail. Через какое- то время на почту, указанную при регистрации, придёт архив с дистрибутивом на установку платформы. Скачайте его на жёсткий диск Вашего компьютера и распакуйте.
Зайдите в распакованный архив и найдите среди множества файлов файл под названием setup.exe.
Вот он:
Рис. 1.1.1
Запустите этот файл, дважды кликнув по нему левой клавишей мышки (у пользователя Windows должны быть административные права). После запуска должно открыться окно
установки учебной версии платформы 1С.
Рис. 1.1.2
В этом окне нажимаем кнопку Далее.
Рис. 1.1.3
В следующем окне обратите внимание на два момента. Первый момент – это компоненты, которые должны будут быть инсталлированы при установке дистрибутива. Если Вы делаете обычную установку, то достаточно оставить компоненту «1С Предприятие»,
«Модули расширения веб-сервера» и «Интерфейсы на различных языках» (то, что
предложено по умолчанию). Для начального изучения этих компонент Вам хватит.
Второй момент, обратите внимание, в какой каталог на жёстком диске будет установлена платформа 1С. Вы можете поменять путь на любой другой, какой хотите, нажав на кнопку Изменить. Мы оставим тот каталог, который есть.
Нажимаем кнопку Далее.
Рис. 1.1.4
На следующей закладке надо установить язык интерфейса. Рекомендуется язык не менять и оставлять тот, который по умолчанию. Это либо Русский, либо Системные установки. Мы ничего не будем менять и нажмём кнопку Далее.
Рис. 1.1.5
В следующем окне нажимаем кнопку Установить. Платформа начнёт устанавливаться, а Вам следует дождаться окончания установки.
Рис. 1.1.6
Всё! Платформа установлена. Осталось нажать кнопку Готово.
Рис. 1.1.7
Платформу мы установили, но сама по себе платформа нам ни к чему. В программе
1С вся работа осуществляется в информационных базах. Что это такое мы разберём чуть позже, а сейчас создадим пустую базу, в которой и будем изучать материал этой книги.
После установки платформы на Вашем рабочем столе должен появиться ярлык «1C Предприятие (учебная версия)». Если дважды кликнуть левой клавишей мышки по этому ярлыку, то откроется окно запуска «1С: Предприятия» или «стартер 1С». В нашем же случае выйдет сообщение о том, что список информационных баз пуст, и вопрос о добавлении базы в список. Отвечаем: «Да».
Рис. 1.1.8
В следующих двух окнах выбираем пункты «Создание новой информационной базы» и «Создание информационной базы без конфигурации…»
Рис 1.1.9 | Рис. 1.1.10 |
В последующих двух окнах нужно придумать имя базы и указать каталог на жёстком диске, в котором база будет храниться.
Рис 1.1.11 | Рис. 1.1.12 |
В последнем окне ничего не меняем и нажмем кнопку Готово. База будет создана и появится в списке информационных баз окна запуска.
Рис. 1.1.13 | Рис. 1.1.14 |
Варианты хранения данных
Только что мы с Вами установили информационную базу 1С. Информационная база нужна для хранения данных, а также в ней описаны все алгоритмы работы с этими данными.
Платформа 1С поддерживает два варианта работы с данными: файловый вариант и клиент-серверный вариант. Мы в этой книге будем иметь дело с файловым вариантом работы.
Файловый вариант предназначен для работы одного или нескольких пользователей в рамках небольшой локальной сети. В этом варианте работы все данные располагаются в одном файле, который, по сути, является файловой СУБД.
Этот файл имеет расширение 1CD и название 1Cv8.
Рис. 1.2.1
Нельзя менять название и расширение этого файла!
При подключении базы в окне запуска 1С необходимо указывать путь расположения файла базы, как это было сделано выше (см. рис. 1.1.12). Если же выделить уже подключенную базу в окне запуска 1С, внизу отобразится путь к каталогу, в котором находится файл базы.
Рис. 1.2.2
Для работы с файловой базой достаточно установить платформу 1С. Схематически работу файловой базы можно представить следующим образом:
Рис. 1.2.3. Схема работы файлового варианта Ещё один вариант работы – это Клиент-серверный. Данный вариант предназначен
для большого числа пользователей в масштабе предприятия. Он реализован на основе трёхуровневой структуры «Клиент-сервер».
Эта структура состоит из трёх звеньев. Первое звено – это SQL сервер (как правило, это не имеющее к фирме 1С приложение, например, Microsoft SQL Server или Postgre). SQL серверов, которые могут работать с 1С, существует ограниченное количество, но мы не будем их все перечислять. Если кто-то заинтересуется подобной информацией, без труда
сможет её найти. В этом приложении хранятся все данные.
Для того чтобы клиентское приложение работало с SQL сервером, необходим посредник. Эту роль выполняет кластер серверов «1С: Предприятия», который, по сути, связывает пользователя программы с SQL сервером. Кластер серверов – это процесс (или процессы), который запущен на каком-либо компьютере. Компьютеры, где запущен сервер SQL и кластер серверов 1С, могут быть разными.
И третье звено – это непосредственно клиентское приложение, в котором работает пользователь.
Рис 1.2.4. Схема работы SQL варианта
Обычное и управляемое приложение
После выхода платформы 8.2. программа 1С может работать в двух режимах: в режиме обычного приложения и в режиме управляемого приложения. Мы очень кратко разберём особенности работы в них. Более подробно отличия этих приложений даются в первой части книги «Основы разработки в 1С: Такси. Разработка в управляемом приложении за 12 шагов».
В обычном приложении интерфейс пользовательского режима «1С: Предприятия» имеет следующий вид:
Рис. 1.2.5
Для того чтобы выполнить какие-то действия (создать документ, распечатать отчёт), пользователь должен работать с меню. Переходя по пунктам меню, пользователь может открывать различные формы. В основном это формы списков справочников и документов (см. рис. 1.2.6), но также могут быть отчёты, обработки, планы счетов и пр.
Рис. 1.2.6
Из формы списка пользователь может открыть форму документа или справочника (см. рис. 1.2.7).
Рис 1.2.7
В управляемом приложении всё несколько по-другому. В случае с интерфейсом Такси
командный интерфейс выглядит так:
Рис. 1.2.8
А форма документа выглядит следующим образом:
Рис. 1.2.9
В этой книге будет дан необходимый минимум по разработке управляемого приложения, кто же заинтересуется особенностями разработки управляемого приложения, может ознакомиться с моей другой книгой «Основы разработки в 1С: Такси. Разработка в управляемом приложении за 12 шагов».
Все примеры в этой книге приведены под управляемым приложением и на управляемых формах.
Система программ «1С: Предприятие» стоит на двух столпах. Это технологическая платформа и прикладные решения.
Технологическая платформа – это, по сути, оболочка, в которой существуют прикладные решения. Сами по себе прикладные решения существовать не могут. Но и платформа без прикладного решения сама по себе никому не нужна. Пользователям она ни к чему.
Прикладное решение – это автоматизация определённой области хозяйственного учета. Например, такие конфигурации как «Бухгалтерия предприятия», «Управление торговлей» и «Зарплата и управление персоналом» являются прикладными решениями, разработанными фирмой 1С. Прикладные решения разрабатываются в основном фирмой 1С, но их могут создавать и сторонние организации. Например, когда Вы научитесь программировать в 1С, то тоже сможете разработать собственное прикладное решение на базе платформы 1С и продавать его (ну или раздавать бесплатно). Иногда прикладное решение еще называют конфигурацией. Конфигурация «1С: Бухгалтерия предприятия», конфигурация «1С: Управление торговлей» и т.д.
Платформа 1С может работать в двух режимах: в режиме «1С: Предприятие» и в режиме «1С: Конфигуратор». Режим «1С: Предприятие» предназначен для работы пользователей прикладного решения. В дальнейшем в книге режим работы пользователей так будет называться или «1С: Предприятие», или пользовательский режим.
Начиная с платформы 8.2 режим «1С: Предприятие» может работать в трёх видах клиентских приложений – это «Толстый клиент», «Тонкий клиент» и «Веб-сервис», а начиная с платформы 8.3. добавился ещё и «Мобильный клиент». Работа тонкого клиента и веб- клиента возможна только в управляемом приложении. С обычным приложением можно работать только под толстым клиентом. Под толстым клиентом можно работать как в обычном, так и в управляемом приложении.
В платформах 8.0 и 8.1 была возможность работы только под толстым клиентом.
Тогда это был обычный и единственный вид клиентского приложения.
Почему появилась необходимость разделения обычного клиентского приложения на три вида – тонкий, толстый и веб-клиент? Виной этому развитие технологий вообще и интернета в частности. Очень часто стала появляться необходимость в работе с «1С: Предприятием» через сеть Internet, и это стало накладывать определённые ограничения, поскольку пропускная способность сети Internet была гораздо уже, чем для обычной локальной сети. Поэтому те технологии платформы, которые существовали при редакциях
8.0 и 8.1, стали неприменимы в новых реалиях. Как следствие, была разработана платформа 8.2, в которой приложение разделилось на три вида: толстый, тонкий и веб-клиент.
Толстый клиент – это обычный клиент «1С: Предприятия». Под этим клиентом возможна работа только в локальной сети Ethernet. Это отдельное приложение, которое устанавливается на компьютер пользователя. Посредством этого приложения можно получить доступ к базам с прикладными решениями как на компьютере пользователя, так и к базам в локальной сети Ethernet. Только под толстым клиентом возможна разработка, то есть доступ к конфигуратору 1С!
Под тонким клиентом возможна работа как по локальной сети Ethernet, так и по сети Internet. Это специальное отдельное приложение, которое тоже устанавливается на компьютер пользователя. Посредством этого приложения можно получить доступ как к базам в локальной сети Ethernet, так и к базам через сеть Internet (для этого на компьютере, где находится база данных, должен быть установлен веб-сервер).
Веб-клиент работает только через веб-браузер. Через веб-браузер возможно зайти в любую базу прикладного решения (если она опубликована на веб-сервере). Для этого нет необходимости в установке какого-то приложения, достаточно на компьютере иметь какой- нибудь веб-браузер.
Мобильный клиент – это один из вариантов мобильной платформы 1С, который позволяет взаимодействовать с мобильного устройства с информационной базой онлайн. Появился в последних версиях платформы 8.3. Вопросы мобильной разработки не рассматриваются в этой книге.
Когда Вы будете разрабатывать или дорабатывать прикладное решение,
ориентируйтесь на то, что пользователи будут работать под тонким клиентом. Более подробно об этом в пятой главе.
Режим «1С: Конфигуратор» предназначен для разработки и отладки прикладного решения. То есть если Вам надо написать какой-нибудь отчёт, обработку или внести изменение в имеющееся прикладное решение, то сделать это Вы сможете только в режиме
«1С: Конфигуратор». Обычно режим «1С: Конфигуратор» просто называют конфигуратор.
Для того чтобы запустить конфигуратор, необходимо нажать на кнопку Конфигуратор
окна запуска программы 1С (см. рис. 1.3.1).
Рис. 1.3.1
Конфигуратор можно запустить только в режиме толстого клиента! В режиме тонкого клиента кнопки конфигуратора просто не будет!
Конфигуратор откроется, и Вы увидите большое окно с различными меню вверху. Вот это большое окно будем называть Рабочий стол разработчика (см. рис. 1.3.2):
Рис. 1.3.2
Слева обычно расположено дерево конфигурации. В нашем случае оно закрыто. Для того чтобы открыть его, необходимо нажать на кнопку Открыть конфигурацию (см. рис.
1.3.3).
Рис. 1.3.3
Конфигурация – это некий набор метаданных, с помощью которого функционирует прикладное решение (справочники, документы, планы счетов и т.д.)
В нашем случае набор метаданных пустой, но если Вы откроете конфигурацию какого-нибудь прикладного решения, он должен быть заполнен. Пока не будем обращать внимания на метаданные, потому что вопросы по работе с ними мы будем рассматривать ниже.
Рис. 1.3.4
Эта вся информация о работе с конфигуратором, которая Вам пока необходима на данном этапе изучения программирования в 1С.
Для того чтобы запустить «1С: Предприятие», необходимо нажать в окне запуска кнопку 1С: Предприятие.
Запустить «1С: Предприятие» можно также из конфигуратора, либо нажав на кнопку
Начать отладку.
Рис. 1.3.5
Либо выполнив команду 1С: Предприятие в меню Сервис.
Рис. 1.3.6
Тогда у Вас откроется прикладное решение, в нашем случае оно пустое (см. рис. 1.3.7). В случае же реальной информационной базы Вы сможете вносить и обрабатывать данные, согласно алгоритмам, которые созданы разработчиками конфигурации.
Рис. 1.3.7
Вся разработка в 1С осуществляется при помощи встроенного языка программирования в 1С. Посредством этого языка разрабатываются различные алгоритмы поведения программы (расчёты, проведение документов и т.п.) В этой части мы рассмотрим базовые основы языка программирования 1С.
Программный модуль
И начнём мы с программного модуля. Что такое программный модуль? Программный модуль – это место, где непосредственно пишется исполняемый код.
В отличие от остальных языков, в 1С программный модуль не является самостоятельной программой и функционирует только в рамках конфигурации 1С, поскольку он является частью конфигурации, или это модуль внешней обработки или отчёта (модуль формы внешней обработки (отчёта)), которые тоже не могут самостоятельно существовать, а работают только в среде «1С: Предприятие».
Программный модуль – это среда, в которой пишется текст на встроенном языке программирования 1С. Этот текст содержит процедуры и функции (их ещё называют одним словом Методы), реализующие те или иные алгоритмы работы программы, которые вызываются системой в определённые моменты (например, при нажатии на кнопку).
Всего существует 11 видов программных модулей, но мы в этой книге затронем только некоторые из них: модуль формы, модуль объекта и т.д. Этого будет вполне достаточно для старта в изучении программирования в 1С.
Рис. 1.4.1. Модуль объекта (внешней обработки)
Рис. 1.4.2. Модуль формы Более подробно сами программные модули будем разбирать в четвёртой главе.
Исходный текст программного модуля состоит из операторов и комментариев.
Комментарии
Разберём первым делом комментарии.
Для того чтобы в программном модуле внести пояснения к коду, программист может написать комментарии, которые не будут читаться компилятором и не будут учавствовать в общей работе кода. Делается это достаточно просто.
Посмотрите на примере, как это выглядит:
Рис. 1.4.3
Как Вы видите на рис. 1.4.3, пишутся две наклонные вправо черты, после них весь текст будет зелёного цвета. Хорошим тоном программирования считается написание – почему мы делаем так, а не иначае. Обращаю Ваше внимание, что после того как Вы стали писать комментарий, на этой строке нельзя написать какой-то работающий оператор, только на следующей строке.
Многострочных комментариев в 1С нет. Но есть способ закомментировать сразу несколько строк. Для этого надо выделить текст и вполнить команду Текст – Блок –
Добавить комментарий (см. рис. 1.4.4 и 1.4.5):
Рис. 1.4.4
Рис. 1.4.5
Операторы
Разберём основной столп языка программирования 1С – операторы.
Что такое оператор? Оператор – это наименьшая автономная часть языка программирования. Любая программа представляет собой последовательность операторов. Операторы 1С можно поделить на две группы: Операторы объявления переменных и Исполняемые операторы.
Операторов объявления переменных два:это оператор явного объявления переменных:
Перем А;
и оператор неявного объявления – оператор присваивания:
А = 1;
Оператор присваивания не только объявляет переменную, но и присваивает этой переменной какое-нибудь значение.
Перем А;
А = 1;
В данном примере переменная уже объявлена, и затем ей присваивается значение.
Исполняемые операторы совершают определённые действия, которые манипулируют переменными или иными сущностями, они могут быть в виде процедур, либо в виде синтетических конструкций типа Если, Цикл и т.п.
Все операторы должны быть разделены между собой точкой с запятой, перенос строки не является признаком разделения оператора.
Ключевые слова
Ключевое слово в языке программирования – это слово, которое имеет определённое значение для компилятора. Его нельзя использовать в названии переменных, процедур и функций. В языке программирования 1С ключевые слова также называют зарезервированными.
В программе 1С список ключевых слов фиксированный, и Вы сможете ознакомиться с ним в приложении к книге.
Язык написания, имена переменных, функций и процедур
Язык написания в программе 1С является двуязычным: кириллица и латиница. То есть в написании имён переменных, функций и процедур можно использовать английский и русский шрифт без каких-либо ограничений. Все ключевые слова могут быть написаны как в русском, так и в английском варианте. Причём регистр написания букв никакой роли не играет. В написании имён переменных, функций и процедур можно использовать любые латинские и кириллические символы, а также цифры и знак подчеркивания – «_».
Например, можно назвать переменные так:
Перем НашаПеремА,А1, п2, V3,weфв_3;
Но платформа выдаст ошибку, назови Вы переменные следующим образом:
Перем НашаПерем%,А#, п2?, V*3,weфв_3-4;
Поскольку язык программирования 1С очень обширен, то не все функции и процедуры можно обхватить текущей книгой. Кое-что будет упущено не специально, а кое-что – преднамеренно, для того чтобы Вы могли научиться работать со справкой.
Работать со справкой очень просто. Для начала необходимо её открыть в конфигураторе: перейдите Главное меню – Справка – Синтакс-помощник. И откройте её.
Рис. 1.5.1
Окно справки состоит из трёх закладок: Содержание, Индекс и Поиск.
Рис. 1.5.2
Закладка Содержание представляет собой дерево справочной информации. Сейчас для Вас всё это тёмный лес. Но когда Вы уже немного начнёте разбираться в языке программирования 1С, то информация в данной закладке станет более осмысленной.
Например, в следующем уроке мы будем проходить переменные, в том числе и строки. Если Вам интересно посмотреть, какие функции и процедуры по работе со строками имеются в платформе 1С, Вы сможете без труда это сделать в справке.
Рис. 1.5.3
Другие закладки более универсальные.
К примеру, Вы забыли, как работает функция Формат. Вы можете зайти на закладку
Индекс и в окне поиска написать слово Формат.
Рис. 1.5.4
И индекс Вам выдаст, что существует функция, процедура или метод какого-нибудь объекта с таким именем в принципе. Для того чтобы перейти непосредственно к искомой функции, надо дважды кликнуть мышкой по слову Формат в поле индекса.
Рис. 1.5.5
Откроется окно, в котором выведены все методы Формат для всех существующих объектов 1С. Их очень много, и придётся из них найти нужный, ориентируясь на главу списка. Нас интересует последняя строка.
После того как мы её визуально нашли, кликнем по ней дважды, и мы перейдём в нужную нам справку.
Рис. 1.5.6
Закладка Поиск вываст все объекты, у которых есть метод Формат.
Рис. 1.5.7
Не очень-то удобный способ поиска, поэтому многие предпочитают поиск по индексу.
Разберём основные свойства конфигурации, которые так или иначе влияют на функционал приложения 1С.
Войдём в конфигуратор базы, которую мы создали в первой части этой главы, нажав на кнопку Конфигуратор в окне запуска 1С. Откроем окно конфигурации и перейдём в её свойства. Для этого необходимо выделить мышкой корень дерева конфигурации (в самом верху), правой кнопкой мышки вызвать контекстное меню и в этом меню выполнить команду Свойства (см. рис. 1.6.1).
Рис. 1.6.1
В правой части рабочего стола разработчика откроется палитра свойств конфигурации (см. рис. 1.6.2).
Рис. 1.6.2
Мы не будем разбирать все свойства, а разберём самые значимые для нас. Первым делом зададим имя и синоним конфигурации (свойства Имя и Синоним). Конфигурация будет называться УправлениеАвтотранспортом (синоним – Управление автотранспортом).
Рис. 1.6.3
Следующее свойство, которое нужно знать, это Основной режим запуска. Значение этого свойства определяет, в каком виде будет работать наше «1С: Предприятие» – в виде управляемого приложения или в виде обычного приложения. В это свойство можно установить одно из двух значений: Управляемое приложение или Обычное приложение (см. рис. 1.6.4).
Рис. 1.6.4
Мы оставим у нашей конфигурации у свойства Основной режим запуска значение
Управляемое приложение.
Загрузим логотип и заставку для нашей конфигурации. В этом нам помогут свойства конфигурации Логотип и Заставка.
Рис. 1.6.5
Если кликнуть на гиперссылку Открыть справа от свойства Логотип или Заставка, то откроется окно выбора картинки.
Рис. 1.6.6
В этом окне следует выбрать картинку для логотипа или заставки (нажать на кнопку
Выбрать из файла, выбрать нужную картинку).
Для логотипа выберем эту картинку.
Рис. 1.6.7
А для заставки эту.
Рис. 1.6.8
Картинки к конфигурации имеются в дополнении, а если Вы хотите создать собственную картинку, то размер картинки для заставки: 600х255 точек.
После того как мы изменили имя и синоним, у нас изменились заголовки программы в дереве конфигурации и в основном окне, а в окне дерева конфигурации рядом с заголовком Конфигурация появился символ * (см. рис. 1.6.9).
Рис. 1.6.9
Это значит, что конфигурация отредактирована и её следует сохранить. Сохранить конфигурацию можно нажав на кнопку Сохранить или комбинацией клавиш Ctrl+S (см. рис. 1.6.10).
Рис. 1.6.10
Затем рядом с заголовком Конфигурация появится символ «!», это означает, что изменения в конфигурацию внесены, но ещё не попали в базу. Для того чтобы все изменения попали в базу и пользователь начал с ними работать, нужно нажать на кнопку Обновить конфигурацию базы данных или клавишу F7 (см. рис. 1.6.11).
Рис. 1.6.11
Только после этого все изменения будут внесены в базу данных.
У нас появится логотип. Чтобы его увидеть, следует открыть окно О программе по следующему пути: Главное меню – Справка – О программе, или кликнуть по иконке Показать информацию о программе в меню Стандартная.
Рис. 1.6.12
Также отобразится заставка при запуске пользовательского режима.
Рис. 1.6.13
Для изучения возможностей языка программирования 1С, мы будем использовать внешние обработки. Что такое обработка? Обработка – это объект конфигурации, предназначенный для реализации различных механизмов обработок информации и сервисных функций. Обработка может быть встроенной в конфигурацию, а может быть внешней, то есть не привязанной ни к какой конфигурации. Подробно вопросы работы с обработками и иными объектами конфигурации мы будем проходить в четвёртой главе.
В этой части изучим, как создавать и сохранять новые обработки, в которых Вы будете делать все Ваши тренировки. В дальнейшем рекомендую Вам на каждую часть главы (и даже, возможно, на каждый пример) создавать отдельную обработку и самостоятельно прописывать все те примеры, которые даются в книге. Если Вы будете прописывать все приведённые мною примеры и выполнять все те рекомендации, которые даются в главах книги, то усвоите нужный материал гораздо лучше, чем просто пролистывая книгу.
Итак, как создать новую обработку? Для этого в конфигураторе базы выполним команду Новый в меню Файл.
Рис. 1.7.1
В открывшемся списке выберем пункт Внешняя обработка и нажимём на кнопку ОК.
Рис. 1.7.2
В результате откроется редактор новой внешней обработки.
Рис. 1.7.3
Назовём как-нибудь новую обработку. Рекомендую Вам в дальнейшем давать имена им по номеру главы, части и примера.
Рис. 1.7.4
Сохраним обработку в любое место на жёстком диске (Главное меню – Файл – Сохранить, или Ctrl + S).
Каким образом мы будем работать с новой обработкой? Делать это мы будем, используя управляемую форму.
На текущем этапе обучения мы не будем подробно затрагивать работу с управляемыми формами, все интересующие нас вопросы на эту тему мы изучим в пятой
главе этой книги.
Просто пока запомните этапы создания новой обработки, формы, команды и обработчиков команды.
Создадим форму обработки. Для этого наведём курсор на элемент Формы в списке и выделим этот элемент.
Рис. 1.7.5
Нажмём правую кнопку мышки, выполним команду Добавить.
Рис. 1.7.6
В открывшемся окне ничего не меняем, нажмём на кнопку Готово.
Рис. 1.7.7
Откроется наша первая созданная форма.
Рис. 1.7.8
Перейдём на закладку Команды в правом верхнем окне, и в подзакладке Команды формы создадим новую команду, нажав на кнопку Добавить. Команда будет создана, а справа откроется палитра свойств этой команды (см. рис. 1.7.9).
Рис. 1.7.9
Назовём нашу команду ПриветМир, для этого изменим свойство Имя (см. рис. 1.7.9).
А после поместим её на форму в виде кнопки. Делается это так: выделяем команду мышкой и
«тащим» её в левое верхнее окно на закладку Элементы в командную панель формы (см. рис. 1.7.10 и 1.7.11).
Рис. 1.7.10
Рис. 1.7.11
1.2) как создать обработчик команды
Нам осталось создать обработчик команды ПриветМир. Для этого необходимо опять зайти в палитру свойств команды (чтобы палитра свойств команды открылась, необходимо кликнуть по команде мышкой, палитра откроется в правой части рабочего стола) и у свойства Действие нажать на кнопку Лупа (см. рис. 1.7.12).
Рис. 1.7.12
Откроется окно, в котором будет предложено выбрать место создания обработчика команды (см. рис. 1.7.13). Оставляем Создать на клиенте и нажимаем на кнопку ОК (см. рис. 1.7.13).
Рис. 1.7.13
После этого в модуле формы будет создана процедура ПриветМир (см. рис. 1.7.14).
Рис.1.7.14
Напишем в ней следующий код (см. листинг 1.7.1).
&НаКлиенте
Процедура ПриветМир(Команда) ПоказатьПредупреждение(,"Привет, мир!!!");
КонецПроцедуры
Листинг 1.7.1 Это процедура предупреждение и в ней текст «Привет, Мир!». Сохраним обработку!
Нам осталось посмотреть, как наша новая обработка работает. Для этого запустим пользовательский режим «1С: Предприятия» прямо из конфигуратора, выполнив команду 1С: Предприятие.
Рис. 1.7.15
В результате запустится «1С: Предприятие» в пользовательском режиме (основной режим, где работают пользователи). В этом пользовательском режиме откроем только что созданную обработку. Для этого необходимо выполнить команду Открыть, которая находится по следующему пути: Сервис и настройки – Файл (см. рис. 1.7.16), в результате откроется окно Открытие, в котором нужно найти файл внешней обработки с расширением epf в том месте, куда Вы её сохранили. Открываем (на предупреждение безопасности отвечаем «Да»), нажимаем на кнопку Привет мир (см. рис. 1.7.17), и выйдет Ваше первое предупреждение (см. рис. 1.7.18).
Рис. 1.7.16
Рис. 1.7.17
Рис. 1.7.18
Точно так же можно открывать файлы любых других обработок.
1.3) Для чего существует отладка
Очень часто возникает необходимость посмотреть, как работает тот или иной код в программном модуле, какие значения принимают переменные, как выполняется обход цикла, срабатывают условия и тому подобное. Для этого существует отладка. Для того чтобы программа остановилась на нужном нам участке кода, достаточно поставить на этот участок точку останова.
Научимся работать с отладкой на примере той обработки, которую сделали в предыдущей части (Привет, Мир). Для этого переделаем код в команде ПриветМир формы обработки. Присвоим переменным некоторые значения.
&НаКлиенте
Процедура ПриветМир(Команда) А = 10;
B = "Текст"; ПоказатьПредупреждение(,"Привет, мир!!!");
КонецПроцедуры
Листинг 1.8.1 Сохраним обработку, запустим её в клиентском режиме «1С: Предприятия», но пока
не будем выполнять команду Привет, Мир.
Для того чтобы отладка работала, она должна быть подключена. Если у Вас на панели конфигурации вместо кнопки Начать отладку (см. рис. 1.8.1) – кнопка Продолжить отладку (см. рис. 1.8.2), то конфигуратор подключен к отладке.
Рис. 1.8.1
Рис. 1.8.2
Отладка подключится автоматически, если Вы запустите из конфигуратора пользовательский режим «1С: Предприятия», нажав на кнопку Начать отладку (см. рис. 1.8.1).
Но иногда бывают ситуации, когда нужно отладить уже запущенное приложение (например, когда пользовательский режим был запущен отдельно от конфигуратора). В конфигураторе можно посмотреть, подключены какие-либо сеансы к отладке или нет. Для этого следует воспользоваться окном Предметы отладки. Открыть это окно можно через Главное меню – Отладка – Подключение.
Рис. 1.8.3
Окно Пердметы отладки разделено на две части: в верхней части все доступные сеансы, а в нижней те сеансы, которые уже подключены к отладке.
Рис. 1.8.4
Если Вы уже запустили сеанс базы не через конфигуратор, а через окно запуска 1С, то
обнаружите, что запущенный сеанс не подключен к отладке. Для этого нужно разрешить отладку в текущем сеансе.
Чтобы разрешить отладку, зайдём в параметры клиентского приложения «1С: Предприятие».
Рис. 1.8.5
В открывшемся окне установим в параметрах Откладка в текущем сеансе и Откладка при перезапуске значение Разрешена (протокол TCP/IP), а затем нужно последовательно нажать на кнопки Применить и ОК.
Если окно Предметы отладки уже открыто, то нажмём на кнопку Обновить (см. рис.
), чтобы подключённый сеанс появился в верхнем окне (см. рис. 1.8.8).
Рис. 1.8.7
Рис. 1.8.8
У нас доступные предметы отладки без пользователя, потому что мы его не завели, позже, когда научимся создавать пользователей (в четвёртой главе), колонка Пользователь будет заполнена. В окне две строки с отладкой – тонкий клиент и сервер, пока не обращая внимания на этот факт, подключим оба предмета. Для того чтобы нужный предмет отладки получился, следует выделить нужную строку и нажать на кнопку Подключить.
После всех подключений предметы отладки исчезнут в верхнем окне и появятся в нижнем.
После этого можно спокойно работать с отладкой.
Если же пользовательское приложение «1С: Предприятие» не запущено, то его можно запустить из конфигуратора, нажав на кнопку Начать отладку панели Конфигурация.
Рис. 1.8.10
Подключать отладку мы научились, научимся с ней работать.
Запустим пользовательский режим «1С: Предприятия», используя кнопку Начать отладку, откроем модуль формы, созданной в седьмой части обработки, и установим точку останова в начале процедуры ПриветМир. Для установки точки останова нужно установить курсор на первую строку тела процедуры (где начинается текст А = 10;, см. листинг 1.8.1) и нажать на кнопку Точка останова одноимённой панели (см. рис. 1.8.11), или выполнить команду Точка останова по пути Главное меню – Отладка (см. рис. 1.8.12).
Рис. 1.8.11
Рис. 1.8.12
После этих действий на поле слева напротив нужной строки кода появится красный кружок, это и есть точка останова.
Рис. 1.8.13
Учитывайте следующий момент: точку останова нужно устанавливать на строке, где написан какой-то код. Если установите точку останова на пустой строке (или где комментарий), то она не сработает.
Если сейчас мы в пользовательском режиме «1С: Предприятия» у запущенной обработки нажмём на кнопку Привет мир, то в конфигураторе, рядом с этой точкой останова, появится стрелочка (см. рис. 1.8.14). Это значит, что точка останова сработала, и Вы можете начать отладку процедуры. В это время работа пользовательского режима «1С: Предприятия» остановится (как бы зависнет).
Рис. 1.8.14
Передвигаться по коду можно с помощью кнопок панели:
Шагнуть в (F11) – перейдём на следующую строку кода, но если в текущей (там, где стрелка) строке какая-то собственная процедура или функция, созданная разработчиком конфигурации или обработки (об этом в третьей главе), то зайдём «внутрь» этой процедуры или функции.
Рис. 1.8.15
Шагнуть через (F11) – переходим на следующую строку кода. Если в текущей строке процедура или функция, созданная разработчиком конфигурации или обработки, то не заходим в эту процедуру или функцию.
Рис. 1.8.16
Шагнуть из (Shift + F11) – если нам не посчастливилось зайти в какую-то собственную процедуру или функцию, то при помощи этой кнопки можно из неё выйти.
Рис. 1.8.17
Идти до курсора (Shift + F10) – можно установить курсор на любой строке кода, после нажатия на эту кнопку отладка перейдёт на неё.
Рис. 1.8.18
Заметьте, код выполнится только после того, как мы пройдём его! Например, если мы сейчас на строке, где переменной А присваивается значение 10, то значение ещё не присвоилось. Для выполнения этого кода (присвоение значения) нужно перейти на следующую строку.
С движением по отладке разобрались. Потренируйтесь отлаживать Ваш пусть даже маленький код (удобнее всего это делать с помощью клавиш).
Научимся смотреть на значения переменных. Для этого дойдём в отладке до нижней строки кода (с предупреждением) и посмотрим на значения переменных А и В.
Рис. 1.8.19
Посмотреть значения той или иной переменной можно двумя способами. Первый – используя окно Вычислить выражение. Путь к этому окну: Главное меню – Отладка – Вычислить выражение.
Рис. 1.8.20
В открывшемся окне в поле Выражение напишем нужную переменную и нажмём на кнопку Рассчитать.
Рис. 1.8.21
Второй способ узнать значение нужной переменной – используя Табло. Табло открывается по следующему пути: Главное меню – Отладка – Табло.
Рис. 1.8.22
Табло откроется в нижней части конфигуратора, и Вы можете в него вводить любые переменные (в колонку Выражение).
Рис. 1.8.23
И в табло, и в окне Вычислить выражение можно производить различные действия над переменными.
Рис. 1.8.24
Эта вся информация об отладке, которая Вам нужна на данном этапе обучения.
Работайте с отладкой, программируйте в отладке, если Вы не понимаете, как работает тот или иной код, то Вам прямой путь в отладку. Это очень мощный и нужный инструмент разработчика.
В заключительной части этой главы разберём, как в платформе 1С можно сохранять и восстанавливать данные.
Сохранение информационной базы
Часто в процессе работы может возникнуть необходимость в резервном копировании данных информационной базой. Поскольку в этой книге мы рассматриваем работу с файловой информационной базой, то и будут приведены варианты сохранения файловой информационной базы. Их два – сохранение файла базы и сохранение dt файла. В первом случае нужно сохранить сам файл базы, который называется 1Cv8.1CD и расположен в каталоге информационной базы.
Узнать каталог файловой информационной базы можно двумя способами.
Первый способ: в окне запуска 1С выделяем нужную базу, в результате внизу появится строка, в которой будет написан путь к базе в файловой системе (рис 1.9.1).
Второй способ: также выделяем базу, нажимаем кнопку Изменить окна запуска 1С, в открывшемся окне Редактирование информационной базы в поле Каталог информационной базы и будет путь к нужной базе (см. рис. 1.9.2). Второй способ удобен, когда строка пути очень длинная и не помещается в окне запуска.
Рис. 1.9.1 | Рис. 1.9.2 |
После того как мы узнали каталог информационной базы, необходимо перейти в этот каталог в проводнике, в каталоге будет ряд файлов. И, как уже упоминалось выше, файл с названием 1Cv8.1CD и есть файл информационной базы.
Рис. 1.9.3
Если Вы его скопируете в какое-нибудь другое место, то вы создадите резервную копию информационной базы (рекомендую после копирования заархивировать этот файл каким-нибудь архиватором, чтобы он меньше занимал место в файловой системе).
Копированием файла 1Cv8.1CD будет сохранена конфигурация, созданная разработчиками, а также те данные, которые были внесены пользователями в базу в процессе работы.
Можно скопировать весь каталог, в котором расположен файл 1Cv8.1CD, тогда будет сохранён журнал регистрации и прочая вспомогательная информация.
Чтобы восстановить данные, нужно файл 1Cv8.1CD поместить в каталог информационной базы. Рекомендую уже имеющиеся файлы в каталоге удалить или переместить их временно в какой-то другой каталог. Но не затирать файлом 1Cv8.1CD такой же имеющийся файл!
Второй вариант сохранения данных – это сохранение dt файла. Для сохранения dt файла необходимо открыть конфигуратор информационной базы, прекратив работу других
пользователей. В конфигураторе нужно выполнить команду Выгрузить информационную базу, которая расположена в подменю Администрирование главного меню.
Рис. 1.9.4
В открывшемся окне Сохранение… необходимо выбрать каталог, в который будет сохранен dt файл выгруженной базы, и назвать файл так, чтобы было понятно, какой базы за какое число этот архив.
Рис. 1.9.5
Чтобы восстановить информационную базу, следует воспользоваться командой Загрузить информационную базу подменю Администрирование главного меню. При этом в базе никто не должен работать.
Имейте в виду, что текущие данные базы будут потеряны!
Когда нужно сохранять файл информационной базы, а когда dt файл?
Фирма 1С однозначно отвечает, что резервное копирование рабочих информационных баз следует выполнять посредством сохранения файла информационной базы, то есть первым способом, который мы разобрали. При помощи dt файла информационной базы можно, например, перенести файловую информационную базу в клиент-серверную. Это касается именно рабочих информационных баз, в которых ведётся учёт какого-то предприятия. В случае же учебных информационных баз сохранять базу лучше при помощи dt файла, чтобы послать её, например, на проверку преподавателю или кому-то показать и чтобы копия занимала меньше места.
Сохранение конфигурации
Помимо самой информационной базы с данными, которые вводили пользователи, можно сохранить конфигурацию этой информационной базы. Такое может понадобиться, когда Вам нужно где-то развернуть пустую базу, например, для доработки.
Для сохранения конфигурации следует воспользоваться командой Сохранить конфигурацию в файл подменю Конфигурация главного меню.
Рис. 1.9.6
В открывшемся окне Сохранение следует указать каталог, в который Вы хотите сохранить файл конфигурации, и при необходимости изменить название файла.
Рис. 1.9.7
Чтобы восстановить конфигурацию информационной базы, следует воспользоваться командой Загрузить конфигурацию из файла подменю Конфигурация главного меню.
Имейте в виду, что внесённые Вами изменения конфигурации будут потеряны!
Итак, мой уважаемый будущий коллега, той информации, которую я Вам предоставил в этой главе, вполне достаточно для того, чтобы начать делать первые шаги в изучении программирования в 1С. Задача этой главы подготовить Вас к освоению нового, уже более интересного материала. Потренируйтесь создавать обработки, формы и примитивные команды. Не думайте пока, для каких целей нужны те или иные вещи, а просто набейте руку. Потом Вы поймёте, что для чего нужно. Попробуйте поработать с отладкой. Также потренируйтесь в создании баз, в выгрузке информационных баз и конфигурации баз. После этой главы можете смело переходить ко второй главе, которая будет уже более глубокой и содержательной. Всего доброго и продуктивного обучения.
Рассмотрим примитивные типы, используемые в языке программирования 1С.
Всего существует четыре основных примитивных типов языка программирования 1С:
Число, Строка, Дата, Булево (Истина-Ложь), а также типы Неопределенно, NULL и тип
Тип.
Примитивные типы |
Число Строка Дата Булево Неопределено NULL Тип |
Таблица 2.1.1
Основная особенность примитивных типов в том, что в значениях этих типов нельзя выделить какие-то составляющие.
Примитивных типов могут быть как переменные, которые задаются где-нибудь в коде, а также реквизиты каких-либо объектов. В этой главе разберём работу с переменными примитивного типа, а создавать реквизиты примитивных типов будем учиться в четвёртой главе.
Для тех, кто изучал другие языки программирования: в языке программирования 1С не надо явно задавать тип переменной. Достаточно просто указать для данной переменной
какое-нибудь значение (Число, Строку, Булево значение или Дату), и она автоматически присвоит себе тип указанного значения. В то же время при создании реквизитов объектов конфигурации следует тип указать явно, но об этом Вы узнаете из четвёртой главы.
Первый примитивный тип Число. Это могут быть любые числа: целые и дробные числа, положительные и отрицательные.
Например: 23; 23.4; 233.33333. Можно использовать любые цифры, дробная часть разделяется символом «.» (точка). Отрицательное число начинается символом «-»: -23. По справочной информации, максимальная разрядность числа 38 знаков. Так как основные задачи в 1С не связаны с астрономическими расчётами и т.п., то этой разрядности будет достаточно.
Над типом Число определены главные математические операции: сложение, вычитание, умножение, деление. Вот как они выглядят:
Рис. 2.1.1
Подробно об основных операциях с числами вы узнаете в четвёртой части этой главы.
Второй примитивный тип – это тип Строка. Строка – это любой набор символов, заключённый в кавычки: . Строки могут быть однострочные и многострочные (текст).
Однострочная строка будет выглядеть так:
Рис. 2.1.2
А многострочная строка задаётся следующим образом:
Рис. 2.1.3
В многострочной строке каждая из строк не заканчивается кавычкой, а каждая последующая начинается с символа «|» (вертикальная черта).
Для строк есть операция сложения, выполняемая оператором «Плюс» (+). Это значит, что при сложении строки "Мама мыла " и строки "раму" получится строка "Мама мыла раму":
"Мама мыла " + "раму" = "Мама мыла раму".
Пустая строка задаётся следующим образом: "" (две сдвоенные кавычки без пробела). Подробнее об операциях со строками Вы узнаете в пятой части этой главы.
Третий примитивный тип – это тип Дата. Значения данного типа содержат дату григорианского календаря с 1 января 1 года нашей эры. Дата в языке программирования 1С задаётся в виде строки цифр в следующем формате – 'ГГГГММДДччммсс',
где:
ГГГГ – четыре цифры года, включая тысячелетие и век, например, 2013 или 1997; ММ – две цифры месяца, например, 02 – это февраль, а 12 – декабрь;
ДД – две цифры даты, например, 01 – первое число, или 23 – двадцать третье число; чч – две цифры часов в 24-часовом формате, к примеру: 01 – час ночи, 13 – час дня; мм – две цифры минут, к примеру: 30 – 30 минут, 01 – 1 минута;
сс – две цифры секунд, 20 – это 20 секунд, и так далее.
Также дату можно задавать в таком виде: 'ГГГГММДД'. При таком формате часы, минуты и секунды будут равны нулю.
Пустая дата задается следующим образом: '00000000000000' .
Таким образом, если Вы родились 20 января 1989 г., то задать данную дату на языке программирования 1С можно двумя способами:
'19890120' или '19890120000000'.
А если Вы хотите просто задать время 1 час 30 минут, то будет следующий вид: '00010101013000'. Подробно об операциях с датами Вы узнаете в шестой части этой главы.
Четвёртый примитивный тип – это тип Булево. Булево – это логический тип, у которого всего два значения – Истина и Ложь.
Рис. 2.1.4
На данном этапе обучения этого достаточно. Более подробно об операциях с типом
Булево Вы узнаете в третьей части настоящей главы. И ещё два типа – это NULL и Неопределенно.
Тип NULL – значения данного типа используются исключительно для определения отсутствующих значений при работе с запроса. С языком запросов мы научимся работать в девятой главе.
Тип Неопределенно применяется, когда надо использовать пустое значение, не принадлежащее ни к одному другому типу. Данный тип так и задаётся.
А = Неопределено;
Мы разобрали примитивные типы языка программирования 1С, и давайте узнаем, как работать с переменными.
Переменные
Прежде чем начать изучать переменные определённых примитивных типов определимся с понятием Переменная.
Что такое переменная? Научным языком – Переменная – это идентификатор, определённый некоторым типом, способный менять своё значение в ходе выполнения программы.
Каким образом объявляются переменные в языке программирования 1С? Делается это двумя способами:
Переменная может быть объявлена явным образом, тогда она сразу начинает своё существование (причём в ней нет никакого значения). Пишем оператор Перем, название этой переменной, потом либо запятая и название другой переменной, либо точка с запятой.
Рис. 2.1.5
Явное задание переменных должно быть либо в начале модуля, либо в начале процедуры или функции.
Переменная может быть объявлена неявным образом. Тогда просто пишем название переменной и присваиваем ей какое-нибудь значение.
Рис. 2.1.6
Символ «=» (равно) – это операция присваивания. При помощи этой операции какой- то переменной присваивается определённое значение.
Обращаю внимание тех, кто изучал другие языки программирования.
Непосредственно при написании кода в конфигураторе 1С не нужно явно задавать тип переменной. Достаточно просто указать для данной переменной какое-нибудь значение (число, строку, булево значение), и данная переменная автоматически присвоит себе этот тип. Кроме того, в языке 1С переменная (явно или неявно заданная) может по желанию разработчика в любом месте поменять свой тип.
В этой части Вы узнаете о самых простых способах вывода информации в программе
1С.
Процедура Сообщить
Первый пример, который мы рассмотрим, будет хрестоматийным, с него начинают изучение почти всех языков программирования. Это вывод сообщения Привет, Мир! Фразу
«Привет, Мир!» мы выведем в окно сообщений программы 1С, и сделаем мы это при помощи метода Сообщить.
Создадим внешнюю обработку, форму, команду формы ВывестиСообщение, разместим команду на форме, создадим обработчик этой команды на клиенте (подробно о создании внешних обработок см. Глава 1, Часть 7, стр. 37), напишем в обработчике команды следующий код:
&НаКлиенте
Процедура ВывестиСообщение(Команда) Сообщить("Привет, мир!");
КонецПроцедуры
Листинг 2.2.1 Обращаю Ваше внимание, что в конце всех операторов всегда необходимо ставить
точку с запятой. Это операнд, который даёт знать компилятору 1С, что данный блок
программы завершён и нужно перейти к следующему блоку.
Сохраним, запустим обработку в пользовательском режиме «1С: Предприятия» и выполним команду.
После выполнения Вы увидите, что в нижней части экрана открылось окно Сообщения
и в нём вышел наш текст «Привет, Мир!»
Рис. 2.2.1
Метод Сообщить – это встроенная процедура платформы 1С, которая выводит текстовую информацию в окно сообщений.
Процедуры Предупреждение и ПоказатьПредупреждение
Ещё один интересный метод вывода информации – это метод Предупреждение или ПоказатьПредупреждение. Оба метода процедуры, которые выводят на экран окно предупреждения с нужным текстом.
Процедура Предупреждение работает только тогда, когда в свойство конфигурации Режим использования модальности установлено значение Использовать или Использовать с предупреждениями (см. рис. 2.2.2). В противном случае следует использовать процедуру ПоказатьПредупреждение. Разберёем работу с обоими методами.
Рис. 2.2.2
На форме обработки, которую сделали в начале, создадим новую команду формы ВывестиПредупреждение, поместим её на форму, создадим клиентский обработчик команды, и внутри обработчика команды напишем следующий код:
&НаКлиенте
Процедура ВывестиПредупреждение(Команда) Предупреждение("Привет, мир!");
КонецПроцедуры
Листинг 2.2.2 Теперь перейдём в пользовательский режим «1С: Предприятия», запустим созданную
обработку и нажмём на кнопку Вывести предупреждение.
Рис. 2.2.3
Должно появиться окно с кнопкой ОК и нашей надписью «Привет, мир!»
Если же мы установим у свойства Режим использования модальности нашей конфигурации значение Не использовать (не забудем после этого сохранить конфигурацию и обновить базу данных).
Рис. 2.2.4
В этом случае при попытке выполнения команды Вывести предупреждение возникнет ошибка.
Рис. 2.2.5
Чтобы ошибки не было, следует использовать метод ПоказатьПредупреждение.
Создадим новую команду, которую так и назовём ПокажемПредупреждение, и напишем в ней следующий код:
&НаКлиенте
Процедура ПокажемПредупреждение(Команда) ПоказатьПредупреждение(,"Привет, мир!");
КонецПроцедуры
Листинг 2.2.3
Обратите внимание, что текст пишем во втором параметре!
В случае выключенного использования модальности данный метод будет работать.
Рис. 2.2.6
Подробно работа с отключенной модальностью описана в моей книге «Основы разработки 1С: Такси».
Очень удобно выводить такое предупреждение, когда надо сообщить пользователю то, что он обязательно должен увидеть, иначе часто на окно сообщений внизу не обращают внимания.
Какие ещё особенности есть у данной процедуры?
Этой таймаут и заголовок окна. Таймаут задаёт время в секундах, в течение которого окно будет открыто, а заголовок – это непосредственно заголовок данного окна. По умолчанию таймаут равен 0, это означает, что время не ограничено.
Изменим обработку.
В случае предупреждения будет такой код:
&НаКлиенте
Процедура ВывестиПредупреждение(Команда) Предупреждение("Привет, мир!",5,"Наш заголовок");
КонецПроцедуры
Листинг 2.2.4
А в случае когда используем ПоказатьПредупреждение, такой:
&НаКлиенте
Процедура ПокажемПредупреждение(Команда) ПоказатьПредупреждение(,"Привет, мир!",5,"Наш заголовок");
КонецПроцедуры
Листинг 2.2.5
Запустим обработку заново и посмотрим, что получится:
Рис. 2.2.7
Окно откроется и через несколько секунд закроется. А можно написать и так:
&НаКлиенте
Процедура ПокажемПредупреждение(Команда) ПоказатьПредупреждение(,"Привет, мир!",,"Наш заголовок");
КонецПроцедуры
Листинг 2.2.6
В этом случае окно закрываться не будет.
И ещё один момент. В случае метода Предупреждение, пока пользователь не нажмёт кнопку ОК, дальнейшее выполнение кода программы не произойдёт. Для того чтобы это
увидеть, напишем процедуру Сообщить после процедуры Предупреждение:
&НаКлиенте
Процедура ВывестиПредупреждение(Команда)
Предупреждение("Привет, мир!",,"Наш заголовок"); Сообщить("Ещё раз привет!");
КонецПроцедуры
Листинг 2.2.7
Проверьте работу этого кода самостоятельно.
А вот в случае метода ПоказатьПредупреждение дальнейшее выполнение кода произойдёт в независимости от того, была нажата кнопка ОК или нет.
Изменим код показа предупреждения.
&НаКлиенте
Процедура ПокажемПредупреждение(Команда)
ПоказатьПредупреждение(,"Привет, мир!",,"Наш заголовок"); Сообщить("Ещё раз привет!");
КонецПроцедуры
Листинг 2.2.8
И попробуем его выполнить.
Рис. 2.2.8
В этот раз код продолжил свое выполнение.
В этой части Вы научились работать с примитивными операциями вывода информации в программе 1С. В дальнейшем Вы научитесь выводить информацию гораздо
более удобными способами, но всё равно данные методы Вам пригодятся в будущей работе.
Перед тем как мы начнём изучать числа, строки и даты более подробно, нам нужно будет освоить одну маленькую, но очень важную тему. Это переменные типа Булево.
Булево – это признак истинности или ложности какого-нибудь утверждения.
Например, утверждение «5 меньше 7» – истинно.
А утверждение, что 5 = 7 – ложно.
Как же присваиваются значения переменным типа Булево? Делается это очень просто. Первый способ.
&НаКлиенте
Процедура ВыполнитьКоманду(Команда)
А = Ложь;
Б = Истина;
Сообщить(А); Сообщить(Б);
КонецПроцедуры
Листинг 2.3.1 Данный код напишем в обработчике новой команды (создадим новую обработку,
форму обработки, команду формы и т.д.)
Посмотрим, как выводится всё это в окно сообщений.
Рис. 2.3.1
Мы видим, что разработчики платформы сделали вывод булевых значений на экран в наиболее комфортном пользователю виде.
Второй способ. Булево значение может быть задано в виде какого-либо логического
выражения, например:
&НаКлиенте
Процедура ВыполнитьКоманду2(Команда) А = 5 > 7;
Б = 5 < 7;
Сообщить(А); Сообщить(Б);
КонецПроцедуры
Листинг 2.3.2
Посмотрим, что выйдет в окно сообщений.
Рис. 2.3.2
Ответьте, почему вышли такие сообщения?
Операции над переменными типа Булево
Всего в языке программирования 1С существует три операции над переменными типа
Булево: это НЕ, И, ИЛИ.
Для того чтобы их понять, рассмотрим три таблицы.
Первая операция – НЕ – логическое отрицание. Логическое отрицание меняет булево значение на противоположное.
Понять функционирование этой операции вам поможет следующая таблица:
А | Б |
Истина | Ложь |
Ложь | Истина |
Табл. 2.3.1 Следующая операция – И – конъюнкция. Конъюнкция возвращает истину только
тогда, когда оба значения истинны.
Понять функционирование данной операции Вам поможет следующая таблица:
А | Б | С = А И Б |
Истина | Истина | Истина |
Ложь | Истина | Ложь |
Истина | Ложь | Ложь |
Ложь | Ложь | Ложь |
Табл. 2.3.2 Третья операция – ИЛИ – дизъюнкция. Дизъюнкция возвращает истину тогда, когда
хотя бы одно значение истинно.
Понять функционирование данной операции Вам поможет следующая таблица:
А | Б | С = А ИЛИ Б |
Истина | Истина | Истина |
Ложь | Истина | Истина |
Истина | Ложь | Истина |
Ложь | Ложь | Ложь |
Табл. 2.3.3 Если у Вас возникли проблемы с осознанием данных операций, перепишите эти
таблицы куда-нибудь и используйте их всякий раз, когда будете работать с данным типом.
Впоследствии вы освоите эти логические операции и легко будете ими манипулировать.
Для наглядности приведём пару примеров из таблиц на языке программирования 1С (для этого необходимо опять создать новую обработку):
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) А = Ложь;
Б = Истина;
С = Не А;
Сообщить(С); С = А И Б;
Сообщить(С); С = А Или Б;
Сообщить(С); КонецПроцедуры
Листинг 2.3.3
Смотрим, что получилось.
Рис. 2.3.3
Самостоятельно выполните все операции из таблиц и проверьте, правда ли там написана.
А можно ли выполнять логические операции подряд?
Да, можно, логические операции выполняются слева направо и имеют следующий уровень старшинства:
Первый: выполняются операции в скобках. Второй: операция НЕ.
Третий: операция И. Четвёртый: операция ИЛИ.
Чтобы не путаться в операциях, я советую Вам использовать скобки, где только возможно.
Рассмотрим пример.
&НаКлиенте
Процедура ВыполнитьКоманду2(Команда)
А = Ложь;
Б = Истина;
С = Ложь;
Д = А и С или Б; Сообщить(Д);
КонецПроцедуры
Листинг. 2.3.4
В данном примере сначала будет работать операция И между А и С.
Смотрим таблицу 1.3.2: А – Ложь, С – Ложь, результат А И С будет Ложь.
Следующим шагом будет выполнение операции ИЛИ между Ложью (результат предыдущей операции) и значением Б, которое Истина.
Результат будет Истина.
Рис. 2.3.4.
А если нам надо, чтобы прошла сначала операция ИЛИ между С и Б, а потом только операция И между А и тем, что получилось, то для этого необходимо использовать скобки.
&НаКлиенте
Процедура ВыполнитьКоманду2(Команда)
А = Ложь;
Б = Истина;
С = Ложь;
Д = А и (С или Б); Сообщить(Д);
КонецПроцедуры
Листинг 2.3.5
Результат диаметрально противоположный. Почему?
Благодаря скобкам сначала выполняется операция ИЛИ между С и Б,
так как С – Ложь, а Б – Истина, результат будет Истина (см табл. 2.3.3). Потом между значением А (которое Ложь) и значением Истина (результатом предыдущей операции) выполняется операция И. Результат будет Ложь (см табл. 2.3.2).
Рис. 2.3.5
Рассмотрим ещё один пример со скобками и операцией НЕ.
&НаКлиенте
Процедура ВыполнитьКоманду3(Команда) А = Ложь;
Б = Истина;
Д = Не А Или Б; Сообщить(Д);
Д = Не (А Или Б);
Сообщить(Д) КонецПроцедуры
Листинг. 2.3.6
Посмотрите, какой будет результат, и попробуйте сами его объяснить, используя вышеприведённые таблицы (табл. 1.3.1 – 1.3.3).
Операторы сравнения
Рассмотрим более подробно операторы сравнения. Это:
Больше: >
Меньше: <
Больше или равно: >= Меньше или равно: <= Не равно: <>
Равно: =
Все эти операторы применимы для всех примитивных типов. Рассмотрим их для чисел (опять создадим новую обработку).
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) Д = 5 > 5;
Сообщить("5 > 5 это - "); Сообщить(Д);
Д = 5 >= 7;
Сообщить("5 >= 7 это - "); Сообщить(Д);
Д = 6 < 8;
Сообщить("6 < 8 это - "); Сообщить(Д);
Д = 7 <= 9;
Сообщить("7 <= 9 это - "); Сообщить(Д);
Д = 7 <> 10;
Сообщить("7 <> 10 это - "); Сообщить(Д);
Д = 7 = 7;
Сообщить("7 = 7 это - "); Сообщить(Д);
КонецПроцедуры
Листинг 2.3.7
Смотрим, что получилось.
Рис. 2.3.6
Точно так же с данными операциями сравнения можно применять операции НЕ, ИЛИ. Скомпонуем из вышеприведённого примера следующий:
&НаКлиенте
Процедура ВыполнитьКоманду2(Команда)
Д = (5 > 5) И (5 >= 7);
Сообщить("(5 > 5) И (5 >= 7) это - ");
Сообщить(Д);
Д = (6 < 8) Или (7 <= 9);
Сообщить("(6 < 8) Или (7 <= 9) это - "); Сообщить(Д);
Д = Не (7 <> 10) Или (7 = 7);
Сообщить("Не (7 <> 10) Или (7 = 7) это - "); Сообщить(Д);
КонецПроцедуры
Листинг 2.3.8
Смотрим, что получилось. Объясните данный результат.
Рис. 2.3.7
В этой части научимся работать с примитивным типом Число и освоим все необходимые для программирования операции над числами. Со всем остальным Вы без труда сможете познакомиться в справке.
Создадим новую обработку, в которой будем проводить все манипуляции с переменными (форму обработки, команду и обработчик команды).
Зададим простые переменные:
&НаКлиенте
Процедура ВыполнениеКоманды(Команда)
Перем А, Б, С; Перем Д, Г, Е;
КонецПроцедуры
Листинг 2.4.1
Присвоим переменным числа, и выполним элементарные операции:
А = 10; Б = 12; С = 3; Д = А + Б - С;
Г = А * Б; Е = А/Б;
Листинг 2.4.2
Результат выведем в окно сообщений:
Сообщить(Д); Сообщить(Г); Сообщить(Е);
Листинг 2.4.3
Сохраняем обработку, смотрим на результат:
Рис. 2.4.1
О порядке выполнения операций. Сначала выполняются операции умножения и деления, потом – операции сложения и вычитания. Операции умножения и деления выполняются слева направо.
К примеру, в формуле:
сначала А делится на Б, потом всё это поделится на С. А при операции:
сначала Б поделим на С, а потом это всё вычтем из А. Что же нам сделать, если в выражении:
сначала нужно поделить Б на С, а потом А поделить на полученный результат? Или в другом выражении сначала вычесть А из Б, а потом разность поделить на С? Для этого нам пригодятся операторные скобки.
Запишем так:
или:
Проверим это утверждение на практике:
&НаКлиенте
Процедура ВыполнениеКоманды2(Команда) Перем А, Б, С;
Перем Д, Г, Е; А = 23;
Б = 7;
С = 4;
Е = А/Б/С;
Д = А - Б/С;
Сообщить("А/Б/С = "); Сообщить(Е); Сообщить("А - Б/С = "); Сообщить(Д);
Е = А/(Б/С);
Д = (А - Б)/С;
Сообщить("А/(Б/С) = "); Сообщить(Е);
Сообщить("(А - Б)/С = "); Сообщить(Д);
КонецПроцедуры
Листинг 2.4.4
Посмотрим на результат:
Мой Вам совет, можете вдоволь злоупотреблять этими скобками. Если Вы сомневаетесь, какая операция будет выполняться в первую очередь, заключайте в скобку ту операцию, которая Вам нужна.
Следующий оператор, который нас интересует, это оператор % – остаток от деления.
Например:
в данном случае берётся остаток от деления А на Б. 10 % 7 = 3.
23 % 7 = 2.
При помощи этого оператора Вы можете проверить кратно одно число другому или нет: если одно число кратно другому, то остаток от деления будет 0.
Узнаем при помощи этого оператора, кратно ли число 22 двум и четырём (см. листинг
2.4.5).
&НаКлиенте
Процедура ВыполнениеКоманды3(Команда)
Перем А, Б, С; Перем Д, Г, Е;
А = 22;
Б = 2;
С = 4;
Д = А % Б; Г = А % С;
Сообщить("А % Б = "); Сообщить(Д); Сообщить("А % С = "); Сообщить(Г);
КонецПроцедуры
Листинг 2.4.5
Ввод чисел на форме
Забежим немного вперёд и изучим, как вводить цифры на форме (см. Глава 5, Часть 3, стр 320).
Создадим новую обработку и форму, а на форме создадим реквизит формы с типом Число. Добавляется новый реквизит на форме следующим способом: на закладке Реквизиты правого верхнего окна формы следует выполнить команду Добавить реквизит.
Реквизит будет добавлен, но тип у этого реквизита по умолчанию Строка.
Рис. 2.4.4
Рис. 2.4.5
(3) 2.19) Ввод чисел на форме - при вводе параметров, длина уже 79-81
Для того чтобы у реквизита установить тип Число, следует нажать на кнопку «…» у поля Тип в палитре свойств реквизита и в открывшемся окне поставить флаг рядом с типом Число.
Обратите внимание на параметры Длина и Точность, длина задаёт общую длину числа, а точность – количество знаков после запятой.
Рис. 2.4.7
Но, и это важно, длина уже включает в себя точность. Например, если у нас длина 5, а точность 2, то мы сможем ввести такое число: 123.45, но не сможем такое: 1234.56.
Проверим, как это работает, установим длину 5, точность 2, нажмём на кнопку ОК, и у нас в палитре свойств появятся свойства Длина и Точность с установленными значениями.
Рис. 2.4.8
Изменим имя реквизита и поместим его на форму. Для этого необходимо выделить созданный реквизит и, удерживая нажатой левую клавишу мышки, «перетащить» выделенный реквизит на закладку Элементы левого верхнего окна формы в корень Форма.
Рис. 2.4.9
В результате реквизит появится на форме.
Рис. 2.4.10
Сохраним обработку, запустим её в пользовательском режиме и посмотрим, какие числа мы сможем вводить. Напомню, что мы установили длину 5, а точность 2.
Рис. 2.4.11
Вы увидите, что мы можем максимум указать три цифры перед запятой и две – после.
Самостоятельно попробуйте поустанавливать разную длину и точность числа.
Изучим основные функции работы с числами.
Функция Окр
Первая функция для примитивного типа Число, с которой мы научимся иметь дело, это функция Окр. Функция Окр округляет число до нужного количества знаков после запятой. Если мы напишем:
Окр(12.122123,3), то результат будет – 12,122. А при
Окр(12.124623,1), результат будет – 12.1, А при
Окр(12.124623), результат будет – 12.
У этой функции обязателен только первый параметр – число, которое нужно округлить. Во втором необязательном параметре (можно не указывать) отмечается, сколько знаков после запятой нужно оставить. Если второй параметр не указан, то произойдёт округление до целого числа.
Посмотрим, как работает этот метод (сделайте новую обработку, форму, команду и
т.д.)
&НаКлиенте
Процедура ВыполнениеКоманды(Команда) В = Окр(12.122123,3);
Сообщить(В);
В = Окр(12.124623,1);
Сообщить(В);
В = Окр(12.124623);
Сообщить(В); КонецПроцедуры
Листинг 2.4.6 Запустим и протестируем обработку в пользовательском режиме «1С: Предприятия».
Рис. 2.4.12
Всё очень просто.
В функцию Окр можно использовать ещё и третий параметр, это системное перечисление РежимОкругления. Оно бывает двух видов:
РежимОкругления.Окр15как10 и РежимОкругления.Окр15как20
В первом случае число 1,5 округляется до 1 в меньшую сторону, во втором случае число 1,5 округляется до 2 в большую сторону.
Рассмотрим пример:
&НаКлиенте
Процедура ВыполнениеКоманды2(Команда)
В = Окр(12.1345,3, РежимОкругления.Окр15как10); Сообщить(В);
В = Окр(12.1345,3, РежимОкругления.Окр15как20); Сообщить(В);
КонецПроцедуры
Листинг 2.4.7
Перезапустим обработку в пользовательском режиме «1С: Предприятия» и проверим, как пройдёт округление.
Рис. 2.4.13
Как Вы уже поняли, режим округления необязательный параметр, то есть можно его опустить, если Вам это не критично. По умолчанию, то есть когда второй параметр не указан, режим округления всегда Окр15Как20.
Функция Цел
Следующая функция – это функция Цел. Функция Цел отсекает дробную часть от целого числа. Напишем следующий код:
&НаКлиенте
Процедура ВыполнитьКоманду3(Команда) Перем А,Б,С;
А = 23;
Б = 7;
С = 4;
В = Цел(442.11344554);
Сообщить(В);
В = Цел(0.12341);
Сообщить(В);
В = Цел ((А*С)/Б);
Сообщить(В); КонецПроцедуры
Листинг 2.4.8 Теперь посмотрим, как этот код отработает в пользовательском режиме «1С:
Предприятия»:
Рис. 2.4.14
Функция Pow
Следующая функция – это возведение в степень, функция Pow – это xy. Фукнция имеет следующий синтаксис:
Pow(x,y)
Числа х и у могут принимать любые значения, в том числе дробные и отрицательные.
Единственно, если y меньше 0, то число х всегда должно быть положительным, иначе сгенерируется ошибка. Рассмотрим примеры:
&НаКлиенте
Процедура ВыполнитьКоманду4(Команда)
В = Pow(100,0.2);
Сообщить(В);
В = Pow(100,5);
Сообщить(В);
В = Pow(100,-2);
Сообщить(В);
В = Pow(100,0);
Сообщить(В);
В = Pow(0,100);
Сообщить(В); КонецПроцедуры
Листинг 2.4.9 Проверим работу обработки в пользовательском режиме «1С: Предприятия».
Рис. 2.4.15
Функция Sqrt
Ещё одна интересная для нас функция – это квадратный корень Sqrt. Пишется она в
виде:
Sqrt(Х),
где Х – неотрицательное число.
Несколько примеров:
&НаКлиенте
Процедура ВыполнитьКоманду5(Команда)
В = Sqrt(100);
Сообщить(В); В = Sqrt(9); Сообщить(В); В = Sqrt(7); Сообщить(В);
КонецПроцедуры
Листинг 2.4.10
Получится следующий результат:
Рис. 2.4.16
Округлим последнее вычисление до двух знаков после запятой:
В = Окр(Sqrt(7),2);
Сообщить(В);
Листинг 2.4.11
Рис. 2.4.17
В этой части Вы научились работать с числами. Функций работы с числами гораздо больше, чем те, что мы перечислили в этой главе. С ними Вы сможете ознакомиться в справочной информации. Потренируйтесь самостоятельно с оставшимися функциями.
В этой части научимся работать со строками.
Создадим новую обработку и форму обработки, в которой мы проведём все манипуляции с переменными типа Строка. На форме обработки создадим команду, в обработчике которой зададим три переменных типа Строка (напомню, строки задаются посредством написания текста в кавычках).
&НаКлиенте
Процедура ВыполнитьКоманду(Команда)
ПеремФамилия = "Иванов"; ПеремИмя = "Петр"; ПеремОтчество= "Васильевич";
КонецПроцедуры
Листинг 2.5.1 Первая операция, которую мы разберём, это сложение строк, или операция
конкатенации:
ПеремФИОПолностью = ПеремФамилия + " " + ПеремИмя + " " + ПеремОтчество;
Листинг 2.5.2 Добавим процедуру Сообщить, чтобы посмотреть на результат сложения:
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) ПеремФамилия = "Иванов"; ПеремИмя = "Петр"; ПеремОтчество= "Васильевич";
ПеремФИОПолностью = ПеремФамилия + " " + ПеремИмя + " " + ПеремОтчество; Сообщить(ПеремФИОПолностью);
КонецПроцедуры
Листинг 2.5.3 Сохраним обработку, запустим и посмотрим, что выйдет в окне сообщений:
Рис. 2.5.1
Обратите внимание, строки можно складывать как посредством переменных типа строка, так и посредством написания самой строки.
То есть можно написать и так:
ПеремФИОПолностью = "Фамилия: " + ПеремФамилия +
", имя: " + ПеремИмя +
", отчество " + ПеремОтчество;
Листинг 2.5.4 Подправим предыдущий код, и в окне сообщений должна выйти следующая надпись:
Рис. 2.5.2
Разберём очень интересный и нужный для нас набор системных значений – это Символы. Всего этот набор содержит шесть значений, и мы поочерёдно рассмотрим некоторые из них на примере Иванова Петра Васильевича. Будем добавлять код из листингов ниже в обработчики команд обработки и смотреть на результат в окне сообщений.
Первое значение – это Возврат каретки, в случае применения этого значения перечисления текст будет переноситься на новую строку в начало:
ПеремФИОПолностью = ПеремФамилия + Символы.ВК +
ПеремИмя + Символы.ВК + ПеремОтчество;
Листинг 2.5.5
Рис. 2.5.3
Следующее значение – это Горизонтальная табуляция, имитирует нажатие клавиши
Tab на клавиатуре при написании текста:
ПеремФИОПолностью = ПеремФамилия + Символы.Таб +
ПеремИмя + Символы.Таб + ПеремОтчество;
Листинг 2.5.6
Рис. 2.5.4
Продолжаем. Символ пробела, называется Символ непрерывного пробела:
ПеремФИОПолностью = ПеремФамилия + Символы.НПП +
ПеремИмя + Символы.НПП + ПеремОтчество;
Листинг 2.5.7
Рис. 2.5.5
Последний символ, который нас интересует, это Перенос строки:
ПеремФИОПолностью = ПеремФамилия + Символы.ПС +
ПеремИмя + Символы.ПС + ПеремОтчество;
Листинг 2.5.8
Рис. 2.5.6
Ещё перенос строки можно сделать, используя символ «|» (вертикальная черта), тогда надо на строке оставлять кавычку открытой, а на следующей строке, не открывая кавычку, сразу ставим вертикальную черту. Например:
СтрокаСПереносом = "Тут мы будем переносить строку
|вот мы на новой строке"; Сообщить(СтрокаСПереносом);
Листинг 2.5.9
Рис. 2.5.7
Символы Перевод формы и Вертикальная табуляция в данном уроке мы рассматривать не будем. Поэкспериментируйте с изученным набором символов, попробуйте использовать разные комбинации символов.
У многих новичков возникает вопрос, как отобразить кавычки непосредственно в тексте. Сделать это очень просто:
ФИО = "Иванов Иван Иванович по кличке ""Иваныч"""; Сообщить(ФИО);
Листинг 2.5.10
Рис. 2.5.8
Пишем сдвоенные кавычки и внутри нужное слово.
Ввод строк на форме
Научимся создавать поля ввода строк на форме. Для этого мы снова забежим немного вперёд в работу с формами (см. Глава 5, часть 3, стр 320).
Создадим новую обработку и форму, а на этой форме создадим реквизит формы с типом Строка. Для этого на закладке Реквизиты правого верхнего окна формы выполним команду Добавить реквизит.
Рис. 2.5.9
После нажатия на иконку будет создан новый реквизит формы и справа откроется палитра свойств этого реквизита.
Рис. 2.5.10
Переименуем реквизит. Для этого в палитре свойств, которая отрыта справа, изменим поле Имя. По умолчанию в этом поле значение Реквизит1, у нас будет значение Фамилия.
После изменения свойств название реквизита на закладке Реквизиты изменится.
Рис. 2.5.11
Свойства Тип и Длина оставим такими, какими они установились по умолчанию. По умолчанию всем новым реквизитам формы устанавливается тип Строка, который нам и нужен.
Следующим шагом поместим новый реквизит на форму, для этого необходимо выделить созданный реквизит и, удерживая нажатой левую клавишу мышки, «перетащить» его на закладку Элементы левого верхнего окна формы в корень Форма.
Рис. 2.5.12
В результате на форме появится поле ввода, которое будет связано с реквизитом формы.
Рис. 2.5.13
Мы создали реквизит формы и можем обращаться к нему напрямую в обработчиках команд формы. Проверим это. Создадим команду, которую назовём, как всегда, ВыполнитьКоманду, и поместим её на форму.
Рис. 2.5.14
В обработчике команды просто выведем в сообщение то, что у нас введено в поле ввода, которое связано с реквизитом формы, то есть мы выведем в сообщении значение реквизита формы.
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) Сообщить(Фамилия);
КонецПроцедуры
Листинг 2.5.11
Проверим работу новой обработки.
Рис. 2.5.15
Теперь Вам небольшое задание: сделайте так, чтобы в поля ввода можно было вводить фамилию, имя и отчество, а при выполнении команды формы выводите фамилию, имя, отчество одной строкой, как показано на рисунке ниже.
Рис. 2.5.16
Функция СтрДлина
Так, с самими строками разобрались, с вводом строк на форме понятно, перейдём к изучению функций и процедур для работы со строками.
Первая наша функция будет СтрДлина. Эта функция возвращает длину строки, то есть количество символов в строке, включая пробелы, возвраты кареток, переносы, табуляции и т.д.
Создадим новую обработку с формой, а также реквизит формы ФИОПолностью с типом Строка и команду формы.
В обработчике команды напишем следующий код:
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) ДлинаСтроки = СтрДлина(ФИОПолностью);
Сообщить("СтрДлина (" + ФИОПолностью + ") = " + ДлинаСтроки);
КонецПроцедуры
Листинг 2.5.12
Введём любое ФИО и смотрим на результат:
Рис. 2.5.17
Как видно, длина строки Сидоров Леонид Александрович – 28 символов.
СтрДлина возвращает число, которое является длиной строки, указанной в параметре.
Вы заметили, что мы «сцепили» строку с числом в этой операции:
"СтрДлина (" + ФИОПолностью + ") = " + ДлинаСтроки
Листинг 2.5.13 Произошло преобразование строки в число. Подробнее операции преобразования
будем изучать в заключительной части этой главы.
Функции СокрЛ, СокрП, СокрЛП
Часто бывают случаи, когда строка может задаться пользователем либо перенестись из другой программы в виде:
«Иванов Иван Иванович »
И много пробелов в конце строки.
Для того чтобы отсечь все эти ненужные пробелы, есть специальные функции:
СокрЛ(<Строка>) – отсекает пробелы слева. СокрП(<Строка>) – отсекает пробелы справа.
СокрЛП(<Строка>) – отсекает пробелы справа и слева
Чтобы продемонстрировать возможность этих функций, сделаем в уже созданной обработке команду, в обработчике которой будет следующий код:
&НаКлиенте
Процедура ВыполнитьКоманду2(Команда)
НачСтроки = "НачСтр/"; КонСтроки = "/КонСтр";
Сообщить(НачСтроки + ФИОПолностью + КонСтроки);
КонецПроцедуры
Листинг 2.5.14
После перезапуска обработки специально добавим пробелы в поле ввода перед самой строкой и после:
Рис. 2.5.18
Результат выполнения команды должен получиться следующим:
Рис. 2.5.19
Пробелы мешают, их нужно убрать, для этого используем вышеприведённые функции.
Чтобы продемонстрировать их работу, допишем код:
НачСтроки = "НачСтр/"; КонСтроки = "/КонСтр";
ФИОСокрЛ = СокрЛ(ФИОПолностью); ФИОСокрП = СокрП(ФИОПолностью); ФИОСокрЛП = СокрЛП(ФИОПолностью);
Сообщить("СокрЛ: " + НачСтроки + ФИОСокрЛ + КонСтроки); Сообщить("СокрП: " + НачСтроки + ФИОСокрП + КонСтроки); Сообщить("СокрЛП: " + НачСтроки + ФИОСокрЛП + КонСтроки)
Листинг 2.5.15
И посмотрим, что получится:
Рис. 2.5.20
Мой Вам совет: как можно больше злоупотреблять данными функциями, поскольку часто многие пользователи по ошибке или по иным причинам ставят пробелы после уже введённого слова. А потом при дальнейшей работе это выглядит очень некрасиво.
Используйте вышеприведённые функции в том коде, где мы выводили ФИО (см. стр.
92), попробуйте ставить лишние пробелы, и посмотрите, что из этого у Вас получится.
Функции Лев, Прав
Рассмотрим функции Лев и Прав. Эти функции выбирают нужное количество символов слева и справа строки соответственно и возвращают укороченную строку.
Разберём функцию Лев. Функция выбирает нужное количество символов слева. Она задаётся в таком виде:
Лев(<Строка>,<КоличествоСимволов>)
Где:
Строка – та строка, которую функция обрабатывает;
КоличествоСимволов – количество символов, которые будут выбраны.
Посмотрим, как она работает на уже знакомом примере с фамилиями. Создадим новую команду формы обработки, и в её обработчике будет следующий код:
Процедура ВыполнитьКоманду3(Команда) Фамилия = "Иванов";
Имя = "Петр"; Отчество = "Сергеевич";
ФИОКратко = Фамилия + " " +
Лев(Имя,1) + ". " +
Лев(Отчество,1) + "."; Сообщить(ФИОКратко);
КонецПроцедуры
Листинг 2.5.16
Должна получиться следующая строка:
Рис. 2.5.21
Рассмотрим другой пример.
Имеем автомобильные номера вида «ва345укRU23». По условиям задачи код региона всегда будет состоять из двух символов и букв «RU». Надо получить номер без кода региона.
Номер = "ва345укRU23"; НомерБезКода = Лев(Номер,7); Сообщить(НомерБезКода);
Листинг 2.5.17
Смотрим. В результате должна отобразиться следующая строка:
Рис. 2.5.22
Перейдем к функции Прав. Эта функция выбирает справа нужное количество символов. Она пишется в таком виде:
Прав(<Строка>,<Количество символов>)
Где:
Строка – та строка, которую функция обрабатывает.
Количество символов – количество символов, которые будут выбраны.
Рассмотрим её на нашем примере с номером, только на этот раз получим код региона.
Номер = "ва345укRU23"; КодРегиона = Прав(Номер,4); Сообщить(КодРегиона);
Листинг. 2.5.18
Данный код должен выводить следующий результат:
Рис. 2.5.23
А теперь, используя функцию Лев и Прав, получите три цифры номера.
Рассмотрим другой пример, который использует также функцию СтрДлина. Иногда некоторые поставщики выгружают товар с артикулом перед наименованием. Выглядит это, к примеру, так:
«34221 Ручка шариковая» или
«23444 Тетрадь в клетку, 12 листов»
Мы знаем, что артикул всегда состоит из пяти символов, нам надо их отсечь. Как это сделать?
Для этого нужно отобрать справа количество символов, равное длине названия без артикула. Сделать это необходимо так: узнать длину строки и вычесть из нее 5 (длина артикула априори всегда пять символов).
Товар1 = "34221 Ручка шариковая";
Товар2 = "23444 Тетрадь в клетку, 12 листов"; НаимТовар1 = СокрЛП(Прав(Товар1,СтрДлина(Товар1) - 5)); НаимТовар2 = СокрЛП(Прав(Товар2,СтрДлина(Товар2) - 5));
Сообщить(НаимТовар1); Сообщить(НаимТовар2);
Листинг 2.5.19
На выходе должны получиться следующие строки:
Рис. 2.5.24
Пытливый читатель спросит, почему мы вычитаем 5, а не 6 вместе с пробелом, а потом не применяем функцию СокрЛП? Дело в том, что в условиях задачи сказано, что длина артикула 5, а не 6. То, что между артикулом и названием стоит пробел, это не более чем особенность выгрузки.
Может вполне быть и так:
Товар1 = "34221 Ручка шариковая";
Товар2 = "23444Тетрадь в клетку, 12 листов";
Что тогда получится, если Вы будете вычитать из длины 6?
А теперь потренируйтесь и получите отдельно артикул и отдельно общее наименование и выведите это в окно сообщений.
Функция Сред
В предыдущем примере мы получали из автомобильного номера три цифры, используя функции Прав и Лев. Сейчас узнаем, как можно это сделать проще. Для этого мы будем использовать функцию Сред. Эта функция выберет из строки нужное количество символов, начиная с определённого номера. Она имеет следующий синтаксис:
Сред(<Строка>,<Номер первого символа>, <Количество выбираемых символов>)
Где:
Строка – наша строка.
Номер первого символа – номер, с которого начинается наша выборка.
Количество выбираемых символов – количество выбираемых символов.
Переработаем пример с номером:
Номер = "ва345укRU23"; НомерЦифры = Сред(Номер,3,3); Сообщить(НомерЦифры);
Листинг 2.5.20
Посмотрите самостоятельно, как работает код выше.
Разберём ещё один пример со знакомыми нам уже артикулами:
Товар1 = "34221 Ручка шариковая";
Товар2 = "23444 Тетрадь в клетку, 12 листов";
Артикул1 = Сред(Товар1,1,5); Артикул2 = Сред(Товар2,1,5);
Сообщить(Артикул1); Сообщить(Артикул2);
Листинг 2.5.21
В этом примере также первый параметр в функциях Сред – наша строка, второй – это начало артикула (это первый символ), а третий – длина самого артикула.
Рис. 2.5.25
Теперь задание. Используя данную функцию, получите название товара. Подсказка: нужно применять функцию СтрДлина.
Функция СтрНайти
Продолжим изучение функций строк, и следующая функция – СтрНайти. Функция СтрНайти находит вхождение искомой подстроки в строку поиска и возвращает номер первого символа искомой подстроки в строке поиска. Если подстрока не найдена, возвращается 0.
Рассмотрим простой вариант синтаксиса:
Найти(<Исходная строка>,<Строка поиска>).
Где:
Исходная строка – строка, в которой ищется подстрока;
Строка поиска – сама подстрока поиска.
Пример работы этой функции в коде:
Номер = "ва345укRU23";
НомерНачRU = СтрНайти(Номер,"RU"); Сообщить(НомерНачRU);
Листинг 2.5.22
В результате выполнения кода (сделайте на форме созданной ранее обработки новую команду с обработчиком) мы увидем, что функция возвратит цифру 8. Это и есть номер символа, с которого начинается искомая строка «RU». Запомните эту функцию, она в Вашей работе может очень пригодиться.
Если подстрока поиска входит по нескольку раз в нашу строку, то возвращается самый первый номер вхождения.
Рассмотрим ещё пример. Уже более практичный. Нам необходимо отделить имя от фамилии в строке.
Напишем следующий код в обработчике новой команды на форме обработки:
ФамилияИмя1 = "Иванов Алексей"; ФамилияИмя2 = "Маликова Анна";
НомПроб1 = СтрНайти(ФамилияИмя1," "); НомПроб2 = СтрНайти(ФамилияИмя2," ");
Имя1 = Сред(ФамилияИмя1,
НомПроб1 + 1, СтрДлина(ФамилияИмя1) - НомПроб1);
Имя2 = Сред(ФамилияИмя2,
НомПроб2 + 1, СтрДлина(ФамилияИмя2) - НомПроб2);
Сообщить(Имя1); Сообщить(Имя2);
Листинг 2.5.23
Разберём этот код. Сначала при помощи функции Найти мы вычислим номер первого пробела. Затем, обладая этой информацией, мы получаем имя контрагента. Для получения имени используем функцию Сред. У этой функции три параметра: первый параметр – наша строка, второй параметр – номер пробела плюс один (поскольку имя начинается со следующего символа, то прибавим единицу), а третий параметр – это длина оставшегося имени. Длину оставшегося имени мы получим, если вычтем из общей длины строки номер, с которого начинается пробел.
Рис. 2.5.26
Теперь, используя данную функцию, получите фамилию контрагента.
Функция СтрЗаменить
Ещё одна функция, которая нам тоже много будет помогать, это функция СтрЗаменить. Функция СтрЗаменить ищет определённую подстроку, и если она найдена, то меняет её на другую подстроку. Функция имеет следующий синтаксис:
СтрЗаменить(<Строка>,<Подстрока поиска>,<Подстрока замены>)
Где:
Строка – это та строка, с которой ведётся работа;
ПодСтрокаПоиска – та строка, которую нужно найти;
ПодСтрокаЗамены – на что будет заменена ПодСтрокаПоиска, если будет найдена.
Сделаем следующий пример:
ФИО = "Иванов Петр Григорьевич"; ФИОСлит = СтрЗаменить(ФИО," ",""); ФИОСлит2 = СтрЗаменить(ФИО," ","_");
Сообщить(ФИОСлит); Сообщить(ФИОСлит2);
Листинг 2.5.24 В выполненном примере мы либо вообще уберём пробел, либо заменим его символом
подчеркивания. Посмотрим, как выполнится этот код:
Рис. 2.5.27
Ещё пара примеров на данную функцию:
МногоСтрок = "Первая строка
|Вторая строка
|Третья строка";
ОднаСтрока = СтрЗаменить(МногоСтрок,Символы.ПС," "); Сообщить(ОднаСтрока);
Листинг 2.5.25
Теперь, наоборот, допишем к вышеприведённому коду:
МногоСтрок2 = СтрЗаменить(ОднаСтрока, " ",Символы.ПС); Сообщить(МногоСтрок2);
Листинг 2.5.26
В примере с ФИО (см. листинг 2.5.23) самостоятельно сделайте так, чтобы Фамилия и Имя были на новой строке, и чтобы после каждого слова стояла точка.
Функция СтрЧислоВхождений
Немного похожая функция – это СтрЧислоВхождений. Функция вычисляет число вхождений строки поиска в заданной строке.
Функция СтрЧислоВхождений имеет следующий синтаксис:
СтрЧислоВхождений(<Строка>,<Подстрока Поиска>).
Строка – это строка, с которой работает данная функция.
Подстрока поиска – это строка, количество вхождений которой вычисляет данная функция.
Рассмотрим пример:
ФИО = "Иванов Петр Григорьевич"; ЧислоПробелов = СтрЧислоВхождений(ФИО," ");
Сообщить("Пробел встречается в строке " + ЧислоПробелов + " раз");
Листинг 2.5.27 В этом примере мы задали строку с пробелами и хотим выяснить, сколько пробелов в
заданной строке. Для этого используем функцию СтрЧислоВхождений, в которой задаём
строку и искомые символы. В данном случае – это пробел.
Рассмотрим функции для работы с многострочными строками. Это функции СтрЧислоСтрок и СтрПолучитьСтроку.
Функция СтрЧислоСтрок
Начнём с функции СтрЧислоСтрок.
СтрЧислоСтрок(<Строка>)
Функция СтрЧислоСтрок имеет только один параметр – сама строка, а возвращает количество строк в заданной строке, если она многострочная. И 1, если это одна строка.
Сделаем пример с использованием функции СтрЧислоСтрок:
МногоСтрок = "Первая строка
|Вторая строка
|Третья строка"; КолСтрок1 = СтрЧислоСтрок(МногоСтрок);
Сообщить(МногоСтрок);
Сообщить("В этой строке " + КолСтрок1 + " строки");
ОднаСтрока = СтрЗаменить(МногоСтрок,Символы.ПС,Символы.НПП); КолСтрок2 = СтрЧислоСтрок(ОднаСтрока);
Сообщить(ОднаСтрока);
Сообщить("В этой строке " + КолСтрок2 + " строки");
Листинг 2.5.28
Должен получиться следующий результат:
Рис. 2.5.28
Эта функция простая, и у Вас не должно возникнуть каких-то затруднений.
Функция СтрПолучитьСтроку
Следующая функция СтрПолучитьСтроку. Функция СтрПолучитьСтроку получает из многострочной строки строку с заданным номером.
Функция имеет следующий синтаксис:
СтрПолучитьСтроку(<Строка>,<Номер строки>)
Где:
Строка – это заданная строка;
Номер строки – номер строки, которая будет возвращена (нумерация строк ведётся с 1).
Если номер будет больше количества строк или равен нулю, то ничего не вернётся, при этом ошибки тоже не будет. Функция вернёт пустую строку.
Сделаем на форме обработке следующий пример:
МногоСтрок = "Первая строка
|Вторая строка
|Третья строка";
ВтораяСтрока = СтрПолучитьСтроку(МногоСтрок,2); Сообщить(ВтораяСтрока);
Листинг 2.5.29
В данном примере мы задаём многострочную строку, а потом получаем вторую строку
в ней.
Посмотрите самостоятельно, как будет работать код выше.
Небольшое задание: поразбивайте, как мы это делали прежде, ФИО на строки, и получите какую-нибудь строку с помощью этой функции. Номер строки можно вводить с поля ввода на форме. Сделайте так, чтобы пользователь мог вводить только целые числа.
Функции НРег, ВРег, ТРег
Рассмотрим три очень похожие функции – НРег, ВРег, ТРег.
Первая функция приводит все символы в нижний регистр, вторая – в верхний регистр, третья – в титульный регистр, когда первый символ каждого слова в строке будет верхним.
Задаются они очень просто:
НРег(<Строка>) ВРег(<Строка>) ТРег(<Строка>)
Сделаем следующий пример:
ФИО = "иванов петр григорьевич"; ФИОВРег = ВРег(ФИО);
ФИОНРег = НРег(ФИО); ФИОТРег = ТРег(ФИО);
Сообщить(ФИОВРег); Сообщить(ФИОНРег); Сообщить(ФИОТРег);
Листинг 2.5.30
Должен получится следующий результат:
Рис. 2.5.29
Функции простые. Теперь небольшое задание. В предыдущем примере, где несколько строк (см. стр. 103), приведите первую строку в верхний регистр, вторую – в нижний регистр, третью – в титульный регистр.
Функция ПустаяСтрока
И последняя функция, которую мы рассмотрим, – это ПустаяСтрока.
Функция ПустаяСтрока имеет один параметр – саму строку, и возвращает Истина, если строка пустая, и – Ложь, если строка содержит символы.
Пустую строку можно задать, написав сдвоенные кавычки: "", пробела между ними быть не должно.
Сделаем следующий пример:
ФИО = "Иванов Петр Григорьевич"; ФИО2 = "";
ПризнакПустСтр1 = ПустаяСтрока(ФИО); ПризнакПустСтр2 = ПустаяСтрока(ФИО2);
Сообщить(ПризнакПустСтр1); Сообщить(ПризнакПустСтр2);
Листинг 2.5.31
Проверьте самостоятельно, как работает этот код.
В этой части мы рассмотрели все нужные функции для работы со строками. Практика показывает, что знание этих функций позволит Вам решить большинство задач со строками, которые возникают при работе с программами 1С.
В этой части разберем переменные типа Дата.
Создадим новую обработку, форму обработки, на которой будем проводить все манипуляции с переменными типа Дата.
Из первой части этой главы мы знаем, что переменные типа Дата задаются либо в таком виде 'ГГГГММДДччммсс', либо в таком 'ГГГГММДД' (см. стр. 60). В этой части мы сначала научимся вводить даты на форме, в дальнейшем в этой части все переменные типа Дата будем использовать с формы, а потом изучим некоторые моменты работы с датами.
Ввод дат на форме
Научимся создавать реквизиты формы с типом Дата. Мы уже знаем, как создать реквизит с типом Строка. В случае типа Дата принцип похожий: на закладке формы Реквизиты следует выполнить команду Добавить реквизит, в результате будет создан реквизит с типом по умолчанию Строка (см. рис. 2.6.1).
Рис. 2.6.1
Необходимо поменять этот тип. Для этого в палитре свойств реквизита, открывшейся справа, изменим значение у свойства Тип. Делается это следующим образом: после нажатия на кнопку «…» свойства Тип откроется окно, в котором следует установить флаг рядом с типом Дата.
Рис. 2.6.2
После нажатия кнопки ОК окна Редактирование типа данных, значение в поле Тип
палитры свойств поменяется.
Рис. 2.6.3
Обратите внимание, что в палитре свойств появилось поле Состав даты. Это системное перечисление, у которого имеются три значения: Дата, Время, и Дата и время.
Рис. 2.6.4
Для того чтобы лучше понять за что отвечает это системное перечисление, создадим ещё два реквизиты с типом Дата, но с разными составами даты, а у созданного реквизита оставим состав даты Дата, а сам реквизит назовём НашаДата.
Рис. 2.6.5
Второй созданный реквизит назовём Наше время, у него будет тоже тип Дата, а состав даты – Время.
Рис. 2.6.6
И последний реквизит НашаДатаИВремя тоже будет с типом Дата, состав даты будет
Дата и время.
Рис. 2.6.7
Все эти реквизиты поместим на форму.
Рис. 2.6.8
Если сейчас мы сохраним обработку и запустим её в клиентском режиме «1С: Предприятия», то увидим, что в разные поля мы можем вводить разную информацию. В поле Наша дата – только дату, в поле Наше время – только время, а в поле Наша дата и время – дату и время.
Рис. 2.6.9
Посмотрим, какие значения хранятся в этих реквизитах, для этого создадим команду, которая будет выводить реквизиты в сообщении.
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) Сообщить(НашаДата); Сообщить(НашеВремя); Сообщить(НашаДатаИВремя);
КонецПроцедуры
Листинг 2.6.1
В результате выполнения команды должны выйти следующие сообщения:
Рис. 2.6.10
Во всех случаях у нас отображается полная дата с годом, месяцем, днём, часом и т.д. В случае состава даты Дата – час, минута и секунда равны 0, а в случае состава даты Время – год, месяц и день равны 1. Так даты не только отображаются, но и хранятся, если поставить точку останова в конце процедуры обработчика события и посмотреть на все три реквизита в отладке, то мы увидим те же даты с теми же данным.
Рис. 2.6.11
Но работать с датами в том виде, как они отображаются на рисунке 2.6.11, не совсем удобно. Так получается, потому что функция Сообщить конвертировала дату в строку, один к одному, как есть. Научимся делать так, чтобы даты можно было выводить в более
наглядном виде. В этом нам поможет функция, которая конвертирует тип Дата в тип Строка
по нужным правилам.
Функция Формат
Функция Формат может конвертировать в строку не только даты, но и числа, и тип
Булево. Мы изучим её работу с типом Дата, с другими типами она работает аналогично.
Функция Формат имеет следующий синтаксис:
Формат(<Значение>, <ФорматнаяСтрока>)
Где:
Значение – это значение переменной;
ФорматнаяСтрока – строковое значение, которое включает в себя параметры вывода значения на экран.
Расмотрим, как работает функция Формат. Для этого на форме создадим новую команду, в которой выполним следующий пример:
НашаДатаСтрока = Формат(НашаДата,"ДФ = ""дд.ММ.гггг"""); Сообщить(НашаДатаСтрока);
Листинг 2.6.2
Посмотрим, какая дата выйдет в окне сообщений:
Рис. 2.6.12
Разберём работу со вторым параметром форматной строкой применительно к датам.
Сам второй параметр форматная строка имеет тип Строка.
У любой форматной строки должно быть имя. В рассматриваемом выше случае оно – ДФ. И значение - "дд.ММ.гггг". Поскольку значение должно быть в кавычках, а мы знаем из предыдущей части, что кавычки внутри строки задаются двойными кавычками, то мы ставим двойные кавычки вокруг значения. Если бы мы вводили второй параметр интерактивно, то он был бы в таком виде ДФ="дд.ММ.гггг".
Познакомимся с именами форматной строки для типа Дата.
ДФ – формат даты. Данный формат можно компоновать из множества разных значений.
Вот эти значения:
д (d) – день месяца (цифрами) без лидирующего нуля;
дд (dd) – день месяца (цифрами) с лидирующим нулем;
ддд (ddd) – краткое название дня недели *);
дддд (dddd) – полное название дня недели *);
М (M) – номер месяца (цифрами) без лидирующего нуля;
ММ (MM) – номер месяца (цифрами) с лидирующим нулем;
МММ (MMM) – краткое название месяца *);
ММММ (MMMM) – полное название месяца *);
к (q) – номер квартала в году;
г (y) – номер года без века и лидирующего нуля;
гг (yy) – номер года без века с лидирующим нулем;
гггг (yyyy) – номер года с веком;
ч (h) – час в 12-часовом варианте без лидирующих нулей;
чч (hh) – час в 12-часовом варианте с лидирующим нулем;
Ч (H) – час в 24-часовом варианте без лидирующих нулей;
ЧЧ (HH) – час в 24-часовом варианте с лидирующим нулем;
м (m) – минута без лидирующего нуля;
мм (mm) – минута с лидирующим нулем;
с (s) – секунда без лидирующего нуля;
сс (ss) – секунда с лидирующим нулем;
вв (tt) – отображение половины дня AM/PM (действительно только для языков конфигурирования, поддерживающих 12-часовой вариант представления времени).
Регистр в данном написании важен!
Запоминать эти значения не нужно, их можно найти в синтакс-помощнике в описании функции Формат (для того чтобы перейти в синтакс-помощник нужной функции, необходимо установить курсор на эту функцию и нажать комбинацию клавиш Ctrl+F1, в появившемся списке выбрать пункт Глобальный контекст/Функции форматирования/Формат).
Разберёмся с тем, как компоновать формат даты из них. Делается это очень просто. Можем написать вот так:
Формат(НашаДата,"ДФ = ""дд- ММММ-гггг """);
Формат(НашаДата,"ДФ = ""ММММ-гггг """);
Или даже вот так:
Формат(НашаДата,"ДФ = ""ММММ-гггг/дд(гг) """);
Проверьте самостоятельно, какая дата отобразится в окне сообщений.
Таким образом, при помощи разных значений формата даты можно скомпоновать любую дату или время так, как Вам нравится, но не следует в форматной строке использовать слова и буквы, чтобы не получился такой казус:
НашаДатаСтрока = Формат(НашаДата,"ДФ = ""День: дд, месяц: ММММ""");
Листинг 2.6.3
Проверяем. Вот как некрасиво вышло:
Рис. 2.6.13
Поэтому используйте только спецсимволы.
Рассмотрим другое имя – ДЛФ, это локальный формат даты, который указывает вариант отображения частей даты. Вариантов всего пять:
D – дата цифрами ("01.09.2022")
DD – дата с месяцем прописью ("1 сентября 2022 г.") DT – дата с временем ("01.09.2022 14:05:30")
Т – время ("14:05:30")
DDT – дата с месяцем прописью и временем ("1 сентября 2022 г. 14:05:30").
В этом варианте нет таких широких возможностей для творчества. Задаётся все просто.
Например: ДЛФ = DD.
Выполним следующий пример:
НашаДатаСтрока = Формат(НашаДатаИВремя,"ДЛФ = D"); Сообщить(НашаДатаСтрока);
НашаДатаСтрока = Формат(НашаДатаИВремя,"ДЛФ = DD"); Сообщить(НашаДатаСтрока);
НашаДатаСтрока = Формат(НашаДатаИВремя,"ДЛФ = DT"); Сообщить(НашаДатаСтрока);
НашаДатаСтрока = Формат(НашаДатаИВремя,"ДЛФ = T"); Сообщить(НашаДатаСтрока);
НашаДатаСтрока = Формат(НашаДатаИВремя,"ДЛФ = DDT"); Сообщить(НашаДатаСтрока);
Листинг 2.6.4
Рис. 2.6.14
Конструктор форматной строки
В платформе 8.3 имеется возможность не набирать форматную строку вручную, а использовать для этих целей конструктор форматной строки. Чтобы создать форматную строку при помощи конструктора, нужно во втором параметре функции Формат ничего не писать, а просто поставить курсор (см. рис. 2.6.15).
Рис. 2.6.15
После этого правой клавишей мышки вызвать контекстное меню, и выполнить в нём команду Конструктор форматной строки (см. рис. 2.6.16).
Рис. 2.6.16
В открывшемся конструкторе нас интересует закладка Дата, в которой мы можем установить как свободный формат даты, так и локальный, и тут же можно проверить на примере, как будет выглядеть строка (см. рис. 2.6.17).
Рис. 2.6.17
После нажатия кнопки ОК нужный формат даты встанет в форматную строку (см. рис.
2.6.18).
Рис. 2.6.18
Итак, мы узнали, как нам красиво выводить даты на экран, следующим шагом перейдём непосредственно к функциям, работающим с датами.
Вычитание дат
Рассмотрим интересную особенность типа Дата – это способность вычитания дат. Даты можно вычитать одну из другой. Результатом будет точная разница между датами в секундах. Создадим новую обработку, форму, на форме которой сделаем два реквизита с типом Дата (Дата1 и Дата2) и составом даты – Дата и время.
Создадим команду, в обработчике которой напишем следующий код:
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) РазницаДат = Дата2 - Дата1;
Сообщить("Между " + Формат(Дата1,"ДЛФ=DT") + "
|и " + Формат(Дата2,"ДЛФ=DT") + "
| " + РазницаДат + " секунд"); КонецПроцедуры
Листинг 2.6.5
Получится такой результат:
Рис. 2.6.19
Понятно, что количество секунд – это не информативные данные, а как узнать ровное количество дней между датами, мы узнаем немного позже. Наберитесь терпения.
Функции Год, Месяц, День, Час, Минута, Секунда
Рассмотрим ряд похожих функций для работы с типом Дата. Это функции:
Год(<Дата>), Месяц(<Дата>), День(<Дата>), Час(<Дата>), Минута(<Дата>), Секунда(<Дата>).
У данных функций один параметр – дата, а возвращают они число, которое соответствует году, месяцу, дню, часу, минуте и секунде соответственно. Выполним пример для наглядности.
&НаКлиенте
Процедура ВыполнитьКоманду2(Команда) ПеремГод = Год(Дата1); ПеремМес = Месяц(Дата1); ПеремДень = День(Дата1); ПеремЧас = Час(Дата1); ПеремМин = Минута(Дата1); ПеремСек = Секунда(Дата1);
Сообщить("В дате " + Формат(Дата1,"ДЛФ=DT") + "
|Год - " + ПеремГод + "
|Месяц - " + ПеремМес + "
|День - " + ПеремДень+ "
|Час - " + ПеремЧас + "
|Минута - " + ПеремМин + "
|Секунда - " + ПеремСек); КонецПроцедуры
Листинг 2.6.6
На выходе должен получиться следующий результат:
Рис. 2.6.20
Функции НачалоГода, НачалоДня, НачалоКвартала, НачалоМесяца, НачалоНедели, НачалоЧаса, НачалоМинуты
Разберём ряд похожих друг на друга функций. Это:
НачалоГода(<Дата>), НачалоКвартала(<Дата>), НачалоМесяца(<Дата>), НачалоНедели(<Дата>), НачалоДня(<Дата>), НачалоЧаса(<Дата>), НачалоМинуты(<Дата>)
Все они возвращают дату и время начала периода, именем которого они называются.
Например, если мы берём дату 12.09.2012, то функция НачалоГода возвратит дату 01.01.2012, а функция НачалоНедели возвратит дату 10.09.2012. Чтобы было наглядно, рассмотрим очень простой пример:
&НаКлиенте
Процедура ВыполнитьКоманду3(Команда) ДатаНачГода = НачалоГода(Дата1); ДатаНачКвартала = НачалоКвартала(Дата1); ДатаНачМесяца = НачалоМесяца(Дата1); ДатаНачНедели = НачалоНедели(Дата1); ДатаНачДня = НачалоДня(Дата1); ДатаНачЧаса = НачалоЧаса(Дата1); ДатаНачМинуты = НачалоМинуты(Дата1); НашаДатаФормат = Формат(Дата1,"ДЛФ=DT");
Сообщить("Мы ввели дату " + НашаДатаФормат);
Сообщить("НачалоГода( " + НашаДатаФормат + " ) = " + ДатаНачГода); Сообщить("НачалоКвартала( " + НашаДатаФормат + " ) = " + ДатаНачКвартала); Сообщить("НачалоМесяца( " + НашаДатаФормат + " ) = " + ДатаНачМесяца); Сообщить("НачалоНедели( " + НашаДатаФормат + " ) = " + ДатаНачНедели); Сообщить("НачалоДня( " + НашаДатаФормат + " ) = " + ДатаНачДня); Сообщить("НачалоЧаса( " + НашаДатаФормат + " ) = " + ДатаНачЧаса); Сообщить("НачалоМинуты( " + НашаДатаФормат + " ) = " + ДатаНачМинуты);
КонецПроцедуры
Листинг 2.6.7
Посмотрим, какой результат на выходе.
Рис. 2.6.21
Ещё один пример. У нас имеются две даты, и нужно получить количество дней между ними, причём сразу целое. Можно, конечно, вычесть даты, потом поделить 3600, умножить результат деления на 24 и округлить до целого. Но я не рекомендую Вам так делать, поскольку разница между датами 12 августа 2012 23:59:59 и 13 августа 2012 07:33:40 будет меньше одного дня, то при округлении или выделении целого получится 0.
Поэтому лучше сделать всё проще. Получить начало дня первой даты, потом начало дня второй даты и вычесть первую из второй.
Реализуем это:
&НаКлиенте
Процедура ВыполнитьКоманду4(Команда) Дата1НачалоДня = НачалоДня(Дата1); Дата2НачалоДня = НачалоДня(Дата2);
КолДней = (Дата2НачалоДня - Дата1НачалоДня)/(3600*24);
Сообщить("Между " + Формат(Дата1,"ДЛФ=DT") + " и
|" + Формат(Дата2,"ДЛФ=DT") + " " + КолДней + " дней"); КонецПроцедуры
Листинг 2.6.8
Должен получиться следующий результат:
Рис. 2.6.22
Функции КонецГода, КонецДня, КонецКвартала, КонецМесяца, КонецНедели, КонецЧаса, КонецМинуты
Рассмотрим противоположные функции, это:
КонецГода(<Дата>), КонецКвартала(<Дата>), КонецМесяца(<Дата>), КонецНедели(<Дата>), КонецДня(<Дата>), КонецЧаса(<Дата>) и КонецМинуты(<Дата>).
Все они возвращают дату и время конца периода, именем которого они называются. Например, если мы берём дату 12.09.2012 12.12.02, то функция КонецГода возвратит дату 31.12.2012 23.59.59, а функция КонецНедели возвратит дату 16.09.2012 23.59.59. Рассмотрим простой пример:
&НаКлиенте
Процедура ВыполнитьКоманду5(Команда) ДатаКонецГода = КонецГода(Дата1); ДатаКонецКвартала = КонецКвартала(Дата1); ДатаКонецМесяца = КонецМесяца(Дата1); ДатаКонецНедели = КонецНедели(Дата1); ДатаКонецДня = КонецДня(Дата1); ДатаКонецЧаса = КонецЧаса(Дата1); ДатаКонецМинуты = КонецМинуты(Дата1);
НашаДатаФормат = Формат(Дата1,"ДЛФ = ДДВ"); Сообщить("Мы ввели дату " + НашаДатаФормат);
Сообщить("КонецГода("+ НашаДатаФормат + ") = " + ДатаКонецГода); Сообщить("КонецКвартала("+ НашаДатаФормат + ") = " + ДатаКонецКвартала); Сообщить("КонецМесяца(" + НашаДатаФормат + ") = " + ДатаКонецМесяца); Сообщить("КонецНедели(" + НашаДатаФормат + ") = " + ДатаКонецНедели); Сообщить("КонецДня(" + НашаДатаФормат + ") = " + ДатаКонецДня); Сообщить("КонецЧаса(" + НашаДатаФормат + ") = " + ДатаКонецЧаса); Сообщить("КонецМинуты(" + НашаДатаФормат + ") = " + ДатаКонецМинуты);
КонецПроцедуры
Листинг 2.6.9
Рис. 2.6.23
Для тренировки попробуйте разницу дат вычислить с помощью функции КонецДня.
Функции ДеньГода, ДеньНедели, НеделяГода
И ещё три похожие функции, это:
ДеньГода(<Дата>) ДеньНедели(<Дата>) НеделяГода(<Дата>)
У этих методов один параметр – Дата, и они возвращают соответственно номер дня года, номер дня недели и номер недели года указанной даты.
Опять простой пример:
НомерДняГода = ДеньГода(Дата1); НомерДняНедели = ДеньНедели(Дата1); НомерНеделиГода = НеделяГода(Дата1);
Сообщить("День " + Формат(Дата1,"ДЛФ = ДД") + " является
|" + НомерДняГода + " днем в году.
|" + НомерДняНедели + " днем в недели.
|Неделя этого дня: " + НомерНеделиГода + " неделя в году.");
Листинг 2.6.10
И выведем всё это в окно сообщений.
Рис. 2.6.24
Функция ДобавитьМесяц
Ещё одна очень важная функция для работы с датами – это функция Добавить месяц.
Функция имеет следующий синтаксис:
ДобавитьМесяц(<Дата>,<Количество Месяцев>)
Где:
Дата – это заданная дата;
Количество месяцев – этот параметр имеет тип число – количество месяцев, которые прибавляются или отнимаются (если число отрицательное) от заданной даты.
Рассмотрим пример. Пользователь задаёт некоторую дату, и нам надо получить начало следующего месяца после этой даты, начало следующего квартала и начало следующего года.
НачалоТекущегоМесяца = НачалоМесяца(Дата1); НачалоСледующегоМесяца = ДобавитьМесяц(НачалоТекущегоМесяца,1);
НачалоТекущегоКвартала = НачалоКвартала(Дата1); НачалоСледующегоКвартала = ДобавитьМесяц(НачалоТекущегоКвартала,3);
НачалоТекущегоГода = НачалоГода(Дата1); НачалоСледующегоГода = ДобавитьМесяц(НачалоТекущегоГода,12);
Сообщить("Вы ввели следующую дату: "
+ Формат(Дата1,"ДЛФ = ДД")); Сообщить("Начало следующего месяца от этой даты: "
+ Формат(НачалоСледующегоМесяца,"ДЛФ = ДД")); Сообщить("Начало следующего квартала от этой даты: "
+ Формат(НачалоСледующегоКвартала,"ДЛФ = ДД")); Сообщить("Начало следующего года от этой даты: "
+ Формат(НачалоСледующегоГода,"ДЛФ = ДД") + ".");
Листинг 2.6.11
Выведем всё это в окно сообщений.
Рис. 2.6.25
Данный код можно было написать короче, здесь я написал так, чтобы Вам было более понятно.
Вот короткий вариант:
НачалоСледующегоМесяца = ДобавитьМесяц(НачалоМесяца(Дата1),1); НачалоСледующегоКвартала = ДобавитьМесяц(НачалоКвартала(Дата1),3); НачалоСледующегоГода = ДобавитьМесяц(НачалоГода(Дата1),12);
Сообщить("Вы ввели следующую дату: "
+ Формат(Дата1,"ДЛФ = ДД")); Сообщить("Начало следующего месяца от этой даты: "
+ Формат(НачалоСледующегоМесяца,"ДЛФ = ДД")); Сообщить("Начало следующего квартала от этой даты: "
+ Формат(НачалоСледующегоКвартала,"ДЛФ = ДД")); Сообщить("Начало следующего года от этой даты: "
+ Формат(НачалоСледующегоГода,"ДЛФ = ДД") + ".");
Листинг 2.6.12
Для тренировки получите начало предыдущего месяца, предыдущего квартала, предыдущего года от введённой даты.
Функция ТекущаяДата()
И под конец простая функция – ТекущаяДата(). У этой функции нет никаких параметров, и она возвращает текущую системную дату на компьютере.
Рассмотрим простой пример:
ДатаТекущая = ТекущаяДата();
Сообщить("На данный момент текущая дата " + Формат(ДатаТекущая, "ДЛФ = ДДВ"));
Листинг 2.6.13 В данном примере мы устанавливаем переменной значение текущей даты и выводим
это на экран. Можете самостоятельно поработать с этим методом, вывести в различных
форматах.
На этом наше знакомство с типом Дата закончилось. В данной части Вы узнали всё необходимое для работы в программе 1С с типом Дата. Тип Дата Вам будет встречаться очень часто, поскольку «1С: Предприятие» – программа для автоматизации учётных систем, а они все работают с датами. Поэтому если Вам не понятна работа с данным типом, то лучше углубленно изучить его, используя дополнительные материалы.
В последней части этой главы мы разберём функции преобразования типов и функцию СтрШаблон. Так же, как и в предыдущих уроках, создадим новую обработку и форму обработки, где будем проводить все манипуляции с преобразованием типов.
Функции преобразования
В данной книге будут рассмотрены только три вида преобразования: из строки в число, из числа в строку, чисел и строк в дату.
Преобразование из числа в строку
Делается это достаточно просто:
Строка(1.212)
Рассмотрим пример:
&НаКлиенте
Процедура ПреобразованиеИзЧислаВСтроку(Команда) Перем ПеремЧисло;
Надпись = "Наше число - "; ПеремЧисло = 1.22112;
ПеремСтрока = Строка(ПеремЧисло);
НадписьСЧислом = Надпись + ПеремСтрока; Сообщить(НадписьСЧислом)
КонецПроцедуры
Листинг. 2.7.1 В этом примере мы задаём переменные Надпись и ПеремЧисло, первой переменной
присваиваем строку, а второй присваиваем числовое значение. Далее преобразуем число в
строку при помощи функции Строка. Мы передаём в эту фукнцию в качестве параметра число, а она возвращает нам строку. Складываем две строки и результат выводим в окно сообщений.
Конечный итог должен быть следующим:
Рис. 2.7.1
Всё просто. Но пытливый читатель спросит меня: зачем нам нужна данная функция преобразования, если в предыдущих примерах мы просто складывали строку с числом и получалась строка? Да, это верно, так и есть, и если мы переделаем наш пример по-другому:
Перем ПеремЧисло;
Надпись = "Наше число - "; ПеремЧисло = 1.22112;
НадписьСЧислом = Надпись + ПеремЧисло; Сообщить(НадписьСЧислом)
Листинг 2.7.2
То получится такой же результат.
Но если мы сделаем наоборот: сначала напишем число, а потом строку. Вот так:
Перем ПеремЧисло;
Надпись = "Наше число - "; ПеремЧисло = 1.22112;
НадписьСЧислом = ПеремЧисло + Надпись; Сообщить(НадписьСЧислом)
Листинг 2.7.3
То при выполнении возникнет ошибка:
Рис. 2.7.2
Получается, что мы с числом пытаемся сложить строку, и возникает исключительная ситуация.
Иногда возникают случаи, когда без использования преобразования числа в строку не обойтись. Например, когда мы используем два числа, которые необходимо сначала сложить, прежде чем вывести, можно это сделать через отдельную переменную, а можно и сложив внутри оператора Строка.
Сделаем следующий пример:
&НаКлиенте
Процедура ПреобразованиеИзЧислаВСтроку2(Команда) Перем ПеремЧисло1,ПеремЧисло2;
Надпись = "Наше число - ";
ПеремЧисло1 = 1.22112;
ПеремЧисло2 = 1.213444;
НадписьСЧислом = Надпись + Строка(ПеремЧисло1+ПеремЧисло2); Сообщить(НадписьСЧислом);
КонецПроцедуры
Листинг 2.7.4
Рис. 2.7.3
Потом попробуйте получить надпись без использования функции Строка и посмотрите, что получится.
Преобразование из строки в число
Рассмотрим преобразование из строки в число. Оно довольно редко применимо, но всё же разберём его, поскольку возникают иногда случаи, когда без данного преобразования не обойтись.
Выполняется оно просто: используем функцию Число с одним параметром, в которой в качестве параметра в скобках указывается строка числом.
Рассмотрим пример:
&НаКлиенте
Процедура ПреобразованиеИзСтрокиВЧисло(Команда) Перем ПеремСтрока1, ПеремСтрока2;
ПеремСтрока1 = "45";
ПеремСтрока2 = "34";
ПеремЧисло1 = Число(ПеремСтрока1); ПеремЧисло2 = Число(ПеремСтрока2);
Сообщить(ПеремСтрока1 + " + "+ ПеремСтрока2 + " = " + Строка(ПеремЧисло1 + ПеремЧисло2));
КонецПроцедуры
Листинг 2.7.5
Разберём код выше: сначала задаём две переменные и присваиваем им строковые значения в виде цифр, преобразуем строковые значения в числа, потом в сообщении их складываем и выводим в окно.
Рис. 2.7.4
В реальности на моей практике такая задача стояла, и не раз, когда приходилось обрабатывать различные выгрузки из Excel, DBF, XML и т.п. Но это уже предмет другого разговора.
Преобразование в дату
Для преобразования в дату используется функция Дата. У неё есть два синтаксиса: для строк и для чисел.
Рассмотрим синтаксис для строк. Для того чтобы преобразовать строку в дату, строка должна иметь следующий вид (его мы разбирали в части 6 текущей главы):
«ГГГГММДДЧЧММСС».
Это может выглядеть так:
Дата("20120922200202");
Синтаксис для чисел будет следующим:
Дата(Год,Месяц,День,Час, Минута,Секунда).
Обязателен в данном формате только первый параметр. Потому можно написать и в таком виде:
Дата(Год,Месяц, День) Или
Дата(Год,Месяц)
Или Дата(Год)
Сделаем следующий пример:
&НаКлиенте
Процедура ПреобразованиеВДату(Команда) Дата1 = Дата("20120909110012"); Дата2 = Дата(2012,09,09,11,0,12); Дата3 = Дата(2012,09,09);
Сообщить(Формат(дата1,"ДЛФ = ДДВ")); Сообщить(Формат(дата2,"ДЛФ = ДДВ")); Сообщить(Формат(дата3,"ДЛФ = ДДВ"));
КонецПроцедуры
Листинг 2.7.6
В этом примере мы задаём даты в двух разных видах и выводим это всё в окно сообщений.
Рис. 2.7.5
Можно задать время, в этом случае первые четыре параметра должны быть равны 1.
Время1 = Дата(1,1,1,23,59,59);
Сообщить(Формат(Время1,"ДЛФ=T"))
Листинг 2.7.7
Поэкспериментируйте самостоятельно с различными способами задания дат. И напоследок в этом уроке мы узнаем, как работает функция СтрШаблон.
Функции СтрШаблон
Часто возникает необходимость вставить в какую-то строку определённые значения.
Для этого можно использовать конкатенацию. Что мы раньше и делали. Например, так:
Информация = "Гражадани " + ФИО + " должен " + Долг + " р. ";
Листинг 2.7.8
Где ФИО и Долг – это строка и число соответственно.
Но можно поступить более гибко, используя метод СтрШаблон. Этот метод
возвращает строку с подставленными параметрами. В качестве первого параметра этого метода выступает строка, а остальные параметры – это те параметры, которые присутствуют в строке.
В самой строке в функции параметр обозначается символом %, а после него номер параметра. Например: "Фамилия: %1, имя: %2, отчество: %3".
Для демонстрации реализуем следующую задачу: на форме обработки (создадим новую) разместим два реквизита ФИО (тип Строка) и Долг (тип Число), а также команду Информация. При выполнении команды будем выводить строку следующего вида: «Иванов должен 10 р. 45 коп.»
Обработку и форму Вы, надеюсь, создали самостоятельно. На форме создадим два реквизита: ФИО (тип Строка) и Долг (тип Число (длина 10, точность 2)), а также команду Информация. Всё это разместим на форме (см. рис. 2.7.6).
Рис. 2.7.6
Сначала найдём остаток в копейках целый. То есть если мы вводим 10.45, то нужно получить число 45. Для этого будем использовать оператор получения остатка от деления –
%.
Мы умножем весь наш долг на 100 и получим остаток от деления полученного произведения на 100. Если у нас было число 10.45, то мы получили 1045, а остаток от деления числа 1045 на 100 будет 45.
&НаКлиенте
Процедура Информация(Команда)
Остаток = (Долг * 100) % 100; ЦелыйДолг = Долг - Остаток/100;
КонецПроцедуры
Листинг 2.7.9
А потом вычислим целый долг без дробной части.
Следующим шагом при помощи метода СтрШаблон получим строку, в которой подставим значение из реквизита ФИО, а также значения переменных ЦелыйДолг и Остаток, и выведем эту строку в сообщение.
Информация = СтрШаблон("Гражданин %1 должен %2 р. %3 коп.",
ФИО,ТекущаяДата, ЦелыйДолг, Остаток);
Сообщить(Информация);
Листинг 2.7.10
Посмотрим, как работает наш код.
Рис. 2.7.7
В этой части вы научились преобразовывать строки в числа и – наоборот, а также получать тип Дата, используя строковые и числовые типы. А функция СтрШаблон Вам пригодится, чтобы подставлять в строки разные значения корректным способом.
Третья глава очень объёмная по знаниям – изучим основные операторы. Научимся работать с конструкцией Если, разберём два вида цикла, будем пробовать делать собственные процедуры и функции и освоим такой нужный оператор как Попытка.
Начнём мы с очень необходимого оператора, без которого просто никуда. Это оператор условия Если…Тогда.
Оператор условия управляет выполнением программы в зависимости от логического выражения.
Простейший вариант данного оператора будет следующим:
Если <Условие> тогда
[Операция1];
………..
[ОперацияN];
………..
КонецЕсли;
Рассмотрим подробнее. Для того чтобы начали выполняться операции внутри конструкции Если…Тогда, нужно, чтобы выражение Условие принимало значение Истина. Если Условие принимает значение Ложь, то программа не будет заходить внутрь конструкции. Всё просто. Теперь пример.
Создадим обработку, форму, на форме создадим реквизит Число1 с типом Число ((длина 10, точность 2), в дальнейшем такие числа будут так и представляться – Число(10,2)), команду формы. Команду и реквизит поместим на форму.
Рис. 3.1.1
В обработчике команды формы напишем следующий код:
&НаКлиенте
Процедура ВыполнениеКоманды(Команда)
Если Число1 > 0 тогда
Сообщить("Число " + Число1 + " больше нуля"); КонецЕсли;
КонецПроцедуры
Листинг 3.1.1
В данном коде мы указали, что если реквизит Число1 больше нуля, то выводим сообщение. В противном случае ничего не делаем.
Сохраним обработку и посмотрим, как она работает.
Рис. 3.1.2
Это самый примитивный вариант использования оператора Если!
Условие у оператора Если может быть практически каким угодно, главное, чтобы возвращалось значение типа Булево.
Например, может быть такой вариант:
Если Число1 > 1 и Число1 < 10 тогда….
Или такой вариант:
Условие = Число1 > 1 и Число1 < 10; Если Условие тогда…
И так далее. Более подробно про работу с булевыми типом см. Глава 2, Часть 3, стр.
68.
Продолжим изучать конструкцию Если… Что если нам надо выполнить какие-нибудь операции, когда выполняется наше условие, и другие операции, когда оно не выполняется? В
этом нам поможет оператор условия Иначе.
Рассмотрим схему:
Если <Условие> тогда
[Операция1];
………..
[ОперацияN];
Иначе
[Операция_2];
……….
[Операция_N]
КонецЕсли;
В данном случае выполнение программы после оператора Иначе будет тогда, когда
Условие примет значение Ложь.
Доработаем пример, создадим ещё одну команду и обработчик команды:
&НаКлиенте
Процедура ВыполнениеКоманды2(Команда)
Если Число1 > 0 тогда
Сообщить("Число " + Число1 + " больше нуля"); иначе
Сообщить("Число " + Число1 + " равно нулю или меньше нуля"); КонецЕсли;
КонецПроцедуры
Листинг 3.1.2 В вышеприведённом коде мы вводим некоторое число в программу, пишем условие,
что если это число больше нуля, то выводим соответствующее сообщение, но также
используем оператор Иначе, после которого сообщаем, что число меньше или равно нулю. Запустим обработку и посмотрим, как она работает.
Рис. 3.1.3
Опять усложним текущий пример. Что если нам необходимо вывести сообщение, когда число равно нулю, или, к примеру, равно 10?
Для этого мы используем условную конструкцию ИначеЕсли …Тогда. Рассмотрим схему:
Если <Условие> тогда
[Операция1];
………..
[ОперацияN];
ИначеЕсли <Условие2> тогда
[Операция_2];
………..
[Операция_2N];
ИначеЕсли <Условие3> тогда
[Операция_2];
………..
[Операция_2N];
Иначе
[Операция_N];
……….
[Операция_NN]
КонецЕсли;
Операторов ИначеЕсли…Тогда внутри условия может быть бесконечное множество, оператор Иначе всегда должен быть один и идти после всех операторов ИначеЕсли…Тогда.
Усложним пример:
&НаКлиенте
Процедура ВыполнениеКоманды3(Команда)
Если Число1 >= 1 тогда
Сообщить("Число " + Число1 + " Больше или равно единицы"); ИначеЕсли Число1 >0 и Число1 < 1 тогда
Сообщить("Число " + Число1 + " Меньше 1, но больше 0"); ИначеЕсли Число1 = 0 тогда
Сообщить("Число " + Число1 + " Равно нулю"); иначе
Сообщить("Число " + Число1 + " Меньше нуля"); КонецЕсли;
КонецПроцедуры
Листинг 3.1.3 В примере выше мы проверяем, больше или равно 1 введённое нами число, если да, то
сообщаем об этом. Потом проверяем, входит ли оно в интервал от 0 до 1, если да, то опять
сообщаем. Следующим шагом проверяем, равно ли оно нулю, если да, то сообщаем.
И если число не удовлетворяет всем вышеприведённым условиям, то есть число меньше
нуля, выводим сообщение об этом.
Рис. 3.1.4
Обращаю Ваше внимание, что условия ИначеЕсли будут выполняться только в том случае, когда не выполнились все предыдущие условия.
Например, если мы изменим код так:
Если Число1 > 0 тогда
Сообщить("Число " + Число1 + " Больше или равно единицы"); ИначеЕсли Число1 >0 и Число1 < 1 тогда
Сообщить("Число " + Число1 + " Меньше 1, но больше 0"); ИначеЕсли Число1 = 0 тогда
Сообщить("Число " + Число1 + " Равно нулю"); иначе
Сообщить("Число " + Число1 + " Меньше нуля"); КонецЕсли;
Листинг 3.1.4 Где в первом условии укажем, что Число1 больше 0, то программа никогда не зайдёт
во второе условие.
К примеру, число 0.6 – в этом случае выполнится первое условие, а после произойдёт выход из оператора. Второе условие, что Число1 больше 0 и меньше 1 никогда не будет выполняться.
Обратите внимание на один момент, если в Условии сразу указана переменная типа
Булево, то не надо писать так:
Если НашеУсловие = Истина тогда… Если НашеУсловие = Ложь тогда…
Достаточно просто написать условие, например:
Если НашеУсловие тогда…
Или:
Если Не НашеУсловие тогда….
Переделайте предыдущий пример: создайте переменную типа Булево с нужным условием и подставляйте её в конструкцию Если…Тогда.
Закончим разбирать оператор Если. Попробуйте сами усложнить последний пример (листинг 3.1.4), добавив различные дополнительные сравнения.
Следующим шагом изучим похожий оператор, но несколько упрощённый –
Вычислить выражение по условию. Он имеет следующий синтаксис:
?(<Условие>,<Выражение1>,<Выражение2>)
Где:
Условие – это логическое выражение, в зависимости от результата которого будет возвращено либо Выражение1, либо Выражение2;
Выражение1 – возвращается, если логическое выражение Истина; Выражение2 – возвращается, если логическое выражение Ложь;
Рассмотрим пример: при помощи оператора вычислить выражение по условию будем выводить сообщение, больше реквизит Число1 нуля или меньше.
&НаКлиенте
Процедура ВыполнениеКоманды4(Команда)
Сообщение = ?(Число1 > 0,"Число " + Строка(Число1) + " больше 0",
"Число " + Строка(Число1) + " меньше или равно 0");
Сообщить(Сообщение); КонецПроцедуры
Листинг 3.1.5 В изучаемом примере первый параметр оператора «?» это наше условие: Число1 > 0,
второй параметр – строка с текстом, что наше число больше нуля, она будет возвращаться,
если первый параметр будет Истина. И третий параметр – строка с текстом, что наше число ноль или меньше нуля, она будет возвращаться, если первый параметр будет Ложь.
Посмотрите, как работает команда.
Сделаем ещё один пример: извлечём квадратный корень из реквизита Число1, для этого значение под корнем всегда должно быть положительным. Если реквизит Число1 меньше 0, то умножим этот реквизит на -1.
&НаКлиенте
Процедура ВыполнениеКоманды5(Команда)
ЧислоДляКорня = ?(Число1 < 0, Число1*(-1),Число1); Корень = Окр(Sqrt(ЧислоДляКорня),5);
Сообщить("Корень из модуля числа " + Строка(Число1) + " равен " + Строка(Корень)); КонецПроцедуры
Листинг 3.1.6
Разберите пример выше самостоятельно.
В этой части Вы изучили один из основных операторов языка программирования 1С. Если Вам не понятно его действие, то смотрите, как работает программа в отладке. Вы должны хорошо владеть данным оператором, чтобы перейти к дальнейшему изучению языка программирования 1С.
В этой части начнём изучать циклы. Что такое вообще Цикл? Цикл – действие, выполняемое определённое количество раз. Под действием понимается один или несколько операторов.
Рис. 3.2.1
Изучите рисунок 3.2.1, он как раз применим к осваиваемой теме: пока идёт перечисление какого-нибудь параметра от одного значения до другого, выполняются определённые действия. Как только параметр достигает максимального значения, мы выходим из цикла и продолжаем выполнение программы.
Первый цикл который мы изучим, будет цикл Для…Цикл.
Оператор Для … Цикл имеет следующий синтаксис (пока мы его рассмотрим в самом простом виде, а углублять будем по мере изучения):
Для ИмяПеременной = Выражение1 по Выражение2 цикл
//операторы
КонецЦикла.
Где:
ИмяПеременной – это переменная счётчика цикла (итерационная переменная), его значение увеличивается на единицу при каждом повторении цикла;
Выражение1 – числовое выражение, оно задаёт начальное значение, которое присваивается счётчику цикла при первом обходе. Может быть любое целое число;
Выражение2 – максимальное значение счётчика цикла. Когда переменная ИмяПеременной становится больше Выражение2, программа выходит из цикла, то есть операторы внутри конструкции Для …Цикл больше не выполняются. Может быть любое целое число;
Цикл – ключевое слово, которое открывает тело цикла;
КонецЦикла – ключевое слово, которое закрывает тело цикла;
Всё, что находится между ключевыми словами Цикл и КонецЦикла, будет выполняться, пока ИмяПеременной находится в интервале от Выражение1 до Выражение2.
Обращаю внимание, что Выражение1 всегда должно быть меньше или равно
Выражение2.
Создадим новую обработку, форму, и в обработчике команды формы напишем следующий код:
&НаКлиенте
Процедура ВыполнитьКоманду1(Команда)
Для н = 1 по 10 цикл; Сообщить("н = " + н);
КонецЦикла;
КонецПроцедуры
Листинг 3.2.1
В примере выше мы создали цикл Для…Цикл, где переменная счётчика цикла называется «н», и начальное его значение равно 1, а конечное его значение равно 10. При каждом обходе цикла выводится сообщение о том, чему равно «н».
Самостоятельно посмотрите, что выйдет в окне сообщений при выполнении созданной команды.
Циклы можно вкладывать друг в друга. Сделаем следующий пример:
&НаКлиенте
Процедура ВыполнитьКоманду2(Команда) Для н = 1 по 5 цикл
Для к = 1 по 3 Цикл
Сообщить("н.к = " + н + "." + к ); КонецЦикла;
КонецЦикла;
КонецПроцедуры
Листинг 3.2.2
Как работает такой цикл? Сначала выполняется внешний цикл, то есть переменной «н»
присваивается значение 1, потом полностью выполняется внутренний цикл, то есть значение
«к» проходит от 1 до 7, после этого управление передаётся опять на внешний цикл.
Сохраним обработку и посмотрим, как работает команда.
Рис. 3.2.2
Если Вам трудно понять очерёдность внешнего и внутреннего цикла, поставьте самостоятельно сообщения перед внутренним циклом и после него, тогда всё встанет на свои места.
Значения Выражение1 и Выражение2 могут быть заданы разработчиком в виде переменных.
Добавим у формы обработки два реквизита Выражение1 и Выражение2 (тип
Число(2,0, неотрицательное)) и поместим их на форму.
Рис. 3.2.3
В обработчике новой команды напишем следующий код:
&НаКлиенте
Процедура ВыполнитьКоманду3(Команда) Если Выражение1 >= Выражение2 тогда
ПоказатьПредупреждение(,"Выражение2 должно быть больше Выражение1"); иначе
Для н = Выражение1 по Выражение2 цикл Сообщить(" н = " + н);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Листинг 3.2.3
Разберите код выше самостоятельно и посмотрите, как он работает (для лучшего понимания рекомендую посмотреть на работу кода в отладке).
Продолжим изучение цикла Для..Цикл. Усложним схему цикла, введя оператор
Прервать.
Оператор Прервать прерывает выполнение цикла в любой его точке. После выполнения этого оператора управление передаётся оператору, следующему после ключевого слова КонецЦикла.
С оператором Прервать конструкция цикла будет иметь следующий вид:
Для ИмяПеременной = Выражение1 по Выражение2 цикл
//операторы
Прервать.
//операторы
КонецЦикла.
Реализуем пример, который объяснит использование этого оператора.
&НаКлиенте
Процедура ВыполнитьКоманду4(Команда)
Для н = 1 по 10 цикл к = 1/н;
Сообщить("к = " + Окр(к,3)); Прервать;
КонецЦикла;
КонецПроцедуры
Листинг 3.2.4
Сохраним обработку и посмотрим, как она работает. Должен получиться следующий результат:
Рис. 3.2.4
Как видно из результата выполнения обработки, выполнился только первый шаг цикла, дальше цикл не стал продолжаться. Как правило, оператор Прервать ставят внутри определённого условия.
Реализуем ещё один пример:
&НаКлиенте
Процедура ВыполнитьКоманду5(Команда)
Для н = - 10 по 10 цикл Если н = 0 тогда
Прервать;
КонецЕсли;
к = 1/н;
Сообщить("к = " + Окр(к,3)); КонецЦикла;
КонецПроцедуры
Листинг 3.2.5 В этом примере цикл следует от -10 до 10. В том случае когда счётчик цикла равняется
нулю, мы выходим из цикла, чтобы не сгенерировалась исключительная ситуация. Проверьте
самостоятельно работу этой команды.
Пытливый читатель может спросить: а что делать, если нам не нужно выходить после
того, как счётчик цикла станет равен 0? Что если нужно просто пропустить выполнение операторов цикла для такого счётчика?
А в этом нам поможет оператор Продолжить. Углубим схему конструкции.
Для ИмяПеременной = Выражение1 по Выражение2 цикл
//операторы
Продолжить;
//операторы
Прервать.
//операторы
КонецЦикла.
Оператор Продолжить передаёт управление в начало цикла, после этого происходит вычисление и проверка условий выполнения цикла. Всё, что следует за данным оператором, на этой итерации цикла выполняться не будет.
Операторы Прервать и Продолжить применимы во всех циклах платформы 1С!
Чтобы понять как работает оператор Продолжить, реализуем сначала код ниже, и посмотрим результат работы этого кода:
&НаКлиенте
Процедура ВыполнитьКоманду6(Команда)
Для н = 1 по 10 цикл к = 1/н;
р = 1/(Pow(н,2));
Сообщить("1/н = " + Окр(к,3)); КонецЦикла;
КонецПроцедуры
Листинг 3.2.6
А теперь подправим пример следующим образом:
&НаКлиенте
Процедура ВыполнитьКоманду6(Команда)
Для н = 1 по 10 цикл к = 1/н;
р = 1/(Pow(н,2));
Сообщить("1/н = " + Окр(к,3)); Продолжить;
Сообщить("--------------------");
Сообщить("1/н^2 = " + Окр(р,3)); КонецЦикла;
КонецПроцедуры
Листинг 3.2.7
Выполните обработку. Как видите, сообщение о делении единицы на «н» в квадрате не выходит, потому что оператор Продолжить каждый раз в итерации цикла передаёт управление в начало цикла.
Также оператор Продолжить можно выполнять внутри условия. Доработаем пример с делением на число:
&НаКлиенте
Процедура ВыполнитьКоманду7(Команда) Для н = - 10 по 10 цикл
Если н = 0 тогда Продолжить;
КонецЕсли; к = 1/н;
Сообщить("1/н = " + Окр(к,3)); КонецЦикла;
КонецПроцедуры
Листинг. 3.2.8 В примере выше при «н» равном нулю мы не прерываем цикл, как это делали в
предыдущем примере, и у нас не произошло деление на 0 – не возникло исключительной
ситуации, а просто мы начали цикл с новой итерации. Счётчик цикла (переменная «н») при этом увеличился.
Только что мы с Вами изучили самый простой вид цикла, который есть в языке программирования 1С. Он простой, но основополагающий, научитесь хорошо его понимать и с лёгкостью им пользоваться. Только после этого приступайте к изучению следующих частей данного урока.
Рассмотрим ещё один цикл, это цикл с условием. Разберём принцип его работы по следующей схеме:
Рис. 3.3.1
Перед телом цикла задаётся какое-то условие, пока данное условие истинно, выполняется тело цикла, в противном случае программа выходит из цикла. Рассмотрим синтаксис оператора Пока … Цикл в программе 1С.
Пока <Условие> Цикл
//операторы
Продолжить;
//операторы
Прервать;
КонецЦикла;
Ключевое слово Пока задаёт некоторое условие Условие, которое должно иметь тип Булево, после данного условия следует ключевое слово Цикл, открывающее тело цикла, а закрывает тело цикла ключевое слово КонецЦикла.
Операторы Продолжить и Прервать обладают теми же функциями, как и в предыдущем цикле Для…Цикл. Это переход в начало цикла и выход из цикла соответственно.
Перед тем как рассматривать примеры цикла Пока...Цикл, мы изучим Рекурсию переменных.
Рекурсия – определение нового значения параметров при помощи старого значения, используя единый идентификатор.
Посмотрим, как это выглядит.
и = 0;
и = и + 1;
Переменная и увеличивает сама себя на 1. После выполнение первой строки в переменной и хранится значение 0, а после выполнения второй строки – значение 1.
Также может быть, например, и такая рекурсия:
и = 10;
и = и - 5; и = и + 3;
В этом случае в переменной и после первой строки – значение 10, после второй – значение 5, а после третей – значение 8.
Сделаем самый элементарный пример, и на нём же изучим рекурсию и цикл Пока…Цикл. Пример таков: нам необходимо вывести ряд чисел от 0 до 100 с шагом 5 (0,5,10,15 и т.д.).
Циклом Для…Цикл, который мы изучали в предыдущей части, сделать этот пример можно: нужно при помощи оператора % определять, кратен ли текущий счётчик цикла 5 или нет, и исходя из этого выводить сообщение. Но гораздо проще и понятнее будет сделать данную задачу, используя цикл Пока...Цикл.
Создадим обработку, форму и в обработчике команды формы напишем следующий
код:
&НаКлиенте
Процедура ВыполнитьКоманду1(Команда) н = 0;
Шаг = 5;
Пока н <= 100 Цикл Сообщить("н =" + н); н = н + 5
КонецЦикла;
КонецПроцедуры
Листинг 3.3.1
Разберём код выше. В первых строках процедуры задаём начальное значение выводимой переменной (всегда задавайте начальные значения переменных!), потом шаг, с которым она будет выводится на экран.
После ключевого слова Пока задаём условие цикла: цикл будет выполняться, пока переменная «н» меньше или равна 100. То есть пока переменная «н» меньше или равна
значению 100, то программа будет заходить в тело цикла снова и снова, и будут выполняться операторы в цикле. Как только данное условие перестанет выполняться, то произойдёт выход из цикла и исполнятся операторы после ключевого слова КонецЦикла. В теле цикла сначала выводим сообщение чему равно «н», а потом выполняем рекурсию переменной, увеличивая её на 5, иначе мы получим бесконечный цикл (переменная «н» не увеличивается и всегда меньше 100, и цикл будет выполняться «вечно»).
Остерегайтесь бесконечных циклов Пока Цикл! Это зло!
Сохраним обработку, запустим и посмотрим, как работает код выше. Рекурсивно можно вычитать, умножать и делить переменные (для типа Число).
Рекурсивный вызов возможен также для строк и дат.
Еще один пример на рекурсию. Сделаем команду, в которой вычисляется факториал числа «н».
5! = 1*2*3*4*5
У формы обработки создадим реквизит типа Число (2,0, неотрицательное) и поместим его на форму, также создадим команду и обработчик команды.
&НаКлиенте
Процедура ВычислениеФакториала(Команда) Если н > 0 тогда
НачалоФакториала = 1;
Итерация = 0;
Пока Итерация < н цикл Итерация = Итерация + 1;
НачалоФакториала = НачалоФакториала*Итерация; КонецЦикла;
Сообщить(Строка(н) + "! = " + Строка(НачалоФакториала)); Иначе
ПоказатьПредупреждение(,"Число должно быть больше 0"); КонецЕсли;
КонецПроцедуры
Листинг 3.3.2
Разберём пример выше. Проверяем больше ли нуля число, факториал которого нужно вычислить. Если оно больше, то задаём переменную НачалоФакториала, которая равна единице и которая будет рекурсивно увеличиваться (это и будет наш факториал), и переменную Итерация (равна 0, это будет счётчик цикла).
Определяем цикл Пока Цикл, он будет работать, пока переменная Итерация меньше переменной «н» – условие цикла. То есть если мы «н» задали равным 5, то цикл будет выполняться при следующих значениях переменной Итерация: 0 (начальное значение),1,2,3,4.
Сразу же в начале тела цикла увеличиваем переменную Итерация на 1. Второй и последний шаг: внутри цикла рекурсивно вызываем переменную
НачалоФакториала, умножая её на переменную Итерация.
То есть в первом шаге цикла: НачалоФакториала = 1 * 1 = 1. Во втором шаге цикла: НачалоФакториала = 1 * 2 = 2.
В третьем шаге цикла: НачалоФакториала = 2 * 3 = 6. И так далее.
В конце выводим значение начала факториала.
Разберите код выше в отладке, если он Вам не понятен, посмотрите, как изменяются переменные.
Самостоятельно переделайте пример так, чтобы Итерация начиналась с 1, поменяйте условие цикла или место рекурсии переменной Итерация, чтобы пример работал правильно.
Сделаем ещё один пример цикла Пока…Цикл. Имеем две даты, вторая дата старше первой, надо вывести все даты в промежутке между ними. Создадим новую обработку, форму обработки, два реквизита формы ДатаНачала и ДатаОкончания (тип Дата, состав даты Дата), поместим оба реквизита на форму.
Создадим на форме команду ВыводДат, в обработчике которой напишем следующий
код.
&НаКлиенте
Процедура ВыводДат(Команда)
Если ДатаНачала < ДатаОкончания тогда ДатаСчетчика = ДатаНачала;
Пока ДатаСчетчика <= ДатаОкончания цикл Сообщить(Формат(ДатаСчетчика,"ДЛФ = ДД")); ДатаСчетчика = ДатаСчетчика + 3600*24;
КонецЦикла; иначе
ПоказатьПредупреждение(,"Начальная дата должна быть раньше конечной
даты");
КонецЕсли;
КонецПроцедуры
Листинг 3.3.3
Разберём код выше.
Первым шагом мы проверяем на то, что дата начальная должна быть всегда меньше даты конечной, иначе выдаём пользователю предупреждение.
После того как проверка прошла, мы переменной ДатаСчетчика присваиваем значение начальной даты, делаем это для того, чтобы потом спокойно увеличивать дату счётчика не опасаясь, что изменится как-то значение в поле ввода. В условии цикла мы проверяем то, что дата счётчика меньше или равна дате конечной. Если условие истинно, то заходим в тело цикла. В теле цикла первым делом выводим на экран дату счётчика. А потом
– внимание! – мы делаем то, что называется рекурсией переменных (о чём я Вам рассказывал в начале этой части главы), но только применимо к датам.
После таких манипуляций ДатаСчетчика увеличивается на один день. Опять проверяем наше условие, если ДатаСчетчика всё ещё меньше или равно ДатаОкончания, то идём в цикл, иначе – выходим из него.
Самостоятельно проверьте, как работает созданный выше код.
На этом мы закончим изучение циклов. Всего в языке программирования 1С три вида циклов. Два из них мы изучили в этом уроке. Третий цикл будем изучать в седьмой главе, когда будем проходить универсальные коллекции значений. Изучите и научитесь работать с циклом Пока…Цикл, изучите и освойте рекурсию переменных. Поскольку в практической работе Вам часто придётся сталкиваться с этим циклом.
В четвёртой части изучим работу с процедурами и функциями. Что такое процедура?
Процедура – это идентификатор, выполняющий некоторые действия, определённые пользователем, или системные. Говоря простым языком: если мы напишем (или, говоря правильно, вызовем) где-то внутри нашего кода некоторую процедуру (неважно – нами написанную или процедуру платформы 1С), то когда выполнение программы дойдёт до этой строки кода, будут выполнены определённые действия.
Например, уже знакомые нам процедуры Сообщить и ПоказатьПредупреждение. Из предыдущих примеров Вы видели, что при выполнении процедуры Сообщить в окне сообщений внизу появляется текст, введённый в качестве первого параметра данной процедуры. А при выполнении процедуры ПоказатьПредупреждение появляется всплывающее окно с текстом, который задан в качестве второго параметра процедуры. Вывод сообщения в окне сообщений и появление всплывающего окна – это и есть действия, которые происходят при выполнении процедур Сообщить и ПоказатьПредупреждение.
Что такое функция?
Функция – это идентификатор, выполняющий некоторые действия, определённые пользователем, или системные, и возвращающий значение определённого типа. Как видите, функция отличается от процедуры только тем, что возвращает какое-то значение. К примеру, функция СтрДлина вычисляет длину строки, которая передаётся в неё в качестве параметра, и возвращает это значение пользователю в виде числа. Или функция ТекущаяДата определяет системную текущую дату компьютера и возвращает это значение в виде даты.
В языке программирования 1С разработчик или внедренец может самостоятельно разрабатывать любые процедуры и функции, которые необходимы для выполнения алгоритма программы.
У многих может возникнуть вопрос: для чего необходимо самим писать процедуры или функции?
Во-первых, вы упростите свой код. Если он будет описан с помощью процедур, такой код будет хорошо читаем и понятен для следующего разбора, причём, возможно, и Вами.
Гораздо проще работать с кодом, который разбит на несколько методов, чем с одной длинной
«простынёй» кода.
Во-вторых, чтобы не писать много раз одно и то же в коде. Если у Вас один и тот же код повторяется несколько раз, то лучше его написать в процедуре или функции, а потом просто использовать написанную процедуру или функцию в нужных местах. Так Вы не только сделаете хорошо читаемый код, но и подстрахуете себя от возможных ошибок.
Понятно, что одно дело исправить ошибку в одном месте внутри процедуры или функции, а другое дело – в десяти местах: Вы можете исправить в девяти местах, а в десятом забыть или пропустить, в результате качество Вашей работы будет страдать.
Это была теоретическая часть, изучим синтаксис процедур в самом простом для начинающих варианте.
Процедура ИмяПроцедуры()
//операторы
КонецПроцедуры
Разберём этот синтаксис. Ключевое слово Процедура пишется всегда перед названием метода. После этого ключевого слова всегда идёт название процедуры. Все названия процедур внутри одного модуля должны быть уникальны. Поскольку в данном примере синтаксиса процедура представлена без параметров (их мы разберём позже), то после названия процедуры нужно написать левую и правую скобки вместе. После этих скобок идут операторы, которые описывают те или иные действия внутри процедуры (для удобного чтения рекомендуется начинать писать операторы процедуры со следующей строки и делать отступ с помощью клавиши Tab, или при помощи команды Увеличить отступ: Главное меню
– Текст – Блок). Ключевое слово КонецПроцедуры завершает код процедуры. Что бы Вы ни написали после этого ключевого слова, всё это к этой процедуре не будет иметь никакого отношения.
Так же в предыдущих листингах Вы должны были обратить внимание на конструкцию &НаКлиенте перед описанием процедур управляемой формы. Это так называемая директива компиляции, с её помощью разработчик может задать, где будет выполняться его код, на сервере или на клиенте. Более подробно работу этой директивы мы разберём в пятой главе, посвящённой работе с управляемыми формами. Пока же просто устанавливайте эту директиву перед началом всех процедур и функций, которые Вы используете в модуле формы. На данном этапе обучения Вам не стоит задумываться о её сути.
Разработаем пример. В этом примере пользователь вводит на форме два числа, и оба раза вычисляется квадратный корень из данных чисел. Если число меньше нуля, то пользователю выходит целый ряд сообщений. Вывод этого ряда сообщений мы и выполним в процедуре.
Создадим обработку, форму, у формы создадим два реквизита ЧислоА и ЧислоБ с
типом Число(10,2), которые поместим на форму. В модуле формы напишем следующую процедуру:
&НаКлиенте
Процедура СообщениеОНеправильномЧисле()
Сообщить("Введенное число меньше нуля"); Сообщить("Вычисление не будет произведено"); Сообщить("Задайте другое число");
КонецПроцедуры
Листинг 3.4.1
А в обработчике команды формы – нижеприведённый код:
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) Если ЧислоА >= 0 тогда
КореньА = Sqrt(ЧислоА);
Сообщить("Корень из числа А = " + Окр(КореньА,5)); иначе
СообщениеОНеправильномЧисле(); КонецЕсли;
Если ЧислоБ >= 0 тогда КореньБ = Sqrt(ЧислоБ);
Сообщить("Корень из числа Б = " + Окр(КореньБ,5)); иначе
СообщениеОНеправильномЧисле(); КонецЕсли;
КонецПроцедуры
Листинг 3.4.2
Разберём пример выше.
Мы проверяем больше или равно нуля наше ЧислоА и ЧислоБ соответственно, если да
– то вычисляем корень, если нет – вызываем собственную процедуру, которая выводит целый ряд сообщений. Точно такие же действия проделываем с числом Б.
Запустите обработку и посмотрите, как работает данный код.
Сейчас пытливый читатель спросит: ведь эти два отрезка кода, когда вычисляем и выводим квадратный корень первого числа, а потом вычисляем и выводим квадратный корень второго, очень похожи. Нельзя ли и их каким-нибудь образом сделать в виде процедуры, чтобы не писать лишний код? И можно ли сделать так, чтобы какое-то число мы вводили с формы, а какое-то задавали в коде?
Да, можно.
Для этого мы рассмотрим наш более усложнённый синтаксис. Обратите внимание: всё, что касается параметров, справедливо и для процедур, и для функций. Просто сейчас мы
рассмотрим данный вопрос на примере процедур.
Процедура ИмяПроцедуры(Параметр1, Параметр2, ….,ПараметрN)
//Операторы КонецПроцедуры
После названия процедуры внутри скобок идёт описание параметров, которые будут переданы в процедуру. Когда мы применяем где-то описанную процедуру, параметры должны передаваться в той последовательности, в которой описаны в процедуре. Названия параметров внутри процедуры должны совпадать с названиями в скобках.
Переделаем наш пример.
Создадим процедуру ВычислитьКореньИВывести:
&НаКлиенте
Процедура ВычислитьКореньИВывести(ЧислоПодКорнем, НазваниеЧисла) Если ЧислоПодКорнем >= 0 тогда
КореньА = Sqrt(ЧислоПодКорнем);
Сообщить("Корень из числа " + НазваниеЧисла + " = " + Окр(КореньА,5)); иначе
Сообщить("Число " + НазваниеЧисла + " меньше нуля"); Сообщить("Вычисление не будет произведено"); Сообщить("Задайте другие числа");
КонецЕсли;
КонецПроцедуры
Листинг 3.4.3 И создадим новую команду формы, в обработчике которой вызовем созданную
процедуру:
&НаКлиенте
Процедура ВычислитьКорень(Команда) Перем А;
А = 10.11;
ВычислитьКореньИВывести(А,"А"); ВычислитьКореньИВывести(ЧислоБ,"Б");
КонецПроцедуры
Листинг 3.4.4
Во вновь созданной процедуре ВычислитьКореньИВывести у нас два параметра: это число, которое будет под корнем, и название этого числа. Внутри процедуры мы совершаем с этими параметрами все необходимые действия: вычисляем квадратный корень числа и выводим сообщения с названием числа. Как видите, внутри процедуры используются те же названия переменных, что и были заданы в скобках после имени процедуры.
Перейдём к коду, в котором вызывается созданная нами процедура – обработчик команды ВычислитьКорень. Сначала мы задаём явно переменную, которой присваиваем
число в коде, и передаём эту переменную в процедуру ВычислитьКореньИВывести, также вторым параметром указываем название числа, это значение типа Строка. А потом мы используем реквизит формы: уже значение этого реквизита предаём в процедуру.
Параметры процедуры нельзя путать. Если мы напишем так:
ВычислитьКореньИВывести("А",А);
то мы попытаемся извлечь квадратный корень из строки, платформа выдаст ошибку. Очень часто начинающие программисты путают местами параметры, что приводит к различным проблемам.
Ещё один момент – количество параметров, заданных в процедуре при разработке, должно соответствовать количеству параметров при использовании процедуры в коде.
Мы не можем написать так:
ВычислитьКореньИВывести(А);
Платформа выдаст ошибку.
С параметрами есть один важный момент. Когда мы передаём параметр в процедуру, то мы передаём не просто само по себе число, строку или какой-то объект, а, по сути, передаём ссылку на данное число, строку или объект. Это значит, что если внутри процедуры мы изменим параметр, то поменяется и значение в той переменной, которая была передана в виде параметра в процедуру.
Звучит несколько сложно, но один простой пример прояснит картину.
Сделаем в модуле формы новую процедуру ВычислитьКореньПоМодулюИВывести:
&НаКлиенте
Процедура ВычислитьКореньПоМодулюИВывести(ЧислоПодКорнем, НазваниеЧисла) ЧислоПодКорнем = ?(ЧислоПодКорнем >=0,ЧислоПодКорнем,ЧислоПодКорнем*(-1)); КореньА = Sqrt(ЧислоПодКорнем);
Сообщить("Корень из модуля числа " + НазваниеЧисла + " = " + Окр(КореньА,5));
КонецПроцедуры
Листинг 3.4.5 Создадим новую команду ВычислитьКореньПоМодулю и в её обработчике напишем
следующий код:
&НаКлиенте
Процедура ВычислитьКореньПоМодулю(Команда) ВычислитьКореньПоМодулюИВывести(ЧислоА, "Число А");
КонецПроцедуры
Листинг 3.4.6
В данном примере если ЧислоПодКорнем меньше нуля, то мы его рекурсивно умножаем на минус единицу.
Запустим этот пример. И при вводе отрицательного числа будет изменено само число, которое мы ввели в поле ввода. Поле ввода, напомню, связанно с реквизитом, то есть значение в самом реквизите поменялось.
В каких-то случаях Вас этот момент не будет сильно волновать, но в других случаях Вы захотите, чтобы переменная, которую передаёте в процедуру или функцию, оставалась прежней. Как это сделать?
Смотрим следующий синтаксис:
Процедура ИмяПроцедуры(Знач Параметр1, Знач Параметр2, ….,Знач
ПараметрN)
//операторы КонецПроцедуры
Ключевое слово Знач перед параметром означает, что этот параметр передаётся в процедуру по значению, то есть изменение параметра внутри процедуры никак не повлияет на значение фактического параметра, который был передан в процедуру. Ключевое слово Знач является необязательным, т.е. переменная может передаваться как «ссылочно», так и по значению.
Теперь изменим наш предыдущий пример.
Подправьте процедуру «ВычислитьКореньПоМодулюИВывести»
Процедура ВычислитьКореньПоМодулюИВывести(Знач ЧислоПодКорнем, НазваниеЧисла)
ЧислоПодКорнем = ?(ЧислоПодКорнем >=0,ЧислоПодКорнем,ЧислоПодКорнем*(-1)); КореньА = Sqrt(ЧислоПодКорнем);
Сообщить("Корень из модуля числа " + НазваниеЧисла + " = " + Окр(КореньА,5));
КонецПроцедуры
Листинг 3.4.7
Обработчик команды ВычислитьКореньПоМодулю не изменится.
Запустим обработку, и при вводе отрицательного числа в поле посмотрим, изменится ли само введённое число или нет.
Рис. 3.4.1
Продолжим рассматривать передачу параметров в процедуры и функции. Мы уже знаем, что все параметры, которые мы передаём в процедуру или функцию, обязательны, то есть когда вы в коде задаёте процедуру, то обязаны перечислить их все, но есть возможность создать параметр по умолчанию, тогда не будем указывать этот параметр при вызове процедуры.
Рассмотрим синтаксис.
Процедура ИмяПроцедуры(Параметр1 = Умол1, ….,ПараметрN = УмолN)
//Операторы КонецПроцедуры
Разберём вышеприведённый синтаксис. Такая форма описания параметра означает, что этот параметр имеет значение по умолчанию и тем самым он становится необязательным, то есть когда мы будем вызывать такую процедуру в модуле, то вольны не указывать этот параметр, тогда в теле процедуры при вычислениях ему автоматически присвоится значение по умолчанию.
Доработаем пример. В этот раз мы вычислим корень числа и выводим его на экран с точностью до пятого знака, но оставим возможность программисту менять точность при использовании процедуры.
Создадим новую процедуру ВычислитьКореньИВывестиСОкруглением:
&НаКлиенте
Процедура ВычислитьКореньИВывестиСОкруглением(Знач ЧислоПодКорнем, НазваниеЧисла, Точность = 5)
ЧислоПодКорнем = ?(ЧислоПодКорнем >=0,ЧислоПодКорнем,ЧислоПодКорнем*(-1)); КореньА = Окр(Sqrt(ЧислоПодКорнем),Точность);
Сообщить("Корень из модуля числа " + НазваниеЧисла + " = " + КореньА); КонецПроцедуры
Листинг 3.4.8 Для этой процедуры сделаем другую команду ВычислитьКореньСОкруглением, и в её
обработчике напишем следующий код:
&НаКлиенте
Процедура ВычислитьКореньСОкруглением(Команда)
ВычислитьКореньИВывестиСОкруглением(ЧислоА,"А"); ВычислитьКореньИВывестиСОкруглением(ЧислоБ,"А",7);
КонецПроцедуры
Листинг 3.4.9
Разберём пример выше. Мы доработали процедуру ВычислитьКореньСОкруглением, добавив параметр Точность, который по умолчанию равен 5. Его мы используем для округления числа, которое получилось при извлечении квадратного корня. После этого мы используем процедуру два раза. Первый раз без третьего параметра, а второй раз третий параметр указываем явно.
Сохрании обработку, запустим её и введём любое число:
Рис. 3.4.2
Как Вы видите, в первый раз значение вышло с точностью до пятого знака, а второй – до седьмого.
Обращаю Ваше внимание, что параметр, который передаётся по значению, также может быть и параметром по умолчанию.
Рассмотрим такой синтаксис:
Процедура ИмяПроцедуры(Знач Параметр1 = Умол1, , …., Знач
ПараметрN = УмолN)
//Операторы КонецПроцедуры
Синтаксис Выше нам говорит, что параметр по умолчанию будет передаваться по значению.
Сделаем следующий пример. В этом примере, если Точность округления будет меньше 5, то будем выводить все равно с точностью равной 5.
Создадим новую процедуру ВычислитьКореньИВывестиТочностьПять:
&НаКлиенте
Процедура ВычислитьКореньИВывестиТочностьПять(Знач ЧислоПодКорнем, НазваниеЧисла, Знач Точность = 5)
ЧислоПодКорнем = ?(ЧислоПодКорнем >=0,ЧислоПодКорнем,ЧислоПодКорнем*(-1)); Точность = ?(Точность < 5, 5, Точность);
КореньА = Sqrt(ЧислоПодКорнем); Сообщить("Корень из модуля числа " +
НазваниеЧисла + " = " + Окр(КореньА,Точность));
КонецПроцедуры
Листинг 3.4.10 Создадим новую команду ВычислитьКореньСТочностьюПять, и в её обработчике
напишем следующий код:
&НаКлиенте
Процедура ВычислитьКореньСТочностьюПять(Команда) ВычислитьКореньИВывестиСОкруглением(ЧислоА,"А"); ВычислитьКореньИВывестиСОкруглением(ЧислоБ,"Б",2);
КонецПроцедуры
Листинг 3.4.11
Разберите пример выше самостоятельно.
Изучим последний оператор, который в этот раз применим просто к процедурам, а не к их параметрам. Это оператор Возврат.
Рассмотрим синтаксис.
Процедура ИмяПроцедуры(Параметр1, Параметр2, ….,ПараметрN)
//операторы
Возврат;
//операторы КонецПроцедуры
В синтаксисе выше параметры могут быть заданы каким угодно из вышеперечисленных способов. Когда в ходе выполнения процедуры встретится ключевое слово Возврат, то программа тут же выйдет из неё и её выполнение прекратится. После этого действия работать будут операторы, следующие после ключевого слова КонецПроцедуры.
Сделаем пример. В этом примере мы опять будем вычислять квадратный корень числа, но если это число отрицательное, выполним выход из процедуры.
Создадим процедуру ВычислитьКореньТолькоПоложительныхЧисла:
&НаКлиенте
Процедура ВычислитьКореньТолькоПоложительныхЧисла(ЧислоПодКорнем, НазваниеЧисла) Если ЧислоПодКорнем < 0 тогда
ПоказатьПредупреждение(,"Нельзя извлекать квадратный корень из отрицательного числа!"); Возврат;
КонецЕсли;
КореньА = Sqrt(ЧислоПодКорнем);
Сообщить("Корень из числа " + НазваниеЧисла + " = " + Окр(КореньА,5)); КонецПроцедуры
Листинг 3.4.12 Опять создадим новую команду ВычислитьКореньПоложительногоЧисла и в её
обработчике напишем следующий код:
&НаКлиенте
Процедура ВычислитьКореньПоложительногоЧисла(Команда) ВычислитьКореньТолькоПоложительныхЧисла(ЧислоА,"А"); ВычислитьКореньТолькоПоложительныхЧисла(ЧислоБ,"Б");
КонецПроцедуры
Листинг 3.4.13
Разберём пример выше. В самом начале процедуры мы проверяем, меньше ли нуля параметр ЧислоПодКорнем или нет. Если меньше нуля, то выводим предупреждение и посредством оператора Возврат выходим из процедуры.
Сохраним и перезапустим нашу обработку.
Рис. 3.4.3
Обращаю Ваше внимание: чтобы Вы ни написали после слова Возврат, всё это выполняться уже не будет. Теперь самостоятельно напишите сообщение после ключевого слова Возврат и посмотрите, отобразится оно или нет.
Только что мы изучили с Вами работу с процедурами в языке программирования 1С. Теперь Вы самостоятельно сможете создавать любые процедуры, какие захотите.
Разберём синтаксис написания функций. Как было уже сказано ранее, всё, что мы изучили касательно параметров на примере процедур, абсолютно справедливо и для функций.
Итак, синтаксис функций.
Функция ИмяФункции(<Параметры>)
//операторы
Возврат ВозвращаемоеЗначение;
КонецФункции
Рассмотрим синтаксис выше. Ключевое слово Функция идёт всегда перед названием функции. Поскольку все параметры мы разобрали на примере процедуры, не будем подробно останавливаться на этом. После параметров идут операторы, которые описывают те или иные действия внутри функции (для удобного чтения кода рекомендуется начинать писать их со следующей строки и делать отступ с помощью клавиши Tab). Основное отличие функции от процедуры в том, что ключевое слово Возврат не только завершает выполнение функции, но и возвращает определённое значение в то место кода, где была вызвана эта функция.
Ключевое слово КонецФункции завершает код функции. Как и в случае процедуры, всё, что Вы написали после данного слова, не будет иметь к вашей функции никакого отношения.
Рассмотрим пример. Создадим функцию Сигнум, параметром которой является некоторое число, и она возвращает 1, если число больше нуля; ноль, если число равно нулю; и -1, если число меньше нуля.
&НаКлиенте
Функция Сигнум(ЧислоА) Перем Сигн;
Если ЧислоА > 0 тогда Сигн = 1;
ИначеЕсли ЧислоА = 0 тогда Сигн = 0
ИначеЕсли ЧислоА < 0 тогда сигн = -1
КонецЕсли;
Возврат Сигн;
КонецФункции
Листинг 3.4.14 Создадим новую команду ВычислитьСигнумЧисла, а также реквизит формы ЧислоА
(тип Число(10,2)), и в обработчике команды напишем следующий код:
&НаКлиенте
Процедура ВычислитьСигнумЧисла(Команда) В = Сигнум(ЧислоА);
Сообщить("Signum (" + ЧислоА + ") = " + В); КонецПроцедуры
Разберём код выше.
Листинг 3.4.15
В модуле формы мы создали функцию, которая называется Сигнум, и указали, что у
неё только один параметр, который назвали ЧислоА. После этого мы задали переменную внутри функции, которую будем возвращать, и назвали её Сигн. Делаем сравнение, в результате которого Сигн становится равен либо 1, либо 0, либо - 1. И в конце функции возвращаем переменную Сигн.
Разберём код в обработчике команды ВычислитьСигнумЧисла. В первой строке вызываем вновь созданную функцию Сигнум (передаём в неё значение реквизита ЧислорА), а то что она возвращает, присваиваем переменной В, значение которой выводим в сообщении.
Сохраните обработку и посмотрите, как работает функция.
Обращаю Ваше внимание, что необязательно писать один Возврат, и только в конце функции, вполне может быть и такой вид функции:
&НаКлиенте
Функция л_Сигнум(ЧислоА) Если ЧислоА > 0 тогда
Возврат 1;
ИначеЕсли ЧислоА = 0 тогда Возврат 0;
Иначе
Возврат -1 КонецЕсли;
КонецФункции
Листинг 3.4.16 Как видно из данного примера, после каждого результата сравнения мы возвращали
нужное нам значение.
Ещё одной особенностью функций является то, что необязательно какой-то переменной присваивать значение функции. Эту функцию можно использовать в качестве процедуры.
Сделаем пример, с помощью которого Вы поймёте данный тезис. В этом примере мы будем вычислять квадратный корень из числа и возвращать значение в виде параметра, а сама функция будет возвращать Истина, если удалось вычислить, и – Ложь, если нет.
Напишем в модуле формы следующую функцию:
Функция ВычислитьКвадратныйКорень(НазваниеЧислаПодКорнем, ЧислоПодКорнем, КореньЧисла) Если ЧислоПодКорнем < 0 тогда
Сообщить("Нельзя вычислять корень из отрицательного числа"); Возврат Ложь;
иначе
КореньЧисла = Окр(Sqrt(ЧислоПодКорнем),5);
Сообщить("Корень из числа " + НазваниеЧислаПодКорнем + " = " + КореньЧисла); Возврат Истина;
КонецЕсли;
КонецФункции
Листинг 3.4.17 Опять создадим новую команду ВычислитьКореньЧислаФункцией и в её обработчике
напишем следующий код (создайте реквизиты формы ЧислоА (Число (10,2)) и ЧислоБ (Число 10,5)):
&НаКлиенте
Процедура ВычислитьКореньЧислаФункцией(Команда) ВычислитьКвадратныйКорень("А",ЧислоА,ЧислоБ);
КонецПроцедуры
Листинг 3.4.18
Разберём пример выше. Функция ВычислитьКвадратныйКорень имеет три параметра: название числа под корнем, само число, которое будет под корнем, и корень из этого числа.
Если число под корнем меньше нуля, то мы возвращаем Ложь, соответствующее сообщение, и ничего не считаем, а если нет – то возвращаем Истина, вычисляем число и выводим соответствующее сообщение.
В процедуре-обработчике команды мы используем эту функцию в виде процедуры: она ничего не возвращает! Поскольку нам в этом случае неинтересно, что она вернёт, нам важно знать, какое будет число Б. Но, возможно, в другом месте программы нам и нужно будет знать, что вернёт эта функция, и мы уже будем её использовать именно как функцию.
На этом мы закончим нашу интересную и огромную часть про функции и процедуры.
Теперь Вы самостоятельно сможете создавать любые процедуры и функции, которые Вам необходимы. В этой части мы изучили почти всё, что необходимо для дальнейшей работы. Остался только момент про экспорт процедур и функций, но этот вопрос мы будем проходить в четвёртой главе.
В заключительной части третьей главы мы рассмотрим оператор Попытка… Исключение. В чём суть этого оператора? Как Вы уже заметили из предыдущих примеров, в ходе выполнения программы могут возникать разные ошибки, такие, как деление на ноль, корень из отрицательного числа и прочие. Эти ошибки ещё называют исключительными ситуациями. Мы эти ошибки обходили конструкцией Если...Тогда, но не всегда возможно применить данную конструкцию, чтобы обойти исключительную ситуацию. Поэтому в языке программирования 1С существует оператор Попытка…Исключение.
Рассмотрим его синтаксис.
Попытка
//операторы попытки Исключение
//операторы исключения.
КонецПопытки
Ключевое слово Попытка открывает список операторов, выполнение которых может привести к исключительной ситуации. Все операторы между ключевыми словами Попытка и Исключение это Операторы попытки.
Ключевое слово Исключение открывает список операторов, которые будут выполняться в том случае, если вызвана исключительная ситуация операторами попытки.
Если во время выполнения программы один из операторов попытки вызвал ошибку выполнения программы (исключительную ситуацию), то выполнение данного оператора прерывается и управление передаётся на первый оператор исключения. Причём обращаю Ваше внимание, что управление будет передано и в том случае, если исключительную ситуацию вызвали функции и процедуры, разработанные программистом и применяемые в качестве операторов попытки. Естественно, что если ошибка произошла в процедуре или функции, то её выполнение будет прервано.
Создадим обработку, форму, реквизит формы ЧислоА с типом Число(10,2), команду на форме и в обработчике команды, напишем следующий пример:
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) Попытка
КореньЧислаяА = Sqrt(ЧислоА);
Сообщить("Квадратный корень числа А = " + Окр(КореньЧислаяА,5)); Исключение
Сообщить("Попытка извлечь корень из отрицательного числа"); КонецПопытки;
КонецПроцедуры
Листинг 3.5.1
Разберём пример выше.
В этом коде мы используем ключевые слова Попытка, Исключение, КонецПопытки. Эти ключевые слова всегда должны быть в наличии и представлены в такой очерёдности, как мы видим.
После ключевого слова Попытка мы пытаемся вычислить квадратный корень реквизита формы. Если всё получается, то выводим сообщение о квадратном корне из числа, если нет, то выводим сообщение, что пытаемся извлекать корень из отрицательного числа.
Таким образом, в примере вычисление квадратного корня и вывод сообщения являются операторами попытки. А сообщение об ошибке – это оператор исключения, на этот оператор (их может быть несколько) перейдёт программа после вызова исключения.
Операторы попытки, следующие после строки, когда, где была инициализирована ошибка, исполняться не будут.
Запустите вновь созданную обработку и посмотрите, как она работает. Если Вы всё сделали правильно, то увидите, что при попытке вычисления отрицательного числа никакой критичексой ошибки или исключительной ситуации не возникает, просто выйдет сообщение о корне из отрицательного числа. А что если нам нужно, чтобы всё-таки ошибка вышла и в тоже время операторы исключения сработали?
Для этого есть оператор ВызватьИсключение. Переделаем пример.
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) Попытка
КореньЧислаяА = Sqrt(ЧислоА);
Сообщить("Квадратный корень числа А = " + Окр(КореньЧислаяА,5)); Исключение
ВызватьИсключение;
Сообщить("Попытка извлечь корень из отрицательного числа"); КонецПопытки;
КонецПроцедуры
Листинг 3.5.2
В данном примере после операторов исключения мы написали оператор
ВызватьИсключение.
Сохраним обработку, перезапустим и введём отрицательное число. В результате появится следующее окно:
Рис. 3.5.1
Как видите, оператор исключения отработал, и сразу вышла ошибка о неправильном параметре. Оператор ВызватьИсключение особенно удобно использовать на этапе отладки, когда исключительная ситуация может сложиться в различных случаях и необходимо точно знать, где она произошла и в результате чего она произошла.
Сделаем пример, когда исключительная ситуация будет происходить внутри функции, которая используется в качестве оператора попытки.
Пример будет следующим: вычислим квадратный корень некоторого числа с округлением, потом возведём в квадрат и посчитаем погрешность: вычтем из заданного числа получившийся квадрат.
Напишем в модуле формы следующую функцию:
&НаКлиенте
Функция ВычислитьИОкруглитьКорень(ЧислоПодКорнем,Точность = 5) КореньЧисла = Окр(Sqrt(ЧислоПодКорнем),Точность);
Возврат КореньЧисла; КонецФункции
Листинг 3.5.3
Создадим команду ПолучитьПогрешностьОкругления и в обработчике команды напишем следующий код:
&НаКлиенте
Процедура ПолучитьПогрешностьОкругления(Команда) Попытка
А2 = Pow(ВычислитьИОкруглитьКорень(ЧислоА,10),2); ПогрешностьОкругления = ЧислоА - А2;
Сообщить("Погрешность окуругления = " + ПогрешностьОкругления); Исключение
Сообщить("Ошибка при вычислении"); КонецПопытки;
КонецПроцедуры
Листинг 3.5.4
Сохраним и запустим обработку.
Если сделано всё правильно, то Вы увидите, что при введении положительного числа выходит результат, а в случае отрицательного числа – сообщение об ошибке.
Разберите данный пример самостоятельно.
Сейчас мы рассмотрели оператор Попытка…Исключение. Теперь Вы сможете избегать неприятных ситуаций с возникновением ошибок. Особенно желательно использовать данный оператор в критических моментах выполнения кода, например, при записи чего-либо в базу.
На этом третья глава закончилась. В ней Вы научились работать с условиями, а также освоили два из трёх операторов цикла. После данного урока Вы сможете создавать собственные процедуры и функции, а также использовать оператор Попытка…Исключение в своей практике программирования.
(3) 4.01 (Главе 4. Основы конфигурирования?) 162-163
В предыдущих главах мы освоили элементарные азы программирования, научились работать с переменными примитивных типов (строка, число, дата и булево), изучили циклы, условия, функции, процедуры и попытки. Это все те основы, которые необходимы для старта в интересную и, главное, перспективную профессию программиста 1С.
В этой главе мы разберём основы конфигурирования платформы 1С. Доскональное изучение всех метаданных не является целью этого труда, поэтому мы не будем сильно углубляться в конфигурирование, а изучим только основные понятия, которые дадут основу изучения программирования в 1С.
Рис. 4.1.1
Итак, первая часть нашей главы – это основы конфигурации. Что такое Конфигурация?
Конфигурация – это единство различных взаимосвязанных составных частей (учётные данные, формы вывода, печатные формы, роли, интерфейсы и пр.), являющееся моделью предметной области, для автоматизации которой и разрабатывается данное программное обеспечение.
Например, имеется некая прикладная задача, а «1С: Предприятие» и создано для
реализации прикладных задач, суть которой – автоматизация бухгалтерского учёта, или торгового учёта, или любого другого учёта, необходимого пользователю. Под эту задачу разрабатывается конфигурация, при помощи которой в «1С: Предприятии» реализуется модель нужного учёта.
К примеру, если в учёте требуется хранить информацию об автомобилях, то разрабатывается справочник Автомобили, реквизитами которого являются марка автомобиля, вид автомобиля, его гос. номер и т.п. Этот справочник отображает реальный предмет учёта.
Так и во всём остальном.
На рисунке 4.1.1. приведена пустая конфигурация (мы изменили только название, см.
Глава 1, Часть 6, стр. 31). Такая конфигурация бывает обычно перед началом какой-либо разработки. В реальности любая конфигурация всегда содержит какие-нибудь метаданные. Что такое метаданные? Метаданные – это объекты конфигурации. К примеру, конкретный справочник Автомобили – это объект метаданных. Документ Счет на оплату – тоже объект метаданных.
У каждого объекта метаданных есть свой прототип, который определяет основные свойства и методы этого объекта метаданных. Как Вы заметили из рисунка 4.1.1, конфигурация имеет древовидную структуру, где сама конфигурация это, по сути, корень дерева, а ветки – Справочники, Документы, Константы и т.д. – это прототипы метаданных. Соответственно в рамках нужных прототипов и создаются определённые объекты метаданных. Например, в ветке Справочники будут созданы все справочники, то есть объекты, необходимые для хранения постоянной или условной информации. У всех объектов, созданных в ветке Справочники, будет примерно одинаковый набор свойств и методов (в зависимости от параметров конкретного объекта метаданных).
В этой части, для примера, мы разработаем небольшую конфигурацию по учёту автотранспорта, название которой дали в первой главе.
А для этого нам потребуется изучить основные прототипы метаданных.
(3) 4.02 Константы - что хранят в себе 163-167
Константы
И первый прототип, который мы изучим, это Константы.
Рис. 4.1.2
Если Вы изучали другие языки программирования, то у Вас будет лёгкое недоумение
от того, что константы в 1С не несут в себе такую же функциональную нагрузку, как в языках Паскаль, С и т.п. В конфигурации 1С константы хранят в себе постоянную или условно постоянную информацию, которая или никогда не изменяется, или изменяется очень редко.
Это может быть, к примеру, название организации, ИНН организации и т.п. Основное отличие констант 1С в том, что пользователь в принципе может изменять данные константы по своему усмотрению. Для работы с константами в конфигурации имеется ветвь Константы. Она выделена на рисунке 4.1.2.
Для того чтобы добавить константу, необходимо кликнуть по ветке Константы правой кнопкой мышки, откроется контекстное меню, в котором нужно выполнить команду Добавить.
Рис. 4.1.3
Константа будет добавлена, а справа откроется окно Свойства (или палитра свойств константы).
Рис. 4.1.4
В окне значение в свойство Имя – это будет имя константы. Назовём константу
НазваниеОрганизации (на название имён объектов метаданных распространяются
опеределённые правила, например, должны отсутствовать пробелы и спецсимволы, кроме символа подчеркивания «_»). Также введём значение в поле Синоним – аналог имени, который будет отображаться пользователю (к синонимам требования гораздо проще, чем к именам, например, можно использовать пробелы). Укажем Тип константы (мы пока знаем только четыре типа), для этой константы будет тип Строка. Длина – это длина строки, сделаем её равной ста.
Рис. 4.1.5
Допустимая длина может быть либо фиксированной, либо переменной. Переменная отличается от фиксированной тем, что если в первом случае Вы ввели при длине 100 символов строку из 20 символов, то в базе будет храниться строка из 20 символов, а в фиксированном случае будут храниться все 100 символов, остальные 80 заполнятся пробелами.
Мы создали первую константу!
Создайте самостоятельно следующие константы: ДатаНачалаРаботыОрганизации (тип Дата, состав даты Дата, см. рис. 4.1.6), ПроцентНалогаНаПрибыль (тип Число с точностью до одной сотой, см. рис. 4.1.7).
Рис. 4.1.6 | Рис. 4.1.7 |
В итоге должен получиться следующий набор констант:
Рис. 4.1.8
Для констант можно создать собственную форму. Для этого, следует выделить ветку Константы, вызвать правой клавишей мышки контекстное меню и выполнить команду Создать форму констант (см. рис. 4.1.9).
Рис. 4.1.9
В открывшемся конструкторе формы оставляем всё без изменения и нажимаем кнопку Готово. На экране отобразится форма констант, которая также появится в ветке Общие – Общие формы дерева конфигурации.
Рис. 4.1.10
Рис. 4.1.11
Более подробно работу с формами мы рассмотрим в пятой и шестой главе.
(3) 4.03 что значит знак * в окне конфигурации 167
После того как мы создадали константы и форму констант, у окна конфигурации появился знак * (см. рис. 4.1.12), это значит, что конфигурация отредактирована, но не сохранена. Чтобы её сохранить, нужно нажать на кнопку Сохранить (см. рис. 4.1.13).
Рис. 4.1.12 | Рис. 4.1.13 |
(3) 4.04 что значит знак «!» в окне конфигурации 168-170
После сохранения у окна конфигурации появится знак «!» (см. рис. 4.1.14). Это значит, что конфигурация сохранена, но не загружена в базу.
Рис. 4.1.14
Почему так? В базе 1С хранятся две конфигурации (даже три, если база на поддержке).
Это конфигурация базы данных, т.е. те наборы метаданных, с которыми непосредственно работает пользователь. И просто конфигурация, с которой работает разработчик – рабочая конфигурация. Разработчик (программист) не может напрямую менять конфигурацию базы данных, он работает только с рабочей конфигурацией! После того, как внесены все изменения в рабочую конфигурацию, можно или обновить конфигурацию базы данных, нажав на соответствующую кнопку (см. рис. 4.1.15). Или вернуться обратно к конфигурации базы данных, выполнив команду Вернуться к конфигурации базы данных (см. рис. 4.1.16), тогда все изменения затрутся, и конфигурация разработчика станет идентична конфигурации базы данных.
Рис. 4.1.15
Рис. 4.1.16
Обновим конфигурацию базы данных (рис. 4.1.15) и запустим «1С: Предприятие».
Запустить «1С: Предприятие» из конфигуратор можно или нажав на кнопку Начать отладку
(см. рис. 4.1.17):
Рис. 4.1.17
Или выполнив команду 1С: Предприятие в Главное меню – Сервис.
Рис. 4.1.18
После запуска пользовательского режима в верхней панели появится меню Сервис, раскрыв которое, мы увидим команду Форма констант (см. рис. 4.1.19).
Рис. 4.1.19
После выполнения этой команды откроется форма, которую мы создали ранее (см. рис. 4.1.20).
Рис. 4.1.20
Внесите в неё какие-нибудь данные и нажмите на кнопку Записать и закрыть, после этого константы запишутся в базу данных. Почему так произошло, мы изучим позже, когда будем проходить объектные типы (глава 6).
(3) 4.05 Для чего применяются Справочники? 170-175
Справочники
Изучим следующий прототип объектов конфигурации – это Справочники.
Справочники используются для работы с постоянной или условно постоянной информацией, но, в отличие от констант, данная информация может содержать множество значений. К примеру, если мы разрабатываем конфигурацию для учёта автотранспорта, то такой информацией могут быть марки автомобилей, информация о самих автомобилях, информация о водителях и т.п.
По умолчанию у любого справочника имеется два реквизита – это Код и Наименование. Это так называемые стандартные реквизиты, в действительности их больше, но мы пока остановимся на этих двух. Иногда стандартных реквизитов бывает достаточно, но чаще всего прикладная задача требует хранения вспомогательной информации. Для этого создаются реквизиты справочника, позволяющие хранить любую дополнительную информацию об элементе справочника.
Применительно к автомобилям – это может быть гос. номер, основной водитель, вид коробки передач (автоматическая или ручная), марка автомобиля и т.п. Ещё одна возможность справочников – это возможность создавать табличные части, в которых хранится однотипная информация, количество которой может быть изменчивым. Например, для автомобиля это может быть комплектация: какой-то автомобиль может идти с подушкой безопасности и стеклоподъёмниками, а какой-то просто со стеклоподъёмниками.
Реквизитов и табличных частей может быть неограниченное количество. Разберём поэтапно создание справочника. Создадим первый справочник –
МаркиАвтомобилей.
Как и в случае констант, выделим ветку Справочник, вызовем при помощи правой клавиши мыши контекстное меню и в этом меню выполним команду Добавить.
Рис. 4.1.21
Откроется редактор справочника. Введём в поле Имя название справочника МаркиАвтомобилей, а в поле Синоним – синоним справочника (то, что будет видеть пользователь) Марки автомобилей.
Рис. 4.1.22
В этом справочнике не будет реквизитов, поэтому сразу перейдём на закладку Данные и выставляем длину кода 3 (поле Длина кода), а длину наименования 10 (поле Длина наименования).
Рис. 4.1.23
На этой закладке мы можем также задать тип стандартного реквизита Код и основное
представление этого справочника (как он будет отображаться в полях ввода в виде кода или в виде наименования). Оставим всё по умолчанию, и закроем конструктор этого справочника.
Создайте самостоятельно справочник МоделиАвтомобилей с такой же длиной кода и длиной наименования.
Подсказка: можете скопировать справочник МаркиАвтомобилей, в скопированном справочнике поменять имя и синоним.
Следующим шагом создадим справочник Автомобили. Точно так же кликаем правой кнопкой мышки на ветку дерева Справочники, и выполняем команду Добавить.
Вновь откроется редактор справочника. Внесём название справочника Автомобили, и перейдём на закладку Данные. Длину кода установим такую же, как и в предыдущих справочниках – 3, а длину наименования сделаем 50.
На этой же закладке создадим реквизиты справочника. Первый реквизит ГодВыпуска
(тип Дата (состав даты Дата)), второй – ГосНомер (тип Строка (длина 10)).
Рис. 4.1.24
И третье, самое интересное, мы создаём реквизит Марка, тип которого будет Ссылка на справочник МаркиАвтомобилей.
Рис. 4.1.25
Точно так же добавьте реквизит Модель, тип которого Ссылка на справочник
МоделиАвтомобилей.
Более подробно ссылочные типы мы будем разбирать в следующей главе.
В завершение создадим табличную часть и назовём её ДополнительныеОпции. В табличной части создадим реквизит Опция с типом ссылка на справочник Опции автомобилей (создайте самостоятельно, без реквизитов, длина кода 3, длина наименования 50).
Рис. 4.1.26
И последний справочник, который создадим в этой части, это будет справочник Гаражи, у которого нет реквизитов, а длина кода и наименования такая же, как у справочника Опции (3 и 5).
Создайте его самостоятельно. Сохраните конфигурацию и обновите базу данных.
Посмотрим, как сейчас выглядит пользовательский режим. Все справочники появились в верхней панели (см. рис. 4.1.27).
Рис. 4.1.27
Если мы сейчас попробуем создать какой-то автомобиль, то обнаружим, что заголовки в форме списка и в форме элемента совпадают.
Рис. 4.1.28
И там и там – Автомобили. Если же мы хотим, чтобы у формы списка был заголовок, например, – Машины, а у формы элемента – Автомобиль, то мы сможем сделать это
достаточно легко. Просто заполним свойства Представление объекта и Представление списка справочника. Сделать это можно в редакторе документа, на закладке Основные.
Рис. 4.1.29
После этих действий заголовки формы списка справочника Автомобили и формы элемента поменяются.
Рис. 4.1.30
Причём заметьте, поменялось и название команды, которая открывает форму списка справочника Автомобили в верхнем меню.
Пока не будем создавать никакие элементы справочников, сделаем это после того, как изучим все свойства этого прототипа.
(3) 4.06 Предопределенные элементы - что это?
Предопределённые элементы
У любого справочника можно создать предопределённые элементы.
Предопределённый элемент – это элемент, который создан в конфигураторе, и с ним можно работать как с обычным элементом. Этот элемент есть всегда, в платформе 8.2 его нельзя было пометить на удаление и удалить, в платформе 8.3. предопределённые объекты можно удалять в пользовательском режиме. Создадим два предопределённых элемента у справочника Марки автомобилей – Российские и Иномарки.
Открыть список предопределённых элементов можно двумя способами. Первый – в редакторе справочника на закладке Прочие следует нажать на кнопку Предопределенные.
Рис. 4.1.31
Второй способ – выделяем нужный справочник в дереве метаданных, вызываем правой клавишей мышки контекстное меню и выполняем команду этого меню Открыть предопределенные данные.
Рис. 4.1.32
В результате откроется список предопределённых элементов, в этом списке добавим
новый предопределённый элемент.
Рис. 4.1.33
Точно так же создадим элемент Иномарки.
Рис. 4.1.34
Рекомендую все предопределённые элементы справочника создавать до того, как Вы начнёте заполнять его, это позволит избежать проблем с нумерацией в будущем.
Предопределённые элементы мы создали, теперь сохраним конфигурацию, обновим базу данных, запустим «1С: Предприятие» и кликнем по команде Марки автомобилей в верхней панели. В результате выполнения команды откроется форма списка справочника Марки автомобилей, где уже будут два предопределённых элемента.
Рис. 4.1.35
Если мы создадим новый элемент в «1С: Предприятии» (см. рис. 4.1.36), то он будет отличаться от предопределённого по значку рядом с наименованием (см. рис. 4.1.37).
Подчинённый справочник
Рис. 4.1.36
Рис. 4.1.37
(3) 4.07 Подчиненный справочник - особенности? какая вкладка создания?
В конфигурации 1С можно разрабатывать подчинённые справочники. В подчинённом справочнике каждый его элемент имеет владельца, который является элементом или группой другого справочника. Элемент подчинённого справочника не может существовать без владельца.
Например, у нас есть два справочника Марки автомобилей и Модели автомобилей. У марки автомобиля может быть несколько разных моделей, поэтому естественно их связать между собой. В нашем случае справочник Марки автомобилей должен стать владельцем справочника Модели автомобилей. Сделаем это.
Для этого откроем редактор справочника Модели автомобилей и перейдём на закладку
Владельцы.
Список владельцев пустой. Нажмем на карандаш в правом верхнем углу, должно открыться окно выбора объектов, в котором установим флажок возле справочника Марки автомобилей и нажмём кнопку ОК.
Рис. 4.1.39
Использование подчинения оставляем Элементам.
Рис. 4.1.40
Сохраним конфигурацию и запустим «1С: Предприятие» в пользовательском режиме.
Откроем справочник Марки автомобилей, и откроем форму элемента, который создали в прошлом подразделе – Ford.
Вы видите, вверху элемента справочника появилась команда Модели автомобилей.
Платформа автоматически разместила эту команду в панели навигации элемента справочника. Если мы сейчас кликнем по ней, то откроется список всех моделей автомобилей, у которых владелец – текущей элемент справочника Марки автомобилей. В нашем случае он пустой, поэтому мы добавим какую-нибудь модель автомобиля (см. рис. 4.1.42).
Рис. 4.1.42
Рис. 4.1.43
Теперь создадим новую марку (пусть это будет KIA) и добавим для неё новую модель (пусть это будет Rio).
Рис. 4.1.44
А теперь попробуем создать новый элемент справочника Автомобили, на форме элемента выберем какую-нибудь марку (пусть будет Ford), и попробуем выбрать модель. Напомню, что Марка и Модель – это реквизиты соответствующих типов.
Рис. 4.1.45
Рис. 4.1.46
Как видите, в форме выбора модели есть выбор и моделей Ford, и моделей KIA, что согласитесь, немного неудобно и не совсем правильно – пользователь может ошибиться и выбрать модель другой марки.
Как же сделать так, чтобы в форме выбора были модели только для той марки, которая выбрана в реквизите элемента справочника? Для этого нам понадобится зайти в конфигураторе в свойства реквизита Модель справочника Автомобили (дважды кликнув левой клавишей мышки по реквизиту в дереве конфигурации). В открывшейся палитре свойств нас интересует свойство Связи параметров выбора.
Рис. 4.1.47
При помощи этого свойства можно настроить зависимость выбираемых параметров от
значений других реквизитов. Откроем форму Связи параметров выбора, нажав на кнопку
«…» справа поля.
Рис. 4.1.48
Поскольку нам нужно установить связь реквизита Модель с реквизитом Марка, то
«перетащим» этот реквизит из левой части в правую.
Рис. 4.1.49
Рис. 4.1.50
Нажмём кнопку ОК формы связи параметров выбора.
Рис. 4.1.51
Сохраним конфигурацию, обновим базу данных, попробуем создать новый элемент справочника Автомобили. Выберем марку Ford и попробуем выбрать модель.
Рис. 4.1.52
Как видите, на форме выбора моделей только одна модель, у которой владелец марка
Ford.
(3) 4.08 Иерархический справочник - какие есть виды иерархии справочника?
Иерархический справочник
Любой справочник можно сделать Иерархическим – это значит, что пользователь сможет создавать каталоги (или, говоря простым языком, папки), в которых будут содержаться элементы.
Сделаем справочник Гаражи иерархическим. Для этого в редакторе справчоника нужно перейти на закладку Иерархия и установить флаг Иерархический справочник.
Рис. 4.1.53
Иерархия у справочников бывает двух видов: Иерархия групп и элементов и просто
Иерархия элементов.
Иерархия групп и элементов – это каталоги, которые в себе содержат определённые элементы. А что такое Иерархия элементов? Это когда один элемент подчинён другому.
К примеру, есть большой гараж (ангар), в котором много маленьких гаражей. Вам необходимо вести учёт автомобилей по большому гаражу, поскольку они могут стоять вне маленьких, а также учёт по маленьким гаражам. В этом случае справочник Гаражи будет удобно сделать с Иерархией элементов. Но если ещё понадобится объединять гаражи по какой-то общей группе, по которой не будет вестись отдельного учёта, то необходимо сделать Иерархию групп и элементов. Например, может быть каталог Авто база, в котором будут перечислены все гаражи.
Посмотрим, как выглядит иерархический справочник Гаражи в пользовательском режиме «1С: Предприятия». Сохраним конфигурацию, обновим базу данных и откроем форму списка справочника Гаражи.
Рис. 4.1.54
Как видите, на форме списка, кроме команды Создать, появилась ещё команда Создать группу. При выполнении команды Создать будет открыта форма на создание нового элемента, а при выполнении команды Создать группу – форма на создание группы (каталога).
Создадим каталог Авто база.
Рис. 4.1.55
В поле Наименование напишем наименование группы Авто база. Родитель будет пустой. После нажматия кнопки Записать и закрыть, группа будет создана. Зайдём в каталог, кликнув по нему два раза, и добавим новый элемент, в этот раз выполнив команду Создать.
Рис. 4.1.56
Открылась форма, в которой родитель уже заполнен. Назовем элемент Гараж № 1.
Сохраним элемент.
Рис. 4.1.57
Этот новый гараж Гараж № 1 находится в группе Авто база.
(3) 4.09 Документы - для чего предназначены
Документы
Документы предназначены для отражения определённых событий в программе, которые имеют отношение к предметной области. Например, касательно учёта автотранспорта, это могут быть события прибытия автомобиля в гараж, убытия из гаража и постановки на ремонт. Основными стандартными реквизитами документов являются Номер документа и Дата документа. Как и в случае со справочниками, остальная вспомогательная информация может храниться в реквизитах и табличных частях. Суть их такая же, как у реквизитов и табличных частей справочников.
Основное отличие Документов от Справочников в том, что Документ может делать движения в регистрах накопления, сведений, бухгалтерии и расчёта.
(3) 4.10 Что такое Движения документа?
Что такое Движения документа? Движения документа – это записи в регистрах накопления, сведений, бухгалтерии и расчёта, которые создаются при проведении документа и уничтожаются при отмене проведения документа. Всё просто. Разработчик самостоятельно настраивает, по каким регистрам будет делать движение его документ, естественно, что регистр перед этим должен быть создан.
Создадим четыре документа: Прибытие в гараж, Выбытие из гаража, Заправка
топлива и Отчет о расходе топлива.
Впоследствии первый будет делать соответствующие движения по регистру накопления Пробег автомобиля, а последние два – по регистру накопления Расход топлива, но мы дойдём до этого, когда будем разбирать регистры накопления.
Для того чтобы создать документ, следует кликнуть правой кнопкой мышки по ветке
Документы дерева конфигурации и выполнить команду Добавить.
Рис. 4.1.58
Откроется редактор вновь созданного документа. Назовём документ ПрибытиеВГараж – такое значение присвоим свойству Имя, синоним должен заполниться автоматически.
Рис. 4.1.59
Следующим шагом создадим реквизиты, для этого перейдём на закладку Данные, в которой добавим три реквизита: Автомобиль, Гараж и Дата прибытия.
Рис. 4.1.60
Реквизит Автомобиль будет иметь тип Ссылка на справочник Автомобили, Гараж – тип Ссылка на справочник Гаражи, а ДатаПрибытия – Дата (состав Дата и время).
Рис. 4.1.61
Точно так же создадим документ Выбытие из гаража (можно создать копированием – скопируем документ Прибытие в гараж, изменим название документа и названия реквизитов). Реквизиты – Автомобиль, Гараж и ДатаВыбытия. Типы реквизитов аналогичны типам в документе Прибытие в гараж.
Создадим документ Заправка топлива, у документа создадим два реквизита: ДатаЗаправки с типом Дата (состав даты Дата) и ТипТоплива (ссылка на справочник ТипыТоплива, справочник Типы топлива создайте самостоятельно, без реквизитов, длина кода 3, длина наименования 10).
У документа Заправка топлива создадим табличную часть Автомобили, где будет два реквизита: Автомобиль (тип ссылка на справочник Автомобили) и Количество (тип Число(10,2)). Табличные части у документов создаются таким же образом, как и у справочников: переходим на закладку Данные, или выполняем команду Добавить табличную часть, или, выделив ветку Табличные части, вызываем правой клавишей мышки контекстное меню, в котором выполняем команду Добавить.
Рис. 4.1.62
Табличная часть будет создана, переименуем ее в Автомобили. Для этого в палитре свойств, которая откроется справа, изменим свойство Имя.
Рис. 4.1.63
И добавим новый реквизит созданной табличной части.
Рис. 4.1.64
Назовем его Автомобиль и присвоим тип ссылка на справочник Автомобили.
Рис. 4.1.65
Точно так же добавим реквизит Количество с типом Число (10,1).
И последний документ Отчет о расходе топлива создайте самостоятельно, в этом документе будет точно такой же набор полей, как и в документе Заправка топлива, только вместо ДатаЗаправки будет поле ДатаОтчета.
Рис. 4.1.66
Мы создали все необходимые документы для нашей конфигурации.
Зайдите в пользовательский режим «1С: Предприятия» и попробуйте создать несколько разных документов.
(3) 4.11 Ввод на основании - Что такое Ввод на основании? какая закладка?
Рассмотрим ещё одну интересную особенность объектов 1С – это Ввод на основании.
Что такое Ввод на основании? Это значит, что на основе какого-то имеющегося объекта
(документа или справочника) можно создать новый объект другого вида, причём часть полей нового объекта будут заполнены автоматически, а их значения взяты из основного объекта. Данная особенность очень удобна, поскольку позволяет в некоторых случаях экономить пользователю время и исключает возможность возникновения дополнительных ошибок.
Доработаем нашу конфигурацию так, чтобы на основании документа Прибытие в гараж можно было создать документ Выбытие из гаража, причём реквизиты Автомобиль и Гараж должны заполняться автоматически.
В редакторе документа Выбытие из гаража перейдём на закладку Ввод на основании.
Рис. 4.1.67
В верхнем окне Вводится на основании нажмём на карандаш, после этого откроется окно выбора объектов.
Рис. 4.1.68
В окне выбора объектов установим флаг напротив документа Прибытие в гараж и нажмём кнопку ОК.
После этого в верхнем окне закладки Ввод на основании появится выбранный документ:
Рис. 4.1.69
А если зайдём в аналогичную закладку редактора документа Прибытие в гараж, то мы увидим, что окно Является основанием заполнено.
Рис. 4.1.70
Теперь нам необходимо разработать механизм заполнения документа на основании другого документа. Для этого нужно создать в модуле объекта документа, который вводится на основании, процедуру Обработка основания.
(3) 4.12 ввод на основании, какой конструктор?
Можно это сделать вручную, а можно воспользоваться конструктором. Мы воспользуемся конструктором. Для этого, не выходя из закладки Ввод на основании конструктора документа Выбытие из гаража, нажмём на кнопку Конструктор ввода на основании.
Рис. 4.1.71
Откроется конструктор, в котором следует заполнить реквизиты Автомобиль и
Гараж.
Рис. 4.1.72
В правом верхнем окне показаны реквизиты документа основания (документа Прибытие в гараж), а в нижнем окне реквизиты текущего документа Выбытие из гаража. При установке курсора на строку нужного поля в верхнем левом окне зелёным флажком будут отмечены реквизиты документа основания, тип которых совпадает с типом
выделенного поля (см. рис 4.1.73).
Чтобы совместить реквизит основного документа с реквизитом документа основания, необходимо выделить строку с нужным реквизитом в нижней таблице и дважды кликнуть на соответствующий реквизит правой верхней таблицы. Мы совместим реквизиты Автомобиль
– Автомобиль и Гараж – Гараж.
Рис. 4.1.73
Нажмем ОК окна Конструктор ввода на основании, и процедура заполнения на основании будет создана автоматически.
Рис. 4.1.74
Сохраним конфигурацию и обновим базу данных. Самостоятельно создайте документ
Выбытие из гаража на основании документа Прибытие в гараж.
(3) 4.13 Журнал документов - для чего служит?
Журнал документов
Следующий объект конфигурации, который мы рассмотрим, – это Журнал документов. Журнал документов, как ясно из названия, предназначен для просмотра документов, причём это могут быть документы разного вида. Как Вы уже видели, в списке каждого документа можно посмотреть только документ одного вида. Но иногда очень полезно видеть документы разных видов в одном месте. Для этого и необходим журнал документов. Каждый документ может быть отнесён к тому или иному журналу, либо быть вообще без журнала. В отличие от справочников и документов, журнал не добавляет новой
информации в систему, а служит только для отображения имеющейся информации.
Создадим журнал документов Прибытие – Выбытие автомобилей, в котором будут отображаться документы Приезд в гараж и Выбытие из гаража.
Для этого нужно кликнуть правой кнопкой мышки по ветке дерева метаданных
Журналы документов и выполнить команду Добавить.
Рис. 4.1.75
Откроется редактор журнала, в котором в свойство Имя введём название журнала – ПрибытиеВыбытиеАвтомобилей. А в свойстве Синоним изменим значение на Прибытие- выбытие автомобилей.
Рис. 4.1.76
Необходимо задать регистрирующие документы, то есть те документы, которые будут отражаться в журнале. Перейдем в закладку Данные, и заполним окно Регистрирующие документы. Для этого нажмём на кнопку Редактировать элемент списка в виде карандашика и в открывшемся окне поставим флажки у документов Прибытие в гараж и Выбытие из гаража.
Рис. 4.1.77
Нажмём ОК. Журнал, в принципе, готов.
Запустим пользовательский режим «1С: Предприятия» и посмотрим, как выглядят документы в новом журнале (я надеюсь, Вы парочку уже создали).
Рис. 4.1.78
Из формы журнала Вы видите, что у нас только колонки с номером, датой и типом документа, что, согласитесь, иногда бывает недостаточно. Добавим в журнал ещё две колонки, это – Гараж и Автомобиль. Для этого воспользуемся окном Графы на закладке Данные редактора журнала документов.
Добавим новую графу в журнал документов. Для этого выделим ветку Графы, и нажмём на кнопку Добавить верхней панели.
Рис. 4.1.79
Графа добавилась, для этой графы нам необходимо задать, какие поля документов
будут отображаться. Для этого, в палитре свойств графы нужно нажать на кнопку «…» свойства Ссылки, откроется окно, в котором следует указать реквизиты документов журнала, которые должны отобразиться в этой графе (см. рис. 4.1.80).
Рис. 4.1.80
Графу можно переименовать.
Рис. 4.1.81
После этих доработок журнал документов будет выглядеть гораздо интереснее:
Рис. 4.1.82
Самостоятельно добавьте новую графу Автомобиль, чтобы журнал выглядел следующим образом:
Рис. 4.1.83
(3) 4.14 Перечисления - что это?
Перечисления
Следующий объект конфигурации – Перечисления. Перечислениями называют объекты конфигурации, которые содержат в себе постоянные значения, не изменяемые в процессе работы с программой. Перечисления задаются на этапе конфигурирования, и их нельзя менять пользователю во время работы программы.
Создадим перечисление Коробка передач с двумя значениями: Ручная и Автоматическая. И добавим новый реквизит в справочник Автомобили с ссылкой на созданное перечисление.
Для создания кликнем правой клавишей мышки по пункту Перечисления и выполним команду Добавить.
Рис. 4.1.84
Откроется меню элемента перечисления. Назовём новое перечисление
КоробкаПередач (значение в свойстве Имя).
Рис. 4.1.85
Осталось создать значения перечисления, для этого перейдём на закладку Данные и выполним команду Добавить.
Рис. 4.1.86
Значение будет создано, назовем его Ручная.
Рис. 4.1.87
Точно так же создадим второе значение – Автоматическая.
Следующим шагом сделаем так, чтобы ссылка на это перечисление была реквизитом справочника Автомобили, то есть чтобы у конкретного автомобиля можно было выбрать коробку передач – ручную или автоматическую. Для этого перейдём в справочник Автомобили и добавим новый реквизит Коробка передач, тип которого будет ссылка на перечисление Коробка Передач.
Рис. 4.1.88
В пользовательском режиме «1С: Предприятия» в уже созданных элементах справочника Автомобили (если их у Вас нет, то создайте) установим значения в новый реквизит Коробка передач.
Рис. 4.1.89
Мы научились создавать в конфигураторе справочники, перечисления, документы и журналы документов. Теперь плавно перейдём к изучению регистров. Вся информация, которая вводится с помощью документов, может быть отражена в регистрах, для того чтобы впоследствии можно было её извлечь и проанализировать.
(3) 4.15 Регистр сведений - для чего хранится?
В конфигурации 1С можно создать четыре вида регистра, это: Регистр накопления, Регистр сведений, Регистр бухгалтерии и Регистр расчета. В этой книге мы рассмотрим два регистра: Регистр накопления и Регистр сведений.
Для начинающих изучения принципов функционирования регистров накопления и сведений будет вполне достаточно, чтобы представлять, каким образом ведётся учёт в данной программе.
И первым делом мы рассмотрим регистр сведений. Более подробно о том, как работать с регистрами сведений, вы узнаете в десятой главе. В этой главе мы изучим только моменты, связанные с конфигурированием регистра сведений.
Регистр сведений
Регистры сведений необходимы для хранения различной информации, которая может быть важна для прикладной области. Эта информация хранится в разрезе измерений, также она может изменяться во времени.
(3) 4.16 что означает Периодический Регистры сведений
Регистры сведений, информация которых изменяется во времени, называются Периодическими. Периодичность может быть разной, может быть периодичность в секунду, минуту, час и т.д. максимум – год.
(3) 4.17 чем отличается регистр сведений от справочника?
Поскольку Вы уже изучили справочники, то у Вас должен возникнуть вопрос: чем отличается регистр сведений от справочника, и, самое главное, когда нужно использовать справочник, а когда регистр сведений.
Основное отличие в использовании справочников и регистров сведений в том, что в
справочниках должны храниться объекты аналитики (контрагенты, номенклатура, автомобили, виды топлива и т.д.), а в регистре сведений должны храниться показатели для этих объектов. Например, это может быть цена на топливо у того или иного поставщика. Или гараж по умолчанию, где должен стоять автомобиль.
Причём у регистров сведений осуществляется контроль уникальности – нельзя создать две записи с одинаковым набором измерений (чего нет у справочников). К примеру, если у нас будет непериодический регистр сведений Цены на топливо с измерениями Тип топлива и Поставщик и одним ресурсом – Цена, то мы не сможем создать две одинаковых записи с одними и теми же наборами измерений Тип топлива и Поставщик. У регистров сведений контроль уникальности осуществляется в разрезе измерений.
Кроме измерений у регистра сведений ещё существуют Ресурсы и Реквизиты. Ресурс должен хранить основную информацию регистра сведений, то есть те данные, ради которых он создан, а Реквизит содержит дополнительную второстепенную информацию о записи.
(3) 4.18 какие бывают режимы записи Регистра сведений?
Регистры сведений бывают подчинённые регистратору, тогда записи в них будут создаваться при проведении документов и независимые, тогда пользователь сам может создавать записи. В первом случае в свойстве Режим записи устанавливается значение Подчинение регистратору, а во втором – Независимый.
Создадим в нашей конфигурации регистр сведений Основной гараж автомобиля, где измерение будет Автомобиль с типом ссылка на справочник Автомобили, и ресурс: Гараж с типом ссылка на справочник Гаражи, этот регистр будет непериодическим.
Для создания регистра сведений нужно кликнуть правой клавишей мышки по ветке конфигурации Регистры сведений, и в открывшемся контекстном меню выполнить команду Добавить.
Рис. 4.1.90
Откроется редактор регистра сведений, в котором в поле Имя введём название регистра – ОсновнойГаражАвтомобиля,в поле Периодичность установим периодичность Непериодический, а в поле Режим записи оставим значение Независимый – это значит, пользователь сам сможет создавать записи регистра сведений.
Рис. 4.1.91
Сделаем измерение и ресурс. Для этого перейдём на закладку Данные, в которой создадим измерение Автомобиль (тип ссылка на справочник Автомобили). Это будет единственное измерение этого регистра сведений. И добавим единественный ресурс – Гараж (тип ссылка на справочник Гаражи).
Рис. 4.1.92
Рис. 4.1.93
Почему мы сделали только одно измерение – Автомобиль? Очевидно из названия, что у автомобиля может быть только один гараж. Как следствие, не должно быть двух записей регистра сведений с одинаковыми автомобилями и разными гаражами. Поэтому мы задали только одно измерение, поэтому может быть только одна запись с конкретным автомобилем, напомню, что у регистров сведений обеспечивается уникальность записей в разрезе измерений.
(3) 4.19 привязать запись регистра сведений к конкретному элементу так, чтобы, когда мы удалим это элемент, удалилась и эта запись
Поскольку у нас основной гараж будет устанавливаться для конкретного автомобиля, то логичнее привязать запись регистра сведений к конкретному элементу справочника так, чтобы, когда мы удалим это элемент, удалилась и эта запись. Делается это при помощи свойства измерения регистра сведений Ведущее.
Рис. 4.1.94
Если это свойство у измерения установлено, то записи регистра сведений, в которых в измерении содержится ссылка на определённый объект, будут существовать до тех пор, пока не будет удален этот объект.
И у этого свойства есть приятный интерфейсный бонус: в панели навигации формы элемента объекта появится команда на открытие формы записей регистра сведений, где будут перечислены только те записи регистра, у которых в измерении содержится ссылка на открытый объект.
Проверим это. Сохраним конфигурацию, обновим базу данных и зайдём в один из элементов справочника Автомобили.
Рис. 4.1.95
Вверху формы элемента появилась гиперссылка Основной гараж автомобиля, если мы по ней кликнем, то откроется форма записей регистра сведений Основной гараж автомобиля, в которой мы можем добавить новую запись.
Рис. 4.1.96
Заметьте, поле Автомобиль записи регистра сведений заполнилось автоматически. Это произошло потому, что установлено свойство Заполнять из данных заполнения измерения Автомобиль.
Рис. 4.1.97
Самостоятельно попробуйте отключить это свойство, и посмотрите, как будет заполняться поле Автомобиль.
После заполнения всех полей, сохранения, запись появится в форме списка регистра сведений. В нашем случае это форма отображает только те записи, у которых в измерении Автомобиль записан автомобиль, форма которого открыта.
Рис. 4.1.98
Причём мы не сможем добавить ещё один основной гараж автомобиля. Выйдет ошибка.
Вы видите, что при такой организации данных, мы можем быть уверены, что у нашего автомобиля только один основной гараж.
Перейдём к периодическим регистрам сведений. Для этого создадим новый регистр сведений Цены на топливо, у которого в свойстве Периодичность установим значение В пределах дня, то есть наш регистр будет с периодичностью День.
Рис. 4.1.100
У нового регистра будет два измерения Тип топлива (ссылка на справочник Типы топлива) и Поставщик топлива (ссылка на справочник Контрагенты, создайте справочник самостоятельно – длина кода 3, длина наименования 50, с одним реквизитом Полное наименование (Строка (100))). И один ресурс – Цена (Число (10,2)).
Рис. 4.1.101
Сохраним конфигурацию, обновим базу данных и попробуем заполнить новый регистр сведений.
В этом регистре мы можем заводить одной датой разные комбинации измерений и одну и ту же комбинацию измерений разными датами, но не сможем завести на одно число две разные цены для определённого поставщика и определённого типа топлива.
Рис. 4.1.103
А если цена будет по дню меняться несколько раз? Как быть? Можно создать более маленькую периодичность (секунда), но и в этом случае, если цена будет меняться несколько раз за секунду, то не получится отобразить такое изменение. Выход из подобной ситуации – сделать регистр подчиненным регистратору, а периодичность такого регистра – по позиции регистратора.
Рис. 4.1.104
В этом случае мы сможем создавать сколько угодно регистраторов, пусть даже с одним и тем же временем, и наш регистр будет нормально заполняться (удалите все созданные ранее записи регистра сведений Цены на топливо).
Для проверки работы подчинённого регистра создадим новый документ Установка цен на топливо со следующими реквизитами и свойствами.
Рис. 4.1.105
Рис. 4.1.106
Не забудем установить ссылочные типы для реквизитов (какие – определите самостоятельно).
Более подробно работу с документами будем проходить во второй части шестой
главы.
При помощи конструктора движений создадим обработку проведения по регистру накопления. Чтобы он открылся, нужно нажать на кнопку Конструктор движений в закладке Движения редактора документа.
Рис. 4.1.107
Информация по ценам в этом документе находятся в табличной части, поэтому выберем в поле конструктора Табличная часть единственную табличную часть документа Цены топлива, чтобы заполнение происходило из неё.
Рис. 4.1.108
Подберём в измерение ТипТоплива и ресурс Цена соответствующие реквизиты из табличной части, а в измерение ПоставщикТоплива – реквизит Поставщик из шапки.
Рис. 4.1.109
Все сделали, нажмём кнопку ОК и в модуле документа Установка цен автоматически будет создана процедура, которая осуществляет создание записей регистра сведений.
Рис. 4.1.110
Ничего в ней не будем изменять, сохраним конфигурацию и обновим базу данных.
После этого попробуем создать несколько одинаковых документов с одинаковыми поставщиками, с одинаковыми типами топлива, но с разными ценами.
Рис. 4.1.111
Рис. 4.1.112
Они прекрасно проведутся. Посмотрим, как будут выглядеть записи в регистре сведений. В этот регистр мы зайдём через команду Функции для технического специалиста.
Рис. 4.1.113
Если у Вас эта команда отсутствует, то включить её можно в параметрах.
Рис. 4.1.114
Рис. 4.1.115
После выполнения команды откроется окно Функции для технического специалиста, в котором нужно выбрать элемент Цены на топлива ветки Регистры сведений дерева конфигурации.
Рис. 4.1.116
Рис. 4.1.117
Как видите, у нас получилось несколько одинаковых записей с разными ценами. Почему такое стало возможным? Ведь Период, по сути, тоже измерение, и по нему тоже должен вестись контроль уникальности записей? Потому что мы периодичность установили По позиции регистратора, а позиция регистратора это не только дата документа, это – момент времени, в который входит дата и время документа, а также ссылка на сам документ. У двух разных документов будет два разных момента времени, поэтому и возможна такая запись регистра сведений, как на рис. 4.1.117.
(3) 4.20 Регистр накопления - что хранит?
Регистр накопления
Регистр накопления хранит в себе данные о движении различных материальных величин, это может быть: прибытие и выбытие материалов, оборот денежных средств и т.п. Вся информация о движении хранится в разрезе измерений, а сама информация об учёте (количество, сумма и т.п.) хранится в ресурсах. Помимо этого есть реквизиты, в которых хранится прочая справочная информация.
(3) 4.21 Основная функция регистра накопления?
Основная функция регистра накопления заключается в суммировании ресурсов, то
есть если какая-либо информация хранится в регистре накопления, то вы можете в любой момент извлечь сумму всех ресурсов по любым измерениям, которые Вам интересны.
Регистр накопления не может существовать без Регистратора, то есть документа, который при проведении создаёт записи регистра.
(3) 4.22 сколько типов Регистров накопления?
Регистры накопления бывают двух видов. Это Оборотные регистры и Регистры остатков.
(3) 4.23 что фиксируют Оборотные регистры?
Оборотные регистры просто фиксируют наличие движения по данному регистру, без разницы, был ли приход или расход.
(3) 4.24 что фиксируют Регистры остатков
Регистры остатков фиксируют движения двух видов: приход и расход.
Ярким примером сущности, которая может храниться в оборотном регистре, является прибыль: она может только появиться, нам интересен сам факт наличия прибыли, к примеру, сколько прибыли было за предыдущий месяц. Поэтому если разрабатывать регистр накопления, который вёл бы учёт прибыли, то он должен быть оборотным. В нашей конфигурации в оборотном регистре будет храниться пробег автомобиля. Пробег не может
«прийти» или «уйти», он всегда накапливается, и нам нужно знать, какой пробег у автомобиля был за неделю, месяц, год.
Другое дело – товар: он приходит и уходит, и нам необходимо знать остатки товара на складе или в организации, поэтому регистр накопления, который ведёт учёт товара, должен иметь вид регистра остатков. В нашем случае мы будем вести учёт топлива: сколько заправили топлива в автомобиль, и сколько его автомобиль израсходовал.
(3) 4.25 что такое Измерения.
Это общая информация о регистрах. Теперь перейдём к их строению. Разберём сначала, что такое Измерения. Информацию в регистрах накопления можно хранить в нескольких разрезах.
Например, нам необходима информация о наличии топлива в автомобилях. Само по себе топливо уже будет измерение, но просто сведения о топливе будут неполными. Нам необходимо знать, куда именно заправлено наше топливо, в какой автомобиль, поэтому мы вводим ещё одно измерение – автомобиль. Пусть топливо будет Аи95 и Аи92 (измерение Топливо), а автомобиль – Директора и Гл. инженера (измерение Автомобиль). Смотрим на таблицу 4.1.1*.
Топливо | Автомобиль | Количество, л. |
Аи95 | Директора | 1 |
Аи92 | Гл. инженер | 2 |
Аи95 | Гл. инженер | 5 |
Табл. 4.1.1
* Предположим, что разные виды топлива можно заправлять в один автомобиль, и вести по ним учёт.
Согласно таблице 4.1.1, топливо типа Аи95 заправлено в автомобили Директора и Гл. инженера, всего топлива этого вида заправлено шесть литров. А в автомобиль Гл. инженера заправлено топливо Аи92 и Аи95, всего семь литров.
(3) 4.26 важная функция измерений?
Таким образом, мы подошли к важной функции измерений – возможности суммировать нужный ресурс по любому значению измерения.
Создадим регистр накопления в нашей конфигурации. Это будет регистр оборотов
ПробегАвтомобиля, у него будет одно измерение – Автомобиль, соответствующего типа, и один ресурс – Пробег типа Число (10,0).
Для создания нового регистра выделим ветку дерева метаданных Регистры накопления и вызовем правой клавишей мышки контекстное меню. В этом меню выполним команду Добавить.
(3) 4.27 создание регистра накопления Обороты, закладки
Рис. 4.1.118
Откроется редактор регистра накопления, в этом редакторе на закладке Основные введём Наименование (это будет имя созданного регистра), а вид регистра установим Обороты.
Рис. 4.1.119
Затем на закладке Данные создадим измерение Автомобиль (тип ссылка на справочник Автомобили) и ресурс Пробег (тип Число(10,0)).
Рис. 4.1.120
Следующим шагом необходимо отметить те документы, которые будут делать движения по созданному регистру. Перейдём на закладку Регистраторы и установим флаг рядом с документом Прибытие в гараж, именно этим документом будет фиксироваться пробег.
Рис. 4.1.121
В реквизиты документа Прибытие в гараж самостоятельно добавьте реквизит Пробег с точно таким же типом, как и у ресурса Пробег вновь созданного регистра накопления (Число (10,0)).
Для удобства и скорости можете этот ресурс просто «скопировать», а потом
«вставить» в реквизиты документа Прибытие в гараж, или вообще «перетащить».
Рис. 4.1.122
Конфигурировать регистр накопления мы закончили – можно закрыть его редакторы.
(3) 4.28 где прописать движения при проведении документа?
Следующим шагом нам нужно прописать сами движения, которые должны сформироваться при проведении документа.
Для этого в дереве документов выделим нужный нам документ (это будет Прибытие в гараж), вызовем правой кнопкой мыши контекстное меню, и в этом меню в подменю Конструкторы найдём команду Конструктор движений, выполним эту команду и в результате откроется окно Конструктор движения регистров.
Рис. 4.1.123
В окне Конструктор движения регистров необходимо проставить соответствие
измерений и ресурсов регистра с реквизитами документа.
Рис. 4.1.124
После того как проставим соответствие, нажмём кнопку ОК, и будет создана процедура проведения с соответствующим кодом. Пока не будем разбирать этот код, работу с набором записей регистров накоплений Вы будете проходить в десятой главе.
Сохраним конфигурацию, обновим базу данных и откроем какой-нибудь документ Прибытие в гараж, заполним у этого документа поле Пробег и проведём. А после проведения посмотрим, какие движения сделал этот документ по регистру накопления Пробег автомобиля (для того чтобы посмотреть на движения, откроем форму списка регистра накопления через команду Функции для технического специалиста).
Рис. 4.1.125
Рис. 4.1.126
Перейдём к регистрам остатков.
Создадим новый регистр накопления Топливо в автомобилях. Это будет регистр Остатков, у нового регистра будет два измерения – ТипТоплива и Автомобиль соответствующих типов, и один ресурс – Количество типа Число(10,1).
Рис. 4.1.127
Рис. 4.1.128
Регистраторами будут документы Заправка топлива и Отчет о расходе топлива.
Рис. 4.1.129
С регистром накопления пока закончим, можете закрыть редактор. Следующим шагом пропишем движения, которые должны возникнуть при проведении документа Заправка топлива.
Уже знакомым нам способом (рис. 4.1.123, стр. 213) откроем конструктор движений
документа Заправка топлива.
Рис. 4.1.130
У этого документа данные для движений по регистру накопления будем брать из табличной части Автомобили. Поэтому в поле Табличная часть конструктора выберем значение Автомобили.
Рис. 4.1.131
После выбора табличной части в правом верхнем поле появятся реквизиты из табличной части документа. Нам необходимо проставить соответствия между измерениями и ресурсами регистра накопления и реквизитами шапки и табличной части документа.
Подсказка: сопоставление можно выполнить автоматически, нажав на кнопку Заполнить выражения, будет выполнено сопоставление по типу реквизитов и измерений (ресурсов, реквизитов).
Рис. 4.1.132
Тип движения регистра оставим Приход, поскольку данный документ будет отображать факт прибавления топлива в автомобиле.
Если Вам непонятно, какое движение должен делать тот или иной документ, то руководствуйтесь следующим мнемо-правилом:
Если природа документа отражает увеличение какой-нибудь сущности где-либо (приход товара на склад, приём «налички» в кассу, начисление налога со сделки и т.п.), то этот документ должен делать движение прихода по регистру накопления. Если же природа документа отражает уменьшение какой-нибудь сущности где-либо (отгрузка товара, выдача «налички» из кассы, оплата налога и т.п.), то этот документ должен делать движение расхода по регистру накопления.
Нажмем кнопку ОК, и будет создана обработка проведения с соответствующим кодом.
То же самое проделаем с документом Отчет о расходе топлива, только ставим Тип движения регистра – Расход.
Рис. 4.1.133
Сохраним конфигурацию, обновим базу данных, создадим и проведём документ
Заправка топлива.
Рис. 4.1.134
А также документ Отчет о расходе топлива.
Рис. 4.1.135
И посмотрим в форме списка регистра Топливо в автомобилях, какие движения сделали эти документы.
Рис. 4.1.136
План видов характеристик
Рассмотрим такой интересный объект конфигурации, как план видов характеристик.
Часто при разработке прикладных решений могут появляться задачи добавления дополнительных характеристик различным объектам учёта. Например, у нас есть справочник Гаражи, вполне возможно, что в процессе работы нам понадобится хранить такую информацию, как место гаража, длина, ширина, тип гаража и т.д.
Всю дополнительную информацию можно хранить в реквизитах справочника, и это решение вполне имеет право на жизнь, но только в том случае, когда состав характеристик всегда будет один и тот же, и он заранее известен. Если же состав реквизитов будет постоянно меняться, то нам каждый раз придётся переписывать конфигурацию: добавлять новый реквизит со всеми вытекающими последствиями (переписывание форм и т.п.)
Может быть и иная ситуация: у разных объектов может быть разный состав характеристик. Например, для какого-то гаража важно указать длину и ширину, а для какого- то эта информация не столь критична. Тогда часть реквизитов будут лишними.
Во всех подобных случаях рациональнее использовать планы видов характеристик, в которых хранится дополнительная информация объектов аналитического учёта. Что такое план видов характеристик? По сути это такой справочник, в котором элементы (характеристики) могут быть разных типов. Например, есть характеристика Высота гаража, тип которой Число. В характеристику Высота гаража можно записать только число и не более. Причём у одного плана видов характеристик могут быть характеристики разных типов. Таким образом, можно резюмировать: если у обычного справочника все элементы этого справочника одного типа (ссылка на этот справочник), то у плана видов характеристик элементы могут быть разных типов, в зависимости от того, как настроено в конфигурации.
Сделаем следующую задачу: реализуем возможность хранения различных характеристик справочника Гаражи. Характеристики могут быть в виде примитивных типов (например, количество мест в гараже), а также в виде каких-то значений (например, расположение гаража: Север, Юг и т.д.), которые могут создавать сами пользователи.
Создадим план видов характеристик ДополнительныеСвойстваГаражей.
Рис. 4.1.137
Рис. 4.1.138
В редакторе плана видов характеристик на закладке Основные обратим внимание на поле Тип значения характеристик, в этом поле необходимо задать тип (или типы) будущих характеристик. Характеристики нашего нового плана вида характеристик будут только тех типов, которые указаны в этом поле. Если нажать на кнопку «…» этого поля, то откроется окно редактирования типа данных.
Рис. 4.1.139
В этом окне можно задать как конкретный тип, который будет у всех характеристик объекта, так и перечень типов, установив флаг Составной тип данных. Мы зададим все примитивные типы.
Рис. 4.1.140
Но в условиях задачи было сказано, что характеристики могут храниться в виде каких- то определённых значений, и у пользователя должна быть возможность выбрать одно из этих значений. Причём эти значения пользователь может задать самостоятельно. Где наиболее оптимально хранить значения той или иной характеристики?
Заметьте, нужно сделать так, чтобы эти значения не пересекались. К примеру, у нас будет характеристика Расположение гаража, эта характеристика будет содержать
произвольные значения расположения гаража (Север, Юг, Запад и т.д.) А также будет характеристика Тип гаража, которая будет содержать произвольные значения типа гаража (Кирпичный, Железный и т.д.) Значения этих характеристик не должны пересекаться.
Например, если мы выберем характеристику Расположение гаража, то должны видеть только значения расположения, но никак не значения типа гаража.
Можно, конечно, создать отдельные справочники Расположение гаража и Тип гаража, но мы не можем быть уверены, что потом не добавятся ещё какие-либо новые характеристики, которые будут содержать произвольные значения, и нам опять не придётся менять конфигурацию. Самым оптимальным решением будет создать единый справочник для хранения всех значений подобных характеристик. Этот справочник должен быть подчинён плану видов характеристик ДополнительныеСвойстваГаражей. В этом случае у любой характеристики (элемента плана видов характеристик), тип которой Ссылка на подчинённый справочник, будет свой набор значений, ни с чем не пересекающийся.
Немного запутанно? Сейчас всё станет понятно!
Создадим такой справочник и назовём его СвойстваГаражей (длина кода – 3, длина наименования – 50, реквизитов нет). На закладке Владельцы справочника СвойстваГаражей установим единственного владельца – план видов характеристик Дополнительные свойства гаражей (см. рис. 4.1.141).
После создания справочника перейдём в редактор план видов характеристик Дополнительные свойства гаражей и в свойстве Тип значения характеристик (на закладке Основные) добавим новый тип – ссылку на справочник Свойства гаражей (см. рис. 4.1.142). После этого мы сможем создать элементы (характеристики) нашего плана видов характеристик с этим типом, а также создать элементы справочника Свойства Гаражей, подчинённые нужной характеристике.
Рис. 4.1.141
Рис. 4.1. 142
Но это ещё не всё, в плане видов характеристик нужно указать, что значения характеристик хранятся именно в справочнике Свойства гаражей. Указывается это в свойстве Дополнительные значения характеристик на закладке Основные.
Рис. 4.1.143
В это свойство нужно выбрать название справочника, который подчинён нашему плану видов характеристик и в котором будут храниться значения характеристик.
И последний шаг: свяжем воедино гараж, дополнительные свойства гаража (характеристики) и значение этих свойств (значения характеристик). Когда мы создадим какие-то свойства гаражей, их значения, то эти данные и конкретные гаражи будут отдельно.
Мы сделаем это, создав непериодический и независимый регистр сведений, который назовём ЗначениеСвойствГаражей.
Рис. 4.1.144
Нам нужно определить состав измерений и ресурсов. Самое очевидное создать три измерения: Гараж (тип ссылка на справочник Гаражи), Свойство (тип ссылка на план видов характеристик ДополнительныеСвойстваГаражей) и Значение свойства. Но будет ли данный способ правильным? Очевидно, нет, так как возможна запись следующего вида:
Гараж №1 | Тип гаража | Каменный |
Гараж №1 | Тип гаража | Железный |
То есть у одного гаража будет одно свойство с двумя разными значениями, что, согласитесь, неправильно. Поэтому логично создать два измерения, в которых будут указаны гаражи и свойства, и один ресурс, в котором будет указано значение свойства гаража.
Создадим измерения.
Рис. 4.1.145
Рис. 4.1.146
У измерения Гараж установим свойство Ведущее. Создадим ресурс Значение, тип у
которого будет характеристика плана видов характеристик Дополнительные свойства гаражей.
Рис. 4.1.147
В результате в ресурсе Значение будут значения тех характеристик, которые указаны в плане видов характеристик Дополнительные свойства гаражей.
Пока остановимся на этом. Сохраним конфигурацию, обновим базу данных и откроем план видов характеристик Дополнительные свойства гаражей, используя меню Функции для технического специалиста.
Создадим первую характеристику Длина, тип которой будет Число.
Рис. 4.1.148
Самостоятельно точно так же создайте характеристику Ширина, тип которой так же будет Число.
Создадим характеристику Расположение, тип значения которого будет ссылка на справочник Свойства гаражей.
Рис. 4.1.149
Зададим значения у этого свойства, для этого перейдём в подчинённый справочник Свойства гаражей, нажав на гиперссылку Свойства гаражей формы элемента плана видов характеристик, в котором создадим несколько значений этого свойства.
Рис. 4.1.150
Аналогично создадим характеристику Вид гаража с типом ссылка на справочник Свойства гаражей и с некоторыми значениями.
Все нужные на данный момент свойства гаражей созданы, должен получиться следующий список плана видов характеристик:
Рис. 4.1.152
Попробуем при помощи регистра Значение свойств гаражей привязать какую-нибудь характеристику и её значение к определённому гаражу. Открывать сам регистр не нужно, достаточно открыть нужный элемент справочника Гаражи и выполнить команду в виде гиперссылки Значение свойств гаражей, которая расположена вверху формы элемента.
Рис. 4.1.153
Создадим новую запись регистра, в которой выберем свойство Вид гаража.
Попробуем выбрать значение для этого свойства. Нам сразу будет предложено выбрать тип данных. Что несколько неудобно, согласитесь.
Рис. 4.1.155
Если мы выберем тип Свойства гаражей, то будут предложены значения всех свойств, что тоже очень неудобно.
Рис. 4.1.156
Приведём выбор значения в нормальный вид. Для этого вернёмся в конфигуратор и откроем палитру свойств ресурса Значение регистра сведений Значение свойств гаражей.
В этой палитре нас интересуют два поля – Связь по типу и Связи параметров выбора (рис. 4.1.157). В свойстве Связь по типу необходимо указать измерение, которое будет определять тип значения нашего ресурса. В нашем случае это будет измерение Свойство (см. рис. 4.1.158).
Рис. 4.1.157
Рис. 4.1.158
При помощи свойства Связи параметров выбора настраивается зависимость одних реквизитов от других (в нашем случае – зависимость ресурса от измерения). В открывшейся форме связи нужно выбрать реквизит Свойство. И если Вы всё правильно сделали, то в форме связи должна появиться строка, как на рис. 4.1.159.
Рис. 4.1.159
Так мы настроили отбор по владельцу, и при выборе элементов справочника Свойства гаражей будут выходить только те элементы, владелец у которых указан в измерении Свойство текущей строки регистра. Сохраним конфигурацию, обновим базу данных и попробуем задать пару характеристик для справочника Гаражи.
Рис. 4.1.160
Рис. 4.1.161
Обработки
Обработки
С Обработками Вы уже знакомы. В предыдущих главах мы работали с внешними обработками, но могут быть и обработки в составе конфигурации.
Рис. 4.1.162
Можно создать как внешнюю обработку, так и обработку, встроенную в конфигурацию. У обработок также могут быть реквизиты и табличные части. Создадим
простую обработку в конфигурации, просто для примера, назовём её РасчетРасходаТоплива, на форме этой обработки сделаем простой расчёт потенциального расхода топлива на заданный пробег (например, расход по документам 10 литров на 100 км, проехал 1000 км, плановый – 100 литров).
Для создания новой обработки выделим ветку Обработки дерева конфигурации, вызовем правой клавишей мышки контекстное меню и выполним команду Добавить.
Откроется редактор обработки, в котором укажем имя – РасчетРасходаТоплива.
Рис. 4.1.163
На закладке Формы создадим основную форму обработки.
Рис. 4.1.164
Откроется конструктор формы обработки, в котором оставим всё как есть и нажмём кнопку Готово.
Откроется редактор формы обработки, на этой форме мы создадим три реквизита – ПлановыйРасход (заголовок Плановый расход, л/100 км, см. рис. 4.166), Пробег (заголовок – Пробег, км) и РасходПоПробегу (заголовок – Расход по пробегу, л). У первых двух реквизитов тип будет Число(10,0), у последнего – тип Число(10,2). Все эти реквизиты поместим на форму (если Вы забыли, как это делается – просто реквизит «перетаскиваем» в левое верхнее окно в корень дерева Форма).
Рис. 4.1.166
Рис. 4.1.167
Создадим команду формы Посчитать, которую также поместим на форму.
Создадим обработчик команды Посчитать на клиенте.
Рис. 4.1.169
И в обработчике команды подсчитаем расход по пробегу.
&НаКлиенте
Процедура Посчитать(Команда)
РасходПоПробегу = Пробег * ПлановыйРасход /100; КонецПроцедуры
Листинг 4.1.1
Сохраним конфигурацию, обновим базу данных и запустим «1С: Предприятие» в пользовательском режиме.
Созданную обработку мы сможем открыть, используя меню Сервис.
Рис. 4.1.170
И в этой обработке мы сможем посчитать плановый расход по нужному пробегу.
Рис. 4.1.171
Из любой обработки можно сделать внешнюю: в конфигураторе следует выделить нужную обработку, вызвать правой клавишей мышки контекстное меню и выполнить команду этого меню Сохранить как внешнюю обработку, отчет…
Рис. 4.1.172
Откроется окно Сохранение, в котором можно изменить имя внешней обработки и выбрать каталог, куда она будет сохранена.
Рис. 4.1.173
В обработки конфигурации можно добавить какую-нибудь внешнюю обработку. Для этого, нужно выделить ветку Обработки дерева метаданных, вызвать контекстное меню и
выполнить команду Вставить внешнюю обработку, отчет…
Рис. 4.1.174
Откроется окно Открытие, в котором нужно выбрать файл внешней обработки.
Отчёты
Отчёты необходимы для анализа информации о деятельности предприятия. Более подробно отчёты Вы будете изучать в 11-й главе. Пока заметим, что отчёты могут быть сами по себе (внешние отчёты), а могут и входить в состав конфигурации.
(3) 4.31 Основные метаданные ветки «Общие». Параметры сеанса - что это?
Метаданные ветки Общие
Разберём основные метаданные ветки Общие дерева конфигурации, которые пригодятся в первоначальной работе.
Параметры сеанса
Параметры сеанса – это переменные, которые доступны в течение всего сеанса пользователя в любом месте конфигурации. Например, в параметрах сеанса можно хранить текущего пользователя или имя компьютера.
Создадим параметр сеанса, который назовём ИмяТекущегоКомпьютера. Для этого выделим ветку Параметры сеанса и в контекстном меню выполним команду Добавить.
Рис. 4.1.175
В правой части экрана откроется палитра свойств параметра сеанса, где введём название, синоним и тип (Строка (50)), если у Вас очень длинное имя компьютера, то увеличьте длину строки).
Рис. 4.1.176
Определяются параметры сеанса в модуле сеанса, который мы будем проходить ниже (часть вторая текущей главы, стр. 279), тогда же и научимся определять имя текущего компьютера.
Определяемые типы
Кроме примитивных и ссылочных типов (ссылочные типы будем проходить в шестой главе), в конфигураторе 1С можно задать предопределяемый тип. Например, у нас много где встречается такой реквизит как цена, который имеет всегда тип Число (длина 10, точность 2). Чтобы никогда не задумываться о параметрах числа для реквизитов, в которых будут храниться цены, можно создать предопределённый тип, который назовём, как вариант, ТипДляЦен. И этот тип можно использовать во всех подобных реквизитах.
Создадим такой тип: выделим ветку Определяемые типы и выполним команду
Добавить.
Рис. 4.1.177
В правой части откроется палитра свойств определяемого типа, где мы зададим такие параметры как Имя, Синоним и Тип определяемого типа.
Рис. 4.1.178
После мы можем у всех реквизитов конфигурации, в которых хранятся какие-либо цены, поменять тип. Для этого следует открыть палитру свойств нужного реквизита, в палитре нажать на кнопку «…» у свойства Тип, и выбрать созданный определяемый тип из папки Определяемый Тип окна редактирования типа данных.
Рис. 4.1.179
Ещё у нас остался ресурс Цена регистра сведений ЦеныНаТопливо, поменяйте тип у этого ресурса самостоятельно.
Общие реквизиты
В процессе разработки конфигурации могут возникать ситуации, когда у ряда объектов может быть одинаковый реквизит. Например, реквизит Комментарий или Ответственный у документов. В платформе 8.3 есть возможность создать несколько общих реквизитов, которые разработчик может использовать в том или ином объекте на своё усмотрение.
Создадим общий реквизит Комментарий, который будем использовать во всех документах (только документах). Для создания общего реквизита выделим ветку Общие реквизиты, вызовем контекстное меню и выполним команду Добавить.
Рис. 4.1.180
После добавления общего реквизита справа откроется палитра свойств этого реквизита, где укажем имя, синоним и зададим тип (Строка(1000)).
Рис. 4.1.181
Применение реквизита в объектах указывается в категории Использование палитры свойств реквизита. В этой категории нас интересуют два свойства – Состав и Автоиспользование. Разберёмся со свойством Автоиспользование. Именно при помощи этого свойства мы определяем, как будет использоваться общий реквизит по умолчанию. Если установлено значение Использовать, то значит, что реквизит используется везде, и нужно задать объекты, в которых не нужно использовать этот реквизит (при помощи свойства Состав). Если же установлено значение Не использовать, то наоборот – реквизит по умолчанию нигде не используется, и нужно задать объекты, где мы будем использовать этот реквизит (при помощи того же свойства Состав).
Рис. 4.1.182
По умолчанию устанавливается значение Не использовать. Мы так и оставим значение этого реквизита по умолчанию и зададим состав объектов, в которых будет использоваться общий реквизит. Для этого нужно нажать на гиперссылку Открыть свойства Состав, откроется окно состава общих реквизитов, где в верхней части расположено дерево объектов метаданных, к которым можно применить общий реквизит, а в нижней – метаданные, к которым общий реквизит применён.
Рис. 4.1.183
Чтобы общий реквизит использовался в нужном объекте, необходимо в верхней части окна в колонке Использование, установить Использовать напротив нужного объекта. После этого объект отобразится в нижней части окна.
Если мы настроим состав для общего реквизит Комментарий, как на картинке выше, и откроем любой документ, к которому применили общий реквизит, то увидим этот реквизит на форме документа.
Рис. 4.1.184
Роли
При конфигурировании какого-либо программного решения могут возникнуть задачи разграничения прав ряда пользователей. Например, у каких-то пользователей может быть право на создание, проведение и удаление документов Прибытие в гараж и Выбытие из гаража, а у каких-то нет. Данное разграничение прав в конфигурации 1С выполняется при помощи ролей.
В нашей конфигурации создадим три роли: ПолныеПрава, Диспетчер, УчетчикТоплива.
У роли ПолныеПрава, как ясно из названия, будет полный набор прав на все метаданные. Запомните! Роль с полными правами всегда обязательна в конфигурации. У ролей Диспетчер и Учетчик топлива будет следующий набор прав:
Роль | Объект метаданных | Права |
Диспетчер | Справочники: | |
Марки автомобилей Модели автомобилей Опции Автомобили Гаражи Свойства гаражей | Полные | |
Тип топлива Контрагенты | Чтение, просмотр | |
Документы | ||
Прибытие в гараж Выбытие из гаража | Полные | |
Заправка топлива Отчет о расходе топлива Установка цен на топливо | Чтение, просмотр | |
Журналы документов | ||
Прибытие-выбытие автомобилей | Чтение, просмотр | |
ПВХ |
Дополнительные свойства гаражей | Полные | |
Регистры сведений | ||
Основной гараж автомобиля Значение свойств гаражей | Полные | |
Цены на топливо | Чтение, просмотр | |
Регистры накопления | ||
Пробег автомобиля | Полные | |
Топливо в автомобилях | Чтение, просмотр | |
Константы | ||
Все константы | Чтение, просмотр | |
Ветка Общие | ||
Параметры сеанса | Получение, установка | |
Общие реквизиты | Просмотр, редактирование | |
Форма констант | Просмотр | |
Учётчик топлива | Справочники: | |
Марки автомобилей Модели автомобилей Опции Автомобили Гаражи Свойства гаражей | Чтение, просмотр | |
Тип топлива Контрагенты | Полные | |
Документы | ||
Прибытие в гараж Выбытие из гаража | Чтение, просмотр | |
Заправка топлива Отчёт о расходе топлива Установка цен на топливо | Полные | |
Журналы документов | ||
Прибытие-выбытие автомобилей | Чтение, просмотр | |
ПВХ | ||
Дополнительные свойства гаражей | Чтение, просмотр | |
Регистры сведений | ||
Основной гараж автомобиля Значение свойств гаражей | Чтение, просмотр | |
Цены на топлива | Полные | |
Регистры накопления | ||
Пробег автомобиля | Чтение, просмотр | |
Топливо в автомобилях | Полные | |
Константы | ||
Все константы | Чтение, просмотр | |
Ветка Общие | ||
Параметры сеанса | Получение, установка | |
Общие реквизиты | Просмотр, редактирование | |
Форма констант | Просмотр |
Табл. 4.1.2
Первым делом создадим роль с полными правами. Для создания роли нужно выделить ветку Роли», вызвать контекстноем меню, в котором выполнить команду Добавить.
Рис. 4.1.185
Роль будет создана, и сразу же откроется палитра свойств роли и редактор прав.
Рис. 4.1.186
Назовём новую роль ПолныеПрава (свойство Имя). Для того чтобы установить у этой роли права на все объекты, воспользуемся меню Действия редактора прав, в котором выполним команду Установить все права.
Рис. 4.1.187
Также для полных прав рекомендуется установить флаг Устанавливать права для новых объектов, чтобы при создании нового объекта метаданных роли Полные права добавлялись все права на этот объект.
Рис. 4.1.188
Всё! Роль с полными правами создана. Создадим пользователя с полными правами. Но перед этим необходимо обновить конфигурацию базы данных, потому что пользователь создаётся в базе данных и новую роль Полные права необходимо «загрузить» в конфигурацию базы данных.
Для создания пользователя базы данных в конфигураторе нужно войти в список пользователей. Список пользователей в конфигураторе доступен по следующему пути: Главное меню – Администрирование – Пользователи.
Рис. 4.1.189
В открывшемся списке следует нажать на кнопку Добавить, после этого откроется окно добавления нового пользователя.
Рис. 4.1.190
Введём имя Администратор, все остальное оставим как есть и перейдём на закладку
Прочее.
Рис. 4.1.191
На этой закладке нас интересует список Доступные роли. Пока в нём только одна роль
– Полные права. Поставим у этой роли флаг и нажмём кнопку ОК – пользователь создан. С этого момента, когда Вы будете входить в «1С: Предприятие» (без разницы, в пользовательский режим, или в конфигуратор), платформа потребует выбрать пользователя. Пока у нас только один пользователь – Администратор.
Рис. 4.1.192
Создадим ещё одну роль, новой роли дадим название Диспетчер, и в открывшемся конструкторе прав установим права Толстый клиент, Интерактивное открытие внешних обработок и Интерактивное открытие внешних отчётов у конфигурации, остальной набор прав для конфигурации оставим как есть.
Рис. 4.1.193
Следующим шагом необходимо для ряда объектов установить полные права (см. табл.
, стр. 240), а для ряда – урезанные: только для чтения и просмотра.
В рамках этой книги мы не будем подробно разбирать смысл того или иного права, изучим только общие моменты.
Установим у роли Диспетчер для справочника Марки автомобилей полные права (кроме интерактивного удаления). Чтобы это сделать, следует найти нужный справочник в дереве конфигурации редактора роли.
Рис. 4.1.194
Найдём справочник МаркиАвтомобилей и установим у этого справочника флажки всех прав, кроме права Интерактивное удаление и Интерактивное удаление предопределённых.
Право Интерактивное удаление даёт пользователю возможность удалить объект непосредственно без контроля ссылочной целостности, что не всегда корректно. Подробно удаление объектов будем изучать в шестой главе.
Для быстрой отметки воспользуемся кнопкой Пометить все элементы, а отметки прав Интерактивное удаление и Интерактивное удаление предопределённых снимем вручную. Должен получиться следующий набор прав:
Рис. 4.1.195
Для документа Прибытие в гараж полный набор прав будет выглядеть следующим образом:
Рис. 4.1.196
А для справочника Типы топлива дадим права только на чтение и просмотр, в этом случае будет следующий набор прав:
Рис. 4.1.197
Самостоятельно установите права на объекты согласно таблице 4.1.2 для роли Диспетчер, потом создайте роль УчетчикТоплива (не забудьте поставить право конфигурации Толстый клиент) и также самостоятельно установите права для этой роли согласно всё той же таблице 4.1.2. Для новых прав создайте пользователей Диспетчер и Учётчик с соответствующими наборами ролей. Проверьте доступ к объектам из таблицы 4.1.2.
Общие картинки
Научимся добавлять в конфигурацию 1С общие картинки, которые потом можно использовать в декорациях или при создании подсистем.
Для добавления общей картинки следует выделить подветку Общие картинки ветки
Общие, вызвать контекстное меню и в этом меню выполнить команду Добавить.
Рис. 4.1.198
Откроется редактор общей картинки, в котором можно внести название картинки, а также выбрать произвольную картинку из файловой системы, нажав на кнопку Выбрать из файла (см. рис. 4.1.199).
Рис. 4.1. 199
После выбора картинка появится в редакторе.
Рис. 4.1.200
И соответствующий пункт появится в ветке Общие картинки.
Рис. 4.1.201
Добавим ещё две картинки.
Рис. 4.1.202
В дальнейшем эти картинки будем использовать при работе с подсистемами.
Подсистемы
В конце этой части мы изучим Подсистемы. Как Вы заметили, работать со справочниками, документами и прочими объектам конфигурации, которые свалены в меню функций текущего раздела, не совсем удобно. Логичнее все объекты разбить по каким-то разделам. Сделать это можно при помощи объекта Подсистемы. Очень подробно работа с этим объектом даётся в моей книге «Основы разработки в 1С: Такси. Разработка в управляемом приложении за 12 шагов». Здесь же мы коснёмся только самых общих моментов, необходимых для дальнейшей работы.
Прежде чем начать создавать подсистемы, определим, сколько их будет, как они будут называться и какие объекты войдут в их состав. Логично конструировать подсистемы по прикладным областям. В нашей конфигурации можно сделать три подсистемы: Учёт автомобилей, Учёт топлива и НСИ (нормативно-справочная информация). Обратите внимание, подсистемы Учёт автомобилей и Учёт топлива по своей сути соответствуют ролям Диспетчер и Учётчик топлива. Распределим объекты конфигурации по подсистемам следующим образом (по аналогии с ролями):
Подсистема | Объект конфигурации |
Учёт автомобилей | Справочники: Марки автомобилей Модели автомобилей Опции Автомобиль Гаражи Свойства гаражей Документы: Прибытие в гараж Выбытие из гаража Журнал: Прибытие-выбытие автомобилей Планы видов характеристик: Дополнительные свойства гаражей Регистры сведений: Основной гараж автомобиля Значение свойств гаражей Регистры накопления: Пробег автомобиля |
Учёт топлива | Справочники: Тип топлива Контрагенты Документы: Заправка топлива Отчёт о расходе топлива Установка цен на топливо Регистры сведений: |
Цены на топливо Регистры накопления: Топливо в автомобилях | |
НСИ | Справочники: Марки автомобилей Модели автомобилей Опции Автомобиль Гаражи Свойства гаражей Тип топлива Контрагенты Планы видов характеристик: Дополнительные свойства гаражей Регистры сведений: Основной гараж автомобиля Значение свойств гаражей Константы и форма констант, перечисления, общие картинки, параметры сеанса, предопределяемые типы, роли |
Табл. 4.1.3
Как видите, объекты в подсистемах могут пересекаться, то есть один объект метаданных может быть в нескольких подсистемах. Создадим первую подсистему Учёт автомобилей. Для этого в дереве метаданных конфигурации в ветке Общие выделим ветку Подсистемы, вызовем правой кнопкой контекстное меню, в котором выполним команду Добавить.
Рис. 4.1.203
Откроется редактор подсистемы, в котором введём название и, самое главное, оставим включённым флаг Включать в командный интерфейс.
Рис. 4.1.204
Если этот флаг включен, то подсистема будет отображена в виде закладки в пользовательском режиме «1С: Предприятия».
Следующим шагом нужно привязать объекты из таблицы выше к подсистеме. Для этого в редакторе подсистемы перейдём на закладку Состав и в верхнем окне поставим флажки рядом с теми объектами, которые будут в подсистеме (в нижнем окне они отобразятся автоматически).
Рис. 4.1.205
И установим общую картинку в подсистему.
Рис. 4.1.206
Самостоятельно создайте остальные подсистемы и настройте их состав согласно таблице выше.
Небольшое дополнение. Если вы у роли ПолныеПрава по какой-то причине забыли установить флаг Устанавливать права для новых объектов (см. рис. 4.1.188, стр. 242), то права на просмотр подсистем не будут установлены. Их в этом случае нужно поставить вручную.
Последний шаг: обязательно проверьте у роли Полные права, установилось ли у всех новых подсистем право на просмотр для этой роли, иначе зайдя под Администратором, Вы не увидите закладок, которые привязаны к подсистемам.
Рис. 4.1.207
После сохранения конфигурации, обновления базы данных и запуска пользовательского режима интерфейс должен предстать в таком виде.
Рис. 4.1.208
Если мы хотим изменить внешний вид рабочего стола в пользовательском режиме, то нужно воспользоваться свойствами конфигурации Интерфейс клиентского приложения (см. рис. 4.1.209). Это свойство позволяет нам разместить панели на рабочем столе в клиентском режиме как нам удобно. В этой книге не будем подробно разбираться с настройками пользовательского интерфейса, просто сделаем так, чтобы панель с разделами была слева, а панель открытых – снизу.
Рис. 4.1.209
Откроем палитру свойств конфигурации (для этого нужно выделить родитель дерева конфигурации, вызвать контекстное меню и в этом меню выполнить команду Свойства). В открывшейся палитре нажмём на гиперссылку Открыть свойства Интерфейс клиентского приложения, в результате откроется окно Интерфейс клиентского приложения.
Рис. 4.1.210
В этом окне справа показаны все панели, которые имеются, а слева – все их возможные расположения относительно рабочего стола. Разместим панель разделов слева, а панель открытых – снизу. Панель функций текущего раздела уберём.
Рис. 4.1.211
Если после этих настроек мы сохраним конфигурацию и обновим базу данных, то рабочий стол в пользовательском режиме будет следующего вида:
Рис. 4.1.212
Что такое команда? какие группы команд бывают?
Узнаем, что такое команды и какие виды команд бывают.
Более подробно вопросы работы с командами в целом и командами формы разбираются во второй части книги «Основы разработки в 1С: Такси».
Что такое команда? Команда в понятиях платформы 1С – это объект, с помощью которого пользователь может выполнять какие-либо действия.
чем отличаются глобальные и локальные команды?
Все команды можно разделить на две большие группы: глобальные команды и локальные команды формы. Глобальные команды предназначены для работы с приложением в целом. А локальные команды формы действуют только в контексте конкретной формы.
Например, команда открытия формы списка справочника или документа – это глобальная команда, её можно выполнять практически из любого места конфигурации. А команда, которая обрабатывает нажатие на кнопку Закрыть формы документа, – это локальная команда. Она действует только в контексте определённой формы.
В текущей части четвёртой главы мы изучим глобальные команды. Их можно разделить на общие команды и подчинённые.
Общие команды расположены в ветке Общие команды дерева метаданных. Это могут быть команды, не относящиеся к каким-то определённым объектам, или команды, которые относятся сразу к нескольким объектам
Рис. 4.1.213
А подчинённые команды расположены в ветке Команды того объекта, которому они подчинены. Эти команды нужны для выполнения действий, связанных с объектом, которому они подчинены.
Рис. 4.1.214
какие виды глобальных команд?
Глобальные команды разделяются на два вида: навигационные команды и команды действия.
Навигационные команды – это команды, необходимые для перемещения по приложению. В навигационные команды входят команды открытия списков документов, справочников и журналов документов.
Команды действия – побуждают пользователя совершить какое-то новое действие. Создать новый документ или справочник, открыть уже созданный документ, открыть форму
отчёта или запустить обработку.
Как определить или как установить, что какая-то команда – это команда навигации, а какая-то команда – это комнада действия. За это отвечает свойство команды Группа. Чтобы разобраться с этим свойством, создадим общую команду, которую назовём Общий журнал (это будет «муляж» команды навигации). Для создания общей команды следует выделить ветку Общие команды ветки Общие дерева метаданных, вызвать контекстное меню и выполнить команду Добавить.
Рис. 4.1.215
Команда будет создана. В открывшейся справа палитре свойств в поле Имя напишем название команды ОбщийЖурнал и обратим внимание на свойство Группа. Если мы нажмём на кнопку «…» этого свойства, то откроется окно Группа по умолчанию.
Рис. 4.1.216
В окне Группа по умолчанию перечислены все возможные группы команд. Это группы разделены на четыре больших множества – множество групп панели навигации, групп панели действий, групп панели навигации формы и групп командной панели формы. С панелью навигации формы и с командной панелью формы мы разберёмся в следующей главе, когда будем изучать формы, а в этой главе познакомимся с группами панели навигации и панели действий. Если выбрана группа панели навигации (название группы начинается на Панель
навигации.), то общая команда будет командой навигации. Если же выбрана группа панели действий (название группы начинается на Панель действий.), то общая команда будет командой действий.
Мы назвали команду Общий журнал, и это должна быть команда навигации. Чтобы она стала командой навигации – нужно выбрать или группу Панель навигации.Важное, или Панель навигации.Обычное, или Панели навигации.См. также. От того какую мы группу панели навигации выберем, будет зависеть её видимость в командном интерфейсе подсистемы, которой принадлежит команда. Выберем группу Панель навигации.Важное.
Рис. 4.1.217
Ещё нам нужно указать подсистему команды. От этого будет зависеть, в какой раздел интерфейса она попадёт. Укажем подсистему Учёт автомобилей. Для того чтобы указать, что команда относится к подсистеме Учёт автомобилей, можно воспользоваться редактором подсистемы, или окном Дополнительно. Воспользуемся окном Дополнительно. Для этого выделим команду в дереве метаданных, вызовем контекстное меню и выполним команду Дополнительно.
Рис. 4.1.218
Справа откроется окно Дополнительно, в котором интересует закладка Подсистемы, в этой закладке и поставим флаг радом с подсистемой Учёт автомобилей, к которой будет относиться общая команда.
Рис. 4.1.219
И нам осталось описать событие, которое будет срабатывать при выполнении этой команды. Для этого откроем модуль команды.
Рис. 4.1.220
В модуле уже должна быть создана процедура-обработчик команды, удалим в ней закомментированный код и напишем простое сообщение.
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды) Сообщить("Команда в разработке");
КонецПроцедуры
Листинг 4.1.2
Если сейчас мы сохраним конфигурацию, обновим базу данных, то в командном интерфейсе раздела Учёт автомобилей обнаружим нашу команду.
Рис. 4.1.221
При выполнении которой выйдет сообщение:
Рис. 4.1.222
Наша команда выделена жирным, потому что мы указали группу Панель навигации.Важное. Если укажем группу Панель навигации.Обычное, то команда будет в общем списке команд.
Рис. 4.1.223
А если указать группу Панели навигации.См. также, то команда будет в отдельной группе См. также.
Рис. 4.1.224
Если же мы укажем группу из групп панелей действий, то это уже будет команда действий. Например, укажем группу Панель действий.Создать.
Рис. 4.1.225
Теперь это команда действий, которая появится в отдельном меню Создать
командного интерфейса подсистемы.
Рис. 4.1.226
При выборе других групп команда будет расположена в других меню. Для группы Панель действий.Отчеты будет меню Отчеты.
Рис. 4.1.227
А для группы Панель действий.Сервис будет меню Сервис.
Рис. 4.1.228
Мы рассмотрели общие команды, но могут ещё быть подчинённые команды, это команды, которые относятся к какому-то объекту.
Например, у справочника МаркиАвтомобилей можно создать подчинённую ему команду.
Рис. 4.1.229
В результате будет создана подчинённая справочнику команда, а справа откроется палитра свойств, в которой можно указать имя, синоним и, самое главное, задать группу команды.
Рис. 4.1.230
Для подчинённых команд доступен точно такой же список команд, как и для общих.
Подчинённая команда может быть как командной навигации, так и командой действий. Единственное отличие подчинённой команды от общей, что для подчинённой команды нельзя указать подсистему, которой она принадлежит. Если мы откроем окно Дополнительно только что созданной подчинённой команды, то не обнаружим выбор подсистем.
Рис. 4.1.231
Если будет выбрана группа панели навигации или панели действий, то эта команда отобразится в разделе той подсистемы, к которой относится головной объект.
Например, у новой команды справочника Марки автомобилей укажем группу Панель действий.Отчеты.
Рис. 4.1.232
Поскольку справочник Марки автомобилей относится к подсистемам Учет автомобилей и НСИ,
Рис. 4.1.233
то вновь созданная команда и появится в этих подсистемах.
Рис. 4.1.234
Рис. 4.1.235
Команды, которые мы сейчас разобрали – независимые глобальные команды – это команды, необходимые для работы с приложением в целом. Когда нужно открыть какую-то форму списка, напечатать отчёт или запустить обработку, используются независимые глобальные команды.
Кроме независимых команд существуют Параметризуемые глобальные команды – это команды, для выполнения которых нужен какой-то определённый параметр (или несколько). Без этого параметра они выполняться не могут. Например, для печати информации о конкретной марке автомобиля необходимо создать параметризуемую команду.
Создадим команду ПечатьМаркиАвтомобиля, это команда будет подчинена справочнику Марки автомобиля, и группу у неё укажем Командная панель формы.Важное, а в качестве типа параметра команды будет ссылка на справочник Марки автомобиля.
Рис. 4.1.236
В результате, как на форме элемента справочника, так и на форме списка справочника, появится вновь созданная команда.
Рис. 4.1.237
Более подробно работу с подчинёнными командами в разрезе командного интерфейса формы рассмотрим в следующей главе.
На этом мы закончим изучать основы конфигурирования программы 1С. Знаний, которые предоставлены в этой главе, Вам вполне хватит, чтобы окунуться в мир программирования 1С и начать осваивать работу с конфигуратором. В следующей части мы изучим модули.
Во второй части текущей главы мы разберём модуль управляемого приложения, модуль сеанса, общий модуль, модуль объекта, модуль менеджера объекта и модуль формы. Для эффективного закрепления материала выполняйте все примеры, приведённые в листингах.
Прежде чем рассматривать работу модулей, разберём небольшую тему – это локальные и глобальные переменные.
Локальные и глобальные переменные
Рассмотрим такое важное понятие в языке программирования, как локальные и глобальные переменные.
Что такое локальная переменная? Любая переменная, описанная внутри процедуры, функции или общего модуля – это локальная переменная. Как задать переменную (или переменные) внутри процедур и функций, мы знаем: либо через ключевое слово Перем, либо сразу присвоив переменной какое-нибудь значение (см. листинг 4.2.1).
Процедура НашаПроцедура() Перем А,Б;
В = 10;
Г = "Привет, мир!" КонецПроцедуры
Листинг 4.2.1
В листинге 4.2.1 переменные А и Б заданы явным способом, а В и Г – через значение.
Локальные переменные создаются при использовании процедуры или функции, где они созданы, и уничтожаются, когда процедура или функция заканчивают свою работу. С локальными переменными можно работать только в рамках процедуры, функции, где они созданы, как следствие, мы не сможем к переменным, созданным в одной процедуре, обратиться из другой процедуры.
Что такое глобальные переменные? Для того чтобы ответить на этот вопрос, рассмотрим пример в рамках модуля формы. Для этого создадим новую обработку и форму этой обработки, и в самом верху модуля формы напишем слово Перем и перечислим переменные через запятую, а в конце напишем точку с запятой. Это и будут глобальные переменные!
Так же, как и в случае процедур или функций, в модуле формы управляемого приложения перед переменными следует указывать директивы компиляции &НаКлиенте или
&НаСервере. В этой части все переменные и методы в модуле формы будут выполняться в клиентском контексте под директивой &НаКлиенте.
Директивы компиляции будем изучать в пятой главе.
В коде на листинге 4.2.1 переменные А,Б,В – заданы локально, а переменные А0,Б0,В0
– глобально.
&НаКлиенте Перем А0, Б0; &НаКлиенте Перем В0;
&НаКлиенте
Процедура НашаПроцедура() Перем А,Б;
В = 100;
КонецПроцедуры
Листинг 4.2.2 После того как мы задали глобальные переменные в начале модуля, мы можем
обращаться к ним в любой процедуре или функции модуля. Для демонстрации реализуем
пример с листинга 4.2.3, создадим команду формы Выполнить команду и обработчик команды в модуле формы.
&НаКлиенте Перем А, Б;
&НаКлиенте
Процедура ИзменитьЗначенияПеременных() А = А + 100;
Б = А;
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) Сообщить("А = " + А); Сообщить("Б = " + Б); ИзменитьЗначенияПеременных(); Сообщить("А = " + А); Сообщить("Б = " + Б);
КонецПроцедуры
А = 10;
Б = -100;
Листинг 4.2.3
Разберём код из листинга 4.2.3. В начале модуля мы задаём переменные А и Б, а в конце модуля присваиваем им значения. Почему значения присваиваются в конце модуля? Потому что процедуры и функции должны описываться непосредственно перед кодом, который пишется в самом модуле. Да, в модуле формы мы можем написать почти любой код, и этот код выполнится во время открытия формы.
После мы создаём процедуру ИзменитьЗначенияПеременных, в которой манипулируем с глобальными переменными. И в обработчике команды ВыполнитьКоманду работаем с нашими глобальными переменными.
Рис. 4.2.1
Сначала переменные А и Б были такими, какими мы задали их в конце модуля, но после выполнения процедуры ИзменитьЗначенияПеременных они изменились.
А что будет, если имея глобальную переменную, внутри процедуры или функции задать локальную переменную с таким же именем?
Выполним пример из листинга 4.2.4, и мы увидим, что как А была равна 1, так и осталась. Потому что, задав явно переменную внутри процедуры, мы создали локальную переменную, пусть с тем же названием, но абсолютно другую. Как только процедура выполнилась, данная локальная переменная уничтожилась.
Задание локальных переменных работает только в том случае, если её задали именно явно, через ключевое слово Перем.
&НаКлиенте Перем А;
&НаКлиенте
Процедура ВыполнитьКоманду(Команда) Сообщить("А = " + А); ИзменитьПеременную(); Сообщить("А = " + А);
КонецПроцедуры
&НаКлиенте
Процедура ИзменитьПеременную() Перем А;
А = 10000;
КонецПроцедуры А = 1;
Листинг 4.2.4
Рис. 4.2.2
Модули
Перейдём к модулям.
Что такое модуль? По-простому, модуль – это непосредственно та среда, в которой программист пишет свои алгоритмы, процедуры и функции. Но особенность платформы 1С в том, что модуль это не только текстовый редактор, по сути, это программа на языке программирования 1С. И в зависимости от того, в каком модуле Вы опишете тот или иной метод, он будет выполняться в том или ином контексте.
К примеру, процедуры, написанные в модуле формы, будут работать только тогда, когда открыта или создана (это не одно и то же) форма, где они написаны. Вы не сможете обратиться к процедурам формы элемента справочника, если обратитесь к справочнику как к объекту.
Поэтому разрабатывая или дорабатывая программное обеспечение, Вы должны чётко понимать, на каком уровне будут написаны ваши алгоритмы. А какие есть уровни, мы выясним в этой части главы.
Каждый программный модуль связан с остальными объектами конфигурации, эта связь называется контекстом. Всего существует два вида контекста: глобальный и локальный. Глобальный контекст виден для всех, он, по сути, создаёт общую среду работы программы. Локальный контекст действует только в рамках объекта.
Если мы создадим процедуру в рамках глобального контекста и назовем её, к примеру,
РасчетСебестоимости:
РасчетСебестоимости()
то в любом месте программы мы сможем использовать эту процедуру, и она без проблем выполнится.
А если мы создадим процедуру, назовём её РассчитатьПробег:
РассчитатьПробег()
в модуле объекта справочника Автомобили и сделаем её экспортной (с экспортом процедур и функций мы разберёмся позже), то обратиться к ней мы сможем только посредством объекта справочника Автомобили:
ОбъектСправочника = СправочникАвтомобилиСсылка.ПолучитьОбъект(); ОбъектСправочника. РассчитатьПробег();
Изучим виды модулей. Их много, мы изучим основные, которые чаще всего необходимы в работе.
Начнём с самого низкого уровня – уровень формы.
Модуль формы
Модуль формы должен содержать те процедуры и функции, которые необходимы только для работы этой формы. В управляемом приложении процедуры или функции модуля формы выполняются или в серверном контексте, или в клиентском контексте. Смысл клиентского и серверного контекста будем проходить в следующей главе.
В модуле формы можно создавать и описывать обработчики событий элементов формы и самой формы, а также обработчики событий команд формы. Код в описанных обработчиках событий будет выполняться тогда, когда будет выполнена команда, к которой привязан обработчик события, или когда с элементом формы (самой формой) произойдёт событие, с которым связан обработчик.
С модулем формы мы работали с самого начала курса, и Вы знаете, что попасть в модуль формы легко, для этого достаточно открыть форму и перейти в закладку Модуль.
Рис. 4.2.3
А чтобы увидеть список всех процедур и функций модуля формы, необходимо поставить курсор в модуле формы (в любое место) и выполнить команду Процедуры и функции в меню Текст (Главное меню – Текст).
Рис. 4.2.4
В результате выполнения команды откроется список процедур и функций, которые имеются в модуле формы (это справедливо и для других модулей тоже). Причём в этом списке также присутствуют обработчики событий формы, которые не созданы (выделены треугольными скобками – < >). У созданных процедур и функций слева в списке отображается соответствующий значок.
Рис. 4.2.5
Более подробно работу с формами мы будем проходить в пятой главе.
Модуль объекта
Модуль объекта предназначен для описания процедур и функций, которые необходимы для работы экземпляра объекта конфигурации. Это может быть элемент справочника, или какой-то документ.
Поскольку создать экземпляр справочника, документа можно не только интерактивно, но и программно, то данный модуль призван описать те события, процедуры и функции, которые должны выполняться именно на уровне экземпляра объекта, без разницы, как он создан: программно или интерактивно пользователем.
Кроме того, в модуле объекта можно создавать и описывать обработчики событий, которые возникают при работе с экземпляром объекта. Например, это может быть обработка события записи экземпляра объекта или обработка события проведения экземпляра объекта (для документов).
Подробно обработчики событий объекта будем проходить в шестой главе. Пока же запомним, что все методы (процедуры и функции) модуля объекта можно разделить на две группы: это типовые обработчики различных событий объекта и просто процедуры (функции), созданные разработчиками для осуществления каких-либо действий над экземпляром объекта (например, пересчёт всех цен в табличной части после изменения типа цен в шапке документа).
Это что касается документов и справочников. Когда же Вы работаете с обработками или отчётами, в модуле обработки и отчёта должны быть описаны те процедуры и функции, к которым понадобится доступ тогда, когда Вы программно обратитесь к этому отчёту или обработке.
Как попасть в модуль объекта? Для элементов конфигурации это достаточно просто: в дереве метаданных выделяем интересующий нас объект, кликнем правой кнопкой мышки и в контекстном меню выполняем команду Открыть модуль объекта.
Рис. 4.2.6
В случае внешних отчётов и обработок: находясь непосредственно в менеджере обработки, необходимо нажать на кнопку Действия и в открывшемся меню выполнить команду Открыть модуль объекта.
Рис. 4.2.7
Для того чтобы посмотреть на полный список процедур и функций, которые описаны в модуле объекта, следует установить курсор в область модуля, и выполнить команду Процедуры и функции в меню Текст.
Рис. 4.2.8
Откроется окно Процедуры и функции.
Рис. 4.2.9
В приведённом выше случае процедур и функций никаких нет, потому что мы ничего не создали, а треугольными скобками (< >) выделяются ещё не созданные обработчики событий объекта.
Если мы создадим какую-то процедуру (или функцию), то она появится в этом списке.
Рис. 4.2.10
Если нужно создать какой-нибудь обработчик события, то просто нужно выбрать обработчик из списка и дважды кликнуть левой клавишей мышки по названию. Тогда будет создана процедура обработчика, и рядом с названием обработчика в списке окна появится соответствующий значок.
Рис. 4.2.11
Модули менеджера объекта
Если в модуле объекта описываются методы, предназначенные для работы с экземпляром объекта (подробно экземпляры объектов разберём в шестой главе), то в модуле менеджера объекта описываются методы, которые не привязаны к экземпляру объекта, но привязаны к объекту в целом.
Например, мы можем написать обработку печати товарной накладной документа в модуле объекта, и тогда для печати документа нам нужно будет каждый раз получать экземпляр этого документа. А можем написать обработку печати в модуле менеджера объекта, сделать её экспортной (об этом в конце этой части), тогда достаточно передать ссылку (или массив ссылок) на распечатываемый документ в процедуру печати.
В случае когда процедура печати в модуле объекта, код для печати будет выглядеть
так:
ОбъектСправочника = СправочникСсылка.ПолучитьОбъект(); ОбъектСправочника.Печать();
А когда процедура печати в модуле менеджера объекта, код будет следующий:
Документы.ВыбытиеИзГаража.Печать(СсылкаНаДокумент);
В первом примере код не совсем корректен: мы получили полный доступ к объекту и можем что-то случайно с ним сделать, как-то изменить его. Получать доступ к объекту нужно только тогда, когда мы с ним действительно желаем что-то сделать, а лишний раз лучше это не делать.
Во втором же случае мы просто передаём ссылку на объект в какую-то процедуру.
Ссылка – это указатель на объект, она позволяет только прочитать данные объекта, но не даёт изменить эти данные. Поэтому использовать ссылку на какой-то объект более корректно, чем получать экземпляр объекта.
Некоторые операции лучше делать, используя менеджер объекта.
Пока не сильно вдавайтесь в объекты, экземпляры и ссылки, подробно все эти вопросы изучим в шестой главе!
Открыть модуль менеджера объекта можно двумя способами. Непосредственно через дерево метаданных (см. рис. 4.2.12), и в редакторе объекта (см. рис. 4.2.13).
Рис. 4.2.12
Рис. 4.2.13
Кроме того, в модуле менеджера можно описывать обработчики некоторых типовых событий, которые могут возникать при работе с менеджером объекта (например, при получении данных выбора).
Общие модули
В общем модуле описываются процедуры и функции, которые будут доступны из любого места конфигурации. В принципе, это основное предназначение общих модулей. Например, если Вам необходимо проверять остатки товаров на складе при проведении документов, которых может быть несколько видов (реализация товаров, списание товаров и т.д.), то процедуру проверки будет практично написать именно в общем модуле, а потом вызывать в обработчике проведения модуля объекта соответствующего документа при проведении.
Все общие модули располагаются в отдельной ветке конфигурации:
Создадим общий модуль. Для этого следует выделить подветку Модули в ветке Общие дерева метаданных конфигурации, нажать правую клавишу мышки и выполнить команду Добавить.
Рис. 4.2.15
Общий модуль будет создан, и сразу же откроется окно палитры свойств, где мы можем назвать его каким-нибудь именем (назовем его Основной) и установить некоторые настройки модуля.
Рис. 4.2.16
Первый флажок, который нас интересует, – это Глобальный. Это значит, что если он установлен, то процедуры и функции в этом модуле будут выполняться в рамках глобального контекста: можно будет просто в любом месте программы написать название функции или процедуры, и она будет выполняться.
Если же этой галочки не будет, то обратиться к процедуре или функции этого модуля можно будет через сам модуль.
Например, если у нас в неглобальном общем модуле имеется экспортная процедура под названием Расчет():
то обратиться к этой процедуре можно только через обращение к этому модулю:
Основной.Расчет();
Если же общий модуль Основной будет глобальный, то обратиться к ней можно напрямую, минуя обращение к общему модулю:
Расчет();
Не рекомендуется использовать глобальные общие модули, поскольку в этом случае требуется контроль уникальности в названиях процедур и функций во всех глобальных модулях. В ином же случае – контроль уникальности в названиях процедур и функций ведётся только в рамках модуля, где эти методы описаны. Вполне возможно такое:
Основной.Расчет(); Дополнительный.Расчет();
К тому же масштабное использование глобальных общих модулей может негативно отобразиться на производительности программы, поскольку все глобальные модули компилируются при старте приложения. В отличие от неглобальных модулей, которые компилируются в момент обращения к процедуре или функции этого модуля.
Флажок Клиент (управляемое приложение) устанавливается в том случае, когда процедуры или функции данного модуля должны быть доступны в клиентском контексте при работе тонкого клиента.
Флажки Сервер и Внешнее соединение устанавливаются в том случае, когда процедуры и функции данного модуля будут доступны в серверном контексте и во внешнем соединении.
Это значит, что если мы не поставим флажок Внешнее соединение, а в результате работы какое-нибудь внешнее соединение (например, обмен) будет использовать процедуру из этого модуля (к примеру, это может быть в случае, если в результате обмена проводятся какие-нибудь документы, где при проведении используется наша функция), то программа выдаст ошибку.
То же самое и с серверным контекстом. Если на стороне сервера будет выполняться процедура из этого модуля, то платформа выдаст ошибку, в случае если нет соответствующего флажка.
Подробно о серверном и клиентском контексте – в пятой главе.
Если мы установим флаг Вызов сервера для серверного общего модуля, то мы сможем методы этого модуля использовать в клиентском контексте управляемой формы. Это значит, что в клиентском контексте (директива компиляции &НаКлиенте) формы (или команды) у нас будет доступен вызов процедур и функций этого общего модуля (без разницы, под толстым клиентом запущена форма или под тонким).
Повторим. Если мы в настройках общего модуля установим только флаг Клиент, то в клиентском контексте управляемой формы мы сможем использовать экспортные процедуры
и функции общего модуля в клиентском контексте (под директивой &НаКлиенте). Если мы в настройках общего модуля установим флаг Сервер, то мы сможем использовать экспортные методы этого модуля только в серверном контексте (под директивами &НаСервере и &НаСервереБезКонтекста). Если же мы в настройках общего модуля установим флаги Сервер и ВызовСервера, то сможем использовать экспортные методы этого модуля и в серверном контексте (под директивами &НаСервере и &НаСервереБезКонтекста), и в клиентском контексте (под директивой &НаКлиенте).
Если у общего модуля установлен флаг Привилегированный, то при выполнении процедур и функций этого общего модуля будут отключены проверки прав пользователей. Данный режим удобно использовать при выполнении каких-то глобальных и масштабных алгоритмов (например, контроль остатков по партиям). Поскольку очень часто при работе глобальных алгоритмов могут использоваться объекты (справочники, регистры сведений и т.д.), на которые у пользователя нет прав, поэтому, чтобы огульно не давать права на все используемые объекты, необходимо использовать режим Привилегированный общего модуля.
И последний параметр общего модуля – повторное использование возвращаемых значений.
Рис. 4.2.18
Для каких целей этот параметр? Иногда бывают ситуации, что в процессе работы платформы 1С в функцию и процедуры могут передаваться несколько раз одинаковые параметры. Например, нам нужно вычислить курс какой-то валюты к рублю, мы это делаем в отдельном для этого предназначенном модуле в какой-то функции, и передаём в неё параметры: дата и ссылка на валюту. Делаем запрос к базе данных и получаем нужное значение. Если нам опять понадобится вычислить курс этой же валюты к рублю за ту же дату, то мы опять передадим дату и ссылку на эту валюту, а потом снова сделаем запрос к базе данных и вычислим курс. И так каждый раз, что, естественно, скажется на производительности приложения. В целях оптимизации производительности можно кэшировать значения функций, то есть при первой передаче параметров будет обращение к базе и вычисление функции, а при последующей передаче параметров возвращаемое значение будет браться из кэша, нет необходимости каждый раз заново вычислять значение.
Чтобы функции общего модуля кэшировались, в параметр Повторное использование возвращаемых значений необходимо установить или значение На время вызова (кэш будет использоваться, пока работает функция, которая вызвала метод общего модуля), или значение На время сеанса (кэш будет использоваться, пока работает пользователь).
И напоследок. У всех общих модулей есть одна особенность – мы не можете задать
глобальные переменные этого модуля.
С общими модулями закончили. Следующий уровень контекста – это модуль сеанса.
Модуль сеанса необходим для установки параметров сеанса. В первой части этой главы мы создали единственный параметр сеанса в нашей конфигурации – Имя текущего компьютера.
Рис. 4.2.19
Научимся устанавливать параметр сеанса при запуске сеанса пользователя. Для этого нужно открыть модуль сеанса. Делается это достаточно просто: выделяется самый верхний узел конфигурации УправлениеАвтотранспортом, вызывается контекстное меню, в котором следует выполнить команду Открыть модуль сеанса.
Рис. 4.2.20
В результате откроется модуль сеанса, в котором нас интересует один-единственный обработчик событий Установка параметров сеанса. Создадим процедуру-обработчик события, для этого после открытия модуля выполним команду Процедуры и функции меню Текст (модуль должен быть активен – установлен курсор).
Рис. 4.2.21
В открывшемся окне выберем единственный обработчик
УстановкаПараметровСеанса и нажмём кнопку Перейти.
Рис. 4.2.22
В результате будет создана процедура УстановкаПараметровСеанса.
Рис. 4.2.23
Напишем в новой процедуре следующий код:
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры) ПараметрыСеанса.ИмяТекущегоКомпьютера = ИмяКомпьютера();
КонецПроцедуры
Листинг 4.2.5
Где ИмяКомпьютера() – функция глобального контекста, которая возвращает сетевое имя текущего компьютера.
А ПараметрыСеанса – коллекция, которая содержит параметры сеанса.
Проверим, как работает установка параметров сеанса. Для этого создадим обработку, форму обработки, команду формы ПолучитьПараметр, а также обработчик команды на клиенте и на сервере.
В обработчиках команды напишем следующий код:
&НаСервере
Процедура ПолучитьПараметрНаСервере() Сообщить(ПараметрыСеанса.ИмяТекущегоКомпьютера);
КонецПроцедуры
&НаКлиенте
Процедура ПолучитьПараметр(Команда) ПолучитьПараметрНаСервере();
КонецПроцедуры
Листинг 4.2.6 Сохраним конфигурацию, обновим базу данных и перезапустим «1С: Предприятие» в
пользовательском режиме. Запустим обработку и посмотрим, как выполнится команда формы
обработки.
Рис. 4.2.24
Модуль приложения
Рассмотрим модули самого верхнего уровня контекста – это модуль управляемого приложения и модуль обычного приложения. В модулях управляемого и обычного приложения располагаются, как правило, процедуры и функции, связанные с началом и окончанием работы программы.
Методы в модуле управляемого приложения срабатывают тогда, когда идёт запуск в режиме управляемого приложения. А методы в модуле обычного приложения отрабатывают
тогда, когда идёт запуск в режиме обычного приложения. В этой книге мы рассматриваем работу управляемого приложения, поэтому будем работать только с модулем управляемого приложения.
Естественно, данный модуль выполняется в рамках глобального контекста, тем самым все процедуры и функции, которые Вы объявите в модуле управляемого приложения, будут доступны из любого места программы, ещё для этого они должны быть экспортными. Как попасть в модуль управляемого приложения? Есть два способа.
Первый. Необходимо выделить название конфигурации на самом верхнем уровне конфигурации, вызвать контекстное меню и выполнить команду Открыть модуль приложения.
Рис. 4.2.25
Второй. Зайти в палитру свойств конфигурации (см. рис. 4.2.26) и нажать на гиперссылку Открыть свойства Модуль приложения (см. рис. 4.2.27).
Рис. 4.2.26
Рис. 4.2.27
Чтобы создать процедуру-обработчик, которая будет выполняться при том или ином событии с программой, необходимо выполнить команду Процедуры и функции в меню Текст, в результате откроется окно Процедуры и функции, в котором будет отображён список процедур модуля приложения.
Рис. 4.2.28
Их много, функции первых четырёх ясны из названия, а обработка внешнего события позволяет перехватить внешнее событие при подключении оборудования. Остальные обработчики событий нам пока неинтересны.
Создадим методы ПередНачаломРаботыСистемы и ПриНачалеРаботыСистемы.
Рис. 4.2.29
Процедура ПередНачаломРаботыСистемы(Отказ)
// Вставить содержимое обработчика.
КонецПроцедуры
Процедура ПриНачалеРаботыСистемы()
// Вставить содержимое обработчика.
КонецПроцедуры
Листинг 4.2.7
Вы видите, что у метода ПередНачаломРаботыСистемы есть параметр Отказ, это значит, что у нас есть возможность отказаться от запуска программы. В этот метод можно ставить различные проверки (например, проверка лицензирования программы).
Метод ПриНачалеРаботыСистемы необходим для выполнения различных действий при запуске программы. Это может быть подключение оборудования или открытие формы рабочего стола.
Точно так же создадим методы ПередЗавершениемРаботыСистемы и
ПриЗавершенииРаботыСистемы:
Процедура ПередЗавершениемРаботыСистемы(Отказ, ТекстПредупреждения)
// Вставить содержимое обработчика.
КонецПроцедуры
Процедура ПриЗавершенииРаботыСистемы()
// Вставить содержимое обработчика.
КонецПроцедуры
Листинг 4.2.8 Метод ПередЗавершениемРаботыСистемы возникает перед завершением работы
управляемого приложения до закрытия главного окна. В этом методе есть параметр Отказ,
который имеет тип Булево. Если данному параметру установить значение Истина, то работа программы не будет завершена.
Метод ПриЗавершенииРаботыСистемы вызывается самым последним. В этом
методе необходимо выполнять действия, которые необходимы при выходе из программы: запись логов и т.п.
Экспорт процедур, функций и переменных
В завершении этой главы мы изучим экспорт процедур и функций. Экспорт рассмотрим на примере общего модуля.
Для изучения создадим общий модуль, который назовём Математические вычисления.
Рис. 4.2.30
Это будет модуль, который работает в серверном контексте с установленным флагом Вызов сервера, для того чтобы методы из этого модуля можно было использовать в клиентском контексте формы. А также включим кэширование (параметр Повторное использование).
Напишем в общем модуле функцию, которая вычисляет квадратный корень модуля какого-нибудь числа.
Функция КореньМодуляЧисла(ЧислоПодКоронем)
МодульЧисла = ?(ЧислоПодКоронем >= 0, ЧислоПодКоронем,ЧислоПодКоронем*(-1)); Возврат Sqrt(МодульЧисла);
КонецФункции
Листинг 4.2.9
Естественно, возникнет вопрос: а что если нужно будет обратиться к этой функции на какой-либо форме или в любом другом месте? Для этого следует сделать функцию экспортной. Осуществляется это посредством написания слова Экспорт после параметров, функция должна стать такой:
Функция КореньМодуляЧисла(ЧислоПодКоронем) Экспорт
МодульЧисла = ?(ЧислоПодКоронем >= 0, ЧислоПодКоронем,ЧислоПодКоронем*(-1)); Возврат Sqrt(МодульЧисла);
КонецФункции
Листинг 4.2.10 Создадим обработку, в которой будем вычислять квадратный корень модуля числа,
используя функцию из общего модуля. Сделаем всё, что Вы уже умеете: создадим обработку,
форму обработки с реквизитом ЧислоПодКорнем, команду формы Вычислить корень числа (поместим команду на форму), а также обработчик для этой команды. Перед этим не забудем сохранить конфигурацию и обновить базу данных.
Рис. 4.2.31
В обработчике команды вычислим корень числа – реквизита формы, и выведем сообщение.
&НаКлиенте
Процедура ВычислистьКореньЧисла(Команда)
КореньЧисла = МатематическиеВычисления.КореньМодуляЧисла(ЧислоПодКорнем); Сообщить(Окр(КореньЧисла,6));
КонецПроцедуры
Листинг 4.2.11
Запустим обработку и посмотрим, как она будет работать.
Рис. 4.2.32
Если же мы уберём ключевое слово Экспорт у названия метода КореньМодуляЧисла
в общем модуле и попробуем заново выполнить команду, то платформа выдаст ошибку.
Рис. 4.2.33
Чтобы ошибка отобразилась, нужно включить возможность отладки:
Рис. 4.2.34
Рис. 4.2.35
Если процедура или функция экспортная (имеется ключевое слово Экспорт после параметров), то к этой функции можно обращаться вне данного модуля. В противном случае она может быть использована только в том модуле, в котором описана.
Заметьте, что платформа даёт подсказки: если после названия модуля написать точку и нажать клавишу «пробел», то выйдет список из всех экспортируемых процедур этого модуля (см. рис. 4.2.36).
Рис. 4.2.36
Экспорт переменных осуществляется точно так же, как экспорт функций и процедур: задаётся переменная в самом начале модуля и после названия переменной пишется ключевое слово Экспорт, а потом ставится точка с запятой.
Создадим в модуле управляемого приложения переменную РазрядностьПоУмолчанию, в которой будем указывать число знаков дробной части при округлении. Присваивать значение этой переменной будем в процедуре ПриНачалеРаботыСистемы (см. листинг 4.2.12).
Перем РаздрядностьПоУмолчанию Экспорт; Процедура ПриНачалеРаботыСистемы()
РаздрядностьПоУмолчанию = 3; КонецПроцедуры
Листинг 4.2.12
Рис. 4.2.37
Переделаем код из листинга:
&НаКлиенте
Процедура ВычислистьКореньЧисла(Команда)
КореньЧисла = МатематическиеВычисления.КореньМодуляЧисла(ЧислоПодКорнем); Сообщить(Окр(КореньЧисла,РазрядностьПоУмолчанию));
КонецПроцедуры
Листинг 4.2.13
Мы обратились к переменной РазрядностьПоУмолчанию напрямую, потому что модуль управляемого приложения работает в глобальном контексте.
Попробуем выполнить команду обработки.
Рис. 4.2.38
И напоследок изучим ещё одну особенность модулей. Помимо процедур и функций, в модуле можете написать любой код, который нам нужен. Он будет выполняться тогда, когда будет активирован этот модуль. Если это модуль формы, то когда открыта форма, если модуль объекта, то когда было обращение к этому объекту (без разницы, программное или интерактивное).
Например, в имеющейся у нас конфигурации в модуле объекта справочника автомобилей напишите следующий код:
Перем А; А = 3;
Для н = 1 по А Цикл
Сообщить(Строка(н) + "/" + Строка(А)); КонецЦикла;
Листинг 4.2.14
Рис. 4.2.39
Откроем любой элемент справочника. Выйдут сообщения, так как при обращении к объекту сразу идёт выполнение модуля, и если в нём имеется код, то он выполняется.
Рис. 4.2.40
Но есть исключения. Общие модули, модуль сеанса и модуль менеджера служат только для описания процедур и функций.
И, по правилам языка, все процедуры и функции должны идти перед основным кодом
модуля.
Если мы захотим в модуле объекта справочника Автомобили описать какую-то процедуру, то нужно это сделать перед основным кодом, но после описания переменных.
Перем А;
Процедура ВыводГосНомераАвтомобиляВСообщении() Сообщить(ГосНомер);
КонецПроцедуры А = 3;
Для н = 1 по А Цикл
Сообщить(Строка(н) + "/" + Строка(А)); КонецЦикла;
Листинг 4.2.15
Вот и всё. В этой книге мы не будем использовать общие модули и модуль управляемого приложения, а будем работать только с модулем объекта и модулем формы.
В следующей главе мы научимся работать с формами, наконец-то узнаем, что такое клиентский и серверный контекст, и научимся размещать элементы на формах.
(3) 5.01 Глава 5. Работа с управляемыми формами. Часть 1. Создание форм
Научимся работать с управляемыми формами. Информация в этой главе даётся в оптимальном для учащихся объёме, в таком, чтобы Вы научились всему необходимому в работе с формами: создавать формы, размещать элементы и программировать на форме. Более детально работа с управляемыми формами в частности и с управляемым приложением вообще даётся в моей книге«Основы разработки в 1С: Такси. Программированиеуправляемого приложения за 12 шагов.
Часть 1. Создание форм
Создание форм – это самый базовый процесс, с которым столкнётся любой, кто будет вести разработку в 1С под управляемым приложением.
Нам уже приходилось создавать различные формы (как правило, формы обработок) в процессе изучения этой книги, но мы особо не вдавались в подробности этих действий. В этой главе мы изучим вопросы создания форм более основательно. Но перед тем как начать упражняться с управляемыми формами, узнаем, что такое типы форм и что такое основная форма объектов.
Типы форм и основная форма объектов
У всех объектов метаданных есть определённый перечень типов форм. Причём количество и состав типов форм может отличаться в зависимости от прототипа объекта. Например, у справочников это – форма элемента, форма списка, форма группы, форма выбора и форма выбора группы (причём форма группы и форма выбора группы будут доступны только иерархическим справочникам!) А у документов – форма документа, форма списка и форма выбора.
Поэтому, если мы попытаемся создать форму у справочника Гаражи (мы помним, что это иерархический справочник), то будут предложены следующие типы форм:
Рис. 5.1.1
А если попытаемся создать форму документа, то будут предложены такие типы форм:
Рис. 5.1.2
5.03 Основные формы объектов. Сколько может быть основных форм?
Познакомимся с основными формами.
При создании формы какого-либо объекта метаданных на первой странице конструктора формы предлагается указать, что создаваемая форма будет основной (флаг Назначить форму основной).
Рис. 5.1.3
Если мы оставим этот флаг включённым, то созданная форма станет основной.
Что означает этот флаг, и какой смысл в основной форме? Основная форма всегда будет отображаться пользователю при выполнении стандартных команд в интерфейсе «1С: Предприятия», или, говоря простым языком, основная форма всегда будет открываться по умолчанию.
Например, основная форма списка справочника Гаражи отобразится тогда, когда будет выполнена команда навигации в командном интерфейсе раздела, открывающая форму списка.
Рис. 5.1.4
А основная форма элемента справочника Гаражи будет открыта тогда, когда мы попытаемся или создать новый гараж, или открыть имеющийся.
Рис. 5.1.5
У каждого типа формы может быть только одна основная форма, а как следствие: количество основных форм равняется количеству типов форм объектов.
Естественно, у Вас может возникнуть вопрос – какие формы открываются по умолчанию в качестве основных у документов, справочников в нашей конфигурации, если мы никакие основные формы не создавали. В том случае, когда никакие формы не указаны у объекта в качестве основных форм, платформа автоматически сгенерирует основную форму.
Платформа будет автоматически генерировать основную форму даже тогда, когда форма нужного прототипа имеется, но не указана в свойстве Основная форма!
Напомню, что основных форм может быть столько, сколько типов форм у данного прототипа метаданных. Если у документов три типа форм: форма документа, списка и выбора, то это значит, что основных формы у документов тоже может быть только три: основная форма документа, основная форма списка и основная форма выбора
Посмотреть какие формы основные можно или в редакторе документа на закладке
Формы:
Рис. 5.1.6
Или в палитре свойств документа в категории Представление:
Рис. 5.1.7
У справочников типов форм больше, а значит, и основных форм тоже больше.
Рис. 5.1.8
Мы не будем подробно вдаваться в типы форм объектов. По сути, названия всех типов форм интуитивно понятны, и их предназначение без труда ищется в справочной информации.
Создание новых форм
Что такое основные формы и типы форм мы узнали. Научимся создавать разные типы форм. Начнём мы с форм справочников и документов.
Все формы создаются при помощи конструктора форм. Для каждого прототипа объекта (документы, справочники и т.д.) – свой конструктор форм. Для документов – конструктор форм документов, для справочников – конструктор форм справочников и т.д. Вызвать этот конструктор можно несколькими способами (см. рис. 5.1.9, 5.1.10, 5.1.11), но в любом случае вызывать его нужно из того объекта, для которого создаётся форма.
5.04 Создание новых форм - сколько способов вызова конструктора?
Рассмотрим три способа вызова конструктора на примере справочника:
В дереве конфигурации выделяется узел Формы ветки нужного объекта, вызывается контекстное меню, в котором выполняется команда Добавить (см. рис. 5.1.9);
В дереве конфигурации выделяется нужный объект, вызывается контекстное меню, ищется подменю Добавить, и в этом подменю выполняется команда Форма (см. рис. 5.1.10);
В редакторе объекта, на закладке Формы, в окне дерева форм необходимо нажать на кнопку Добавить (см. рис. 5.1.11).
Рис. 5.1.9
Рис. 5.1.10
Рис. 5.1.11
После выполнения команды откроется конструктор формы. Для разных типов объектов конструктор будет иметь разный вид. Например, на рис. 5.1.12 представлен конструктор формы для справочника, а на рис. 5.1.13 – для документа.
Рис. 5.1.12 | Рис. 5.1.13 |
Разберём первую страницу конструктора. Вверху окна нам предложено выбрать тип формы, которая будет создана. Как уже было сказано, в зависимости от прототипа объекта (и даже вида прототипа) список типов форм может быть разный. Для справочников – это один перечень форм, а для документов – другой. Причём обратите внимание на рис. 5.1.12: иногда некоторые типы форм могут быть недоступны. Например, в случае справочника Автомобили недоступны следующие типы форм: форма группы справочника и форма выбора группы справочника, из-за того, что у этого справочника отключена иерархия. Если же мы попытаемся создать форму для справочника Гаражи (у которого иерархия включена), то эти типы будут доступны.
С помощью флага Назначить форму основной мы можем установить, что вновь создаваемая форма станет основной. Если у нас уже есть какая-то основная форма, то она никуда не денется, просто перезапишется свойство объекта, в котором указывается основная форма объекта того типа, форму для которого мы создаём.
Имя – это индикатор формы. В рамках одного объекта не может быть двух форм с одинаковым именем.
Синоним – это свойство, определяет, как форма будет отображаться в пользовательском интерфейсе по умолчанию (может быть несколько форм с одинаковыми синонимами).
Раньше мы всегда на первой странице конструктора останавливались и нажимали кнопку Готово. В этот раз мы продолжим изучать конструктор новых форм. И для этого создадим форму у документа УстановкаЦенНаТопливо. Тип формы будет – Форма документа, назначим будущую форму основной, остальное оставим по умолчанию и нажмём на кнопку Далее (см. рис. 5.1.14).
Рис. 5.1.14 | Рис. 5.1.15 |
В следующем окне (рис. 5.1.15) конструктора формы мы увидим все реквизиты (включая стандартные), табличные части и реквизиты табличных частей объекта. Нам предлагается с помощью флажков отметить, какие реквизиты попадут на будущую форму, а какие нет. Если мы создаём форму документа, форму элемента справочника, форму обработки и т.д., то в списке реквизитов будут присутствовать и реквизиты шапки объекта, и табличные части объекта с реквизитами этих частей. А если мы создаём формы списка или выбора, то будут присутствовать только реквизиты шапки.
После выбора реквизитов и нажатия кнопки Готово, форма будет создана (см. рис.
5.1.16).
Обратите внимание, после того как мы создали форму элемента с включённым флагом Назначить форму основной, в свойство Основная форма документа записалась вновь созданная форма (см. рис. 5.1.17).
типов.
Рис. 5.1.17
Можно создать какое угодно количество форм справочников и документов разных Платформа также предоставляет возможность создания форм копированием. Для этого
в редакторе объекта на закладке Формы следует выделить нужную форму, вызвать
контекстное меню и в этом контекстном меню выполнить команду Скопировать (см. рис. 5.1.18). В результате будет создана новая форма, аналог скопированной, но под другим именем (см. рис. 5.1.19). В случае копирования редактор создания форм открываться не будет, и новая форма не станет основной. Если разработчик желает сделать новую форму основной, то ему следует перевыбрать форму в соответствующем свойстве объекта (см. рис. 5.1.20, 5.1.21).
Рис. 5.1.19
Рис. 5.1.20
Рис. 5.1.21
С созданием форм всё. Создайте самостоятельно основные формы всех документов и формы списков всех документов (укажите все реквизиты, кроме Ссылка, Проведён и Пометка на удаление), а после приступайте ко второй части этой главы, где мы будем изучать командный интерфейс формы.
Часть 2. Командный интерфейс формы
В предыдущей части мы научились создавать формы объектов, узнали, какие типы форм бывают, что такое основная форма, как её задать и поменять. В этой части мы познакомимся с командным интерфейсом формы.
Глобальные команды мы изучали в предыдущей главе (см. Глава 4, Часть 1, стр. 254).
Они делятся на независимые глобальные команды, необходимые для формирования глобального командного интерфейса, и параметризуемые глобальные команды, необходимые для формирования командного интерфейса управляемой формы. Но кроме
глобальных команд на форме можно размещать и локальные команды. В этой части мы научимся работать как с глобальными командами на форме, так и с локальными командами формы.
Но сначала познакомимся с самой управляемой формой.
После того как мы создали форму документа, справочника или любого другого объекта, откроется редактор формы. На рис. 5.2.1 Вы видите редактор управляемой формы документа УстановкаЦенНаТопливо нашей конфигурации.
Рис. 5.2.1
Редактор управляемой формы разбит на три окна.
Окно 1 разбито на две закладки: Элементы и Командный интерфейс.
Элементы – все элементы формы в том порядке, в каком они расположены на форме.
Командный интерфейс – команды, которые могут выполняться на форме.
Окно 2 разбито на три закладки: Реквизиты, Команды и «Параметры».
Реквизиты – содержит реквизиты формы (что это, мы узнаем позже).
Команды – состав команд, которые потенциально можно применить на форме (локальные и глобальные команды).
Параметры – содержит параметры формы (что это, мы узнаем позже).
Окно 3 разбито на две закладки: Форма и Модуль.
Форма – внешний вид формы, как его увидит пользователь.
Модуль – модуль формы для описания событий на встроенном языке. Определим основные термины:
Реквизиты формы – это данные, с которым осуществляется основная работа формы. Более подробно работать с реквизитами мы будем в следующей части, а пока отметим, что имеется основной реквизит. На рис 5.2.1 в окне 2 это реквизит Объект, который выделен жирным шрифтом. При создании типизированных форм (форма документа, элемента справочника, списка и т.п.) основной реквизит создаётся автоматически.
Элементы формы – это «кирпичики» интерфейса формы, при помощи которых пользователь осуществляет взаимодействие с формой. Это могут быть кнопки, поля ввода, переключатели, флаги и т.п.
5.05 Параметры формы - для чего предназначены?
Параметры формы – это данные, с помощью которых осуществляется открытие формы (об этом подробно – в третьей части шестой главы).
Команды формы – это объекты, с помощью которых пользователь осуществляет действия на форме.
На форме можно разместить три вида команд: локальные команды формы, стандартные команды формы и глобальные команды (как независимые, так и параметризуемые).
Рис. 5.2.2
Разберём виды команд.
Локальные команды формы (см. первая закладка, рис. 5.2.2) – команды формы, которые создаются разработчиками приложения только для этой формы и работают только в контексте этой формы. Как правило, размещаются на форме в виде кнопок и служат для описания самых разных действий, которые должны выполняться с формы.
Рис. 5.2.3
Стандартные локальные команды – служат для обработки данных и для управления самой формой. Состав их может отличаться в зависимости от типа формы, прототипа объекта метаданных и прочего функционала. Кроме стандартных локальных команд формы, на форме могут быть стандартные локальные команды некоторых элементов формы. Например, в нашем случае, у таблицы формы ЦеныТоплива тоже имеются стандартные локальные команды (см. рис. 5.2.4). Разработчик приложения не может создавать самостоятельно стандартные локальные команды, а может довольствоваться только тем, что предоставляет платформа 1С.
Рис. 5.2.4
Глобальные команды – на форме можно размещать глобальные команды. Как независимые (навигационные и действия), так и параметризуемые.
Рис. 5.2.5
С командами познакомились, разберем Командный интерфейс (левое верхнее окно, номер 1 на рисунке 5.2.1).
Командный интерфейс формы содержит две группы команд: Панель навигации и
Командная панель (см. рис. 5.2.6).
Рис. 5.2.6
В панели навигации располагаются команды навигации (в неё попадают параметризуемые глобальные команды навигации), а в панели действий располагаются команды действий (параметризуемые глобальные команды действий).
Посмотрим, где на форме в пользовательском интерфейсе расположены панель навигации и команданая панель.
Для того чтобы панель навигации появилась на форме, установим флаг Видимость для ветки Цены на топливо узла Панель навигации (см. рис. 5.2.7) на форме документа УстановкаЦенНаТопливо.
Рис. 5.2.7
Рис. 5.2.8. Панель навигации и командная панель на форме (1 – панель навигации, 2 – командная панель)
Панель навигации на форме формируется исключительно командами из группы Панель навигации закладки Командный интерфейс (см. рис. 5.2.6, 5.2.7), а командная панель формируется командами из группы Командная панель закладки Командный интерфейс, но ещё и стандартными командами командной панели формы с закладки Элементы (см. рис 5.2.9).
Рис. 5.2.9
Эти команды заполнились автоматически, поскольку у командной панели установлено свойство Автозаполнение.
Рис. 5.2.10
Если этот флаг у этого свойства снять, то все кнопки командной панели «исчезнут».
Рис. 5.2.11
Вернёмся к закладке Командный интерфейс формы (см. рис. 5.2.6, 5.2.7). Помимо колонки, в которой расположены команды панели навигации и командной панели, имеются ещё три колонки – Видимость, Автовидимостьи Автоположение. Разберём, для чего они нужны.
При установке флажка в колонке Видимость команда, для которой поставлен этот флаг, будет однозначно всегда показываться на форме (если у пользователя есть соответствующее право).
Следующая колонка – Автовидимость. Данная колонка доступна только для команд, которые добавляются автоматически (о них ниже). При установке флажка в эту колонку автоматически снимается или устанавливается флаг в колонке Видимость. Например, у команды открытия формы списка с отбором по регистратору всех регистров (сведений, накопления, бухгалтерии и расчётов) по умолчанию видимость отключена, поэтому если мы поставим флаг Автовидимость рядом с такой командой, то флаг Видимость у этой команды снимется (как сняты флажки на рис. 2.5.12). Если же разработчику необходимо, чтобы пользователь видел эти команды, то необходимо вручную поставить для них всех видимость, как это сделано на рис. 5.2.6.
Рис. 5.2.12
Устанавливает признак Автовидимость по умолчанию флаг Видимость в значение Истина или нет – определяется разработчиками платформы. В этой книге нет смысла перечислять все возможные варианты зависимостей. Просто при создании формы проверяйте установку флажка Видимость, и если по умолчанию он снят, а Вам нужно чтобы у пользователя был доступ к этой команде, то просто установите этот флажок.
И последняя колонка Автоположение – определяет расположение команды по умолчанию. При снятии флажка с этой колонки команды можно перемещать внутри группы (сразу становятся доступны стрелки на командной панели вверху окна).
Немного подробнее изучим работу с панелью навигации и командной панелью на закладке. Создадим форму документа для документа Прибытие в гараж (если не сделали это ранее).
Рис. 5.2.13
Панель навигации служит для размещения навигационных команд (команды, необходимые для навигации по конфигурации, в случае формы с помощью этих команд осуществляется перемещение на другие формы, как правило, формы списка), это какие-либо глобальные команды (независимые или параметризуемые).
Командная панель предназначена для размещения команд действий, это могут быть или стандартные команды формы (закрытие, запись и т.д.), или глобальные команды действия, или локальные команды формы.
Панель навигации формы состоит из трёх групп, это группы Важное, Перейти и См. также. Разработчик может самостоятельно перемещать команды между группами с помощью мышки: необходимо выделить команду, удерживать клавишу мышки и тащить её куда нужно. Особых затруднений эта операция у Вас вызвать не должна, всё точно так же, как и в командном интерфейсе подсистем.
В панели навигации формы документа Прибытие в гараж автоматически разместилась команда на открытие формы списка регистра накопления Пробег автомобиля с выключенной видимостью (см. рис. 5.2.14).
Рис. 5.2.14
Установим флаг Видимость (флаг Автовидимость автоматически снимется), сохраним конфигурацию, обновим базу данных и посмотрим на панель навигации формы документа Прибытие в гараж:
Рис. 5.2.15
Как Вы видите, в панели навигации формы документа Прибытие в гараж появилась ссылка, по которой можно увидеть движения этого документа по регистру накопления Пробег автомобиля. Достаточно просто по ней кликнуть мышкой.
Рис. 5.2.16
Если в панели навигации мы можем размещать только команды навигации (глобальные), то в командной панели (см. рис. 5.2.17) формы мы можем размещать исключительно команды действия (создания на основании, печать отчётов и т.п.). Это могут быть как глобальные команды, так и локальные.
Рис. 5.2.17
В предыдущей части мы создали возможность ввода документа Выбытие из гаража на основании документа Прибытие в гараж (см. Глава 4, Часть 1, Ввод на основании, стр. 188). Поэтому в командную панель формы автоматически должна добавиться глобальная команда Создать на основании (см. рис. 5.2.18).
Рис. 5.2.18
Обратите внимание: флаг Видимость для команды создания на основании устанавливается автоматически.
Подробно о принципах формирования панели навигации и командной панели смотрите во второй части книги «Основы разработки в 1С: Такси».
5.06 Глобальные команды, добавляемые автоматически - какие команды добавляются автоматически?
Глобальные команды, добавляемые автоматически
Как уже было сказано выше, в панель навигации добавляются глобальныb>команды. А командная панель формы формируется как из глобальных, так и из локальных команд.
Причём Вы уже должны были обратить внимание, что некоторые команды добавляются автоматически (правда, у многих по умолчанию выключена видимость). Автоматически на форму всегда добавляются глобальные параметризуемые команды, у которых в качестве типа параметра выступает ссылка на объект формы (реквизит Объект), или ссылка на объект присутствует в списке параметров. В практике наиболее часто автоматически глобальные команды добавляются при создании форм элементов справочников и форм документов.
Для примера создадим форму элемента справочника Марки автомобилей. Создадим одним из способов: выделим узел Формы справочника Марки автомобилей, вызовем контекстное меню (см. рис. 5.2.19) и выполним единственную команду Добавить.
Рис. 5.2.19
В открывшемся конструкторе оставим переключатель на пункте Форма элементов справочника, а флаг Назначить форму основной оставим включенным. Больше нам ничего от этого конструктора не нужно. Нажмём кнопку Готово.
Во вновь созданной форме сразу перейдём на закладку Командный интерфейс и увидим, что в панели навигации в группе Перейти уже есть команда, для которой, кстати, видимость по умолчанию включена (см. рис. 5.2.20). Выясним, почему эта команда попала в панель навигации.
Рис. 5.2.20
В панель навигации автоматически добавилась параметризуемая команда на открытие формы списка справочника МоделиАвтомобилей с отбором по владельцу (Вы помните, что справочник МоделиАвтомобилей подчинён справочнику МаркиАвтомобилей).
Команда на открытие формы списка справочника с отбором по владельцу является стандартной глобальной параметризуемой командой, параметром этой команды является ссылка на элемент справочника. В нашем случае параметром команды на открытие формы списка справочника МоделиАвтомобилей является выражение Объект.Ссылка, и в тоже время Объект – это основной реквизит формы элемента справочника (см. рис. 5.2.21).
Рис. 5.2.21
Объекты и ссылки на объекты будем изучать в следующей главе.
Также в группу Важное командной панели добавилась автоматически команда ПечатьМаркиАвтомобиля, которую мы сделали ранее (см. Глава 4, Часть 1, Команды, стр. 254).
Рис. 5.2.22
Команда добавилась потому, что мы у этой команды установили в качестве типа параметра команды ссылку на этот справочник.
Рис. 5.2.23
И ещё один момент. Обратили Вы внимание или нет, но команда на открытие формы списка с отбором по регистратору регистра накопления ПробегАвтомобиля появилась в панели навигации формы документа ПрибытиеВГараж. Почему? Потому что документ ПрибытиеВГараж является регистратором вышеупомянутого регистра. И поэтому существует стандартная параметризуемая глобальная команда на открытие формы списка регистра накопления с отбором по регистратору, которая и добавилась в командный интерфейс формы документа (с выключенной по умолчанию видимостью).
Рис. 5.2.24
Создайте самостоятельно формы документов ЗаправкаТоплива и ОтчетОРасходеТоплива, и в командном интерфейсе формы вы обнаружите глобальную параметризуемую команду на открытие формы списка регистра накопления ТопливоВАвтомобилях с отбором по регистратору (см. рис. 5.2.25). Регистратор – это ссылка на документ, форма которого открыта.
Рис. 5.2.25
По умолчанию у команд на открытие форм списка регистров всегда выключена видимость.
5.07 Глобальные команды, добавленные вручную
Глобальные команды, добавленные на форму вручную
В панель навигации команды можно добавлять вручную, перенося их мышкой из вкладки Глобальные команды (см. рис. 5.2.26).
Рис. 5.2.26
В панель навигации можно добавлять только команды навигации, а в панель действия
соответственно команды действия. Конструктор просто не даст Вам возможность сделать неправильно.
В этой книге не будем подробно разбирать вопросы ручного добавления глобальных команд, более подробно эти моменты разбираются во второй главе второй части книги
5.08 Локальные команды формы - для чего?
Локальные команды формы
Помимо глобальных команд, которые размещаются в панели навигации (команды навигации) и в командной панели (команды действия), на форме можно размещать локальные команды формы. Локальные команды формы необходимы для выполнения различных действий на форме. Все локальные команды расположены на закладке Команды в
подзакладках Команды формы и Стандартные команды.
Рис. 5.2.27
На закладке Стандартные команды (см. рис. 5.2.28) перечислены команды формы, которые характеризуют стандартные события с формой или объектом формы. Например, это может быть команда закрытия формы, получения справки, проведения документа и т.п.
Рис. 5.2.28
На закладке Команды формы перечислены команды, созданные разработчиком самостоятельно. Разработчик может создать собственную локальную команду формы. Для этого необходимо на закладке Команды формы нажать на кнопку Добавить (+), после этого вновь созданная команда отобразится в списке и справа появится палитра свойств новой команды (см. рис. 5.2.29). Но команда на самой форме не появится!
Рис. 5.2.29
В этой палитре свойств разработчик может изменить имя команды (имена должны быть уникальны в пределах формы), установить картинку, заголовок, но самое главное – это привязать какую-либо процедуру к команде.
Новую команду формы документа Прибытие в гараж назовём Вывести сообщение.
Рис. 5.2.30
В свойстве Действие указывается процедура, которая должна сработать, когда пользователь выполнит команду (нажмёт на кнопку). Можно выбрать имеющуюся процедуру, а можно создать новую, нажав на кнопку Лупа свойства Действие (см. рис. 5.2.31).
Рис. 5.2.31
После нажатия на кнопку Лупа будет предложено три варианта создания обработчиков команды: на клиенте, на клиенте и на сервере, на клиенте и на сервере без контекста. В четвёртой части этой главы мы узнаем, в чём особенность каждого варианта создания обработчика. Пока оставим переключатель в значении Создать на клиенте и нажмём кнопку ОК, после этого в модуле формы будет создана процедура (см. рис. 5.2.32), а в свойстве Действие локальной команды появится название этой процедуры (см. рис. 5.2.33).
Рис. 5.2.32
Рис. 5.2.33
Причём название процедуры, как правило, совпадает с названием команды, поэтому не используйте в качестве названия команды какие-либо ключевые слова.
В новой процедуре самостоятельно напишите код, который будет выводить какое- либо сообщение.
Нам осталось поместить нашу команду на форму. Команду формы можно разместить либо в командной панели (закладка Командный интерфейс, см. рис. 5.2.34), либо в командной панели формы (закладка Элементы, см. рис. 5.2.35), либо просто на форме (см. рис 5.2.36). Достаточно перетащить её в нужное место мышкой. Естественно, Вы не сможете разместить локальную команду в панели навигации.
Рис. 5.2.34
Рис. 5.2.35
Рис. 5.2.36
После размещения кнопка, соответствующая команде, появится или на командной панели (см. рис. 5.2.37, 5.2.38), или среди элементов формы (см. рис. 5.2.39).
Рис. 5.2.38
Рис. 5.2.39
При нажатии на эту кнопку выполнится код, который описан в процедуре, указанной в свойстве Действие, связанной с этой кнопкой команды.
5.09 Часть 3. Реквизиты и элементы формы. Реквизиты формы. Что такое реквизиты формы?
Часть 3. Реквизиты и элементы формы
Реквизиты формы
Перейдем к изучению реквизитов форм. Что такое реквизиты формы? Это данные, которые привязаны к форме: они создаются, хранятся, отображаются (по возможности) и редактируются на форме. Вне контекста формы эти данные не существуют. Сам по себе реквизит не может отображаться на форме. Для этого служат элементы формы, которые связаны с реквизитами форм (о них позже).
Для чего нужны реквизиты формы? Часто возникают ситуации, что на форме нужно иметь какой-то объект, который используется в работе с этой формой. К этому объекту можно обратиться непосредственно с формы (т.е. он связан с элементом формы), но также этот объект может существовать сам по себе, без связи с каким-то элементом формы, тогда с ним можно работать только в модуле формы. Реквизит формы не хранится в базе данных и играет второстепенную вспомогательную роль (например, с его помощью выполняются какие-либо вычисления).
В управляемом приложении (как и в обычном, кстати) на любой форме имеется возможность создать реквизит, который, по своей сути, будет локальной переменной формы. Как следствие, к реквизиту формы можно обращаться в любой процедуре или функции, написанной в модуле формы (об особенностях доступа к реквизитам формы будет подробно рассказано в четвёртой части это главы).
Это краткая теория. Теперь приступим к практической части.
В предыдущей части мы уже создали форму документа ПрибытиеВГараж. Откроем эту форму и перейдём на закладку Реквизиты (см. рис. 5.3.1).
Рис. 5.3.1
С ней мы и будем работать. Сейчас у нас на форме только один реквизит, который
называется Объект, причём, как Вы могли заметить из рис. 5.3.1, он имеет иерархическую структуру.
Обратите внимание, этот реквизит выделен жирным шрифтом, и если Вы откроете палитру свойств этого реквизита, то свойство Основной реквизит будет установлено. Т.е. реквизит Объект нашей формы является основным реквизитом формы. У формы может быть только один основной реквизит, и с его помощью определяется функциональность формы.
Создадим несколько разных реквизитов у основной формы документа ПрибытиеВГараж. Для того чтобы создать новый реквизит, необходимо нажать на кнопку Добавить реквизит закладки Реквизиты (см. рис. 5.3.2).
Рис. 5.3.2
После того как мы нажмём на эту кнопку, автоматически будет создан новый реквизит (по умолчанию тип нового реквизита – Строка) и в правой части рабочей области конфигуратора откроется палитра свойств этого реквизита (см. рис. 5.3.3).
Рис. 5.3.3
Разберём основные свойства реквизита формы. Первое свойство, которое бросается в глаза, – это Тип. Разработчик может назначить реквизиту практически любой из предоставленных платформой типов: примитивный, ссылочный, объект, таблицу значений, дерево значений и т.д. Причём тип также может быть составным. После нажатия на кнопку
«…» рядом с полем Тип откроется окно Редактирование типов данных (см. рис. 5.3.4), посредством которого можно назначить реквизиту нужный тип.
Очень осторожно стоит использовать типы прикладных объектов (ДокументОбъект, СправочникОбъект и т.п.) Начинающим программистам рекомендуется воздержаться от их использования (кроме случаев, когда данный реквизит является основным, но в этом случае, как правило, тип будет установлен автоматически).
Рис. 5.3.4
Замечу, что при выборе реквизиту формы таких типов, как ссылки, объекты и т.п., реквизит в окне отобразится в виде дерева, где корнем будет название реквизита, а ветками этого дерева – реквизиты объекта, который был выбран.
Например, на рисунке 5.3.5 мы назначили новому реквизиту Реквизит1 тип ДокументСсылка.УстановкаЦенНаТопливо, и в списке реквизитов можно видеть, что Реквизит1 приобрёл древовидную структуру, где в ветках дерева можно наблюдать реквизиты и табличную часть документа Установка цен на топливо.
Рис. 5.3.5
Ссылочные типы мы будем изучать в следующей главе, а пока научимся работать с реквизитами примитивных типов. Поменяем у только что созданного реквизита Реквизит1 тип на Число, для этого в палитре свойств реквизита снова откроем окно Редактирование типа данных свойства Тип, нажав на кнопку «…», и установим новый тип Число.
Рис. 5.3.6
Посмотрим на другие свойства реквизита. Следующим после типа нас интересует свойство Сохраняемые данные (см. рис. 5.3.7). Если это свойство установлено, то при попытке редактирования элемента, связанного с этим реквизитом, будет установлен признак модифицированности формы (символ * рядом с названием).
Рис. 5.3.7
5.10 для чего свойство «Проверка заполнения»?
Ещё одно интересное свойство – это Проверка заполнения (см. рис. 5.3.8).
Рис. 5.3.8
Это свойство устанавливается для реквизитов с примитивными и ссылочными типами, а также для реквизитов с типами Таблица значений и Список значений (эти типы подробно изучим в седьмой и восьмой главах).
Если установить у этого свойства реквизита значение Выдавать ошибку, то незаполненный элемент формы, который привязан к реквизиту, будет подчеркиваться красной линией. А также если функциональность формы предусматривает сохранение данных (например, когда основной реквизит формы тип со значением какого-нибудь объекта), то при попытке сохранения данных, в случае незаполненного элемента формы, привязанного к этому реквизиту, программа выдаст ошибку и сохранение не произойдет.
5.11 Свойства «Просмотр» и «Редактирование» что позволяют?
Свойства Просмотр и Редактирование позволяют настроить видимость реквизита и возможность его редактирования в зависимости от ролей. После нажатия на гиперссылку Открыть реквизита Просмотр (Редактирование) откроется окно настройки доступа (см. рис. 5.3.9). Если для роли установлен флаг, то пользователь, имеющий такую роль, будет видеть этот реквизит (сможет отредактировать), если флаг снят – то пользователь не будет видеть этот реквизит (не сможет редактировать), а если флаг – серый, то видимость этого реквизита (возможность редактировать) будет определяться флагом в шапке формы.
Рис. 5.3.9
Причём установка видимости элемента, к которому привязан реквизит, является вторичной по отношению к видимости этого реквизита: если у определённого реквизита запрещена видимость для определённой роли, то пользователь с этой ролью не увидит элемент, привязанный к этому реквизиту, в любом случае. Даже если на этот элемент пользовательская видимость установлена.
Вернёмся к списку реквизитов на форме (см. рис. 5.3.10):
Рис. 5.3.10
Помимо колонок Реквизит и Тип, у этой таблицы есть ещё две колонки – Расположение на форме и Использовать всегда. Если на форме имеется элемент, который привязан к реквизиту формы, то в колонке Расположение на форме появляется серый квадратик. С этим всё просто. Например, на рис. 5.3.10 реквизит Реквизит1 не привязан ни к какому элементу формы, как следствие, нет серого квадратика, а на рисунке 5.3.11 мы создали поле ввода, привязанное к этому реквизиту, и квадратик появился. С полем Использовать всегда на данном этапе обучения не будем разбираться, чтобы не загружать Вас излишней информацией.
Рис. 5.3.11
5.12 Элементы формы. сколько видов элементов?
Элементы формы
Интерактивная работа с формой осуществляется посредством элементов формы.
Элементы расположены на форме в иерархическом порядке. Этот порядок определяет внешний вид формы. В конфигураторе работа с элементами формы осуществляется в редакторе формы на закладке Элементы, а сама же форма, её графический вид, – на закладке Форма (см. рис. 5.3.12).
Рис. 5.3.12. Элементы формы (1) и вид формы (2)
Для тех, кто работал с обычными формами: нельзя работать с элементами формы (перемещать, удалять, растягивать и т.п.) непосредственно в графическом отображении формы. Вся работа с элементами ведётся в закладке Элементы.
Элементы формы бывают разных видов, вот основные из них:
Форма;
Поле формы;
Группа формы;
Декорация формы;
Таблица формы;
Кнопка формы;
Командные панели.
Позже мы разберём некоторые из них подробнее, единственно отметим, что элемент Форма существует только в единственном экземпляре. И располагается в самом верху иерархии. А элемент Группа формы может содержать в себе другие элементы формы.
Управление элементом возможно как при помощи мышки, так и при помощи командной панели, которая расположена в верхней части закладки Элементы (см. рис. 5.3.13).
Рис. 5.3.13
Разберём некоторые кнопки командной панели. Кнопка Добавить – первая кнопка на командной панели, при нажатии на неё открывается окно с выбором типа элемента, который будет добавлен на форму (см. рис. 5.3.14).
Рис. 5.3.14
После выбора нужного типа элемента и нажатия кнопки ОК этот элемент будет создан и помещён либо непосредственно на форму, либо в какую-нибудь группу, расположенную на форме. В зависимости от того, что на момент нажатия на кнопку было активным.
При нажатии на кнопку Изменить (вторая на рисунке 5.3.14) откроется палитра свойств элемента.
Как работают кнопки Удалить, Переместить вверх и Переместить вниз, понятно из названий, и, думаю, Вы в этом разберетёсь самостоятельно.
При нажатии на кнопку Проверить (см. рис. 5.3.15) на экране показывается представление формы, какой её увидит пользователь.
Рис. 5.3.15
Разберём основные элементы формы, с которыми Вам придётся столкнуться в первое
время.
Элемент Форма
Самый главный элемент, без которого не обходится ни одна форма, это элемент Форма. Данный элемент только один, и он всегда располагается в верхней части дерева элементов и является родителем для всех остальных элементов формы (см. рис. 5.3.16).
Рис. 5.3.16
Для того чтобы открыть палитру свойств формы, достаточно просто дважды кликнуть по элементу Форма левой клавишей мышки или, выделив форму, вызвать контекстное меню, в котором выполнить команду Свойства.
Рис. 5.3.17
Свойств у формы много, и в рамках этой книги мы не будем все их разбирать. Если у кого возникнет желание более глубоко изучить свойства формы, то он найдёт всю нужную информацию в синтакс-помощнике. Изучим несколько свойств.
Режим открытия окна – очень важное свойство формы. Оно определяет, каким образом будет открываться наша форма. Может принимать три значения: Независимый, Блокировать окно владельца, Блокировать весь интерфейс.
При использовании Независимого режима открытия окна, новая форма откроется в рабочей области интерфейса. Она будет как бы «рядом» с тем окном, откуда было инициировано её открытие.
Например, на рис. 5.3.18 мы открыли форму документа Установка цен на топливо из формы списка документов. Эта форма стала сама по себе (режим открытия окна Независимый), и мы, как с помощью стрелок навигации, так и с помощью панели открытых, можем перейти с этой формы на ту форму, откуда она была открыта.
Рис. 5.3.18
5.13 Элемент форма - свойство: РежимОткрытияОкна, что определяет?
Если в свойство РежимОткрытияОкна установить значение Блокировать окно владельца (см. рис. 5.3.19), то форма открывается «поверх» окна, из которого было инициировано её открытие, при этом оно блокирует то окно, из которого было открыто, но в то же время пользователь сможет спокойно осуществлять навигацию по всему интерфейсу.
Рис. 5.3.19
Например, на рис. 5.3.20 мы открыли форму документа УстановкаЦенНаТопливо из списка документов с режимом Блокировать окно владельца. У нас есть возможность перемещаться по интерфейсу, открыть ещё одно окно, но чтобы вернутся в список документов, необходимо закрыть окно документа.
Рис. 5.3.20
Данный режим желательно применять, когда требуется открыть форму, в которую нужно ввести небольшое количество информации.
форм:
По умолчанию режим блокировки владельца устанавливается у следующих видов
Формы элементов и групп справочников;
Формы элементов и групп планов видов характеристик;
Формы счетов;
Формы задач и т.д.
В случае использования режима Блокировать весь интерфейс окно также открывается поверх окна, из которого было инициировано его открытие, но блокируется весь интерфейс
«1С: Предприятия». Пока пользователь не закроет это окно, он не сможет получить доступ ни к одной команде «1С: Предприятия» в текущем сеансе.
5.14 Группа формы - для чего необходима? сколько вариантов?
Группа формы
Этот элемент формы необходим для реализации всевозможных вариантов объединения других элементов формы. В управляемой форме мы не можем самостоятельно размещать элементы на форме, но иногда для удобства работы пользователей возникает необходимость расположить элементы относительно друг друга в разных вариациях.
Например, у нас в документе УстановкаЦенНаТопливо поля Дата и Номер расположены друг под другом, а более удобно, например, чтобы они располагались рядом по горизонтали.
Всего можно создать четыре варианта группы: Обычная, Обычная без отображения, Страницы и Командная панель (см. рис. 5.3.21). Также можно сгруппировать колонки в таблице формы (эту группу мы изучим, когда будем проходить таблицы на форме, см. Глава 8, Часть 1, Группировка колонок, стр. 564).
Рис. 5.3.21
Обычная группа (обычная группа без отображения)
Добавим на нашу форму документа УстановкаЦенНаТопливо обычную группу.
По умолчанию группа добавится вниз элементов формы, перетащите её вверх мышкой или при помощи кнопки Переместить вверх. В закладке Элементы группы отображаются в виде пиктограммы Папка (см. рис. 5.3.23). Наша группа по умолчанию называется Группа1.
Рис. 5.3.23
Пока мы никак не видим, что наша группа на форме, чтобы понять, что группа на форме, перетащим нужные элементы в группу. Делается это с помощью мышки: выделяется нужный элемент и «тащится» в группу. Перенесём в группу элементы Номер и Дата, и на рис. 5.3.24 можно увидеть, как изменится отображение элементов на форме.
Рис. 5.3.24
Элементы в группе Группа1 расположились согласно свойствам группы по умолчанию. Перейдём в палитру свойств группы и узнаем, какие свойства за что отвечают. Для того чтобы перейти в палитру свойств группы, необходимо или дважды кликнуть мышкой по группе, или в контекстном меню группы выполнить команду Свойства. В открывшейся палитре (см. рис. 5.3.25) нас в основном интересуют свойства из закладки Основные. Переименуем группу – изменим значение в свойстве Имя на НомерДата.
Обратим внимание на свойство группы Вид, у этого свойства установлено значение Обычная группа. Всего существуют три вида группы. В этом подразделе мы будем работать с Обычной группой. При выборе групп можно выбрать Обычную группу или Обычную группу без отображения (см. рис. 5.3.21), но в обоих случаях будет выбрана одна и та же группа с видом Обычная группа. Только во втором случае будет снято свойство ОтображатьЗаголовок (в категории Использование). Больше никаких различий между двумя этими видами в форме выбора нет. По сути, это одна и та же группа, разделение на Обычную группу или Обычную группу без отображения сделано больше для удобства.
Мы с Вами изначально выбрали обычную группу, поэтому свойство ОтображатьЗаголовок установлено и на форме отображается текст из свойства Заголовок (см. рис. 5.3.26).
Рис. 5.3.26
Если мы свойство ОтображатьЗаголовок выключим (или бы мы выбрали тип элемента Группа – Обычная группа без отображения, см. рис. 5.3.21), то текста заголовка на форме не будет.
Разберём ещё одно свойство – это Группировка. Именно от значения в этом свойстве будет зависеть, как будут располагаться друг относительно друга элементы в группе. По умолчанию оно всегда установлено: Горизонтальная, если возможно. Если мы установим свойство Вертикальная, то расположение элементов изменится (см. рис. 5.3.28).
Рис. 5.3.28
Объём этой книги не позволяет изучить все свойства групп, да и на данном этапе обучения это не нужно. Пока научитесь работать со свойствами Вид (о других значениях позже), Группировка, Заголовок и ОтображатьЗаголовок.
5.15 группа Страницы - для чего?
Страницы
Рассмотрим следующий очень интересный вид группы – это Страницы. С помощью группы такого вида можно на форме сделать разного рода вкладки и размещать в этих вкладках элементы. Например, нашу форму документа УстановкаЦенНаТопливо можно реализовать в таком виде:
Рис. 5.3.29 | Рис. 5.3.30 |
Реализуем интерфейс формы документа УстановкаЦенНаТопливо с закладками как на рис. 5.3.29 и 5.3.30. Выделим узел Форма дерева элементов, нажмём на кнопку Добавить
командной панели закладки Элементы, откроется окно Тип элемента. В этом окне выберем элемент с названием Группа – Страницы» (см. рис. 5.3.31)
Рис. 5.3.31
После выбора в дереве Форма закладки Элементы добавится ветка с уже знакомой пиктограммой Папка. Это новая группа, только свойство Вид у этой группы будет Страницы (см. рис. 5.3.32).
Рис. 5.3.32
Мы создали на форме группу с видом Страницы, но нам ещё нужно создать страницы.
Сделаем так, чтобы на форме документа было две страницы: одна для реквизитов Шапки (всё, что не входит в табличную часть), а вторая для табличной части Цены. Для того чтобы добавить новую страницу к группе, необходимо установить курсор на группу (с видом Страницы, не забываем, мы её создали только что) и нажать на кнопку Добавить закладки Элементы. В появившемся окне выбора элементов добавится элемент Группа – Страница, который и нужно выбрать (см. рис. 5.3.33).
Рис. 5.3.33
Подобные действия нужно осуществить столько раз, сколько страниц в группе мы хотим сделать. Мы создадим две страницы, в результате элемент Группа2 в дереве формы должен приобрести иерархический вид (см. рис. 5.3.34, элемент Группа1 был перенесён в верх формы).
Рис. 5.3.34
Обратите внимание, что в группах с видом Страница тоже можно устанавливать различные группировки с помощью свойства Группировка (см. рис. 5.3.35).
Нам осталось с помощью мышки «перетащить» нужные элементы по нужным страницам, и наша форма примет вид почти как на рис. 5.3.29 и 5.3.30.
Рис. 5.3.36
Вы заметили, что на рис. 5.3.36 у страниц нет названий. Это потому, что мы не задали заголовки элементам Группа2 и Группа3. Напишем текст в заголовке элемента Группа3 –
«Шапка» (см. рис. 5.3.37), а Группа4 – «Таблица». После этого наша таблица примет более красивый вид (см. рис. 5.3.38).
Рис. 5.3.37
5.16 группа Командная панель - для чего?
Командная панель
Группа с видом Командная панель предназначена для размещений различных кнопок и меню. Причём для групп с таким видом можно указывать Источник, в этом случае группа будет автоматически заполнена командами источника по умолчанию. Для демонстрации работы с командной панелью реализуем следующий пример: изменим представление формы документа УстановкаЦенНаТопливо, так чтобы командная панель формы была в закладке Шапка группы страниц.
Рис. 5.3.39
Начнём.
Первым шагом выключим видимость командной панели самой формы. Для этого установим свойству формы ПоложениеКоманднойПанели значение Нет (необходимо открыть палитру свойств формы и найти свойство ПоложениеКоманднойПанели, категория Использование, см. рис. 5.3.40).
Рис. 5.3.40
После этого командная панель с формы уберётся.
Следующим шагом добавим новую группу с видом Командная панель в страницу
Шапка. Для этого нужно установить курсор на элементе Группа2 (поскольку именно он является закладкой Шапка), нажать на кнопку Добавить и в открывшемся окне выбрать тип элемента Группа – Командная панель (см. рис. 5.3.41).
Рис. 5.3.41
После добавления новой группы переместим её вверх над элементом НомерДата.
Рис. 5.3.42
Группу мы создали, но поскольку наша группа это Командная панель, нам нужно указать, чьи команды будут на этой панели. Делается это при помощи свойства группы Источник команд.
Откроем палитру свойств новой группы и укажем источник команд. В нашем случае три источника – это команды формы, глобальные команды командной панели формы и команды таблицы Цены топлива, связанной с одноимённой табличной частью (см. рис.
5.3.43). Мы выберем источник – Форма. И после этих действий наша группа сразу же заполнится стандартными командами формы (см. рис. 5.3.44).
Рис. 5.3.43
Рис. 5.3.44
Переименуем новую группу в КомандыШапки.
Рис. 5.3.45
На этом мы закончим изучать элемент формы групп. Информации, предоставленной в этой главе, Вам хватит, чтобы объединять элементы в простые группы.
5.17 Поля - для чего?
Поля
Следующая очень обширная группа элементов, которую мы рассмотрим, это Поля ввода. В этом разделе мы научимся работать с полями ввода, и в дальнейшем для ввода какой-то информации в программу будем использовать этот элемент формы.
5.18 Вид «Поле ввода» - что можно вводить?
Посредством элемента формы Поле ввода пользователь имеет возможность просматривать и редактировать реквизиты формы и объектов. Создать поле ввода на форме можно двумя способами. Первый – с помощью кнопки Добавить закладки Элементы, после нажатия на эту кнопку откроется форма выбора типа элемента, в которой нужно выбрать элемент с типом Поле (см. рис. 5.3.46).
Рис. 5.3.46
Второй способ заключается в перетаскивании нужного реквизита из закладки
Реквизиты на форму или в группу формы (см. рис. 5.3.47).
Рис. 5.3.47
На форму можно перетаскивать не только реквизиты формы, но и реквизиты основного реквизита Объект. Особенно это применимо в том случае, когда основной реквизит формы Объект справочника или документа.
Рис. 5.3.48
Если мы добавим элемент с типом Поле ввода на форму (первый способ добавления поля ввода), то на самой форме никакое поле не появится. Так произошло потому, что у вновь созданного поля ввода свойство ПутьКДанным не заполнено (см. рис. 5.3.49). Если же мы будем перетаскивать реквизит формы, то это свойство заполнится автоматически (см. рис. 5.3.50), и, как следствие, поле ввода сразу отобразится на форме.
Рис. 5.3.49
Рис. 5.3.50
Рис. 5.3.51
Разработчик имеет возможность самостоятельно отредактировать свойство ПутьКДанным поля: можно выбрать или реквизит формы, или реквизит основного реквизита (см. рис. 5.3.52).
Рис. 5.3.52
Элементов Поле несколько видов. Разберём самые необходимые из них.
Вид Поле ввода
Самый нужный вид элемента Поле это – Поле ввода (см. рис. 5.3.53). С помощью поля с этим видом мы можем вводить практически любые значения: примитивные (строка, число, дата, булево) и ссылочные (ссылка на справочники, документы и т.д.)
Рис. 5.3.53
Внешний вид Поля на форме будет зависеть от того, какой тип имеет реквизит, указанный в свойстве поля ПутьКДанным. Для реквизита с типом Строка внешний вид поля показан на рис. 5.3.54. Для типов Число, Булево и Дата – на рис. 5.3.55, 5.3.56, 5.3.57. А для ссылочного типа (СправочникСсылка.ТипыТоплива) – на рис. 5.3.58.
Рис. 5.3.54
Рис. 5.3.55
Рис. 5.3.56
Рис. 5.3.57
Рис. 5.3.58
Если у реквизита, который связан с полем ввода, тип Строка, то в некоторых случаях у элемента формы имеет смысл устанавливать свойство МногострочныйРежим в значение Да (см. рис. 5.3.59). Например, это нужно сделать тогда, когда предполагается, что пользователь будет вводить информацию, которая может не войти по длине в поле ввода.
Рис. 5.3.59
Еще одна интересная возможность элемента Поле с типом Поле ввода – это возможность выбирать какие-либо значения из заранее созданного списка. Для демонстрации создадим новый реквизит Выбор (тип Строка) и поместим его на форму в виде поля ввода.
Чтобы реализовать выбор значений, будем использовать два свойства поля ввода, это – РежимВыбораИзСписка, его нужно включить, и свойство СписокВыбора (оба свойства в категории Использование). После нажатия на кнопку «…» свойства СписокВыбора откроется окно, в котором нужно внести все варианты выбора (см. рис. 5.3.60).
Рис. 5.3.60
Причём не важно, какого типа будет реквизит, просто разными значениями будет заполняться поле Значение формы списка выбора.
Для ссылочных типов в конфигураторе можно будет выбрать только предопределённые значения.
После таких настроек у поля ввода на форме появится кнопка списка, при нажатии на которую выпадет список выбора (см. рис. 5.3.61).
Рис. 5.3.61
Заметьте, что в пользовательском интерфейсе в списке будут отображены представления, а после выбора в реквизит запишутся значения.
Чтобы проверить утверждение выше, создадим событие ПриИзменении поля ввода у реквизита Выбор (выберем обработчик события Создать на клиенте, см. рис. 5.3.62).
Рис. 5.3.62
В обработчике события напишем код, в котором просто выведем значение реквизита
Выбор в окно сообщения.
&НаКлиенте
Процедура ВыборПриИзменении(Элемент) Сообщить(Выбор);
КонецПроцедуры
Листинг 5.3.1
Как видите, есть разница между тем, что выбираем и тем, что записывается в реквизит формы.
Рис. 5.3.63
5.19 Вид «Поле надписи»
Вид «Поле надписи»
Этот вид элемента Поле можно применять тогда, когда нужно просто для информации вывести какое-либо значение и у пользователя даже мысли не должно возникнуть о попытке редактирования.
В предыдущем примере мы использовали выбор поля ввода и выводили в сообщении, какое значение присваивается реквизиту. Сделаем так, чтобы это значение отображалось на форме. Для этого опять «перетащим» реквизит Выбор на форму и изменим вид на Поле надписи.
Рис. 5.3.64
Теперь, после выбора значения, помимо сообщения, будет меняться текст в Поле надписи.
Рис. 5.3.65
Этот текст мы сможем прочитать, но не сможем отредактировать.
Рассмотрим ещё один пример. Добавим на форму документа УстановкаЦенНаТопливо поле, в котором будем показывать текущий тип топлива (на который установлен курсор) таблицы формы Цены.
Первым шагом добавим элемент Поле при помощи кнопки Добавить командной панели окна Элементы и сделаем так, чтобы этот элемент был на странице с таблицей формы. Для этого выделим группу страницы, нажмём кнопку Добавить и выберем тип элемента Поле (см. рис. 5.3.66).
Рис. 5.3.66
Назовём новый элемент ТекущийТип, а в свойстве ПутьКДанным укажем путь к полю
ТипТоплива текущих данных таблицы формы ЦеныТоплива (см. рис. 5.3.67).
Установим свойства Заголовок и Вид (см. рис. 5.3.68).
Рис. 5.3.68
После установки значения Поле надписи в свойство Вид отображение элемента Поле
на форме поменялось: непосредственно самого поля ввода нет.
Проверим, как будет работать наше Поле надписи (см. рис. 5.3.69).
Рис. 5.3.69
5.20 Вид «Поле флажка» - для чего?
Вид «Поле флажка»
Для реквизитов с типом Булево можно задать два вида поля – Поле ввода и Поле флажка. Как выглядит Поле ввода для реквизита с типом Булево можно посмотреть на рис. 5.3.70.
Такой вариант интерфейса применим, но не всегда удобен, гораздо практичнее использовать вид поля – Поле флажка (см. рис. 5.3.71).
Рис. 5.3.71
В этом случае поле приобретает более компактный вид.
Но самое интересное – можно сделать разные виды флажка при помощи одноимённого свойства поля ВидФлажка. Это сам флажок, который мы видим на рис. 5.3.71, тумблер – см. рис. 5.3.72, и выключатель – см. рис. 5.3.73.
Рис. 5.3.72
Рис. 5.3.73
Когда вид флажка Тумблер, надписи Истина и Ложь можно заменить более понятными с помощью свойства поля ФорматРедактирования. После нажатия на кнопку
«…» этого свойства откроется конструктор редактирования форматной строки, где на закладке Булево нужно задать представление значений Истина и Ложь (см. рис. 5.3.74).
На рисунке 5.3.75 показано, как будет выглядеть такой тумблер в пользовательском режиме при настройке формата редактирования как на рисунке 5.3.74.
Рис. 5.3.75
5.21 Вид «Поле переключателя» - для чего?
Вид Поле переключателя
С помощью этого поля можно устанавливать на форме различные переключатели.
При этом виде поля нужно работать с уже знакомым нам свойством СписокВыбора, в котором следует указать все возможные значения переключателя.
Для того чтобы понять, как работать с этим полем, создадим реквизит ВыборЧисла с типом число (точность 0), «перетащим» его в элементы и установим для его поля вид Поле переключателя (см. рис. 5.3.76).
Рис. 5.3.76
Следующим шагом следует установить значения переключателя, сделаем это с помощью уже знакомого свойства СписокВыбора (см. рис. 5.3.77), где в левой части таблицы указывается значение, которое примет реквизит при установке того или иного переключателя, а в правой части – отображение этого значения на форме.
Рис. 5.3.77
После соответствующие значения появятся на форме.
Рис. 5.3.78
Причём у нас имеется возможность установить два вида переключателя при помощи свойства ВидПереключателя. Это сам переключатель (см. рис. 5.3.78) и тумблер (см. рис.
5.3.79).
Рис. 5.3.79
С помощью свойства КоличествоКолонок (категория Расположение) можно задать различные расположения переключателя на форме (см. рис. 5.3.80 и 5.3.81). Если свойство КоличествоКолонок равно 0, то все переключатели встают в горизонтальный ряд в зависимости от места на форме, а если равно 1, то – в вертикальный ряд.
Рис. 5.3.80
Рис. 5.3.81
При помощи переключателей мы можем организовывать расположение перечислений на форме. Например, у нашего справочника Автомобили есть реквизит КоробкаПередач, тип которого – ссылка на одноимённое перечисление.
Рис. 5.3.82
Если мы создадим форму элемента справочника Автомобили (сделайте это самостоятельно), то обнаружим, что ссылка на перечисление разместилась на форме в виде поля ввода (см. рис. 5.3.83).
Рис. 5.3.83
Так, конечно, можно работать, но сделаем более удобный вариант в виде переключателя.
У элемента формы справочника Автомобили КоробкаПередач установим в свойстве
Вид значение Поле переключателя, а в свойстве ВидПереключателя – Тумблер (см. рис. 5.3.84).
Рис. 5.3.84
Осталось заполнить СписокВыбора (для быстрого заполнения в окне Список выбора
можно воспользоваться командой Заполнить, см. рис. 5.3.85).
Рис. 5.3.85
А чтобы кнопки тумблера были одинаковой ширины, установим в свойство
ОдинаковаяШирина значение Да.
Рис. 5.3.86
После всех этих настроек внешний вид формы элемента справочника Автомобили
будет таким:
Рис. 5.3.87
На этом закончим изучать поля ввода, этой информации Вам хватит с избытком для дальнейшего изучения материала этой книги.
5.22 Кнопки - как просто добавить
Кнопки
Следующий элемент формы, с которым мы познакомимся, это Кнопки. Частично мы с ними уже сталкивались по мере изучения разработки в 1С. В этом разделе познакомимся с кнопками более подробно. Продолжим работать с формой элемента справочника Автомобили.
Кнопку на форму можно добавить двумя способами.
Первый: используя кнопку Добавить командной панели закладки Элементы. При нажатии на эту кнопку откроется окно Тип элемента, в котором нужно выбрать тип элемента Кнопка (см. рис. 5.3.88).
Рис. 5.3.88
Второй способ: перетащить какую-либо команду на форму (см. рис. 5.3.89).
Рис. 5.3.89
Если мы добавим кнопку на форму первым способом, то она не отобразится на форме, потому что свойство ИмяКоманды у нашей новой кнопки пустое (см. рис. 5.3.90).
Необходимо выбрать команду в этом поле, чтобы кнопка была видна на форме. После нажатия кнопки «…» свойства ИмяКоманды, откроется окно Выбор команды, посредством которого можно выбрать любую команду: от локальных команд формы до глобальных, стандартных команд (см. рис. 5.3.91).
Рис. 5.3.90
Рис. 5.3.91
Кнопка будет создана в любом случае, когда мы свяжем свойство ИмяКоманды с нужной командой. Причём заметьте, кнопка будет создана даже в том случае, если локальная команда формы не связана ни с каким обработчиком. Например, создадим локальную команду формы ВывестиСообщение, у которой свойство Действие будет пустое (см. рис.
5.3.92).
Рис. 5.3.92
Привяжем созданную в начале раздела Кнопку к локальной команде формы ВывестиСообщение. Для этого выберем локальную команду формы в свойстве ИмяКоманды кнопки, тогда кнопка на форме отобразится. Она будет доступна в пользовательском режиме. Просто при нажатии на неё не произойдёт никаких действий.
Рис. 5.3.93
Разберём основные и самые интересные свойства элемента Кнопка. И самое первое свойство – это Вид. У кнопки есть два вида, это Обычная кнопка (см. рис. 5.3.93) и Гиперссылка (см. рис. 5.3.94).
Рис. 5.3.94
Обычно на кнопке – какой-нибудь текст. Этот текст берётся или из имени команды,
которая привязана к кнопке, или из свойства Заголовок команды (если оно заполнено), или из свойства Заголовок кнопки (если оно заполнено).
Для демонстрации утверждения в свойстве Заголовок локальной команды формы ВывестиСообщение напишем текст «Печать», надпись на кнопке поменяется (в свойство кнопки Вид установим обратно значение Обычная кнопка).
Рис. 5.3.95
Если же мы хотим, чтобы рядом с текстом на кнопке была пиктограмма, то необходимо в свойстве Отображение кнопки формы установить значение Картинка и текст, а в свойстве Картинка выбрать нужную картинку с помощью окна Выбор картинки (см. рис. 5.3.96).
Рис. 5.3.96
Нам осталось сделать так, чтобы наша команда работала. Для этого в палитре свойств команды ВывестиСообщение нажмём на пиктограмму Лупа свойства Действие и в открывшемся окне выбора вариантов оставим переключатель на варианте Создать на клиенте (см. рис. 5.3.97).
Рис. 5.3.97
В созданной автоматически процедуре На клиенте напишем код, который просто выведет сообщение.
&НаКлиенте
Процедура ВывестиСообщение(Команда) Сообщить("Эмуляция печати");
КонецПроцедуры
Листинг 5.3.2 Сохраним конфигурацию, перезапустим «1С: Предприятие» и посмотрим, как
отрабатывает наша кнопка (см. рис. 5.3.98).
Рис. 5.3.98
5.23 Декорации - для чего?
Декорации
Этот элемент формы применяется для оформления формы. Декорация может понадобиться, когда необходимо разместить на форме какой-то не связанный с данными текст или какую-нибудь картинку. Чтобы создать декорацию на форме, в закладке Элементы нужно нажать на кнопку Добавить, и в открывшемся окне выбрать или тип Декорация – Надпись, или тип Декорация – Картинка (см. рис. 5.3.99).
Рис. 5.3.99
В обоих случаях будет создан элемент формы Декорация, только в первом случае вид декорации будет Надпись, а в другом – Картинка.
Как уже понятно, элемент Декорация может быть двух видов, это Надпись и Картинка. Когда выбрается тип элемента Декорация – Надпись, или Декорация – Картинка, то свойство декорации Вид уже заполнено, но его можно при необходимости поменять (см. рис. 5.3.100)
Рис. 5.3.100
Если у декорации установлен вид Надпись, то в свойстве Заголовок декорации можно написать любое сообщение. Причём у этого свойства есть кнопка Лупа, нажав на которую, откроется окно ввода строки, где можно ввести как обычную строку (см. рис. 5.3.101), так и форматированную (см. рис. 5.3.102 и 5.3.103).
Рис. 5.3.101
Рис. 5.3.102
Рис. 5.3.103
И хотя мы этому ещё не научились, запомните: не нужно программным способом в заголовок элемента Декорация передавать какие-либо значения. Используйте для этого элемент Поле с видом Поле надписи!
Разберём декорацию с видом Картинка. С помощью этой декорации можно размещать различные статические картинки, которые не будут меняться при открытии разных элементов справочников, документов и т.д.
В четвёртой главе мы добавили общую картинку в конфигурацию (см. стр. 246), эту картинку мы и попробуем использовать в текущем примере.
Добавим новый элемент Декорация – картинка на форму (сдвинем его в верх формы), для того чтобы картинка отобразилась на форме, нужно выбрать какую-либо картинку свойства Картинка (см. рис. 5.3.104).
Рис. 5.3.104
После нажатия на кнопку «…» свойства Картинка откроется форма выбора картинки (см. рис. 5.3.105), в которой пользователь может выбрать картинку из конфигурации, или установить стандартную картинку, или загрузить свою собственную картину.
Не стоит с помощью элемента Декорация размещать картинки, которые будут храниться в базе. Для этого необходимо использовать поле ввода с видом Поле картинки. Как работать с картинками, хранящимися в базе, рассказывается в третьей части книги
«Основы разработки в 1С: Такси».
Рис. 5.3.105
Теперь нужно просто выбрать или общую картинку из конфигурации (закладки Из библиотеки – Из конфигурации), или стандартную картинку, или загрузить картинку из файловой системы.
Выберем картинку из конфигурации (см. рис. 5.3.106).
Рис. 5.3.106
При помощи группы (или групп) разместим декорации следующим образом (сделайте это самостоятельно, как на рис. 5.3.107).
Рис. 5.3.107
На этом мы закончим изучать элементы формы. В дальнейшем при углублении материала мы изучим ещё один нужный элемент – Таблица.
5.24 Часть 4. Программирование управляемых форм. Клиент-серверная архитектура - объяснить суть
Часть 4. Программирование управляемых форм
Мы с Вами дошли до программирования под управляемым приложением. Имейте в виду, что приступать к изучению материалов этой главы лучше имея определённый набор знаний по программированию в среде 1С. Вы должны свободно понимать, что представляют собой переменные в среде 1С, как работают циклы, условия и чем процедура отличается от функции. Если у Вас ещё нет уверенности в этих знаниях, то лучше сначала ознакомится с предыдущими главами. Если же Вы всё это знаете, то можете смело приступать к изучению материала этой части.
5.25 Клиент-серверная архитектура
Клиент-серверная архитектура
Принцип работы «1С: Предприятия 8.3» под управляемым приложением имеет клиент-серверный характер. Не будем углубляться в дебри, скажем только, что это значит,
что какой-то код выполняется в контексте сервера (на компьютере, где работает сервер 1С), а какой-то код в контексте клиента (на компьютере, где работает пользователь клиента 1С).
Причём при разработке управляемого приложения разделение контекста выполнения
программного кода на клиентский контекст и на серверный контектс стало критичным. Узнаем, что означает клиентский контекст выполнения кода, а что – серверный.
Для этого рассмотрим классическую трехзвенную архитектуру «1С: Предприятия». В классическом виде есть клиентские компьютеры, где работают все пользователи, есть кластер серверов «1С: Предприятия», где выполняются все вычисления, и есть SQL-база (СУБД), где хранятся все данные (см. рис. 5.4.1).
Рис. 5.4.1. Клиент-серверная архитектура работы «1С:Предприятия»
На клиентской машине может быть установлено какое-то приложение 1С, которое запускается под толстым или тонким клиентом, а может быть и ничего не установлено, вся работа будет осуществляться посредством веб-клиента из Интернет-браузера. Толстый или тонкий клиент, а также работу под веб-клиентом называют клиентским приложением.
Таким образом, на клиентской машине осуществляется взаимодействие пользователя программы с самой программой 1С. Это взаимодействие осуществляется при помощи механизмов платформы 1С, а также при помощи кода, который написан разработчиками прикладного решения. Выполняясь, этот код задействует ресурсы клиентского компьютера. В этом случае говорят, что он выполняется на клиенте. А контекст выполнения этого кода называют клиентским. Причём нужно различать клиентский контекст под тонким клиентом, под толстым клиентом и под веб-клиентом. Не все методы, которые могут работать под толстым клиентом, будут работать под тонким или веб-клиентом.
Кластер серверов 1С не является чем-то единым целым, а представляет собой несколько запущенных процессов, каждый из которых является сервером 1С. Сервер 1С осуществляет взаимосвязь клиентского приложения с системой управления базы данных (СУБД). Также сервер 1С может исполнять определённый код, тогда говорят, что код выполняется на сервере, а контекст выполнения этого кода – серверный. В случае
выполнения кода на сервере все вычисления будут происходить на той машине, где в этот момент запущен соответствующий экземпляр сервера 1С. Как правило, это мощный и производительный компьютер.
Рис. 5.4.2. Клиентский и серверный контекст выполнения кода При работе в обычном приложении на платформе 8.1 можно было разграничить
выполнение кода на клиентский и серверный контекст, но сделать это можно было или в контексте общего модуля, или в контексте модуля объектов при помощи специальных инструкций процессору.
Форма же в обычном приложении выполнялась полностью на стороне клиентского компьютера. Причём с формы в обычном приложении можно было что угодно делать с базой данных: создавать новые объекты, редактировать их и т.п.
В управляемом приложении всё кардинально поменялось. Теперь на стороне клиентского компьютера форма должна только прорисовывается и всё. Связано это с возникновением тонкого и веб-клиента, которые осуществляют взаимодействие с серверной частью посредством сети Internet. Этот канал связи накладывает существенные ограничения на широту передаваемых данных. И если раньше мы могли на форме делать практически всё: обращаться к базе данных, создавать документы, справочники и т.п., то теперь это стало слишком дорогим удовольствием. Поэтому для нормального функционирования тонкого клиента и веб-клиента в управляемом приложении 1С был существенно переделан механизм работы форм. Форма только прорисовывается на клиенте и всё, а все обработки данных, вычисления и т.п. выполняются на сервере.
5.26 что должен определять разработчик в управляемом приложении?
При разработке управляемых приложений разработчик сам должен определять, какой код будет работать на сервере, а какой на клиенте.
Например, нам нужно на какой-то форме узнать остаток товара на какую-то дату. Для этого мы разместим на форме два реквизита, в одном будет указана ссылка на элемент справочника товаров, а в другом – дата, на которую нужно получить остаток, а также команду Получить остаток, которая помещена на форму в виде кнопки. Следующим шагом нужно определить, что будет выполняться на сервере, а что на клиенте. Понятно, что обработка нажатия на кнопку (обработчик команды Получить остаток) должна выполняться на клиентской машине (где работает пользователь). А функция подсчёта остатков – на серверной (где установлен сервер 1С), поскольку идёт обращение к базе данных. Но это ещё не всё. Нам нужно вызвать из метода, который выполняется на клиенте (обработка нажатия на кнопку), метод, который выполняется на сервере (подсчёт остатков).
В момент, когда метод на клиенте обращается к процедуре или функции, которая должна выполняться на сервере, происходит вызов сервера и передача управления на сервер. Процедура или функция на сервере отрабатывает, и происходит передача управления обратно на клиента, в то место, откуда была вызвана серверная процедура.
И заметьте, вызов сервера будет происходить каждый раз, когда идёт вызов процедуры или функции, которая выполняется на сервере. Причём этот вызов в иных случаях может происходить быстро и быть практически незаметным (при работе по локальной сети), а может быть очень медленным (при работе по сети Internet). Поэтому разработчику при конструировании прикладной системы необходимо очень внимательно относиться к вызову процедур на сервере, чтобы не создавать «тормознутые приложения».
В то же время вызовы серверов могут отличаться. При обычном вызове сервера на сервер передаётся информация о данных формы, но можно вызвать сервер без передачи информации о форме. Это так называемый вызов сервера без контекста. Их отличия мы будем проходить позже.
Таким образом, разработчику прикладного решения придётся решать несколько проблем. Одна из них – это определить, когда следует вызывать серверную процедуру или функцию, а когда нет. Например, нет смысла вызывать метод на сервере внутри какого-то цикла, поскольку во время итерации цикла каждый раз будет происходить вызов сервера и передача управления на клиента. В этом случае нужно вызвать один раз серверный метод перед циклом, а потом уже в цикле использовать результаты работы этого метода.
Ещё одна головная боль хорошего разработчика – определить, какой серверный метод нужно вызывать обычным образом (с передачей реквизитов формы на сервер), а какой метод будет вызываться без контекста. Потому что если мы каждый раз будем отправлять на сервер большие объёмы информации с формы, а потом получать их обратно, это существенно скажется на производительности приложения. Но тут стоит знать, что не все данные с формы при обычном вызове передаются на сервер, а только те, которые были изменены.
Но это ещё не всё, вспомним наш вызов процедуры подсчёта остатков, где мы передаем на сервер какие-то объекты. В нашем случае это ссылка на какой-то элемент справочника Номенклатура и дата. Иногда при передаче каких-либо значений на сервер могут возникнуть определённые проблемы: не все объекты можно передать с клиента на сервер и наоборот, не всё можно передать с сервера на клиент. Например, с сервера на клиент нельзя передать объект справочника или документ и, наоборот, с клиента на сервер нельзя
передать какой-нибудь элемент формы.
5.27 что значит сериализироваться? какие объекты могут сериализироваться?
Для того чтобы объект можно было передавать на сервер, он должен сериализоваться. Сериализация, простыми словами, это возможность представления объекта в каком-то виде, например, в виде текстовой строки, или в виде XML. Для начинающего программиста поначалу сложно будет понять, какой объект подлежит сериализации, а какой нет. Но вся информация об этом содержится в синтаксис-помощнике. Например, объект Массив (массивы будем проходить в седьмой главе) подлежит сериализации.
Рис. 5.4.3
И, естественно, нужно помнить и знать, что при разработке управляемого приложения очень существенно ограничиваются наши действия в контексте серверного и клиентского кода. С клиентского контекста мы не можем получить прямой доступ к объектам базы 1С, у нас нет возможности ими манипулировать (добавлять, изменять, удалять и т.п.), а также не можем обращаться к свойствам этих объектов.
Например, на клиенте у нас не получится прочитать у ссылки на справочник Номенклатура, который хранится в реквизите формы, реквизиты и свойства этой ссылки. При попытке выполнения в клиентском контексте кода вот такого вида: НаименованиеНоменклатуры = Номенклатура.Наименование; произойдёт ошибка. В то же время в серверном контексте нет смысла в выполнении кода, который обрабатывает различные события на форме (нажатие на кнопку и т.п.)
Также стоит учитывать вид клиентского контекста. Какие-то объекты доступны в тонком, толстом и веб-клиенте (как тот же Массив). А какие-то – только в толстом клиенте, например, ТаблицаЗначений (изучим в восьмой главе). Определить, что выполняется в каком виде клиента, можно в справочной информации.
Рис. 5.4.4
Та же ТаблицаЗначений вполне работает в клиентском контексте, но только в режиме
толстого клиента.
Что же из себя представляет форма в клиент-серверном понимании? Форма – это программный объект, который создаётся на сервере согласно настройкам, сделанным в конфигураторе (если формы нет в конфигураторе, то она генерируется автоматически платформой), а потом выводится в клиентском приложении. Таким образом, форма одновременно существует и на сервере, и на клиенте! А как следствие – у формы есть и серверный, и клиентский контекст выполнения кода.
При разработке форм под управляемым приложением разработчик должен сам указывать, какой код будет выполняться на сервере, а какой на клиенте. Делается это при помощи директив компиляции.
5.28 Директивы компиляции - сколько их?
Директивы компиляции
При разработке формы в управляемом приложении программисту нужно явно указывать, какой код выполняется в клиентском контексте, а какой – в серверном контексте. Осуществляется это при помощи директив компиляции, которые предопределены в платформе 1С. Директивы компиляции следует указывать перед каждой функцией или процедурой (а также переменными) в модуле формы, в общем модуле (если общий модуль работает и в клиентском, и в серверном контектсе) и в модуле команды. Все директивы компиляции начинаются с символа амперсанд - &. И от них зависит, в каком контексте будет выполняться код в процедуре или функции. Всего их пять:
&НаКлиенте
&НаСервере
&НаСервереБезКонтекста
&НаКлиентеНаСервереБезКонтекста
&НаКлиентеНаСервере
В этой книге мы изучим только первые три директивы.
5.29 &НаКлиенте - что доступно
&НаКлиенте – когда процедура или функция предварена этой директивой, то данный метод будет выполняться в клиентском контексте. Это значит, что он будет выполняться на той машине, где в текущий момент функционирует клиентское приложение. Из такой процедуры или функции будут доступны все данные формы, а также из неё можно вызывать любую процедуру или функцию текущего модуля. Под этой директивой будет доступен весь клиентский контекст формы, т.е. мы можем вызывать любые функции под директивой &НаКлиенте.
Все обработчики команд всегда выполняются на клиенте. Для того чтобы проверить это утверждение, разместим на любой форме (для этого мы создали новую обработку) произвольную команду (например, Нажатие кнопки) и нажмём на кнопку Лупа свойства Действие этой команды (см. рис. 5.4.5).
Рис. 5.4.5
После нажатия на кнопку Лупа свойства Действие команды платформа предложит выбрать, где создать обработчик события (см. рис. 5.4.6). Заметьте, во всех трёх вариантах создания процедуры обработчика присутствует процедура, которая будет выполняться на клиенте. Просто в случаях выбора Создать процедуру на клиенте и на сервере и Создать процедуру на клиенте и на сервере без контекста будет создана процедура на клиенте, которая будет вызывать процедуру или на сервере, или на сервере без контекста. Ниже мы разберём этот момент.
Рис. 5.4.6
Мы выберем пункт Создать на клиенте, и после нажатия кнопки ОК в модуле формы автоматически появится код, как на листинге 5.4.1.
&НаКлиенте
Процедура НажатиеКнопки(Команда)
// Вставить содержимое обработчика.
КонецПроцедуры
Листинг 5.4.1
Имейте в виду, все обработчики элементов формы должны всегда выполняться под директивой &НаКлиенте (см. листинг 5.4.1). Другими словами – обработка событий всех элементов формы имеет клиентский контекст.
Любая процедура или функция, которая написана под директивой &НаКлиенте,
может использовать все методы этой формы под директивами &НаКлиенте, &НаСервере, &НаСервереБезКонтекста и &НаКлиентеНаСервереБезКонтекста. Поэтому код, показанный на листинге 5.4.2, будет успешно выполняться и не вызовет ошибки.
&НаКлиенте
Процедура НажатиеКнопки(Команда) ПроцедураВыполняемаяНаКлиенте();
КонецПроцедуры
&НаКлиенте
Процедура ПроцедураВыполняемаяНаКлиенте()
//....
КонецПроцедуры
Листинг 5.4.2
Директива &НаКлиенте – единственная директива, из-под которой доступен клиентский контекст формы (все процедуры или функции, которые выполняются под директивами &НаКлиенте).
&НаСервере – код процедуры или функции под этой директивой будет выполняться в серверном контексте, т.е. на машине, где запущен сервер 1С (в случае файловой базы сервер 1С эмулируется платформой). Все данные формы будут переданы на сервер, а потом обратно на форму после завершения выполнения метода. Из процедуры под этой директивой будет доступен весь серверный контекст формы, т.е. все процедуры или функции, которые выполняются на сервере, можно вызвать из метода предварённого этой директивой. Но в то же время клиентский контекст формы не будет доступен.
Проверим работу данной директивы, для этого очистим все обработчики команды Нажатие кнопки, очистим свойство Действие, заново на него нажмём и выберем вариант Создать на клиенте и процедуру на сервере (см. рис. 5.4.7).
Рис. 5.4.7
В результате этих действий автоматически будут созданы две процедуры. Одна на
сервере, а другая на клиенте (см. листинг 5.4.3).
5.30 &НаСервере - что доступно
&НаСервере
Процедура НажатиеКнопкиНаСервере()
// Вставить содержимое обработчика.
КонецПроцедуры
&НаКлиенте
Процедура НажатиеКнопки(Команда) НажатиеКнопкиНаСервере();
КонецПроцедуры
Листинг 5.4.3
В этом листинге процедура клиентского контекста НажатиеКнопки вызывает процедуру серверного контекста НажатиеКнопкиНаСервере. В методе, который выполняется под директивой &НаСервере, нам доступны все данные формы: реквизиты, параметры и т.д. Но нам уже не доступен клиентский контекст формы. Если мы напишем еще одну процедуру под директивой &НаКлиенте (см. листинг 5.4.4) и попытаемся её вызвать из новой серверной процедуры НажатиеКнопкиНаСервере, то при проверке модуля будет сгенерирована ошибка (см. рис. 5.4.8).
&НаСервере
Процедура НажатиеКнопкиНаСервере() ВыполнениеНаКлиенте()
КонецПроцедуры
&НаКлиенте
Процедура НажатиеКнопки(Команда) НажатиеКнопкиНаСервере();
КонецПроцедуры
&НаКлиенте
Процедура ВыполнениеНаКлиенте() КонецПроцедуры
Листинг 5.4.4
Рис. 5.4.8
Платформа просто не видит эту процедуру, потому что из серверного контекста клиентский контекст не доступен, в отличие от обратного случая.
использовании методов (тонкий клиент) и при серверном. Для этого на форме обработки создадим новый реквизит Автомобиль с соответствующим типом (ссылка на справочник Автомобили) и разместим его на форме (см. рис. 5.4.9). Поставим точки останова в процедурах НажатиеКнопки и НажатиеКнопкиНаСервере (см. рис. 5.4.10) и начнём отладку тонкого клиента (см. рис. 5.4.11).
Рис. 5.4.9
Рис. 5.4.10
Рис. 5.4.11
В открывшейся обработке выберем какой-нибудь автомобиль (см. рис. 5.4.12) и нажмём на кнопку Нажатие кнопки.
контексте, и сработала она под тонким клиентом. Попробуем в табло прочитать значение реквизита Автомобиль (см. рис. 5.4.13).
Рис. 5.4.13
Как видно из рисунка 5.4.13, мы получили доступ только к самому реквизиту, но не можем прочитать подчинённые поля этого реквизита.
А если мы перейдём в процедуру НажатиеКнопкиНаСервере, то картинка в табло будет другой (см. рис. 5.4.14).
Рис. 5.4.14
В серверном контексте мы можем получить подробнейшую информацию об объекте
ссылочного типа, включая все подчинённые поля, в отличие от клиентского контекста
тонкого клиента, где мы можем обратиться только в целом к реквизиту.
В то же время к свойствам элемента формы Автомобиль (об элементах формы ниже) можно обращаться как из процедуры НажатиеКнопки, так и из процедуры НажатиеКнопкиНаСервере, то есть из клиентского и из серверного контекста формы (см. рис. 5.4.15 и 5.4.16).
Рис. 5.4.15
Рис. 5.4.16
Не рекомендуется для работы с элементами формы специально делать вызов серверного метода, поскольку такое неоптимальное использование вызова серверных методов может сказаться на производительности приложения в целом.
Ещё раз подытожим, при вызове метода под директивой &НаСервере доступны все данные формы, доступен серверный контекст формы, а также можно вызывать внеконтекстные серверные процедуры и функции (с директивой &НаСервереБезКонтекста). В то же время нужно иметь в виду, что при вызове серверного метода происходит передача всех данных формы на сервер, а потом обратно, что может сказаться на производительности
приложения, особенно запускаемого под тонким клиентом.
5.31 &НаСервереБезКонтекста - отличие от &НаСервере?
&НаСервереБезКонтекста – код процедуры или функции под этой директивой, как и в случае с директивой &НаСервере, будет выполняться в серверном контексте, т.е. на машине, где запущен сервер 1С. Но в отличие от серверного вызова методов, при внеконтекстном серверном вызове, данные формы не будут передаваться на сервер, и, как следствие, не будут доступны из метода под этой директивой. Из процедуры или функции под этой директивой будет отсутствовать доступ к серверному контексту формы, т.е. из процедуры или функции под директивой &НаСервереБезКонтекста нельзя вызвать процедуры или функции под директивой &НаСервере.
Сейчас мы проверим, как работает безконтекстный вызов процедуры или функций. Для этого создадим новую команду НажатиеКнопкиБезКонтекста, которую поместим на форму в виде кнопки (см. рис. 5.4.17). При создании действия для этой команды, выберем вариант Создать на клиенте и процедуру на сервере без контекста.
Рис. 5.4.17
После нажатия кнопки ОК в модуле формы будут автоматически созданы две процедуры, одна будет под директивой &НаКлиенте, а другая – под директивой &НаСервереБезКонтекста (см. листинг 5.4.5).
&НаСервереБезКонтекста
Процедура НажатиеКнопкиБезКонтекстаНаСервере()
// Вставить содержимое обработчика.
КонецПроцедуры
&НаКлиенте
Процедура НажатиеКнопкиБезКонтекста(Команда) НажатиеКнопкиБезКонтекстаНаСервере();
КонецПроцедуры
Листинг 5.4.5
Как уже сказано выше, из внеконтекстной процедуры не доступен серверный контекст формы (как и клиентский, кстати). Проверим это, попытаемся использовать в нашей новой процедуре НажатиеКнопкиБезКонтекстаНаСервера метод под директивой &НаСервере, т.е. процедуру, которая выполняется в серверном контексте формы (см. листинг
5.4.6).
&НаСервереБезКонтекста
Процедура НажатиеКнопкиБезКонтекстаНаСервере() ВыполнениеНаСервере()
КонецПроцедуры
&НаКлиенте
Процедура НажатиеКнопкиБезКонтекста(Команда) НажатиеКнопкиБезКонтекстаНаСервере();
КонецПроцедуры
&НаСервере
Процедура ВыполнениеНаСервере()
КонецПроцедуры
Листинг 5.4.6
Если мы выполним синтакс-проверку модуля, то платформа выдаст ошибки (см. рис.
5.4.18). Из методов под директивой &НаСервереБезКонтекста можно вызвать только методы под такой же директивой, или под директивой НаКлиентеНаСервереБезКонтекста.
Рис. 5.4.18
Также в момент вызова внеконтекстного метода не происходит передача данных формы на сервер и обратно. Как следствие, из внеконтексной процедуры нет доступа ни к реквизитам формы, ни к элементам и т.п. (см. рис. 5.4.19). В то же время, поскольку передача данных формы при вызове внеконтекстного серверного метода не происходит, то вызов такого метода осуществляется гораздо быстрее. Поэтому рекомендуется использовать вызов внеконтекстовых серверных методов для оптимизации работы приложения, когда не нужен доступ к данным формы.
Рис. 5.4.19
В тоже время внеконтекстный серверный метод можно спокойно вызывать как из клиентского контекста (см. листинг 5.4.7), так и из серверного контекста (см. листинг 5.4.7).
&НаСервере
Процедура НажатиеКнопкиНаСервере() НажатиеКнопкиБезКонтекстаНаСервере();
КонецПроцедуры
&НаКлиенте
Процедура НажатиеКнопки(Команда) НажатиеКнопкиБезКонтекстаНаСервере(); НажатиеКнопкиНаСервере();
КонецПроцедуры
&НаСервереБезКонтекста
Процедура НажатиеКнопкиБезКонтекстаНаСервере()
КонецПроцедуры
Листинг 5.4.7
На этом мы закончим изучать директивы компиляции, при помощи этих трёх директив можно выполнить большинство работ с управляемыми формами.
Реквизиты и параметры формы
5.32 Реквизиты формы - для чего предназначены?
Разберём основные моменты работы с реквизитами и параметрами управляемой формы в разрезе клиент-серверной архитектуры. Реквизиты мы уже проходили в предыдущей части, в этой углубим наши знания. Реквизиты формы создаются на закладке Реквизиты редактора формы (см. рис. 5.4.20). А параметры формы – в закладке Параметры (см. рис.
5.4.21).
Создадим новую обработку, форму. На форме создадим следующие реквизиты:
И следующие параметры:
Рис. 5.4.20
Рис. 5.4.21
Реквизиты формы предназначены для хранения данных, с которыми работает форма. Они образуются в момент создания формы и уничтожаются после её закрытия. К реквизитам можно обратиться и в серверном контексте формы, и в клиентском. Т.е. в методах под директивами &НаКлиенте и &НаСервере.
На форме можно создать элемент, который будет связан с реквизитом посредством свойства ПутьКДанным (см. рис. 5.4.22). Посредством этого элемента можно менять значения реквизита формы. Но совсем не обязательно размещать реквизит на форме. Его можно использовать как какую-нибудь внутреннюю переменную формы, которая будет доступна и в серверном, и в клиентском контексте.
Рис. 5.4.22
Когда реквизит размещён на форме, рядом с ним появляется серый квадратик.
Рис. 5.4.23
Параметры необходимы для передачи информации в форму при её открытии, к ним можно получить доступ только в моменты создания формы и её открытия. После её создания параметры будут уничтожены. Если необходимо, чтобы параметр существовал после создания формы, то у него следует установить свойство Ключевой параметр (см. рис. 5.4.24).
Рис. 5.4.24
Работу с параметрами мы разберём в разделе, когда будем изучать вопросы открытия форм. А пока изучим некоторые моменты использования реквизитов.
Для начала посмотрим, как используются реквизиты в серверном и клиентском контексте формы. Тут нет ничего особенного. Мы просто пишем в коде название реквизита и как-то с ним работаем: присваиваем ему какое-то значение, читаем значение этого реквизита и т.п. Для демонстрации создадим две команды, одна будет работать только в клиентском контексте, а вторая будет вызывать также процедуру из серверного контекста. Поместим обе эти команды на форму, с формы удалим поле ввода, связанное с реквизитом рАвтомобиль, а вместо него поместим на форму реквизит рСтрока (изменим заголовок поля ввода, см. рис. 5.4.25).
Рис. 5.4.25
Создадим обработчики событий этих команд. В первом случае будет только обработчик на клиенте, а во втором случае обработчик на клиенте будет делать серверный вызов. В каждом обработчике присвоим реквизиту рСтрока какое-нибудь значение (см. листинг 5.4.8).
&НаКлиенте
Процедура НаКлиенте(Команда)
рСтрока = "Заполнили на клиенте";
КонецПроцедуры
&НаСервере
Процедура НаСервереНаСервере() рСтрока = "Заполнили на сервере";
КонецПроцедуры
&НаКлиенте
Процедура НаСервере(Команда) НаСервереНаСервере();
КонецПроцедуры
Листинг 5.4.8
Посмотрим, как будет работать код при выполнении обеих команд (см. рис. 5.4.26 и 5.4.27).
Рис. 5.4.26
Рис. 5.4.27
Заметьте, в обоих случаях мы не писали какой-то код, чтобы новое значение автоматически отобразилось в поле на форме. Платформа сама обновила элемент формы при изменении реквизита. Во втором же случае изменение реквизита произошло в серверном контексте формы и значение на форме тоже изменилось. В случае команды НаСервере, после того как мы нажали на кнопку, в клиентском обработчике произошёл серверный вызов (когда сработала процедура НаСервереНаСервере), все данные формы были переданы в серверный контекст, затем, после окончания вызова, они были переданы обратно в клиентский контекст формы. В этом же контексте и произошло обновление элемента на форме.
Но в то же время мы не можем использовать реквизит формы при внеконтекстном серверном вызове. Например, код, который показан на листинге 5.4.9, ни к чему не приведёт. Объясните самостоятельно – почему.
&НаСервереБезКонтекста
Процедура КомандаСВызовомСервераНаСервере() Реквизит1 = "Заполнили на сервере";
КонецПроцедуры
&НаКлиенте
Процедура КомандаСВызовомСервера(Команда) КомандаСВызовомСервераНаСервере();
КонецПроцедуры
Листинг 5.4.9
На этом мы закончим изучение форм. В этой главе мы научились создавать формы объектов в конфигураторе, узнали, что такое командный интерфейс, познакомились с реквизитами формы и с элементами формы, а также узнали, что такое клиент-серверная архитектура и директивы компиляции. Этой информации хватит для дальнейшего изучения материала книги. В процессе изучения мы углубим наши знания: научимся открывать форму программно и научимся программно работать с элементами формы.
(3) 6.01 Глава 6. Объектные типы. Часть 1. Объекты метаданных. Теоретическая часть - что такое Объекты в языке программирования?
Общая часть
Перед тем как начнём работать с объектными типами, выясним – что такое Объекты? Рассмотрим пример, на основе которого Вам будет легче осмыслить понятие объектов. Пусть мы имеем объект автомобиль (например, «Лада-Веста», будем патриотами). У автомобиля есть свойства, такие как: объём двигателя, мощность в лошадиных силах, коробка передач (автомат или ручная), количество пассажиров, максимальное количество топлива в бензобаке, текущая скорость автомобиля, вес и т.п.
С этим автомобилем мы можем совершать разные операции: изменять скорость, переключать передачи, заливать бензин, сажать пассажиров и очень многое другое. Мы рассмотрели нашу «Ладу-Весту» как объект в целом, но есть ещё Экземпляры объекта.
Это значит, что «Весту» может купить Вася, Петя или Марья Ивановна, и у каждого из них будет свой Экземпляр объекта «Лада-Веста».
Некоторые свойства экземпляров объекта могут различаться, например, Вася купил
«Ладу-Весту» с автоматической коробкой передач, а Петя – с ручной. Васина скорость в данный момент 100 км/ч, он едет по автостраде, а Петина – 10 км/ч, он плетётся в пробке. Какие-то свойства автомобиля может менять пользователь (например, скорость), а какие-то нет (например, коробку передач). Это открытые и закрытые свойства.
Тем самым приходим к выводу, что Объект в терминах 1С – это некоторая сущность, обладающая Свойствами, над которой можно совершать различные манипуляции посредством Методов. А также у объекта могут быть События. Например, автомобиль тронулся, или остановился, или в него начали закачивать топливо. События отличаются от методов именно тем, что они возникают во время каких-то действий с объектом. Автомобиль остановился, и его скорость стала равно 0, например.
Пользователь программы работает не с самим объектом, а с Экземпляром объекта, который он или создал самостоятельно, или при помощи кода, написанного разработчиком.
Ещё один момент. Обычно водитель совершает действия с автомобилем в определённом порядке: сначала заливает бензин, потом садится в салон, включает зажигание, после этого выжимает сцепление, ставит передачу и трогается. Что произойдёт, если водитель сразу попытается тронуться, не совершив эти действия? Правильно, автомобиль не поедет. То есть действия объекта обладают некоторой историей.
Так же, как и в случае с автомобилем, поведение объекта определяется его историей: к примеру, мы не сможем отсортировать таблицу значений, если она не заполнена.
Хочу предупредить тех, кто изучал объектно-ориентированное программирование в других языках. Язык 1С не является объектно-ориентированным, как говорят сами разработчики платформы, язык 1С – это объектно-прикладной язык. В платформе 1С
существуют различные прототипы объектов, с которыми Вы уже частично знакомы. Это справочники, документ и прочие метаданные, которые называются прототипами. В языке программирования 1С разработчик не может самостоятельно создавать собственные прототипы объектов. Также объекты не обладают такими понятиями, как наследственность, изменчивость и инкапсуляция. Вы сможете работать только с теми прототипами объектов, которые создали разработчики платформы 1С. В этом есть свои плюсы и свои минусы. Плюс в том, что любое решение, с которым Вы будете работать, стандартизировано, Вам будут знакомы все прототипы объектов, в нём используемые. Минус в том, что при разработке самостоятельных решений Вы не сможете создавать собственные прототипы объектов, которые покажутся Вам более уместными в Вашем случае. Придётся довольствоваться тем, что предоставили разработчики платформы.
(3) 6.02 В 1С сколько видов объектов:
В 1С можно условно выделить три вида объектов: Объекты метаданных (прикладные объекты или объекты конфигурации), Общие объекты и Универсальные коллекции значений.
Объекты конфигурации 1С или прикладные объекты – создаются на этапе конфигурирования разработчиком – это справочники, документы, константы и т.п. Пользователь может непосредственно работать с некоторыми объектам – создавать экземпляры объектов и манипулировать ими. Или использовать их – отчёты, обработки и т.п.
Общие объекты – это объекты встроенного языка программирования 1С, которыми может оперировать разработчик, необходимые для различных технических и вспомогательных нужд (например, такой общий объект, как ДиалогВыбораФайла предназначен для работы с диалогом открытия файла, сохранения файла и т.д.)
Универсальные коллекции значений – это так же, как и общие объекты, объекты встроенного языка программирования, которыми может оперировать разработчик. Но, в отличие от общих объектов, они предназначены для хранения наборов данных, причём эти наборы данных хранятся в оперативной памяти компьютера во время запущенного сеанса. Таким образом, когда пользователь прекратит работу с сеансом 1С, то и вся информация этих наборов данных будет уничтожена.
Что общего у каждого вида объекта? У любого объекта из вышеперечисленных видов можно создать Экземпляр объекта. В случае объектов метаданных этот экземпляр будет храниться в базе данных, а в случае общих объектов и универсальных коллекций значений экземпляр объекта будет доступен только во время работы приложения или какого-то блока приложения (например, если какой-то массив будет создан в контексте какой-то формы, то он будет существовать, пока форма работает).
Ещё у объектов могут быть свойства, методы и события.
Свойство объекта – это поле, которое может содержать какую-то информацию, связанную с этим объектом. Это поле может быть доступно для записи (можно записать какую-то информацию в это поле) и для чтения (информацию можно прочитать из этого поля), или просто для чтения. Причём информация в свойстве объекта связана не с самим объектом, а с его экземпляром.
Метод объекта – это процедура или функция, которая выполняет или какое-то действие над экземпляром этого объекта, или возвращает информацию о состоянии экземпляра этого объекта.
Событие – это процедура, которая позволяет перехватить какое-то событие над этим объектом, и либо доработать это событие, либо отменить его.
(3) 6.03 Каким образом можно прочитать свойства объекта или исполнить тот или иной метод?
Каким образом можно прочитать свойство экземпляра объекта или исполнить тот или иной метод? Это делается через точку. Сначала пишется экземпляр объекта, потом точка, потом свойство объекта или его метод.
В общей схеме это будет выглядеть так:
Объект.Свойство Объект.Метод(<Параметры>)
(3) 6.04 какие действия можно совершать со свойствами?
Свойство пишем без скобок, мы можем присвоить ему какое-нибудь значение, а можем и просто прочитать. Например, какой-то переменной присвоить свойство объекта. Если свойство закрыто от редактирования, то можем его только прочитать.
Это выглядит так.
Присваиваем свойству значение:
Объект.Свойство = "Товар";
Читаем значение из свойства и записываем прочитанное значение в переменную:
НашаПеременная = Объект.Свойство;
В первом случае мы присваиваем какому-то свойству строковое значение, причём свойство должно быть тоже строкового типа, иначе оно просто не присвоится.
(3) 6.05 какая возможна ошибка при присвоении реквизиту значения
Вот на это обратите внимание! Очень много ошибок связано с тем, что какому- нибудь реквизиту присваивается значение не того типа. Платформа в этом случае никаких ошибок не генерирует. Просто ничего не присвоится. Будьте внимательны, когда записываете данные в какие-либо свойства (реквизиты).
Разберём, как работают методы:
Объект.Метод(); Объект.Метод(Параметр1, Параметр2); НашаПеременная = Объект.Метод();
НашаПеременная = Объект.Метод(Параметр1, Параметр2);
6.06 отличие в коде методов от свойств? как работают методы?
Метод пишется также через точку, только обязательно должен содержать
открывающую и закрывающую скобки. Скобки могут содержать в себе параметры, а могут и не содержать. Также метод может быть функцией и возвращать какое-либо значение, а может быть процедурой и не возвращать.
В случае объектов метаданных разработчик может создавать собственные методы и свойства (реквизиты), если же мы имеем дело с общими объектами и универсальными коллекциями значений, то можем довольствоваться только теми свойствами и методами, которые предоставляет платформа 1С.
И остались ещё события.
Все виды событий с теми или иными объектами определены заранее, т.е. разработчик не может самостоятельно придумать и создать какое-нибудь новое событие. Он может только создавать событие, которое определено для объекта. Например, для объекта Справочник определены события ПриЗаписи и ПередЗаписью, мы можем создать соотвествующие события и отработать их (допустим, записать какой-то реквизит или выполнить какую-то проверку), но мы не можем создать событие, скажем, ПослеЗаписи, которое будет срабатывать после записи объекта. Мы можем использовать только события ПриЗаписи и ПередЗаписью, и другие события справочников, которые определены создателями платформы 1С.
Разработчик приложения может создать событие ПередЗаписью, где будет описан какой-нибудь алгоритм проверки, который сработает во время этого события, а может и не создавать, в этом случае объект просто запишется без всяких проверок.
Как узнать, какой объект, какие свойства, методы и события имеет? Узнать это можно в синтакс-помощнике. Например, в случае справочников информацию о свойствах, методах и событиях можно посмотреть в следующих каталогах.
Рис. 6.1.1
А в случае Массива в справке мы увидим только каталог с методами и конструкторами.
Рис. 6.1.2
Как создаются объекты? Все объекты, кроме прикладных объектов (объектов метаданных), создаются при помощи конструкторов: пишется какая-то переменная, оператор присваивания и по определённому синтаксису конструктор. Как правило, все конструкторы общих объектов и универсальных коллекций значений используют оператор Новый.
Например, Массив (универсальная коллекция значений) может быть создан так:
мЧисел = Новый Массив;
А Табличный документ (общий объект) создается так:
ТабДок = Новый ТабличныйДокумент;
После выполнения вышеперечисленного кода в первом случае будет создана переменная мЧисел, тип которой будет Массив, а во втором случае будет создана переменная ТабДок, тип которой будет Табличный документ.
Общие объекты и универсальные коллекции значений не могут храниться сами по себе где-то, они должны храниться в переменных. Мы не можем создать массив или табличный документ просто так, мы можем или создать переменную и присвоить этой переменной новый массив при помощи конструктора Новый, или взять готовую переменную (если она уже создана при помощи оператора Перем) и также присвоить этой переменной новый массив при помощи конструктора Новый.
Такой ход действий справедлив для общих объектов и универсальных коллекций значений, но работа с прикладными объектами осуществляется несколько по-другому.
Прикладные объекты 1С
Прикладные объекты – это элементы конфигурации, такие как константы, справочники, документы, регистры сведений и регистры накоплений. Их больше, но нас пока интересуют только эти. Они создаются на этапе конфигурирования, и мы научились это делать в четвёртой главе. А экземпляр прикладного объекта – это элемент справочника или документ, или запись регистра сведений (накоплений), который создал пользователь при работе с прикладным решением. Экземпляр прикладного объекта можно изменить: записать значения в реквизиты, заполнять табличные части, а потом изменённый экземпляр можно сохранить в базу данных. Экземпляр прикладного объекта может храниться в базе данных, а может и не храниться. Например, пользователь может создать какой-то новый документ, заполнить его какими-то даными, но не сохранить этот документ по определённой причине. В этом случае – экземпляр был создан, но не был записан в базу.
У прикладных объектов имеются свойства. Во-первых, это реквизиты, которые созданы разработчиком прикладного решения. Во-вторых, это стандартные реквизиты, созданные разработчиками платформы 1С (их состав отличен для каждого прототипа). В- третьих, это табличные части. И, в-четвёртых, есть свойства, которые не входят ни в одну из вышеперечисленных категорий, но всё равно являются свойствами, к которым можно обратиться (например, ЭтотОбъект для справочников).
(3) особенность модуля объекта
Также у объектов имеются методы. Метод объекта – это процедура или функция, с помощью которой осуществляются манипуляции с экземпляром объекта (например, метод может как-то изменять экземпляр). К методу объекта можно обратиться через экземпляр посредством точки. Например, так:
Объект.Записать();
Разработчик может самостоятельно создать собственный метод объекта в модуле объекта, но чтобы к методу можно было обратиться через экземпляр объекта, этот метод должен быть экспортным (после названия должно следовать ключевое слово Экспорт).
Процедура ПослеЗаписи() Экспорт КонецПроцедуры
Но также можно использовать методы, предоставляемые платформой 1С. У каждого прототипа объекта свой собственный перечень методов. Ознакомиться с ними можно в синтакс-помощнике.
Рис. 6.1.3
Резюмируем. В отличие от общих объектов и универсальных коллекций, у прикладных объектов разработчик прикладного решения может самостоятельно создавать нужные ему свойства и методы. Но также можно воспользоваться теми свойствами и методами, которые были созданы разработчики платформы 1С. Например, у всех справочников есть свойство Наименование. Разработчик конфигурации не может его удалить, в отличие от реквизита, который был создан на этапе разработки.
Менеджер Объекта
Пора выяснить, каким образом в программных модулях осуществляется работа с прикладными объектами.
Основное ключевое понятие прикладных объектов метаданных – это Менеджер. Для каждого прикладного объекта конфигурации существует свой менеджер, посредством которого осуществляется работа с этим объектом. Используя менеджер, можно программно создать объект, получить выборку ссылок объектов (о них мы поговорим позже), найти ссылку на какой-нибудь объект и получить форму объекта.
Для того чтобы создать менеджер прикладного объекта, необходимо обратиться к свойству глобального контекста по имени прототипа, к которому относится объект, чей менеджер мы создаём. Если мы создаём менеджер какого-то справочника, то свойство так и будет называться – Справочники, документа – Документы.
Создадим менеджер документа ПрибытиеВГараж.
&НаСервереБезКонтекста
Процедура СоздаемОбъектНаСервере() ПрибытиеВГаражМенеджер = Документы.ПрибытиеВГараж;
КонецПроцедуры
&НаКлиенте
Процедура СоздаемОбъект(Команда) СоздаемОбъектНаСервере();
КонецПроцедуры
Листинг 6.1.1
Работать с объектными типами мы можем или в серверном контексте формы или вообще на сервере без контекста. Обращение к менеджеру документа в листинге 6.1.1 было выполнено в бесконтекстном вызове сервера. Самостоятельно ответьте – почему.
В коде листинга 6.1.1 мы создали переменную, которая является менеджером объекта документ Прибытие в гараж (тут и далее мы используем конфигурацию, созданную в четвёртой главе). Рассмотрим данный код.
Слово Документы – это свойство глобального контекста, которое является коллекцией менеджеров всех документов конфигурации. Мы можем посмотреть на эту коллекцию, достаточно воспользоваться контекстной подсказкой.
Рис. 6.1.4
ПрибытиеВГараж – название конкретного документа (как оно задано в конфигурации), менеджер объекта, которого мы хотим создать.
Менеджер справочника создается по аналогии с документом:
&НаСервереБезКонтекста
Процедура СоздаемОбъектНаСервере()
ПрибытиеВГаражМенеджер = Документы.ПрибытиеВГараж; АвтомобилиМенеджер = Справочники.Автомобили;
КонецПроцедуры
Листинг 6.1.2 В этом коде всё точно так же, только мы используем свойство глобального контекста
Справочники, которое является коллекцией менеджеров объектов метаданных справочников.
Создадим новую обработку, основную форму обработки и команду формы СоздатьМаркуАвтомобиля. В серверном обработчике команды напишем код, который при помощи менеджера справочника МаркиАвтомобилей создаёт новый экземпляр объекта (см. листинг 6.1.3). Причём переменная НоваяМарка будет иметь тип СправочникОбъект.МаркиАвтомобилей.
&НаСервереБезКонтекста
Процедура СоздатьМаркуАвтомобиляНаСервере() МаркаАвтомобилейМенеджер = Справочники.МаркиАвтомобилей; НоваяМарка = МаркаАвтомобилейМенеджер.СоздатьЭлемент(); НоваяМарка.Наименование = "Renault"; НоваяМарка.Записать();
КонецПроцедуры
&НаКлиенте
Процедура СоздатьМаркуАвтомобиля(Команда) СоздатьМаркуАвтомобиляНаСервере();
КонецПроцедуры
Листинг 6.1.3
В этом случае опять сделали бесконтекстный вызов сервера. Почему?
Сохраним обработку, запустим её в пользовательском режиме «1С: Предприятия» и выполним созданную команду. Перейдём после этого в форму списка справочника МаркиАвтомобилей, где мы обнаружим новый элемент. Этот элемент создали программным способом.
Рис. 6.1.5
Если мы выполним команду из листинга 6.1.3 несколько раз, то появится много элементов справочника с одинаковым названием. Что, согласитесь, неправильно. Ниже мы научимся избегать подобных ситуаций.
Разберём код из листинга 6.1.3. А конкретно – код в процедуре
СоздатьМаркуАвтомобиляНаСервере.
Первой строкой мы создаём менеджер объекта. После этого, используя стандартный метод менеджера объекта СоздатьЭлемент(), мы создаём новый экземпляр объекта Справочник МаркиАвтомобилей. Переменная НоваяМарка – это экземпляр объекта. Через эту переменную мы получаем доступ ко всем свойствам объекта и методам. В данном конкретном случае нас интересует одно свойство – это Наименование (стандартный реквизит), и один метод – Записать. Это закрытые (типовые) свойства и методы, которые автоматически появляются у объекта метаданных, когда его создаёт разработчик прикладного решения.
Остановимся подробнее на методе СоздатьЭлемент(), который является функцией. Эта функция создаёт новый экземпляр объекта Справочник МаркиАвтомобилей, но данный экземпляр существует только в оперативной памяти, непосредственно в базе данных он пока не появился. Но, несмотря на это, у него доступны все свойства (реквизиты) данного объекта и все методы, которые он может применять.
Для того чтобы созданный экземпляр появился в базе, необходимо использовать метод экземпляра объекта Записать(). После того как данный метод успешно отработает, созданный экземпляр объекта сразу же появляется в базе данных.
Все экземпляры объектов 1С имеют типы ДокументОбъект.<НазваниеДокумент>, СправочникОбъект. <НазваниеСправочника> и т.д.
Метод Записать является предопределённым методом экзепляра объекта. А как использовать те методы для экземпляра объекта, которые мы сами написали? Очень просто.
В имеющейся конфигурации в модуле справочника Марки автомобилей создадим метод, который будет выводить сообщение о наименовании и коде в окно сообщений.
Откроем модуль объекта справочника Марки автомобилей.
Рис. 6.1.6
И напишем в нём следующий код:
Процедура ВывестиНаименованиеСКодом() Экспорт Сообщить(Наименование + "(" + Код + ")"); КонецПроцедуры // ВывестиНаименованиеСКодом()
Листинг 6.1.4
В коде выше мы создали свою собственную процедуру и сделали её экспортной. Это простая процедура, призванная Вам показать, как работают собственные методы экзепляров объектов. Ключевое слово Экспорт делает её внешней процедурой (см. Глава 4, Часть 2, Экспорт процедур функций и переменных, стр. 285), это значит, что объект может её вызывать в любом месте программы. Если не указать слово Экспорт, то функцию можно будет использовать только внутри модуля объекта. В принципе, теперь это тоже метод объекта.
(3) как облегчить программирование? напишите Ваш объект и поставите
Небольшой лайфхак, как сделать своё программирование более удобным. Если написать экземпляр объекта и поставить точку после названия экземпляра, то платформа выведет список свойств и методов, с которыми работает данный объект. Используйте эту возможность, и она позволит Вам быстрее писать и избежать многих ошибок.
Допишем нашу последнюю созданную обработку, где будем вызывать новый метод.
&НаСервереБезКонтекста
Процедура СоздатьМаркуАвтомобиляНаСервере() МаркаАвтомобилейМенеджер = Справочники.МаркиАвтомобилей; НоваяМарка = МаркаАвтомобилейМенеджер.СоздатьЭлемент(); НоваяМарка.Наименование = "Renault"; НоваяМарка.Записать(); НоваяМарка.ВывестиНаименованиеСКодом();
КонецПроцедуры
Листинг 6.1.5
Также изменим немного саму обработку: добавим на реквизит формы МаркаАвтомобиля (тип Строка), поместим его на форму (см. рис. 6.1.8), а в свойство наименование нового объекта Марки автомобилей будем присваивать значение этого реквизита.
Рис. 6.1.8
Но если мы попытаемся использовать реквизит МаркаАвтомобиля в том месте, где создаём экземпляр справочника, то у нас возникнет ошибка на этапе проверки модуля.
Дело в том, что мы в коде используем бесконтекстный вызов серверной процедуры, как следствие, мы не можем в процедуре СоздатьМаркуАвтомобиляНаСервере обращаться к реквизитам формы. Из сложившейся ситуации есть два выхода. Первый – сделать контекстный вызов процедуры, второй – передать в процедуру значение реквизита в виде параметра. Давайте применим второй способ.
&НаСервереБезКонтекста
Процедура СоздатьМаркуАвтомобиляНаСервере(НазваниеМарки) МаркаАвтомобилейМенеджер = Справочники.МаркиАвтомобилей; НоваяМарка = МаркаАвтомобилейМенеджер.СоздатьЭлемент(); НоваяМарка.Наименование = НазваниеМарки; НоваяМарка.Записать(); НоваяМарка.ВывестиНаименованиеСКодом();
КонецПроцедуры
&НаКлиенте
Процедура СоздатьМаркуАвтомобиля(Команда) СоздатьМаркуАвтомобиляНаСервере(МаркаАвтомобиля);
КонецПроцедуры
Листинг 6.1.6 Сохраним конфигурацию, обработку, всё перезапустим и откроем заново обработку.
При нажатии кнопки Выполнить должен быть создан элемент справочника
МаркиАвтомобилей, а в окно сообщений выйдет наименование вновь созданного элемента вместе с кодом (см. рис. 6.1.10).
Рис. 6.1.10
А сейчас Вам небольшое задание: в модуле объекта Справочник МаркиАвтомобилей создайте метод, который будет возвращать длину наименования. Доделайте обработку: с помощью созданного метода выводите длину названия вновь созданной марки, а также исключите ситуацию некорректной записи наименования, когда пользователь ввёл пробелы перед или после основного названия (например, так: «KIA »).
Посмотрим, какие типы будут у переменных МаркаАвтомобилейМенеджер и НоваяМарка. Для этого запустим «1С: Предприятие» в режиме отладки и в табло посмотрим на значения этих переменных.
Рис. 6.1.11
У переменной МаркаАвтомобилейМенеджер тип СправочникМенеджер.МаркиАвтомобилей, объекты этого типа предназначены для управления справочником, как объектом метаданных (конфигурации). Причём значение у этой переменной точно такое же.
А в случае с переменной НоваяМарка тип у нас СправочникОбъект.МаркиАвтомобилей, объекты этого типа предназначены для добавления, изменения и удаления объектов справочника. Также при помощи данного типа можно прочитать элемент справочника.
Но читать элементы справочника лучше при помощи другого типа –
СправочникСсылка.
(3) Ссылка объекта - смысл, какой тип
Ссылка объекта
Ссылка прикладного объекта указывает на данные экземпляра объекта, но не хранит сам экземпляр, т.е., получив ссылку на какой-то экземпляр прикладного объекта, мы можем узнать всю информацию об этом экземпляре, но не можем изменить этот экземпляр.
Все ссылки объектов имеют тип СправочникСсылка.<НазваниеОбъекта>, ДокументСсылка.<НазваниеОбъекта> и т.д.
Ссылку можно использовать в качестве переменной и работать с ней, и также в качестве реквизита других объектов метаданных. Если мы используем ссылку как реквизит объекта метаданных, то при изменении экземпляра объекта, на который указывает ссылка, значение в самом реквизите не изменится.
Разберём на примере. В нашем справочнике Автомобили имеется реквизит Марка, который ссылается на элемент справочника Марки автомобилей.
Рис. 6.1.12
Ранее у нас уже был создан элемент справочника Автомобили с маркой Ford.
Рис. 6.1.13
Давайте переименуем элемент Ford справочника Марки в Ford Motor.
Рис. 6.1.14
Если после переименования мы откроем снова элемент справочника Автомобили, в котором указан переименованный элемент справочника Марки автомобилей, то мы увидим, что отображение в реквизите Марка изменилось автоматически.
Рис. 6.1.15
Что это значит? Это не значит, что реквизит Марка справочника Автомобили и сам элемент справочника Автомобили поменялся автоматически? Нет! Это значит, что данный реквизит хранит указатель на экземпляр объекта, который отображается посредством наименования. Поменяли наименование, поменялось только отображение, если бы мы поменяли какой-нибудь другой реквизит справочника Марки автомобилей, то мы бы ничего не заметили в пользовательском режиме.
Идём дальше. Каким образом в программном коде получить ссылку на конкретный объект, который есть в базе? То есть, как нам найти ссылку на какой-то элемент справочника. Сделать это можно несколькими способами: найти по коду, найти по наименованию, найти по реквизиту и найти по нескольким реквизитам через запрос. Запросы мы будем разбирать позже (глава 9, часть 2), а вот первые три метода рассмотрим.
Перед тем как разобрать эти методы, напишем код, который будет создавать элемент справочника Автомобили.
Для этого создадим обработку и поместим на форму обработки реквизиты формы, которые тоже нужно создать: Наименование (тип Строка (длина 50)), ГодВыпуска (тип Дата), ГосНомер (тип Строка (длина 10)), и КоробкаПередач – тип ПеречислениеСсылка. КоробкаПередач (см. рис. 6.1.16).
Рис. 6.1.16
Создадим команду Создать автомобиль и в обработчиках команды напишем следующий код (см. листинг 6.1.7).
&НаСервере
Процедура СоздатьАвтомобильНаСервере() СправочникАвтомобильМенеджер = Справочники.Автомобили; НовыйОбъект = СправочникАвтомобильМенеджер.СоздатьЭлемент(); НовыйОбъект.Наименование = СокрЛП(Наименование); НовыйОбъект.ГосНомер = СокрЛП(ГосНомер); НовыйОбъект.ГодВыпуска = ГодВыпуска; НовыйОбъект.КоробкаПередач = КоробкаПередач;
КонецПроцедуры
&НаКлиенте
Процедура СоздатьАвтомобиль(Команда) СоздатьАвтомобильНаСервере();
КонецПроцедуры
Листинг 6.1.7 В этом коде всё, что мы уже проходили: создаём менеджер объекта, потом создаём
новый экземпляр объекта Справочник Автомобили, и заполняем его свойства (реквизиты)
значениями реквизитов формы. Заметьте, в этот раз используем контекстный вызов сервера.
Пусть Вас не смущает, что реквизиты формы и объекта называются одинаково. У этих свойств разные объекты, поэтому, когда названия совпадают, нет ничего страшного. Наоборот, рекомендуется, в случае программного заполнения реквизитов справочников или документов, называть реквизиты формы так же, как реквизиты объекта, чтобы код был лучше читаемым и можно было использовать метод ЗаполнитьЗначенияСвойств (в восьмой главе мы изучим работу с этим методом).
У нас осталось ещё два реквизита справочника – Марка и Модель, которые имеют типы ссылки на справочники Марки автомобилей и Модели автомобилей. Простой выход – создать реквизиты формы с аналогичными типами. Но мы хотим научиться работать со ссылками, поэтому пойдём другим путём.
Разберёмся сначала с реквизитом Марки автомобилей. Найдём его по коду. Для этого используем метод менеджера справочника Марки автомобилей – НайтиПоКоду.
&НаСервере
Процедура СоздатьАвтомобильНаСервере() СправочникАвтомобильМенеджер = Справочники.Автомобили; НовыйОбъект = СправочникАвтомобильМенеджер.СоздатьЭлемент(); НовыйОбъект.Наименование = СокрЛП(Наименование); НовыйОбъект.ГосНомер = СокрЛП(ГосНомер); НовыйОбъект.ГодВыпуска = ГодВыпуска; НовыйОбъект.КоробкаПередач = КоробкаПередач;
НовыйОбъект.Марка = Справочники.МаркиАвтомобилей.НайтиПоКоду("003"); НовыйОбъект.Записать();
КонецПроцедуры
Листинг 6.1.8
В коде выше мы создаём, как Вы должны уже понять, менеджер объекта справочник
Автомобили, а потом создаём сам экземпляр объекта и заполняем его.
Функция НайтиПоКоду возвращает ссылку на экземпляр объекта справочник Марки автомобилей, которому соответствует код 001. Почему мы задали код в виде строки, а не в виде цифры, например? Чтобы понять это, откроем непосредственно справочник Марки автомобилей в конфигурации, перейдём на закладку Данные и посмотрим, какой тип кода у этого справочника.
Рис. 6.1.17
Тип кода у данного справочника – строка, поэтому код мы ищем по строковому значению.
Таким образом, строка этого кода:
Справочники.МаркиАвтомобилей.НайтиПоКоду("001")
возвращает ссылку на справочник Марки автомобилей, код у которого 001. Если такой нет, возвращается пустая ссылка (о них позже), если с таким кодом несколько элементов, то возвращается один из них, какой конкретно – предугадать невозможно, платформа выберет элемент по своим внутренним идентификаторам.
Рассмотрим синтаксис функции НайтиПоКоду:
НайтиПоКоду(<Код>,<ПоискПоПолномуКоду>,<Родитель>,<Владелец>)
Где:
Код – непосредственно тот код, по которому мы ищем ссылку на элемент;
Поиск по полному коду – если стоит параметр Истина, то поиск будет вестись по
кодам всей иерархии, т.е. необходимо будет указывать код каждой группы, куда входит элемент через флеш. Например, так: 001/005/110, где слева будет располагаться самая верхняя группа, а справа – непосредственно код элемента.
Данное поле необязательно, по умолчанию – Ложь;
Родитель – для иерархических справочников можно указать группу, тогда поиск будет вестись внутри группы. Данное поле необязательно;
Владелец – для подчинённых справочников можно указать владельца, тогда поиск будет
вестись только среди элементов, подчинённых данному владельцу. Данное поле необязательно.
Теперь, когда мы знаем полный синтаксис метода НайтиПоКоду, то мы можем найти ссылку на элемент справочника Модели автомобилей. В базе элемент справочника Марки автомобилей с кодом 001 (Ford Motor) является владельцем элемента справочника Модели автомобилей с названием Focus и кодом 001 (см. рис. 6.1.18).
Рис. 6.1.18
Изменим код в серверном обработчике.
&НаСервере
Процедура СоздатьАвтомобильНаСервере() СправочникАвтомобильМенеджер = Справочники.Автомобили; НовыйОбъект = СправочникАвтомобильМенеджер.СоздатьЭлемент(); НовыйОбъект.Наименование = СокрЛП(Наименование); НовыйОбъект.ГосНомер = СокрЛП(ГосНомер); НовыйОбъект.ГодВыпуска = ГодВыпуска; НовыйОбъект.КоробкаПередач = КоробкаПередач;
Марка = Справочники.МаркиАвтомобилей.НайтиПоКоду("003");
Модель = Справочники.МоделиАвтомобилей.НайтиПоКоду("001",,,Модель); НовыйОбъект.Марка = Марка;
НовыйОбъект.Модель = Модель; НовыйОбъект.Записать();
КонецПроцедуры
Листинг 6.1.9 Ну и писать сам код марки и модели автомобиля в тексте программного кода – плохой
стиль программирования, поэтому давайте создадим два реквизита на форме обработки Код
марки и Код модели с типом Строка(3) и поместим их на форму.
Рис. 6.1.19
Переделаем код: в качестве первого параметра метода НайтиПоКоду укажем реквизиты формы.
Марка = Справочники.МаркиАвтомобилей.НайтиПоКоду(КодМарки);
Модель = Справочники.МоделиАвтомобилей.НайтиПоКоду(КодМодели,,,Марка);
В этом коде мы найденные экземпляры справочников Марки автомобилей и Модели автомобилей записываем в отдельные переменные, которые потом используем при заполнении реквизитов нового объекта.
Сохраним обработку, запустим её в «1С:Предприятии», введём любые данные и выберем коробку передач, а код марки сделаем равным 003, а код модели – 001.
Рис. 6.1.20
Нажмём на кнопку Создать автомобиль и после этого откроем форму списка справочника Автомобили, где мы увидим, что был создан новый элемент справочника. Откроем этот элемент и посмотрим, какая у него марка и модель.
Рис. 6.1.21
Искать элемент справочника просто по коду будет не очень удобно и не совсем практично. Гораздо удобнее осуществлять поиск по наименованию. Для такого поиска необходимо использовать метод менеджера справочника НайтиПоНаименованию.
Переделаем обработку (можете создать новую форму обработки, которая будет дублировать имеющуюся, и сделать новую форму основной). Вместо реквизитов КодМарки и КодМодели создадим реквизит НаименованиеМарки и НаименованиеМодели (тип Строка(10)).
Рис. 6.1.22
Изменённый код будет выглядеть следующим образом:
СправочникАвтомобильМенеджер = Справочники.Автомобили; НовыйОбъект = СправочникАвтомобильМенеджер.СоздатьЭлемент(); НовыйОбъект.Наименование = СокрЛП(Наименование);
НовыйОбъект.ГосНомер = СокрЛП(ГосНомер); НовыйОбъект.ГодВыпуска = ГодВыпуска; НовыйОбъект.КоробкаПередач = КоробкаПередач;
Марка = Справочники.МаркиАвтомобилей.НайтиПоНаименованию(НаименованиеМарки); Модель = Справочники.МоделиАвтомобилей.НайтиПоНаименованию(НаименованиеМодели,,, Марка);
НовыйОбъект.Марка = Марка; НовыйОбъект.Модель = Модель; НовыйОбъект.Записать();
Листинг 6.1.10
Рассмотрим функцию НайтиПоНаименованию более подробно. Синтаксис этой функции следующий:
НайтиПоНаименованию(<Наименование>,<ТочноеСоответствие>,<Родитель>,<Владелец>)
Где:
Наименование – непосредственно то наименование, по которому мы ищем ссылку на
элемент;
ТочноеСоответствие – если стоит параметр Ложь, то поиск будет вестись не точно, то есть, когда левая часть наименования элемента и строка поиска будут совпадать (например, Металл и Металл 01), то поиск выдаст результат. Если стоит Истина, то будут найдены только те элементы, наименование которых точно совпадает со строкой поиска.
Данное поле необязательно, по умолчанию – Ложь. Помните это, что по умолчанию поиск ведётся не точно;
У параметров Родитель и Владелец точно такой же смысл, как и у процедуры
НайтиПоКоду.
Самостоятельно проверьте работу переделанной обработки.
Изучим ещё один метод поиска ссылки на справочник – это НайтиПоРеквизиту. Для этого мы рассмотрим такой пример: будем искать ссылку на элемент справочника Автомобили по гос. номеру.
Создадим новую обработку, на форме которой будут реквизиты ГосНомер (тип Строка (длина 10)) и Автомобиль с соотвествующим типом (см. рис 6.1.23) . В поле Автомобиль будет записан тот автомобиль, который будет найден по введенному гос. номеру.
Для этого создадим команду НайтиАвтомобильПоГосНомеру, в обработчике этой команды напишем следующий код (см. листинг 6.1.11).
Рис. 6.1.23
&НаСервере
Процедура НайтиАвтомобильПоГосНомеруНаСервере() СправочникАвтомобильМенеджер = Справочники.Автомобили; Автомобиль =
СправочникАвтомобильМенеджер.НайтиПоРеквизиту("ГосНомер",ГосНомер);
КонецПроцедуры
&НаКлиенте
Процедура НайтиАвтомобильПоГосНомеру(Команда) НайтиАвтомобильПоГосНомеруНаСервере();
КонецПроцедуры
Листинг 6.1.11
Поясним код выше. В нём мы первоначально создали менеджер справочника Автомобили. После этого реквизиту формы Автомобиль присваиваем значение, которое возвращает функция НайтиПоРеквизиту менеджера справочника.
Рассмотрим синтаксис функции НайтиПоРеквизиту.
НайтиПоРеквизиту(<ИмяРеквизита>, <ЗначениеРеквизита>, <Родитель>, <Владелец>)
Где:
ИмяРеквизита – строковое значение имени реквизита, по которому мы будем искать
ссылку на элемент. Оно должно быть аналогично тому имени, которое указано в конфигураторе;
ЗначениеРеквизита – это значение, по которому должен выполняться поиск. Обращаю Ваше внимание: тип данного значения должен совпадать с типом реквизита. Если объектов с данным реквизитом будет несколько, то будет возвращён один из них. Какой именно – заранее определить невозможно: программа выполнит это по внутреннему идентификатору.
Параметры Родитель и Владелец точно такие же, как для процедуры НайтиПоКоду. Попробуем найти какой-нибудь автомобиль.
Рис. 6.1.24
Пустая ссылка
(3) Пустая ссылка - что это?
Конечно же, у внимательного читателя должен назреть вопрос: что будут возвращать методы НайтиПоКоду, НайтиПоНаименованию и НайтиПоРеквизиту, если элемент справочника, который соответствует коду, наименованию или реквизиту, не был найден. Эти методы будут возвращать Пустую ссылку. Пустая ссылка – это пустое значение какого- нибудь справочника или документа. У менеджеров справочника или документа есть методы, которые возвращают пустую ссылку соответствующих объектов.
Выглядит он так:
ПустойАвтомобили = Справочники.Автомобили.ПустаяСсылка(); ПустойПрибытиеВГараж = Документы.ПрибытиеВГараж.ПустаяСсылка();
Переменные ПустойАвтомобили и ПустойПрибытиеВГараж содержат в себе пустые ссылки на объекты.
Обращаю Ваше внимание, что для каждого вида справочника и каждого документа будет своя собственная пустая ссылка.
Метод ПустаяСсылка очень удобно использовать, когда нам необходимо знать, найден ли элемент справочника по коду (названию, реквизиту) или нет.
Подправим обработку, где мы создавали новый элемент справочника Автомобили так, что если ссылки по названию марки или модели найдены, то записываем автомобиль, если нет, то выходим из процедуры.
Марка = Справочники.МаркиАвтомобилей.НайтиПоКоду(КодМарки); Если Марка = Справочники.МаркиАвтомобилей.ПустаяСсылка() Тогда
Сообщить("Не нашли марку " + Марка); Возврат;
КонецЕсли;
Модель = Справочники.МоделиАвтомобилей.НайтиПоКоду(КодМодели,,,Марка); Если Модель = Справочники.МоделиАвтомобилей.ПустаяСсылка() Тогда
Сообщить("Не нашли модуль " + Модель + " у марки " + Марка); Возврат;
КонецЕсли;
СправочникАвтомобильМенеджер = Справочники.Автомобили; НовыйОбъект = СправочникАвтомобильМенеджер.СоздатьЭлемент(); НовыйОбъект.Наименование = СокрЛП(Наименование); НовыйОбъект.ГосНомер = СокрЛП(ГосНомер); НовыйОбъект.ГодВыпуска = ГодВыпуска; НовыйОбъект.КоробкаПередач = КоробкаПередач; НовыйОбъект.Марка = Марка;
НовыйОбъект.Модель = Модель; НовыйОбъект.Записать();
Листинг 6.1.12
Поясним код выше. Мы ищем элементы нужных справочников, и если их нет, то ничего не записываем. Марка – это ссылка на элемент справочника Марки автомобилей, которую мы ищем по какому-то наименованию. Дальше мы проверяем, равна ли переменная Марка пустой ссылке, которая возвращается методом ПустаяСсылка менеджера соответствующего справочника. Если равна, то выходим из процедуры с помощью операции Возврат. То же самое делаем и для элемента справочника Модели автомобилей.
Помимо метода менеджера объекта есть и метод Пустая у ссылки объекта. Метод
Пустая возвращает Истина, если ссылка пустая, и Ложь – в противном случае. Поиск марки и модели из предыдущего кода можно переделать следующим образом:
Марка = Справочники.МаркиАвтомобилей.НайтиПоКоду(КодМарки); Если Марка.Пустая() Тогда
Сообщить("Не нашли марку " + Марка); Возврат;
КонецЕсли;
Модель = Справочники.МоделиАвтомобилей.НайтиПоКоду(КодМодели,,,Марка); Если Модель.Пустая() Тогда
Сообщить("Не нашли модуль " + Модель + " у марки " + Марка); Возврат;
КонецЕсли;
Листинг 6.1.13
Вы видите, данный метод ссылки аналогичен методу менеджера объекта и позволяет в некоторых случаях оптимизировать код программы.
Ссылка как свойство объекта
У любого объекта справочника, документа или константы есть свойство Ссылка, которое возвращает ссылку на данный объект.
Зачем она нужна, если мы и так можем получить все данные, имея объект? Например, она может применяться тогда, когда мы, создав и записав объект, хотим записать ссылку на этот объект в какой-нибудь реквизит, типом которого будет соответствующая ссылка.
Изменим сделанную выше обработку с созданием автомобиля (Вы создайте новую, чтобы не терять то, что уже наработали): разместим на форме реквизит Автомобиль с типом Ссылка на справочник Автомобили (см. рис. 6.1.25) и после создания нового элемента справочника Автомобиль запишем в этот реквизит ссылку на новый элемент.
Рис. 6.1.25
У элемента формы Автомобиль установим свойство ТолькоПросмотр в Истина, а свойству КнопкаОткрытия поставим значение Да. Тем самым мы не сможем выбрать другой автомобиль в этом поле, но в то же время сможем открыть автомобиль из элемента.
Внизу кода обработчика команды допишем:
/////........предыдущий код НовыйОбъект.Марка = Марка; НовыйОбъект.Модель = Модель; НовыйОбъект.Записать();
Автомобиль = НовыйОбъект.Ссылка;
Листинг 6.1.14
Запустим обработку, заполним все поля и нажмём на кнопку Создать автомобиль. В поле Автомобиль появилась ссылка на тот элемент справочника, который мы создали.
Рис. 6.1.26
Ссылка на перечисление
Такие элементы конфигурации, как Перечисления, тоже являются объектами. Точно так же можно получить менеджер определённого перечисления и ссылку на нужное значение этого перечисления.
Изменим предыдущую обработку, будем установливать значение реквизита КоробкаПередач не из реквизита формы, а программно. Это будет одно и то же значение для любого автомобиля, который будет создан.
Изменим код, где мы присваиваиваем реквизиту объекта КоробкаПередач значение реквизита формы, на следующий:
//..........
НовыйОбъект.ГосНомер = СокрЛП(ГосНомер); НовыйОбъект.ГодВыпуска = ГодВыпуска;
НовыйОбъект.КоробкаПередач = Перечисления.КоробкаПередач.Автоматическая; НовыйОбъект.Марка = Марка;
НовыйОбъект.Модель = Модель;
//..........
Листинг 6.1.15 В данном коде: Перечисление – это свойство глобального контекста, которое является
коллекцией менеджеров перечислений, Перечисления. КоробкаПередач – это менеджер
перечисления КоробкаПередач. А в целом эта строка – ссылка на конкретное значение перечисления Автоматическая.
(3) метод который возвращает объект ссылки, на который она указывает
Получить объект
Мы с Вами научились создавать объекты, получать ссылки на объекты, а что если стоит обратная задача: есть ссылка, и нужно из этой ссылки получить объект и что-то с ним сделать, например, отредактировать какой-нибудь реквизит? Для этого нам понадобится метод ссылки – ПолучитьОбъект. Этот метод возвращает объект ссылки, на который она указывает.
Создадим новую обработку, в которой по введённому названию будем получать объект Гараж и менять его наименование. В этой обработке будет три поля: Текущее название (тип Строка), Новое наименование (тип Строка) и Гараж (тип Ссылка на справочник Гаражи). А две команды: Найти гараж и Изменить гараж (см. рис. 6.1.27).
Рис. 6.1.27
В обработчиках команды Найти гараж напишем следующий код:
&НаСервере
Процедура НайтиГаражНаСервере()
Гараж = Справочники.Гаражи.НайтиПоНаименованию(СокрЛП(ТекущееНазвание),Истина);
КонецПроцедуры &НаКлиенте
Процедура НайтиГараж(Команда)
Если ПустаяСтрока(ТекущееНазвание) тогда Возврат;
КонецЕсли;
НайтиГаражНаСервере(); КонецПроцедуры
Листинг 6.1.16
В обработчике команды Изменить гараж напишем такой код:
&НаСервере
Процедура ИзменитьГаражНаСервере() Если Гараж.Пустая() тогда
Возврат;
КонецЕсли;
ОбъектГараж = Гараж.ПолучитьОбъект(); ОбъектГараж.Наименование = НовоеНазвание; ОбъектГараж.Записать();
КонецПроцедуры
&НаКлиенте
Процедура ИзменитьГараж(Команда) ИзменитьГаражНаСервере();
ОтобразитьИзменениеДанных(Гараж,ВидИзмененияДанных.Изменение); КонецПроцедуры
Листинг 6.1.17
Разберём код выше. В процедуре НайтиГараж мы сначала с помощью функции ПустаяСтрока проверяем, заполнен реквизит ТекущееНазвание или нет. Функция ПустаяСтрока, как Вы помните из предыдущих разделов, возвращает Истина, если строка не заполнена. Поэтому, когда данная функция возвращает Истину, мы выходим из процедуры, дальнейшего вызова сервера не происходит. Если же она заполнена, мы вызываем серверную процедуру НайтиГаражНаСервере, в которой реквизиту формы Гараж присваиваем ссылку, найденную по текущему названию.
В процедуре ИзменитьГаражНаСервере мы проверяем, является ли реквизит Гараж пустой ссылкой. Если да, то выходим. Если нет, мы получаем объект с помощью функции ПолучитьОбъект, меняем наименование и записываем его. Чтобы наша новая ссылка отобразилась на форме, в процедуре ИзменитьГараж применяем метод управляемой формы ОбновитьИзмениеДанных, который обновит отображение элемента на форме.
Запомните метод ПолучитьОбъект, на практике не раз приходится изменять реквизиты документов или справочников, которые по тем или иным причинам были неправильно записаны.
(3) что такое События
События объектов
У многих объектов (но не у всех) имеются События. События – это по сути перехват определённого действия с объектом.
Например, когда мы записываем элемент справочника, мы можем перехватить событие записи элемента и нужным нам способом обработать запись элемента.
Как получить событие объекта?
Для этого необходимо открыть модуль объекта (сделать активным – установить курсор) и выполнить команду Процедуры и функции в меню Текст главного меню.
Рис. 6.1.28
В открывшемся окне Процедуры и функции в скобочках мы видим процедуры и функции, которых ещё нет, но они уже предопределены.
Рис. 6.1.29
Это и есть события объекта. Как Вы видите, все события строго предопределены разработчиками платформы, и Вам при написании собственных алгоритмов придётся учесть это. Все названия событий интуитивно понятны, и мы не будем подробно их разбирать. Кто интересуется, может посмотреть информацию о событии с нужным прототипом объекта в синтакс-помощнике.
Для примера разберём, как работает событие ПередЗаписью справочника Марки автомобилей. Когда будем создавать новый элемент справочника, проверим, есть ли уже существующий элемент справочника с названием как у нового. Если есть, то не будем записывать элемент.
В модуле объекта справочника МаркиАвтомобилей создадим событие ПередЗаписью, кликнув на одноимённую строку в окне Процедуры и функции, которое мы уже открыли
ранее.
Событие создалось в модуле объекта, и мы увидим, что у процедуры ПередЗаписью есть параметр Отказ, если этот параметр принимает значение Истина, то запись не будет произведена.
Рис. 6.1.30
В созданной процедуре пишем следующий код.
Процедура ПередЗаписью(Отказ) Если ЭтоНовый() Тогда
НайденнаяМарка = Справочники.МаркиАвтомобилей.НайтиПоНаименованию(Наименование,Истина);
Отказ = ?(НайденнаяМарка.Пустая(), Ложь, Истина); КонецЕсли;
КонецПроцедуры
Листинг 6.1.18
Код простой, и Вы без труда его разберёте. Метод ЭтоНовый разберёем ниже. Теперь попробуйте записать элемент с уже имеющимся названием самостоятельно.
Пытливый читатель спросит: почему тут использовалась процедура ПередЗаписью, а не, например, ПриЗаписи? Дело в том, что процедура ПередЗаписью срабатывает тогда, когда элемент ещё не записан в базу, в отличие от процедуры ПриЗаписи. Если бы мы написали такой код в обработчике события ПриЗаписи, это событие никогда не дало бы нам записать новый элемент.
Метод ЭтоНовый
У любого объекта справочника и документа есть метод ЭтоНовый. Этот метод возвращает Истину, если объект только что создан интерактивно или с помощью метода СоздатьЭлемент (или СоздатьДокумент), но при этом не записан в базу. То есть до того, как был применен метод Записать.
Сделаем простой пример, демонстрирующий, как этот метод работает. Изменим предыдущую обработку с гаражами (можете создать новую): если по старому названию
гараж не найден, то будем создавать гараж и присваивать ему новое название, а если найден, то менять старое на новое. Пример больше учебный, чтобы показать Вам работу метода ЭтоНовый. Изменим код в процедуре ИзменитьГаражНаСервере.
&НаСервере
Процедура ИзменитьГаражНаСервере() Если Гараж.Пустая() тогда
ОбъектГараж = Справочники.Гаражи.СоздатьЭлемент(); иначе
ОбъектГараж = Гараж.ПолучитьОбъект(); КонецЕсли;
ОбъектГараж.Наименование = ?(ОбъектГараж.ЭтоНовый(), ТекущееНазвание, НовоеНазвание); ОбъектГараж.Записать();
Гараж = ОбъектГараж.Ссылка; КонецПроцедуры
Листинг 6.1.19
В коде выше мы проверяем новый это справочник или нет. Если новый, то присваиваем свойству Наименование значение реквизита ТекущееНазвание.
Пометка на удаление
Удалить элемент объекта из базы «1С: Предприятия» можно двумя способами: удалить непосредственно без контроля ссылочной целостности (тогда могут появиться
«битые ссылки», если ссылка на удалённый элемент объекта была в каком-то реквизите), или удалить через установку пометки на удаление и запуском в работу сервиса по удалению помеченных объектов. Этот сервис контролирует ссылочную целостность и не даст удалить элемент, если на него есть какие-нибудь ссылки. В нашей базе объекты можно удалять и тем, и другим способом.
Разберём и первый, и второй способ удаления.
Для того чтобы пользователь мог удалить элемент объекта без контроля ссылочной целостности, у этого пользователя должна быть хотя бы одна роль, в которой на объект установлено право Интерактивное Удаление.
Рис. 6.1.31
Тогда на форме списка и непосредственно у элемента будет доступна команда
Удалить (см. рис. 6.1.32 и 6.1.33).
Рис. 6.1.32
При попытке воспользоваться этой командой возникнет вопрос.
Рис. 6.1.33
Рис. 6.1.34
При ответе Да марка автомобиля исчезнет из базы навсегда.
Но при этом возникнет очень нехорошая ситуация. Если мы откроем элемент справочника Автомобили, в котором в реквизите Марка была выбранная удалённая марка автомобиля, то увидим неприятное сообщение.
Рис. 6.1.35
Причём такое сообщение возникло не только в поле Марка, где была указана удалённая марка, но и в поле Модель. Это возникло из-за того, что справочник Модели подчинён справочнику Марки, и с удалением марки удалились и все модели, подчинённые этой марке.
Чтобы таких ситуаций не возникало, нужно убирать право ИнтерактивноеУдаление
вообще на все объекты у всех ролей!
Рис. 6.1.36
Когда мы уберём право ИнтерактивноеУдаление у ролей пользователя, то кнопок непосредственного удаления в пользовательском интерфейсе не будет.
Рекомендуется при разработке собственных конфигураций (или объектов) всегда снимать право на непосредственное удаление у всех объектов.
Если мы не можем удалить элемент объекта непосредственно, то этот элемент можно удалить через установку пометки на удаление.
Изучим удаление документа посредством установки пометки на удаление. Для того чтобы пользователь мог устанавливать пометку на удаление, у него должна быть хотя бы одна роль, в которой для нужного объекта установлено право Интерактивная пометка на удаление. А также право Интерактивное снятие пометки удаления, чтобы снять уже установленную пометку на удаление (см. рис. 6.1.37), а также – Интерактивное удаление помеченных, чтобы можно было удалить объект, используя специальный сервис.
Рис. 6.1.37
Если права на нужный объект установлены, то в командном интерфейсе этого объекта появляется команда Пометить на удаление / Снять пометку.
Рис. 6.1.38
Чтобы установить пометку на удаление, нужно выделить элемент справочника или документ (можно выделить несколько) и применить команду Пометить на удаление / Снять пометку, используя меню Ещё или используя контекстное меню. В результате выйдет
сообщение, в котором нас спросят, пометить элемент на удаление или нет.
Рис. 6.1.39
При ответе Да рядом с элементом в списке появится «крестик».
Рис. 6.1.40
Это значит, что документ помечен на удаление и появится в списке сервиса удаления помеченных объектов.
Удалим помеченный элемент справочника. Это делается при помощи стандартной обработки Удаление помеченных объектов. Откроем эту обработку, используя Функции для технического специалиста. Но сначала эти функции необходимо включить в нашем интерфейсе. Для этого необходимо открыть параметры приложения (см. рис. 6.1.41).
Рис. 6.1.41
И в параметрах установим флаг Режим технического специалиста (см. рис. 6.1.42).
Рис. 6.1.42
У пользователя будет доступен режим технического специалиста только в том случае, когда у него имеется хотя бы одна роль, у которой на конфигурацию будет установлено право Режим технического специалиста (см. рис. 6.1.43).
Рис. 6.1.43
После того как мы установим флаг Режим технического специалиста в параметрах приложения, в меню Сервис и настройки пользовательского приложения должна появиться команда Функции для технического специалиста.
Рис. 6.1.44
В окне Функции для технического специалиста в ветке Стандартные нас интересует обработка Удаление помеченных документов (см. рис. 6.1.45). После выбора откроется форма обработки удаления помеченных объектов (см. рис. 6.1.46). В этой обработке мы можем выбрать или полное удаление всех помеченных объектов, или выборочное удаление.
Рис. 6.1.46
Если мы укажем Выборочное удаление и нажмём кнопку Удалить, то появятся помеченные на удаление объекты, сгруппированные в виде дерева, где узлы – это прототипы объектов метаданных (см. рис. 6.1.47). Нажмём кнопку Удалить, и, если нет ссылок на отмеченные объекты, они будут удалены.
Рис. 6.1.47
В нашем случае никакое удаление не произойдёт, потому что на удаляемые объекты имеются ссылки.
Нажмём на кнопку Далее и посмотрим на объекты, в которых используются удаляемые элементы.
Рис. 6.1.49
Кликнем по элементу справочника Автомобили в дереве, и откроется форма элемента соответствующего справочника.
Рис. 6.1.50
Мы научились помечать объекты на удаление и удалять их интерактивно. Узнаем, как это делается в программном коде.
ПометкаУдаления является стандартным реквизитом таких объектов, как Справочник, Документ, ПланВидовХарактеристик и т.д.
Реквизит ПометкаУдаления имеет тип Булево и принимает значение Истина, если элемент объекта помечен на удаление, и принимает значение Ложь, если нет.
Рис. 6.1.51
Напишем программный код, который будет удалять объект и устанавливать пометку удаления. Для удаления непосредственно объекта из базы применяется метод объекта Удалить, а для установки пометки на удаление метод объекта УстановитьПометкуУдаления.
Разберём работу этих методов в новой обработке, в которой будем удалять элементы справочника. Создадим новую обработку, форму, а на форме создадим реквизит Автомобиль (тип Ссылка на справочник Автомобили) и реквизит Удалить непосредственно (тип Булево), а также команду Удалить автомобиль (см. рис. 6.1.52).
Рис. 6.1.52
В случае если флаг установлен – будем удалять объект непосредственно из базы, в противном случае – просто установим пометку на удаление.
В обработчике команды напишем следующий код:
&НаСервере
Процедура УдалитьАвтомобильНаСервере()
Если Автомобиль.Пустая() тогда Возврат;
КонецЕсли;
ОбъектАвтомобиль = Автомобиль.ПолучитьОбъект(); Если УдалитьНепосредственно тогда
ОбъектАвтомобиль.Удалить();
Автомобиль = Справочники.Автомобили.ПустаяСсылка(); иначе
Если Не ОбъектАвтомобиль.ПометкаУдаления тогда ОбъектАвтомобиль.УстановитьПометкуУдаления(Истина,Истина);
КонецЕсли;
КонецЕсли;
КонецПроцедуры &НаКлиенте
Процедура УдалитьАвтомобиль(Команда) УдалитьАвтомобильНаСервере();
КонецПроцедуры
Листинг 6.1.20
Разберём код выше.
Перед непосредственным удалением мы проверяем, выбран ли объект в реквизите, или ссылка пустая. Если она пустая – выходим из процедуры и ничего не делаем. Следующим шагом получаем объект из ссылки. В дальнейшем, если на форме установлен флаг Удалить непосредственно, удаляем объект из базы, иначе, в случае если не установлена пометка на удаление, устанавливаем её.
Разберём метод УстановитьПометкуУдаления подробно. У этого метода следующий синтаксис:
УстановитьПометкуУдаления(<ПометкаУдаления>, <ВключаяПодчиненные>)
Функция УстановитьПометкуУдаления имеет два параметра. Первый параметр ПометкаУдаления имеет тип значения Булево. Если он Истина, то на данный объект будет установлена пометка удаления, в противном случае она будет снята (если она уже установлена). Второй параметр имеется только для справочников и тоже имеет тип значения Булево. В случае когда его значение Истина, будет помечен не только сам объект, но и все подчинённые. Значение по умолчанию обоих параметров – Истина.
Помните, что программное удаление справочников и элементов с помощью пометки на удаление выполнит данную процедуру в более щадящем режиме для базы, чем прямое удаление. Поэтому, хотя это и накладно по времени, рекомендую Вам всегда удалять объекты с помощью установки пометки на удаление, это убережёт Вас от многих проблем в будущем.
Если Вы запустите эту обработку, то заметите, что элемент справочника удалился, даже когда право Интерактивное удаление снято. Всё правильно, потому что мы удалили экземпляр объекта не интерактивным, а программным способом. За удаление объектов программным способом отвечает право Удаление (см. рис. 6.1.53). Если мы снимем флаг права Удаление у справочника Автомобиль и попробуем удалить при помощи обработки, возникнет ошибка (см. рис. 6.1.54).
Рис. 6.1.53
Рис. 6.1.54
Мы начали изучать объекты метаданных. Научились работать с менеджером объектов, создавать программно объекты и находить ссылки на справочники по коду и наименованию и многое другое, что Вам пригодится в дальнейшей работе. Всё это мы сделали на примере справочников, поскольку более подробно с документами будем работать в следующей части данной главы.
Также в этой части мы изучили основные методы и свойства объектов и справочников.
Некоторые из оставшихся мы будем изучать в следующих частях, а с остальными Вы сможете ознакомиться самостоятельно.
Как Вы помните из четвёртой главы, посвящённой конфигурированию, в платформе 1С можно разрабатывать различные документы, которые необходимы для фиксации периодически повторяющихся событий в деятельности предприятия. Например, это может быть покупка и продажа товара, внесение денежных средств, выдача денежных средств и т.п. Основное отличие документа от справочника в том, что документ может делать движения по регистрам. Или, говоря по-другому, мы можем проводить документы.
Проведение документов
Когда разрабатывается документ, необходимо продумать, будет ли этот документ делать какие-нибудь движения по регистрам (бухгалтерским, накопления и т.п.). Если никаких движений данный документ осуществлять не должен (например, это просто счёт в виде бланка), то необходимо на этапе создания запретить ему осуществлять движения.
Сейчас мы научимся делать это.
Продолжим работать с конфигурацией по автотранспорту, которую мы сделали в четвёртой главе, и создадим в этой конфигурации документ Печать путевых листов, который не будет делать движения ни по каким регистрам учёта, а необходим только для печати путевого листа (работу с печатью изучим в 11-м уроке). Включим этот документ в подсистему Учёт автомобилей, права на интерактивное добавление и редактирование, установку пометки на удаление, назначим роли Диспетчер, роли Полные права, дадим все права на этот документ (кроме Интерактивного удаления).
После создания документа на закладке Данные добавим новые реквизиты Автомобиль
и Гараж с соответствующими типами.
Рис. 6.2.1
Дальше нам нужно указать, что наш новый документ не делает никаких движений. Для этого перейдём на закладку Движения и в свойстве Проведение установим значение Запретить.
Рис. 6.2.2
Всё, теперь документ Печать путевых листов не будет делать никаких движений. Все формы для этого документа создайте самостоятельно.
В том случае если документ делает проведения по каким-то регистрам, то в свойстве Проведение (закладка Движения) документа должно быть установлено значение Разрешить, а в списке ниже указан регистр, в который записываются данные из этого документа.
Например, в четвёртой главе был создан документ ПрибытиеВГараж, который делает движение по регистру накопления ПробегАвтомобиля.
Рис. 6.2.3
Алгоритмы, которые осуществляют запись данных документа в регистры, находятся в предопределённой процедуре Обработка Проведения модуля объекта. Эта процедура срабатывает тогда, когда пользователь нажимает кнопку Провести документ, или при программной записи документа с установленным параметром Проведение (об этом ниже).
Если мы откроем модуль документа Прибытие в гараж, то увидим, что в этом модуле уже существует процедура Обработка Проведения. Её создал конструктор проведения, когда в четвёртой главе мы конфигурировали этот документ.
Рис. 6.2.4
Развернём её и увидим некоторый алгоритм, который осуществляет движения по регистру накопления Пробег автомобиля. Более подробно про движения мы поговорим ниже.
Оперативное и неоперативное проведение
Если документ осуществляет движения по регистрам (или, говоря по простому,
«проводки»), необходимо ещё определиться, будет данный документ проводиться
оперативно или нет.
Все документы 1С могут быть проведены в оперативном и неоперативном режиме.
Оперативное проведение – это проведение здесь и сейчас, то есть в текущий момент времени.
Неоперативное проведение – это проведение документа ранее текущего момента времени.
Если хотя бы одна секунда отличается от текущего момента времени, то данное проведение неоперативное!
Когда документ проводится в неоперативном режиме, по сути, учитывается уже свершившийся факт, который не требует контроля, осуществляемого при оперативном проведении (например, контроль остатков). Также необходимо заметить, что если у документа имеется возможность оперативного проведения, то такой документ нельзя провести будущей датой.
Возможность оперативного проведения документа задаётся на этапе разработки документа.
Откроем в конфигурации по учёту автотранспорта редактор уже созданного документа ПрибытиеВГараж и посмотрим, где устанавливается возможность проведения документа в оперативном режиме. Для этого в редакторе документа нужно перейти на закладку Движения.
Рис. 6.2.5
Посмотрим на свойство Оперативное проведение. Если в этом свойстве установлено значение Разрешить, то документы могут проводиться в оперативном режиме. Если – значение Запретить, то они всегда будут проводиться в неоперативном режиме, в любой момент времени.
В каких случаях нам необходимо разрешать оперативное проведение? Однозначно тогда, когда мы автоматизируем оперативный учёт.
Оперативный учёт – это, в двух словах, когда необходимо знать текущую ежеминутную информацию и принимать соответствующие решения.
Самый яркий пример – это розничный магазин: продавец не может в данный момент времени продать покупателю отсутствующий товар. Для того чтобы знать, какие товары есть на складе магазина, а каких нет, необходимо оперативно вести документы прихода товара и выбытия (продажи) товара. Данные документы необходимо вводить в программу по случившемуся факту: пришёл покупатель, отгрузили товар, сразу же в программе создали и провели документ. Тогда продавец в любой момент времени может ответить, есть у него товар в магазине или нет.
При автоматизации любого другого учёта, к примеру, зарплатного или бухгалтерского, нет необходимости точно владеть ежеминутной информацией о состоянии учёта. Как правило, бухгалтера в текущий момент заводят первичные документы, а сводят информацию несколько позже, когда подходит время сдачи бухгалтерской или управленческой
отчётности.
Если вы посмотрите на уже готовые конфигурации 1С, например, «1С: Управление торговлей» или «1С:Розница», то заметите, что многие документы имеют возможность оперативного проведения. А в то же время программы «1С: Бухгалтерия предприятия» или
«1С: Зарплата и управление персоналом» имеют документы с неразрешённым оперативным проведением, потому что оно там не требуется. Например, нет смысла кого-то в оперативном времени устраивать на работу.
Определим в нашей конфигурации, каким документам разрешим возможность оперативного проведения, а каким – запретим.
Начнём с документов Заправка топлива и Отчет о расходе топлива. Первым делом
ответим на вопрос: нужно ли нам знать в текущий момент, сколько топлива в том или ином автомобиле? Предположим, что да! Как мы отправим автомобиль в рейс, не заправив его топливом или не дав денег водителю этого автомобиля? Перед отправкой автомобиля в рейс нам точно нужно знать, сколько на текущий момент топлива в баке автомобиля, и, исходя из этого, принять решение: заправлять автомобиль или нет. Поэтому для этих документов установим разрешение оперативного проведения.
Рис. 6.2.6
Документы Прибытие в гараж и Выбытие из гаража. Нужно ли нам точно в текущий момент знать, какой автомобиль в рейсе, а какой нет? Конечно, нужно, иначе какой смысл фиксировать выбытие и прибытие автомобилей? Единственно, на данный момент мы не сможем получить информацию об этом, потому что не создан регистр накопления, с помощью которого мы сможем осуществлять контроль наличия автомобиля в гараже.
Поэтому у обоих этих документов установим признак оперативного проведения.
Рис. 6.2.7
А вот документу Установка цен на топливо оперативное проведение ни к чему, конечно, понятно, что установить цены будущей датой – это нонсенс, но и не факт, что такое не может произойти. Например, для каких-нибудь прогнозов. Поэтому для данного документа запретим оперативное проведение.
Рис. 6.2.8
Подробно автоматизация оперативного учёта разбирается в моей книге «Разработка оперативного учёта в 1С 8.3».
Нумерация документов
У любого документа имеется стандартный реквизит Номер.
Рис. 6.2.9
Номер документа должен быть уникален. Уникальность может быть или в пределах какого-то периода (года, квартала, месяца, дня), или в целом по документу в пределах базы.
Различные настройки заполнения номеров задаются на закладке Нумерация редактора документа. Обычно при создании документа эта закладка заполняется автоматически.
Посмотрим на закладку Нумерация у документа Печать путевых листов.
Рис. 6.2.10
И самое первое свойство этой закладки – флаг Автонумерация. Если этот флаг установлен, то платформа сама присваивает номера документов. Рекомендую его оставлять установленным, если Вы сами не хотите присваивать номер документу по определённому алгоритму (разумеется, программно). Свойство Длина номера отвечает за длину номера документа, а свойство Тип номера определяет, какой у номера будет тип – Строка или Число. Контроль уникальности нужно устанавливать в том случае, если необходимо запрещать создавать два и более документа с одинаковыми номерами. Периодичность указывает, в каком периоде будет осуществляться контроль уникальности (если установлено значение Непериодический, то контроль уникальности будет вестись по всем документам этого типа). Причём в случае если установлено свойство Автонумерация, то при наступлении следующего периода нумерация автоматически начнётся сначала.
Иногда в организациях хотят, чтобы все номера документов со следующего года начинались сначала. Поэтому есть смысл в документах устанавливать для свойства Периодичность значение В пределах года.
Рис. 6.2.11
Установите это значение для всех документов конфигурации.
И последний момент в нумерации документов, который нас заинтересует, это
Нумератор. Как Вы уже заметили из работы с программой, все документы нумеруются по отдельности. Но иногда необходимо иметь сквозную нумерацию по нескольким документам. К примеру, если нам надо, чтобы мы ввели документ поступления под номером один, потом ещё один документ поступления под номером два, а потом документ реализации под номером три, который будет являться продолжением предыдущих двух номеров. Для этого в платформе 1С можно использовать нумераторы, они позволяют осуществлять сквозную нумерацию любого количества документов.
Рассмотрим сквозную нумерацию на примере документов Прибытие в гараж и Выбытие из гаража. Для этого необходимо создать нумератор: раскроем ветвь Документы дерева конфигурации, установим курсор на ветвь Нумераторы, вызовем контекстное меню и выполним команду Добавить.
Рис. 6.2.12
Нумератор автоматически будет создан, и справа откроется его палитра свойств.
Назовём его Основной, Периодичность установим в пределах года, а всё остальное оставим как есть.
Рис. 6.2.13
Нам осталось указать, какие документы будет использовать созданный нумератор. Для этого в редакторе документа Прибытие в гараж на закладке Нумерация нужно выбрать вновь созданный нумератор.
Рис. 6.2.14
То же самое необходимо сделать и в документе Выбытие из гаража.
Сохраним конфигурацию (если в Вашей базе есть уже созданные документы Прибытие в гараж и Выбытие из гаража, то удалите их), создадим документы прибытия и выбытия из гаража и посмотрим, как будет осуществляться нумерация вновь созданных документов (см. рис. 6.2.15).
Рис. 6.2.15
На этом мы закончим с конфигурированием документов. Перейдём к изучению свойств и методов документов.
Проведен
Большинство закрытых свойств (реквизитов) и методов у документов совпадает со свойствами и методами справочников, которые мы проходили в первой части текущей главы. Но есть такие свойства и методы, которые присутствуют только у документов.
Рассмотрим такое свойство, как Проведен.
Проведен – это свойство документа, которое принимает значение Истина, если документ проведён, и значение Ложь, если документ не проведён. Данное свойство доступно только для чтения. То есть мы не можем самостоятельно что-то записать в это свойство.
Никаким способом. Мы можем только прочитать этот реквизит и тем самым понять, проведён документ или нет.
Выполним простой пример: создадим обработку, имеющую на форме один реквизит с типом Ссылка на документ Прибытие в гараж и один реквизит с типом Булево. Если выбранный в реквизит документ будет проведён, то выключатель, соответствующий реквизиту, будет установлен, в ином случае – нет.
Рис. 6.2.16
У события ПриИзменении элемента формы ПрибытиеВГараж создадим обработчики на клиенте и на сервере (мы сможем прочитать стандартный реквизит документа из ссылки только в серверном контексте, потому что в клиентском контексте мы не можем прочитать реквизиты у ссылки).
Рис. 6.2.17
В этих обработчиках напишем следующий код:
&НаСервере
Процедура ПрибытиеВГаражПриИзмененииНаСервере() Проведен = ПрибытиеВГараж.Проведен;
КонецПроцедуры
&НаКлиенте
Процедура ПрибытиеВГаражПриИзменении(Элемент)
ПрибытиеВГаражПриИзмененииНаСервере(); КонецПроцедуры
Листинг 6.2.1
В этом коде мы при изменении значения поля Прибытие в гараж булевому реквизиту формы Проведен присваиваем значение стандартного реквизита Проведен экземпляра документа Прибытие в гараж, которое тоже имеет тип Булево. К этому свойству мы обратились посредством ссылки на данный объект.
В сохранённой обработке выберем какой-нибудь проведённый документ.
Рис. 6.2.18
Если мы отменим проведение документа и перевыберем документ, то выключатель должен поменяться.
Программное создание, запись и проведение документа
Научимся создавать, сохранять и проводить документы в программном коде.
Документ можно создать при помощи метода СоздатьДокумент() менеджера объекта нужного документа. Этот метод является функцией, которая создаёт и возвращает новый экземпляр объекта. Этот экземпляр уже создан, но ещё не записан в базу. После создания экземпляра документа разработчик должен заполнить реквизиты нового документа и в конце, при помощи метода Записать, сохранить документ.
Научимся создавать документы, для этого разработаем обработку, при помощи которой будем создавать экземпляр документа Прибытие в гараж. Сделаем новую обработку, форму и на форме обработки создадим следующие реквизиты: Автомобиль, Гараж, Дата прибытия и Пробег с типами, как у соответствующих реквизитов документа. А также на форме создадим команду Создать документ.
Рис. 6.2.19
В том случае если все поля заполнены, программа создаст и запишет новый документ, в реквизиты которого будут внесены значения данных полей.
Каким образом мы будем проверять заполнен реквизит или нет? Делать это будем при помощи свойства реквизита Проверка заполнения и метода управляемой формы ПроверитьЗаполнение().
Установим у всех реквизитов формы, которые мы создали, значение в это свойство.
Для этого откроем палитру свойств реквизита формы и установим в свойство Проверка заполнение значение Выдавать ошибку (см. рис. 6.2.20, на примере реквизита Автомобиль).
Рис. 6.2.20
После того как мы у всех реквизитов формы установим значение Выдавать ошибку в свойстве Проверка заполнения, на форме поля этих реквизитов станут подчёркнуты красной линией.
Рис. 6.2.21
С реквизитами закончили. Создадим у команды формы Создать документ клиентские обработчики на клиенте и на сервере, и в клиентском обработчике, прежде чем вызвать серверный обработчик, применим метод ПроверитьЗаполнение(). Этот метод возвращает Истина, если все реквизиты, у которых установлен параметр Проверка заполнения, заполнены, и Ложь – в обратном случае, когда есть хотя бы один не заполненный реквизит.
&НаКлиенте
Процедура СоздатьДокумент(Команда)
Если Не ПроверитьЗаполнение() Тогда Возврат;
КонецЕсли;
СоздатьДокументНаСервере(); КонецПроцедуры
Листинг 6.2.2
Если у нас хотя бы один реквизит не заполнен, то метод ПроверитьЗаполнение вернёт
Ложь, в нашем условии станет Истина, и произойдёт выход из метода.
В пользовательском режиме это будет выглядеть следующим образом.
Рис. 6.2.22
С проверками мы закончили, займёмся создание документа, для этого в серверном обработчике напишем следующий код:
&НаСервере
Процедура СоздатьДокументНаСервере()
ДокОбъект = Документы.ПрибытиеВГараж.СоздатьДокумент(); ДокОбъект.Дата = ТекущаяДата();
ДокОбъект.Автомобиль = Автомобиль; ДокОбъект.Гараж = Гараж; ДокОбъект.ДатаПрибытия = ДатаПрибытия; ДокОбъект.Пробег = Пробег;
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение,
РежимПроведенияДокумента.Оперативный);
КонецПроцедуры
Листинг 6.2.3
Разберём код в процедуре СоздатьДокументНаСервере.
В первой строке при помощи метода СоздатьДокумент мы создали экземпляр объекта. Этот экземпляр объекта содержится в переменной ДокОбъект, которая имеет тип ДокументОбъект.ПрибытиеВГараж. В последующих пяти строках присваиваем значения реквизитам объекта.
Стандартный реквизит документа Дата должен быть всегда заполнен! А если у объекта установлено свойство Автонумерация, то номер заполнять не нужно!
И в последней строке мы записываем документ.
Разберём последнюю строку подробнее. Как видно, у процедуры Записать объекта Документ два параметра. Первый параметр – это режим записи. Режим записи документа – это системное перечисление. Всего существуют три режима записи документа: запись, отмена проведения и проведение. Объяснять каждый режим не надо, поскольку названия их
интуитивно понятны. Первый параметр необязательный, и если он не будет установлен, то документ будет просто записан без проведения.
Следующий параметр – Режим проведения документа. Что такое режим проведения, мы уже знаем. В данном параметре мы устанавливаем, в каком режиме будет проведён данный документ. Обращаю Ваше внимание, что оперативный режим можно установить только в том случае, если у данного документа разрешено оперативное проведение. По умолчанию этот параметр принимает значение Неоперативный. Самостоятельно посмотрите на выпадающий список системных перечислений РежимЗаписиДокумента и РежимПроведенияДокумента.
Как понятно из примера, нет отдельного метода для проведения документа и для отмены проведения документа. Если понадобится провести непроведённый документ, то нужно получить экземпляр этого документа при помощи метода ПолучитьОбъект и записать этот экземпляр с режимом записи документа Проведение. И, наоборот, если нужно отменить проведение документа, то также следует получить экземпляр объекта, а потом записать этот экземпляр с режимом записи Отмена проведения.
Обратите внимание, если режим проведения установлен Оперативный, то в реквизит Дата должна быть записана или текущая дата, или дата, не меньшая даты последнего оперативно проведённого документа.
Продолжим конструировать обработку: создадим два переключателя, в одном будут перечислены режимы проведения документов, а в другом – режимы записей. Для этого создадим два реквизита формы с типом Число (целое: длина 1, точность 0, также установим проверку заполнения). Разместим эти реквизиты на форме, вид поля у обоих установим Поле переключателя, а в свойстве ВидПереключателя установим значение Тумблер.
Рис. 6.2.23
У элемента формы поля Режим записи заполним список выбора двумя значениями:
Запись и Проведение. Для первого значение будет 1, для второго – 2.
Рис. 6.2.24
А у поля Режим проведения заполним список выбора двумя значениями:
Оперативный и Неоперативный. Для первого значение будет 1, а для второго – 2.
Рис. 6.2.25
Как создавать переключатели на форме мы изучали в предыдущей главе, в этом примере мы научимся программно работать с ними.
Доработаем код в обработчиках команды Создать документ.
&НаСервере
Процедура СоздатьДокументНаСервере()
ДокОбъект = Документы.ПрибытиеВГараж.СоздатьДокумент(); ДокОбъект.Автомобиль = Автомобиль;
ДокОбъект.Гараж = Гараж; ДокОбъект.ДатаПрибытия = ДатаПрибытия; ДокОбъект.Пробег = Пробег;
Если РежимЗаписи = 1 Тогда ДокОбъект.Дата = ДатаПрибытия;
ДокОбъект.Записать(РежимЗаписиДокумента.Запись); ИначеЕсли РежимЗаписи = 2 Тогда
Если РежимПроведения = 1 Тогда ДокОбъект.Дата = ТекущаяДата();
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Оперативный);
ИначеЕсли РежимПроведения = 2 Тогда
ДокОбъект.Дата = ДатаПрибытия; ДокОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Листинг 6.2.4
Из листинга Вы видите, что в использовании переключателей в коде нет ничего сложного: просто реквизиты формы РежимЗаписи и РежимПроведения принимают те значения, которые соответствуют выбранному в текущий момент значению переключателя.
В процедуре СоздатьДокументНаСервере в условии проверяем значение переключателя РежимЗаписи, и если оно равно 1, что соответствует установленному тумблеру Запись, то просто записываем документ, при этом дате документа присваивается значение из реквизита ДатаПрибытия. Если реквизит РежимЗаписи равен 2, то это значит, что мы проводим документ. В этом случае всё зависит от значения реквизита РежимПроведения, если оно равно 1 (оперативное проведение), то проводим в оперативном режиме, и тогда стандартному реквизиту Дата присваиваем текущую дату, а иначе – в неоперативном, тогда стандартному реквизиту Дата присваиваем значение из реквизита.
Найти документ
Научимся находить в базе нужный документ, а впоследствии изменять его. Для поисков документов у менеджера объекта Документ имеются два метода –
НайтиПоНомеру и НайтиПоРеквизиту.
Метод НайтиПоНомеру осуществляет поиск документа по номеру. Разберём сначала синтаксис данного метода, а после посмотрим, как этот метод применяется на практике.
НайтиПоНомеру(<НомерДокумента>, <ДатаИнтервала>)
Метод имеет два параметра. Первый параметр – это номер документа, по которому осуществляется поиск в базе. Тут всё понятно.
Второй параметр используется только для документов с периодической нумерацией (см. стр. 430). Поиск будет осуществляться по тому интервалу, в который входит указанная дата. К примеру, если номера документов уникальны в пределах квартала, а дата интервала 15 марта 2021 года, то поиск будет вестись в интервале дат от 1 января 2021 года до 31 марта 2021 года.
Второй параметр необязателен, но если для документов с периодической нумерацией он не будет установлен, то поиск будет вестись с пустой датой, и на выходе всегда будет пустая ссылка. Поэтому если Вам нужно искать документ в текущем периоде у документа с периодической нумерацией, то всегда устанавливайте текущую дату.
Метод НайтиПоНомеру возвращает ссылку на документ, а если по искомому номеру нет документов, то возвращается пустая ссылка. Если параметр НомерДокумента пустой или равен нулю, то возвращается НеОпределено.
Посмотрим, как работает этот метод на практике. Создадим обработку, в которой пользователь будет вводить вручную номер документа, и при нажатии на кнопку будем осуществлять поиск нужного документа.
Сделаем обработку, форму и на форме – два реквизита, один текстовый с длиной текста 9 символов (длина номера документа Прибытие в гараж), а второй будет иметь тип значения Ссылка на документ Прибытие в гараж. Также на форме создадим команду Найти документ, которую поместим на эту же форму.
Рис. 6.2.26
В обработчиках команды Найти документ напишем следующий код:
&НаСервере
Процедура НайтиДокументНаСервере()
ПрибытиеВГараж = Документы.ПрибытиеВГараж.НайтиПоНомеру(НомерДляПоиска,ТекущаяДата());
КонецПроцедуры &НаКлиенте
Процедура НайтиДокумент(Команда)
НайтиДокументНаСервере(); КонецПроцедуры
Листинг 6.2.5 Поскольку у документа Прибытие в гараж установлена периодическая нумерация, то
вторым параметром мы указали текущую дату.
С работой этого метода у Вас не должно возникать каких-то трудностей.
Рис. 6.2.27
Метод НайтиПоРеквизиту осуществляет поиск документа по реквизиту, он аналогичен одноимённому методу для справочников, с той разницей, что у него только два параметра: название реквизита и значение реквизита. Если документов по данному реквизиту несколько, то будет возвращён один из них. Какой именно – точно предугадать невозможно. Данный метод на практике редко применяется, поэтому мы не будем рассматривать его подробно, а Вы в качестве факультатива можете переделать имеющийся поиск документа в поиск по интересному Вам реквизиту.
Изменение имеющихся документов
Очень часто возникают случаи, когда необходимо программно изменить имеющийся документ, тогда нужно использовать знакомый уже метод ПолучитьОбъект. Этот метод является методом ссылки документа и возвращает экземпляр объекта документа, на который указывает ссылка.
Доработаем предыдущую обработку: добавим на форму новый реквизит Дата прибытия, и если документ по номеру найден, то будем изменять одноимённый реквизит в документе на значение из реквизита формы обработки, а после этого проводить документ в неоперативном режиме.
Рис. 6.2.28
Допишем код в обработчике:
&НаСервере
Процедура НайтиДокументНаСервере()
ПрибытиеВГараж = Документы.ПрибытиеВГараж.НайтиПоНомеру(НомерДляПоиска,ТекущаяДата()); Если ПрибытиеВГараж.Пустая() Тогда
Возврат;
КонецЕсли;
ПрибытиеВГаражОбъект = ПрибытиеВГараж.ПолучитьОбъект(); ПрибытиеВГаражОбъект.ДатаПрибытия = ДатаПрибытия;
Если ПрибытиеВГаражОбъект.Проведен Тогда ПрибытиеВГаражОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
иначе
ПрибытиеВГаражОбъект.Записать(РежимЗаписиДокумента.Запись); КонецЕсли;
КонецПроцедуры
Листинг 6.2.6
В коде выше мы получаем объект из ссылки на документ, и если он не пустой, то заменяем дату прибытия, потом проверяем, проведён документ или нет, и если он проведён, то проводим его в неоперативном режиме, а иначе – просто записываем его.
Во второй части этой главы мы существенно углубили свои знания в работе с документами, изучили нумерацию, научились создавать и изменять документы программным способом. Удаление документов и установка пометки на удаление полностью аналогично соответствующим действиям для справочников. Поупражняйтесь в программном удалении документов самостоятельно.
Любая форма, как и любой элемент на форме, является объектом. Это значит, что у формы и у элементов формы имеются методы и свойства. А также мы можем работать с событиями, которые есть у формы, и с событиями, которые имеются у элементов формы.
Основной реквизит
Прежде чем начать изучать свойства, методы и события форм, изучим такое понятие, как основной реквизит формы. Для любой формы можно назначить основной реквизит.
Обычно он назначается автоматически при создании формы с помощью конструктора. Основной реквизит формы определяет стандартную функциональность формы. От основного реквизита зависит, какие у формы будут стандартные функции. Например, если основной реквизит формы ДокументОбъект, то у формы будут такие стандартные команды, как Проведение и Отмена проведения (если у документа не запрещено проведение по регистрам).
У формы элемента справочника основной реквизит имеет тип СправочникОбъект (см. рис. 6.3.1), а у формы документа основной реквизит имеет тип ДокументОбъект (см. рис.
6.3.2). При открытии формы элемента справочника или документа в этот реквизит загружается экземпляр объекта справочника или документа.
Рис. 6.3.1
Рис. 6.3.2
Обычно основной реквизит всегда выделяется в списке реквизитов жирным шрифтом, а также у него установлено свойство Основной реквизит (см. рис. 6.3.3).
Рис. 6.3.3
Каким образом заполняется Основной реквизит с типом ДокументОбъект или
СправочникОбъект мы узнаем, когда будем изучать открытие формы.
Данные формы
Если Вы внимательно посмотрите на тип основного реквизита формы документа и вспомните то, что мы изучали в предыдущей главе про клиент-серверную архитектуру
управляемой формы, то у вас возникнет небольшой диссонанс: «Как так? Тип основного реквизита самый что ни на есть тяжёлый, но он спокойно размещён на форме?» В действительности основной реквизит формы документа хоть и имеет тип ДокументОбъект.<НазваниеДокумента>, но на форму он загружается совсем под другим типом. Под типом ДанныеФормыСтруктура. Для того чтобы убедиться в этом, установим точку останова в конце команды ВывестиСообщение на форме документа Прибытие в гараж, которую мы создали ранее, и посмотрим в отладке, какой тип имеет реквизит формы Объект, который является основным реквизитом формы (см. рис. 6.3.4).
Рис. 6.3.4
Как видно из рисунка 6.3.4, основной реквизит формы Объект имеет тип ДанныеФормыСтруктура (структуры мы будем изучать в следующей части), и что самое важное, через эту структуру мы можем обращаться к реквизитам того объекта, который сейчас загружен. Мы можем их читать и даже, в принципе, можем их изменять.
Более подробно работа с данными формами разбирается во второй главе третьей части книги «Основы разработки в 1С: Такси».
На текущем этапе обучения мы не будем глубоко изучать работу с данными формами. Просто пока уясним, что при открытии форм документов и элементов справочников данные соответствующего объекта загружаются в структуру, посредством которой эти данные можно и читать, и изменять. Для подтверждения этого тезиса выполним небольшую задачу: на форме документа Прибытие в гараж создадим команду Установить текущую дату прибытия (см. рис. 6.3.5). У этой команды будет обработчик на клиенте, в котором мы сначала проверим, проведён ли документ, потом проверим, заполнена ли дата прибытия.
Если она не заполнена, то присвоим ей текущую дату. Если же она заполнена, но день, месяц и год не соответствуют текущим, то опять присвоим ей текущую дату. А иначе – ничего не делаем.
Рис. 6.3.5
Создадим для команды обработчик на клиенте, и напишем в нём следующий код:
&НаКлиенте
Процедура УстановитьТекущуюДатуПрибытия(Команда)
Если Не ЗначениеЗаполнено(Объект.ДатаПрибытия) Тогда Объект.ДатаПрибытия = ТекущаяДата(); Модифицированность = Истина;
Иначе
Если НачалоДня(Объект.ДатаПрибытия) <> НачалоДня(ТекущаяДата()) Тогда Объект.ДатаПрибытия = ТекущаяДата();
Модифицированность = Истина; КонецЕсли;
КонецЕсли;
КонецПроцедуры
Листинг 6.3.1
В этом коде мы читаем и изменяем реквизит ДатаПрибытия основного реквизита формы Объект. Модифицированность – это свойство формы (их мы будем изучать ниже), при установке этому свойству значения Истина на форме появится знак (*) и при закрытии формы будет задаваться вопрос о сохранении.
Доработайте данное задание: проверяйте, проведён ли текущий документ или нет, и если не проведён, то не изменяйте этот реквизит.
Свойства, методы и события формы
Изучим свойства, методы и события управляемой формы. Начнём со свойств.
Установить какое-либо значение в свойство формы можно напрямую, используя палитру свойств формы в конфигураторе. Узнаем, как работать со свойствами в палитре свойств формы из конфигуратора, а также научимся создавать обработчики событий из палитры свойств.
Для примера будем использовать форму документа Выбытие из гаража. Откроем форму документа в конфигураторе, а потом откроем палитру свойств формы. Чтобы открыть палитру свойств формы, необходимо в редакторе формы в закладке Элементы выделить самый верх дерева элементов Форма и либо сделать двойной щелчок левой клавишей мышки, либо вызвать контекстное меню и выполнить команду Свойства (см. рис. 6.3.6).
Рис. 6.3.6
После выполнения команды в правой части экрана должна открыться палитра свойств формы, где перечислены свойства и значения свойств текущей формы, а также события.
Рис. 6.3.7
В предыдущей главе мы уже познакомились со свойством Режим открытия окна (см. стр. 329). Поскольку свойств много, мы не будем разбирать каждое свойство из палитры, но получить информацию о свойстве можно в синтакс-помощнике. Сейчас мы с Вами научимся грамотно работать с синтакс-помощником. В синтакс-помощнике все свойства управляемых форм находятся по пути Интерфейс(управляемый) – Форма клиентского приложения – ФормаКлиентскогоПриложения – Свойства (см. рис. 6.3.8).
Рис. 6.3.8
В папке Свойства перечислены все свойства управляемой формы, причём их больше,
чем в палитре свойств. В описании свойства следует особо обращать внимание на два пункта
это Использование и Доступность. Для примера возьмём свойство Заголовок (см. рис. 6.3.9).
Рис. 6.3.9
Под пунктом Использование написано «Чтение и запись», это значит, что мы можем прочитать значение данного свойства, но также и изменить его, то есть записать в заголовок какое-то значение. Причем как программно в процессе работы, так и в палитре свойств.
А под пунктом Доступность написано «Тонкий клиент, веб-клиент, ...». Это значит, что чтение и запись этого свойства доступны практически под всеми видами клиентов, включая самые «медленные» – тонкий клиент и веб-клиент.
А вот у свойства ИмяФормы под пунктом Использование написано «Только чтение» (см. рис. 6.3.10). Это значит, что мы сможем только прочитать это свойство, но нигде не сможем его изменить в программном коде.
Рис. 6.3.10
Как было сказано в начале текущей части, у каждой формы может быть один основной реквизит. Тип этого основного реквизита влияет на состав свойств, методов и событий форм. Для форм документов, у которых тип ДокументОбъект, будет один состав свойств, методов и событий, а для формы элементов справочника с типом СправочникОбъект – другой.
Причём описания свойств, методов и событий, которые есть у форм с любым основным реквизитом, находятся по уже знакомому нам пути Интерфейс (управляемый) – Форма клиентского приложения – ФормаКлиентскогоПриложения – Свойства.
А свойства, методы и события управляемых форм с тем или иным типом основного реквизита называются расширениями управляемой формы. Они добавляются к стандартным свойствам, методам и событиям.
В синтакс-помощнике описание расширений управляемой формы находятся в каталоге
Интерфейс (управляемый) – Форма клиентского приложения (см. рис. 6.3.11)
Рис. 6.3.11
Таким образом, полная информация о свойствах, методах и событиях формы документа содержится в двух папках справочной информации:
Интерфейс (управляемый) – Форма клиентского приложения – Управляемая форма – типовые свойства и т.д. для всех управляемых форм;
Интерфейс (управляемый) – Форма клиентского приложения – Расширение документа
– свойства и т.д. для форм, у которых основной реквизит – объектный тип какого- нибудь документа.
Познакомимся с событиями формы. Перечень всех событий управляемой формы располагается в палитре свойств внизу списка (см. рис. 6.3.12).
Рис. 6.3.12
Причём заметьте, само по себе событие ничего не значит, для того чтобы оно как-то работало, необходимо создать обработчик этого события – процедуру в модуле формы на клиенте, которая привяжется к соответствующему событию.
Для того чтобы создать обработчик какого-нибудь события на форме, нужно кликнуть на пиктограмму Лупа рядом с этим событием, после этого или будут предложены варианты расположения обработчиков (см. рис. 6.3.13), или событие сразу будет создано (в основном это касается событий, которые выполняются на сервере, например, ПриСозданииНаСервере).
Рис. 6.3.13
С описанием всех событий формы также можно познакомиться в справочной информации. В том же самом разделе Интерфейс(управляемый) – Форма клиентского приложения – ФормаКлиентскогоПриложения, только в папке События (см. рис. 6.3.14).
Рис. 6.3.14
В этой папке перечислены стандартные события для любой формы. События же расширений формы перечислены в соответствующих папках.
Научимся к свойствам формы обращаться непосредственно из формы. Для этого реализуем небольшую задачу: при открытии формы документа Выбытие из гаража в заголовке формы будем выводить автомобиль и время выбытия. Делать мы это будем в событии формы ПриОткрытии. Это событие вызывается после создания формы, но до её открытия. Ещё нам следует снять флаг у свойства формы АвтоЗаголовок (самостоятельно узнайте, что это за свойство и за что отвечает).
Рис. 6.3.15
Создадим обработчик для события формы ПриОткрытии на клиенте (см. рис. 6.3.16).
Рис. 6.3.16
В созданном обработчике напишем следующий код:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если ЗначениеЗаполнено(Объект.Автомобиль) и ЗначениеЗаполнено(Объект.ДатаВыбытия) Тогда
Заголовок = Строка(Объект.Автомобиль) +
" уехал " + Формат(Объект.ДатаВыбытия,"ДЛФ=DD");
иначе
АвтоЗаголовок = Истина; КонецЕсли;
КонецПроцедуры
Листинг 6.3.2
Разберём код в листинге 6.3.2.
Первое – обратите внимание, что к свойствам формы можно обращаться напрямую,
просто написав это свойство. Не нужно писать никаких «ЭтаФорма» и т.д., просто пишем название свойства в коде и с ним работаем. Но! Помним про контекст! К свойствам формы можно обращаться под клиентским и серверным контекстом, т.е. под директивами &НаКлиенте и &НаСервере.
В обработчике события формы ПриОткрытии мы первым делом проверяем, есть ли данные в реквизитах объекта Автомобиль и ДатаВыбытия при помощи уже знакомого нам метода ЗначениеЗаполнено. Обращаемся мы к этим реквизитам через основной реквизит формы Объект, который, как Вы должны помнить, имеет тип ДанныеФормыКоллекция и у которого имеются в составе указанные реквизиты (см. рис. 6.3.17). Если они не заполнены, то свойству АвтоЗаголовок присваиваем значение Истина, и у нас будет выведен заголовок по умолчанию. А если они заполнены, то свойству Заголовок присваиваем определённый текст (Автозаголовок мы и так уже сняли). При помощи функции преобразования значений Строка мы преобразуем ссылку на справочник Автомобили в её строковое значение. А с помощью функции Формат преобразуем дату в читаемый вид. Посмотрим, как теперь открывается форма уже существующего (см. рис. 6.3.18) документа и форма нового (см. рис. 6.3.19).
Рис. 6.3.17
Рис. 6.3.18
Рис. 6.3.19
Из всего множества методов форм рассмотрим только один – РеквизитФормыВЗначение. Как Вы помните, основной реквизит формы для элементов справочников и документов имеет тип ДанныеФормыКоллекция. А что если нам нужно получить все-таки объектный тип? ДокументОбъект.<НазваниеДокумента> или СправочникОбъект.<НазваниеСправочника>?
Как правило, обращение к объекту может понадобиться, если мы хотим получить доступ к каким-нибудь методам объекта (как закрытым, так и собственным). Не рекомендуется получать доступ к объекту для изменения реквизитов объекта! Изменение реквизитов успешно можно сделать посредством основного реквизита формы, и мы уже это делали ранее.
Чтобы показать, как работает метод формы РеквизитФормыВЗначение, выполним небольшую задачу: в документе Выбытие из гаража реализуем возможность получения информации об автомобиле из документа. Для этого в модуле объекта документа создадим экспортную функцию ИнформацияОбАвтомобиле(), которая будет возвращать гос. номер и год выпуска автомобиля. А на форму добавим команду Об автомобиле, при нажатии на которую будет срабатывать функция из модуля документа.
В модуле объекта документа Выбытие из гаража напишем следующую процедуру:
Функция ИнформацияОбАвтомобиле() Экспорт
Возврат "Гос. номер: " + Автомобиль.ГосНомер + "
|год выпуска: " + Формат(Автомобиль.ГодВыпуска,"ДФ=гггг")
КонецФункции
Листинг 6.3.3
Создадим команду формы ОбАвтомобиле, которую разместим в командной панели формы, и укажем у неё картинку (см. рис. 6.3.20).
Рис. 6.3.20
Для команды ОбАвтомобиле создадим обработчики на клиенте и на сервере. Почему в том числе на сервере? Ответьте на этот вопрос самостоятельно, посмотрев описание метода РеквизитФормыВЗначение.
В обработчиках команды формы напишем следующий код:
&НаСервере
Функция ОбАвтомобилеНаСервере()
ОбъектДок = РеквизитФормыВЗначение("Объект"); Возврат ОбъектДок.ИнформацияОбАвтомобиле();
КонецФункции
&НаКлиенте
Процедура ОбАвтомобиле(Команда) ПоказатьПредупреждение(,ОбАвтомобилеНаСервере());
КонецПроцедуры
Листинг 6.3.4
Сохраним конфигурацию, обновим базу данных и попробуем выполнить новую команду (см. рис. 6.3.21).
Рис. 6.3.21
Свойства и события элементов формы
Вы уже знаете, как конфигурировать элементы формы (добавлять, изменять свойства и т.д.). В этой главе мы научимся программно работать с элементами формы. Элемент формы является по сути объектом и тоже имеет свои собственные свойства, методы и события, с которыми можно работать.
Научимся программно обращаться к элементам формы. Для тренировки создадим обработку, форму обработки, на форме создадим несколько реквизитов примитивных типов и несколько элементов: поля ввода реквизитов, группы и декорации. Также на форме создадим команду, которую назовём Доступ к элементам, и обработчик для этой команды на клиенте (см. рис. 6.3.22).
Рис. 6.3.22
На этой форме мы будем тренироваться получать доступ к элементам формы. Доступ ко всем элементам формы осуществляется посредством свойства формы Элементы, которое является коллекцией элементов формы. Поставим в конце процедуры обработчика команды Доступ к элементам точку останова, запустим отладку, выполним эту команду в пользовательском режиме и посмотрим, что находится в свойстве Элементы в табло (см. рис. 6.3.23).
Рис. 6.3.23
Как видно из рисунка, через свойство формы Элементы мы можем получить доступ к свойствам всех элементов, которые размещены на форме. У каждого вида элемента много различных свойств, и объяснять все свойства не входит в рамки этой книги. Поэтому, как и со свойствами формы, научимся получать сведения из справочной информаций.
Справочная информация об элементах формы находится в папке Интерфейс (управляемый). Нас интересуют четыре элемента: Поле формы, Кнопка формы, Группа формы и Декорация формы (см. рис. 6.3.24).
Рис. 6.3.24
Возьмём, к примеру, Поле формы. У этого элемента есть Свойства, События и
Методы (см. рис. 6.3.25).
Рис. 6.3.25
Но поле формы не бывает само по себе, обычно оно имеет какой-нибудь вид, это может быть поле ввода, поле флажка, поле переключателя и т.д. Все эти виды поля ввода являются его расширениями и для них есть дополнительные свойства, методы и события. Их описания имеются в соответствующих каталогах (см. рис. 6.3.26).
Рис. 6.3.26
Причём Вы видите, что расширений поля ввода гораздо больше, чем видов полей ввода, которые мы проходили в этой книге.
Также расширения имеются для Групп (см. рис. 6.3.27) и для Декораций (см. рис.
6.3.28).
Рис. 6.3.27
Рис. 6.3.28
Выполним следующий пример. На только что созданной форме имеется реквизит Булево, который размещён в виде Поля формы с видом Поле флажка. По умолчанию у этого поля стоит вид флажка Выключатель (см. рис. 6.3.29). Изменим программно вид флажка с Выключатель на Тумблер, воспользовавшись уже созданным обработчиком команды ДоступКЭлементам.
Рис. 6.3.29
Перед тем как программно изменять свойство элемента, найдём это свойство в справке и посмотрим его описание (см. рис. 6.3.30).
Рис. 6.3.30
Нас интересует возможность изменения этого свойства (раздел Использование), а также доступу к нему под тонким клиентом (раздел Доступность), иначе пришлось бы делать вызов сервера. И то, и то мы можем сделать. А также узнаем, какой тип имеет данное свойство (раздел Описание). Это системное перечисление ВидФлажка, посмотрим, можно ли обратиться к нему на тонком клиенте (см. рис.6.3.31).
Рис. 6.3.31
Напишем в обработчике команды ДоступКЭлементам код, в котором будем менять вид флажка (см. листинг 6.3.5).
&НаКлиенте
Процедура ДоступКЭлементам(Команда) Элементы.РеквизитБулево.ВидФлажка = ВидФлажка.Тумблер;
КонецПроцедуры
Листинг 6.3.5
Самостоятельно опробуйте работу этого кода.
Решим ещё одну задачу. Для полей ввода даты и строки, которые связаны с реквизитами РеквизитСтрока и РеквизитДата, установим значение свойства ТолькоПросмотр в Истина (см. рис. 6.3.32).
Рис. 6.3.32
После таких настроек при открытии формы мы не сможем редактировать информацию в этих полях. Но сделаем так, чтобы после нажатия на кнопку Доступ к элементам оба этих поля открывались для редактирования (см. листинг 6.3.6).
Самостоятельно найдите свойство ТолькоПросмотр поля ввода в синтакс- помощнике и посмотрите доступность этого свойства.
Добавим код в обработчике события команды ДоступКЭлементам.
Элементы.РеквизитДата.ТолькоПросмотр = Ложь; Элементы.РеквизитСтрока.ТолькоПросмотр = Ложь;
Листинг 6.3.6
Со свойствами элементов разобрались, как Вы поняли, в этом нет ничего сложного: просто обращаетесь к нужному элементу формы посредством коллекции Элементы и через точку получаете свойство, которое или просто читаете, или присваиваете ему какое-нибудь значение того типа, который определён для этого свойства (если не знаете, смотрите в справочной информации).
Научимся работать с событиями элементов формы. В этой книге мы научимся создавать события элементов только посредством конфигуратора, программное создание событий даётся в книге «Основы разработки в 1С: Такси».
В конфигураторе перечень событий элемента находится в палитре свойств в разделе
События (см. рис. 6.3.33).
Рис. 6.3.33
Так же, как и со свойствами, наличие или отсутствие того или иного события определяется расширением этого элемента. Например, на рис. 6.3.33 Вы видите события для элемента формы Поле формы с видом Поле флажка, а для аналогичного элемента формы только с видом Поле ввода будет другой перечень событий (см. рис. 6.3.34).
Рис. 6.3.34
Прочитать информацию о том, у каких полей формы какие события имеются, можно во всё той же справочной информации. Аналогично, как и в случае свойств и методов, состав перечня событий зависит от расширения элемента. Например, у Поля формы есть только одно событие ПриИзменении (см. рис. 6.3.35). Это значит, что это событие имеется у всех полей формы в независимости от их расширения.
Рис. 6.3.35
Все события Поля формы с типом Поле ввода описаны в расширении для поля ввода (см. рис. 6.3.36).
Рис. 6.3.36
Выполним несколько примеров. Если у нас флажок (он имеет вид Выключатель), связанный с реквизитом РеквизитБулево, нажат, то будем показывать поля реквизитов РеквизитДата и РеквизитСтрока, а если флажок снят, то – нет.
Создадим обработчик события ПриИзменении поля формы РеквизитБулево, для этого откроем палитру свойств элемента и нажмём на кнопку Лупа соответствующего события (см. рис. 6.3.37).
Рис. 6.3.37
За видимость элемента на форме отвечает свойство этого элемента – Видимость.
Самостоятельно найдите в синтакс-помощнике информацию о доступности этого свойства. Забегая вперёд, скажем, что оно доступно на тонком клиенте. Поэтому обработчик события создадим только на клиенте. В этом обработчике напишем код, где свойству Видимость соответствующих элементов будем присваивать значение реквизита РеквизитБулево, который связан с нашим полем флажка: значение этого реквизита изменяется при изменении поля флажка.
&НаКлиенте
Процедура РеквизитБулевоПриИзменении(Элемент)
Элементы.РеквизитДата.Видимость = РеквизитБулево; Элементы.РеквизитСтрока.Видимость = РеквизитБулево;
КонецПроцедуры
Листинг 6.3.7
Посмотрим на работу этого события (см. рис. 6.3.38 и 6.3.39).
Рис. 6.3.38
Рис. 6.3.39
И у нашей формы ещё осталась одна недоработка: при первом открытии формы в реквизите РеквизитБулево по умолчанию значение Ложь, но поля ввода всё равно видно. Сделаем так, чтобы они при открытии были скрыты. Для этого создадим клиентскую процедуру, которая и будет отвечать за видимость полей ввода, и эту клиентскую процедуру будем вызывать и в обработчике ПриИзменении поля флажка, и в обработчике ПриОткрытии поля ввода.
Сначала создадим клиентскую процедуру и перепишем обработчик ПриИзменении.
&НаКлиенте
Процедура УстановитьВидимостьРеквизитов() Элементы.РеквизитДата.Видимость = РеквизитБулево; Элементы.РеквизитСтрока.Видимость = РеквизитБулево;
КонецПроцедуры
&НаКлиенте
Процедура РеквизитБулевоПриИзменении(Элемент) УстановитьВидимостьРеквизитов();
КонецПроцедуры
Листинг 6.3.8
Создадим событие формы ПриОткрытии в клиентском контексте.
Рис. 6.3.40
В обработчике события вызовем созданную клиентскую процедуру.
&НаКлиенте
Процедура ПриОткрытии(Отказ)
УстановитьВидимостьРеквизитов();
КонецПроцедуры
Листинг 6.3.9
Доработайте код: скрывайте точно так же декорации и при открытии формы меняйте заголовок поля флажка на Скрыть реквизиты (создайте для этого разные методы).
Рассмотрим ещё один пример: для поля ввода РеквизитСтрока установим кнопку очистки. Для этого необходимо установить флаг у свойства КнопкаОчистки. Мы это сделаем в конфигураторе (см. рис. 6.3.41), а Вы сделайте программно при открытии формы. При нажатии на кнопку очистки стандартно происходит очистка поля ввода. Причём у поля ввода есть такое событие Очистка, которое срабатывает, когда нажимают на эту кнопку.
Перехватим это событие и при очистке будем проверять, заполнено ли поле ввода РеквизитДата, и если заполнено, то не будем очищать это поле и выведем сообщение, что нужно сначала очистить поле ввода РеквизитДата.
Рис. 6.3.41
Найдем событие Очистка у элемента формы РеквизитСтрока и создадим обработчик этого события на клиенте (см. рис. 6.3.42).
Рис. 6.3.42
Заметьте, у процедуры обработчика появился параметр СтандартнаяОбработка (см. рис. 6.3.43). Этот параметр имеет тип Булево и по умолчанию принимает значение Истина. Когда данный параметр имеет значение Истина, происходит стандартная обработка события,
в нашем случае поле ввода будет очищено в любом случае, чтобы мы не написали в этом событии. Если в обработчике события этот параметр примет значение Ложь, то стандартной обработки события не произойдёт, то есть поле ввода не очистится.
Рис. 6.3.43
Напишем в процедуре код по алгоритму, описанному выше (см. листинг 6.3.10).
&НаКлиенте
Процедура РеквизитСтрокаОчистка(Элемент, СтандартнаяОбработка) СтандартнаяОбработка = Ложь;
Если ЗначениеЗаполнено(РеквизитДата) Тогда Сообщить("Очистите сначала дату");
Иначе
СтандартнаяОбработка = Истина; КонецЕсли;
КонецПроцедуры
Листинг 6.3.10
Проверьте работу этого кода самостоятельно.
Открытие формы
Изучим основные моменты открытия форм. Разберём, что происходит в системе во время создания и открытия формы.
Нас интересуют два варианта создания формы. Первый – открытие формы существующего объекта. Второй – открытие формы для нового объекта. В обоих вариантах не имеет значения, как открывается форма – интерактивно пользователем или при помощи программного кода.
Открытие формы существующего объекта
Первый шаг. После того как пользователь инициировал открытие формы существующего объекта, на сервере будет создан экземпляр объекта (документа или справочника) и произойдёт выполнение кода модуля объекта (который идёт после всех процедур модуля). Во время этого происходит считывание данных из базы и заполнение реквизитов экземпляра объекта (документа или справочника). Процесс первого шага осуществляется платформой автоматически, и вмешаться в него мы не можем.
Во время второго шага на сервере создаётся и заполняется экземпляр управляемой
формы, которая указана в свойстве объекта Основная форма объекта (если основной формы нет, то макет формы генерируется автоматически). После того как прошло заполнение управляемой формы данными из экземпляра объекта документа, вызывается событие формы ПриЧтенииНаСервере, которое имеет один параметр ТекущийОбъект, содержащий созданный экземпляр объекта.
Заметьте, когда произошёл вызов этого события, основной реквизит формы Объект уже заполнен данными. Но у нас есть ещё возможность дозаполнить или перезаполнить основной реквизит формы по данным экземпляра объекта.
Только в событии ПриЧтенииНаСервере есть доступ к экземпляру объекта документа!
После заполнения основного объекта формы экземпляр объекта документа на сервере будет уничтожен.
Во время третьего шага идёт уже работа с заполненной формой, которая носит подготовительный характер. Сначала происходит событие ПриСозданииНаСервере, во время выполнения этого события мы можем подготовить форму, когда она ещё находится на сервере. А также отменить создание формы.
И в последнем, четвёртом шаге все данные формы, которые были на сервере, сериализуются и отправляются клиенту. При этом в клиентском контексте срабатывает событие ПриОткрытии, в нём можно выполнять различные манипуляции с формой, которые невозможно сделать на сервере.
Разберём все шаги создания формы на примере. Экспериментировать мы в этот раз будем с формой документа Установка цен на топливо.
Напишем в модуле объекта документа Установка цен на топливо простой код после всех процедур:
Сообщить("Шаг 1. В модуле объекта");
Рис. 6.3.44
Дальше создадим обработчики следующих событий формы: ПриЧтенииНаСервере, ПриСозданииНаСервере и ПриОткрытии. Для этого зайдём в палитру свойств формы и нажмём на кнопку Лупа соответствующих обработчиков (см. рис. 6.3.45).
Рис. 6.3.45
В процедурах обработчиков событий напишем следующий код (см. листинг 6.3.11):
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
Сообщить("Шаг 2. Заполнили данные формы по данным объекта");
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) Сообщить("Шаг 3. Обработка создания формы на сервере");
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Сообщить("Шаг 4. Обработка открытия формы на клиенте"); КонецПроцедуры
Листинг 6.3.11 Сохраним конфигурацию, обновим базу данных и откроем форму документа
Установка цен на топливо (см. рис. 6.3.46).
Рис. 6.3.46
Открытие формы нового объекта
При открытии формы нового объекта будут несколько иные шаги создания формы.
Первый шаг. После того как пользователь инициировал открытие формы нового объекта (документа или справочника) или запустил команду создания объекта на основании, будет создан новый экземпляр соответствующего объекта. После этого произойдёт выполнение кода в модуле объекта (который после всех процедур) и отработает событие в модуле объекта ОбработкаЗаполнения. Если прикладная задача предусматривает создание нового объекта на основании какого-то существующего, то в событии ОбработкаЗаполнения необходимо реализовать заполнение реквизитов и табличных частей нового объекта по имеющимся данным.
Во время второго шага аналогично, как и в случае открытия формы существующего объекта, будет создана форма объекта на сервере и произойдёт заполнение основного реквизита формы по тем данным, которые были заполнены в событии модуля объекта ОбработкаЗаполнения. Но при открытии формы нового объекта на сервере не будет отрабатываться событие ПриЧтенииНаСервере. Потому что в этом случае читать особо и нечего: не создан экземпляр объекта.
Шаги третий и четвёртый, где используются обработки событий
ПриСозданииНаСервере и ПриОткрытии, работают точно так же, как и тогда, когда идёт
открытие формы существующего объекта.
Проверим на практике вышесказанную цепочку, для этого создадим в модуле объекта документа Установка цен на топливо событие ОбработкаЗаполнения, где будем выводить сообщение о первом шаге.
Если Вы забыли, то напомним, как создать событие в модуле объекта. Для этого необходимо открыть сам модуль, активизировать его (то есть установить курсор) и выполнить команду Процедуры и функции (см. рис. 6.3.47).
Рис. 6.3.47
После выйдет окно Процедуры и функции, где выделим пункт Обработка заполнения и нажмём кнопку Перейти (см. рис. 6.3.48).
После этих действий будет создана пустая процедура, в которой напишем код, как в листинге 6.3.9.
Рис. 6.3.48
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Сообщить("Шаг 1.1. Обработка заполнения"); КонецПроцедуры
Листинг 6.3.12
Сохраним конфигурацию, обновим базу данных и интерактивно создадим новый документ Установка цен на топливо. При этом произойдёт открытие формы документа (см. рис. 6.3.49).
Рис. 6.3.49
Заметьте, на рисунке 6.3.49 в окне сообщений нет информации о шаге 2, потому что не произошла обработка события ПриЧтенииНаСервере. В то же время если мы заполним какой-либо информацией реквизиты объекта в обработчике модуля объекта ОбработкаЗаполнения, то эта информация отобразится на форме.
Программное открытие формы
В предыдущих подразделах мы узнали, что происходит при открытии формы и какие обработчики задействованы при открытии формы существующего объекта и открытии
формы нового объекта. В этом подразделе мы научимся открывать формы объектов программным способом и узнаем, как использовать параметры форм.
Понятно, что открыть форму мы можем только в клиентском контексте, именно на том компьютере, где работает пользователь. На сервере нет никакого смысла в открытии формы. Поскольку форма – это основной интерфейсный элемент взаимодействия пользователя с программой. Как следствие, запускать методы открытия форм необходимо в процедурах или функциях, которые расположены под директивой &НаКлиенте. Форму можно открывать под Толстым клиентом, Тонким клиентом и Веб-клиентом.
Научимся программно открывать формы. Для этого будем использовать новую обработку. Создадим у этой обработки форму, команду Открытие формы и разместим команду на форме обработки (см рис. 6.3.50). А также на клиенте создадим действие для этой команды.
Рис. 6.3.50
В дальнейшем все действия подраздела мы будем осуществлять в процедуре на клиенте ОткрытьФорму (см. листинг 6.3.13).
&НаКлиенте
Процедура ОткрытиеФормы(Команда)
// Вставить содержимое обработчика.
КонецПроцедуры
Листинг 6.3.13
В управляемом приложении открыть форму можно при помощи трёх методов глобального контекста – это ПолучитьФорму, ОткрытьФорму и ОткрытьФормуМодально. В этом труде мы изучим только метод ОткрытьФорму, поскольку с его помощью решается большинство задач.
Метод ОткрытьФорму имеет следующий синтаксис:
ОткрытьФорму(<ИмяФормы>, <Параметры>, <Владелец>, <Уникальность>, <Окно>,
<НавигационнаяСсылка>, <ОписаниеОповещенияОЗакрытии>,
<РежимОткрытияОкна>)
Где:
ИмяФормы – непосредственно имя формы (тип Строка). В строке должен быть указан
полный путь к нужной форме.
Это единственный обязательный параметр!
Например, для формы документа Прибытие в гараж имя формы может быть такой: Документ.ПрибытиеВГараж.ФормаОбъекта или такой: Документ.ПрибытиеВГараж.Форма.ФормаДокумента. Ниже мы научимся быстро и без ошибок получать имя формы.
В этой книге разобраны только такие параметры метода: ИмяФормы, Параметры и РежимОткрытияОкна. Работа с остальными параметрами даётся в третьей части книги
«Основы разработки в 1С: Такси».
Научимся безошибочно получать имя формы. Для этого можно использовать контекстную подсказку. Чтобы она сработала, нужно написать название метода и открыть скобку и кавычку:
ОткрытьФорму("
После этого появится контекстная подсказка с группами объектов метаданных (см. рис. 6.3.51). Если она по какой-то причине не вышла, нажмите Ctrl + Space (пробел).
Рис. 6.3.51
Мы выберем прототип метаданных Документ, и после этого отобразится список всех имеющихся в конфигурации документов (см. рис. 6.3.52).
Рис. 6.3.52
Выберем документ ПрибытиеВГараж, отобразится контекстная подсказка, в которой или можно будет выбрать какую-либо конкретную форму, или форму из свойства объекта (см. рис. 6.3.53).
Рис. 6.3.53
Если из выпадающего списка форм мы выберем пункты: ФормаВыбора, ФормаОбъекта и ФормаСписка, то будут открыты формы из соответствующих свойств объекта конфигурации. В нашем случае – это свойства Основная форма объекта, Основная форма выбора и Основная форма списка (см. рис. 6.3.54). Если в каком-то из этих свойств не указана форма, то форма всё равно будет открыта. Она сгенерируется платформой автоматически.
Если в контекстной подсказке, изображённой на рис. 6.3.54, выбрать пункт Форма, то выйдет следующая контекстная подсказка со всеми созданными формами этого объекта метаданных (см. рис. 6.3.55).
Рис. 6.3.55
В этой контекстной подсказке будут все формы, которые есть у объекта метаданных (см. рис. 6.3.56).
Рис. 6.3.56
Если у Вас нет формы списка у этого документа, то создайте её самостоятельно!
Выберем форму списка. Должен получиться следующий код:
ОткрытьФорму("Документ.ПрибытиеВГараж.Форма.ФормаСписка");
Если мы сейчас сохраним обработку, откроем её в нашей конфигурации и применим команду Открытие формы, то откроется форма списка документа Прибытие в гараж, причём в «соседнем» окне (см. рис. 6.3.57).
А если выберем форму документа:
ОткрытьФорму("Документ.ПрибытиеВГараж.Форма.ФормаДокумента");
то откроется пустая форма документа (см. рис. 6.3.58).
Рис. 6.3.58
Открытие форм с передачей параметров
Естественно, у Вас может вознинуть вопрос, каким образом открыть форму уже существующего документа? Для того чтобы ответить на этот вопрос, нам придётся изучить следующий параметр метода ОткрытьФорму – <Параметры>.
ОткрытьФорму(<ИмяФормы>, <Параметры>, <Владелец>, <Уникальность>, <Окно>,
<НавигационнаяСсылка>, <ОписаниеОповещенияОЗакрытии>,
<РежимОткрытияОкна>)
Этот параметр должен иметь тип Структура, где в качестве ключа элемента структуры должно быть задано название параметра, а в качестве значения элемента структуры – значение параметра. Он является необязательным и может быть пропущен, если нет необходимости в передаче каких-либо параметров в форму.
Подробно коллекцию Структура будем проходить в седьмой главе.
Чтобы открыть форму существующего документа или справочника, необходимо использовать параметр Ключ, который есть в расширении справочников и документов, в этот параметр необходимо передать ссылку на открываемый справочник или документ.
Пока звучит немного непонятно, но сейчас Вы поймете, как работать с этим параметром.
Для этого в ранее созданной обработке создадим реквизит Прибытие в гараж с типом
ДокументСсылка.ПрибытиеВГараж и разместим его на форме (см. рис. 6.3.59).
Рис. 6.3.59
Изменим обработчик команды Открытие формы: создадим новую структуру с единственным элементом, ключ которого будет называться Ключ, а в значение подставляться реквизит формы ПрибытиеВГараж – ссылка на документ Прибытие в гараж. И эту структуру будем использовать в качестве второго параметра метода ОткрытьФорму, когда открываем форму документа (см. листинг 6.3.14).
&НаКлиенте
Процедура ОткрытиеФормы(Команда) ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Ключ",ПрибытиеВГараж); ОткрытьФорму("Документ.ПрибытиеВГараж.Форма.ФормаДокумента",
ПараметрыФормы); КонецПроцедуры
Листинг 6.3.14 Перезапустим обработку, выберем в поле Прибытие в гараж какой-нибудь документ
и выполним команду Открыть форму. В результате откроется форма того документа,
который был выбран нами (см. рис. 6.3.59).
Параметр Ключ является расширением управляемой формы для документа. Если при открытии формы объекта (документа, справочника, плана видов характеристик и т.п.) будет передан параметр Ключ со ссылкой на соответствующий объект, то будут выполнены все шаги, которые мы описали в подразделе «Открытие формы существующего объекта» этой части (см. стр. 468).
Рис. 6.3.60
Продолжим изучать открытие форм с параметрами.
Выполним небольшую задачку. В новой обработке создадим форму обработки, а на форме создадим два реквизита – Время и Расстояние с типом Число (см. рис. 6.3.61), а также команду Рассчитать скорость. Эта форма будет основной формой обработки, то есть будет открываться при запуске обработки (см. рис. 6.3.63).
У новой обработки также создадим форму Форма расчета скорости, на которой создадим два параметра Время и Расстояние (см. рис. 6.3.62), а также реквизит Скорость, который разместим на форме.
При выполнении команды Рассчитать скорость основной формы обработки будем открывать форму Форма расчета скорости, где произведём расчёт скорости, деля расстояние на время и записывая результат в реквизит Скорость.
Рис. 6.3.61
Рис. 6.3.62
Рис. 6.3.63
Создадим обработчик для команды Рассчитать скорость, в котором будем открывать форму Форма расчета скорости обработки и передавать в метод открытия формы в качестве
параметра структуру с двумя элементам. Названия ключей элементов соответствуют названиям параметрам формы Форма расчета скорости, а в значения элементов будут передаваться значения соответствующих реквизитов формы (см. листинг 6.3.15).
&НаКлиенте
Процедура РассчитатьСкорость(Команда) ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Расстояние",Расстояние); ПараметрыФормы.Вставить("Время",Время);
ОткрытьФорму("ВнешняяОбработка.Глава6Часть3Обработка3.Форма.ФормаРасчётаСкорости ",ПараметрыФормы);
КонецПроцедуры
Листинг 6.3.15
Нам осталось эту скорость рассчитать, делать мы это будем в обработчике события ПриСозданииНаСервере формы Форма расчета скорости, причём если параметр Время равен нулю, то форму не будем открывать (см. листинг 6.3.16).
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Время = 0 Тогда Сообщить("Время равно 0"); Отказ = истина;
Возврат;
КонецЕсли;
Скорость = Параметры.Расстояние / Параметры.Время; КонецПроцедуры
Листинг 6.3.16
Сохраним обработку и попробуем вычислить скорость (см. рис. 6.3.64 и 6.3.65).
Рис. 6.3.64
Рис. 6.3.65
Для красоты изменим заголовки обоих форм (см. рис. 6.3.66 и 6.3.67).
Рис. 6.3.66
Рис. 6.3.67
Попробуем теперь рассчитать скорость (см. рис. 6.3.68 и 6.3.69).
Рис. 6.3.68
Рис. 6.3.69
Режимы открытия окна
Вы заметили, что каждый раз окна открываются в «соседнем окне», т.е. независимо. В то же время из пятой главы (стр. 329) мы знаем, что существуют различные режимы открытия окна, которые задаются при помощи свойства формы РежимОткрытияОкна. Если мы присвоим свойству формы РежимОткрытияОкна какое-либо значение, то форма всегда будет открываться в этом режиме. Обычно по умолчанию форма открывается в режиме Независимый.
Можно ли программно открыть формы в другом режиме, не меняя при этом свойство формы? Да, можно. Для этого необходимо использовать последний параметр метода ОткрытьФорму – РежимОткрытияОкна.
ОткрытьФорму(<ИмяФормы>, <Параметры>, <Владелец>, <Уникальность>, <Окно>,
<НавигационнаяСсылка>, <ОписаниеОповещенияОЗакрытии>,
<РежимОткрытияОкна>)
В этот параметр следует передавать системное перечисление
РежимОткрытияОкнаФормы, которое содержит три значения:
БлокироватьВесьИнтрефейс
БлокироватьОкноВладельца
Независимый
Доработаем нашу предыдущую обработку, пусть форма расчёта скорости открывается в отдельном окне, для этого будем её открывать с режимом БлокироватьОкноВладельца (см. листинг 6.3.17).
&НаКлиенте
Процедура РассчитатьСкорость(Команда) ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Расстояние",Расстояние); ПараметрыФормы.Вставить("Время",Время);
ОткрытьФорму("ВнешняяОбработка.Глава6Часть3Обработка3.Форма.ФормаРасчётаСкорости ",ПараметрыФормы,,,,,,РежимОткрытияОкнаФормы.БлокироватьОкноВладельца); КонецПроцедуры
Листинг 6.3.17
Посмотрим, как отработает расчёт скорости (см. рис. 6.3.70).
Рис. 6.3.70
Рассмотрим ещё один примитивный тип, который мы не рассматривали во второй главе (поскольку это было бы преждевременно), – это тип Тип.
Да-да, этот тип так и называется – Тип, причём переменную этого типа нельзя задать самостоятельно, как переменные других примитивных типов, и она необходима для сравнения типов.
Сейчас мы научимся сравнивать типы. Как Вы уже знаете, все объекты 1С имеют определённый тип значения, это может быть ссылка на элемент справочника или объект какого-нибудь документа. Иногда необходимо определить, какой тип значения у того или иного объекта. И осуществляется это с помощью примитивного типа Тип. Для сравнения типов используются две функции: функция Тип и функция ТипЗнч.
Тип(<НазваниеТипа>) ТипЗнч(<Переменная>)
Как Вы видите, синтаксис данных функций простой: у каждой всего по одному параметру. У функции Тип – это название типа в кавычках по определённым правилам. А у функции ТипЗнч – та переменная, тип которой мы желаем узнать.
Рассмотрим следующий пример:
Создадим обработку, форму, на которой разместим четыре реквизита: первый будет иметь тип значения число, второй – тип значения дата, третий – тип значения ссылка на какой-нибудь элемент справочника Автомобили, и четвёртый – тип значения ссылка на какой-нибудь документ Прибытие в гараж. А также добавим команду ПроверитьТип.
Рис. 6.4.1
Каждый раз, когда будет выбираться (или вводиться) значение в поле ввода, глобальная переменная будет заменяться выбранным значением. При выполнении команды нужно будет определить, какое значение хранится в глобальной переменной.
В модуле формы зададим глобальную переменную Текущая.
Рис. 6.4.2
Заметьте, мы её задали в клиентском контексте, потому что обращаться к ней будем также в клиентском контексте. Подробно о работе с глобальными переменными формы в книге «Основы разработки в 1С: Такси».
Создадим обработчики события ПриИзменении для каждого поля ввода и напишем в них следующий код:
&НаКлиенте
Процедура РевизитАвтомобильПриИзменении(Элемент) Текущее = РеквизитАвтомобиль;
КонецПроцедуры
&НаКлиенте
Процедура РеквизитДатаПриИзменении(Элемент) Текущее = РеквизитДата;
КонецПроцедуры
&НаКлиенте
Процедура РеквизитПрибытиеПриИзменении(Элемент) Текущее = РеквизитПрибытие;
КонецПроцедуры
&НаКлиенте
Процедура РеквизитЧислоПриИзменении(Элемент) Текущее = РеквизитЧисло;
КонецПроцедуры
Листинг 6.4.1
А в клиентском обработчике команды напишем следующий код:
&НаКлиенте
Процедура ПроверитьТип(Команда)
Если ТипЗнч(Текущее) = Тип("Число") тогда Сообщить("Переменная ""Текущая"" имеет тип число");
ИначеЕсли ТипЗнч(Текущее) = Тип("Строка") тогда Сообщить("Переменная ""Текущая"" имеет тип строка");
ИначеЕсли ТипЗнч(Текущее) = Тип("СправочникСсылка.Автомобили") тогда
Сообщить("Переменная ""Текущая"" имеет тип ссылка на элемент справ. автомобили");
ИначеЕсли ТипЗнч(Текущее) = Тип("ДокументСсылка.ПрибытиеВГараж") тогда Сообщить("Переменная ""Текущая"" имеет тип ссылку на документ ""Прибытие
в гараж""");
ИначеЕсли ТипЗнч(Текущее) = Тип("Неопределено") тогда Сообщить("Переменная ""Текущая"" имеет тип неопределено");
КонецЕсли;
КонецПроцедуры
Листинг 6.4.2
Проверьте самостоятельно, как работает данная обработка.
Кстати, в процедуре ПроверитьТип есть небольшая, скажем, недоработка. Исправьте её самостоятельно.
Как Вы видите, мы точно знаем, какой текущий тип у глобальной переменной.
Определяем мы это при помощи двух функций Тип и ТипЗнч, они возвращают переменную примитивного типа «Тип». Причём при работе с функцией Тип программист сам знает, какой тип должна вернуть данная функция, и задаёт его самостоятельно через кавычки, а функция ТипЗнч, наоборот, принимает любую переменную с любым типом (даже типом неопределено), и возвращает значение примитивного типа «Тип».
В шестой главе книги «Программировать в 1С за 11 шагов» мы узнали, что такое объектные типы и как с ними работать. Объём этой книги не позволяет изучить все объектные типы платформы 1С. Мы изучили самые основные: справочники, документы и формы. Этих знаний достаточно для того, чтобы начать программировать в 1С и делать какие-то элементарные вещи. Потом, в процессе работы, у Вас будет возможность углубить свои знания, но без хорошего базиса Вам будет очень сложно это сделать. Поэтому досконально изучите материал этой главы, выполните все домашние задания к ней. Все эти знания Вам в дальнейшем очень пригодятся.
(3). 7.01. Глава 7. Универсальные коллекции значений - что это?
Универсальные коллекции значений – это объекты, предназначенные для хранения временной информации. Универсальные коллекции значений используют разработчики прикладного решения в своих утилитарных целях для реализации различных алгоритмов. Эти объекты не разрабатываются в конфигурации и, как правило, не хранятся непосредственно в базе данных. Они создаются только на этапе работы программы и уничтожаются при завершении работы того контекста, в котором они были созданы.
Небольшое уточнение: все объекты, кроме объектов метаданных, существуют только в рамках того контекста, в котором они созданы. То есть если общий объект или коллекция значений были созданы в модуле формы, то они будут уничтожены при закрытии формы, или если они были созданы в теле процедуры или функции, то также уничтожатся, когда процедура или функция будут выполнены.
(3). 7.02. оператор создания универсальной коллекции
Универсальные коллекции значений создаются с помощью оператора Новый. Рассмотрим создание общего объекта на примере массива.
Массив1 = Новый Массив;
Всё. После этого универсальная коллекция значений Массив создана и будет уничтожена либо когда закончит действие процедура (или функция), внутри которой она создана, либо если Массив1 – глобальная переменная внутри модуля (например, модуля объекта), пока не закончит работать контекст этого модуля.
Начнём изучение коллекции значений с массивов.
(3). 7.03. Часть 1. Массивы. Что такое Массив?
Что такое Массив? Массив в языке программирования 1С – это коллекция элементов, следующих друг за другом, которые могут быть доступны с помощью индекса. Элементы могут быть любого типа, в том числе и типа Массив. У каждого элемента Массива имеется уникальный номер, который называют Индексом. Посредством индекса можно получить доступ к данному элементу.
Все элементы в Массиве упорядочены, то есть первый элемент имеет индекс, равный нулю, второй – одному, и так далее.
Запомните! В программировании все индексы во всех коллекциях всегда начинаются с нуля!
Научимся создавать и заполнять массивы.
Конструктор массивов
(3). 7.04. Конструктор массивов - что это? как создается?
В языке 1С существует такое понятие, как Конструктор. Конструктор – это вспомогательный инструмент, при помощи которого создаётся определённый объект. Все массивы создаются с помощью конструктора Новый.
Новый Массив (<КоличествоЭлементов1>…<КоличествоЭлементовN>)
Где:
КоличествоЭлементов – необязательный параметр. Он может быть один – тогда мы
создадим одномерный массив, а также их может быть несколько – тогда мы создадим многомерный массив. Многомерные массивы рассмотрим позже, а пока все наши примеры будут с одномерными массивами. Коллекция Массив имеет следующую доступность: тонкий клиент, толстый клиент, мобильный клиент, сервер и т.д. Из этого следует, что эту универсальную коллекцию значений можно использовать в любом контексте. Также переменные с типом Массив можно передавать с клиента на сервер и обратно (возможна сериализация).
Cоздадим обработку, форму обработки, команду, которую разместим на форме, и в обработчике команды на клиенте создадим одномерный массив из пяти элементов.
&НаКлиенте
Процедура СозданиеМассива(Команда) МассивНовый = Новый Массив(5);
КонецПроцедуры
Листинг 7.1.1 Обращаю Ваше внимание, что после того как мы создали массив при помощи
конструктора с параметром, его элементы будут созданы вместе с ним, но они не заполнены
значениями. Если мы посмотрим на этот данный массив в табло отладчика, то увидим напротив каждого элемента тип Неопределено (см. рис 7.1.1).
Рис. 7.1.1
Таким образом, мало создать массив, необходимо ещё заполнить его.
Обращаться к нужному элементу массива можно посредством индекса. Делается это с помощью оператора квадратные скобки. Допишем код в созданной ранее обработке.
&НаКлиенте
Процедура СозданиеМассива(Команда)
МассивНовый = Новый Массив(5); МассивНовый[0] = "Первый"; МассивНовый[1] = 2;
КонецПроцедуры
Листинг 7.1.2 В этом примере с помощью квадратных скобок мы обратились к первому элементу
массива, который имеет индекс ноль, а потом ко второму, имеющему индекс один. Как Вы
уже поняли из примера, элементы массивов в 1С могут быть разных типов. Заполним остальные три элемента какой-нибудь информацией.
МассивНовый[2] = 4; МассивНовый[3] = "Четвертый"; МассивНовый[4] = 8;
Листинг 7.1.3 С помощью оператора квадратные скобки можно также и читать значения элемента
массива.
Сообщить("МассивНовый[0]= " + МассивНовый[0] +
", МассивНовый[1] = " + МассивНовый[1]);
Листинг 7.1.4
Самостоятельно проверьте работу этой обработки.
(3). 7.05. создание массива без элементов
Помимо создания массива с заранее определённым количеством элементов, можно задать массив, не указывая, сколько элементов он будет содержать. Делается это так:
МассивНовый2 = Новый Массив;
В данном случае будет создан массив, но никаких элементов в нём не будет (он будет пуст). Как работать с такими массивами, мы узнаем несколько позже.
Итак, мы научились создавать одномерный массив и заполнять его значениями, а также получать эти значения. Назовём этот вид наполнения массива ручным способом.
(3). 7.06. Обход массива - какой цикл?
Обход массива
Рассмотрим, как нам обойти все элементы массива, чтобы прочитать их или чтобы заполнить массив по нужному алгоритму. Можно сделать это, как называют, «китайским кодом»: получить каждый элемент массива по индексу. Типичный пример китайского кода это то, как мы заполнили элементы массива ранее. Иногда это бывает необходимо. Но иногда необходимо прочитать каждый элемент массива в цикле. Для этого в теле цикла нужно обойти индексы от первого до последнего. Сделаем это с помощью цикла Для…Цикл.
В ранее сконструированной обработке создадим новую команду, в обработчике которой создадим массив, заполним его и обойдём циклом:
&НаКлиенте
Процедура ОбходЦиклом(Команда) МассивНовый = Новый Массив(5); МассивНовый[0] = 3;
МассивНовый[1] = 7;
МассивНовый[2] = 7;
МассивНовый[3] = 9;
МассивНовый[4] = 1;
Для н = 0 по 4 цикл
Сообщить("МассивНовый[" + н + "] = " + МассивНовый[н] ); КонецЦикла;
КонецПроцедуры
Листинг 7.1.5 Вы заметили, мы обходить цикл начали с нуля. Почему? Потому что индексы
коллекций в платформе 1С начинаются с нуля, как уже об этом говорили.
(3). 7.07. метод который возвращает наибольший индекс в массиве
У внимательного читателя возникнет вопрос: каким образом узнать количество элементов массива, когда это не задано в конструкторе или когда мы не знаем, где и как этот массив был создан.
Для этого у объекта Массив существует метод ВГраница(), который возвращает наибольший индекс в массиве. Индекс будет соответствовать количеству элементов массива минус один. Количество элементов массива тоже можно определить при помощи метода Количество() объекта Массив.
То есть цикл, который мы только что написали, можно переделать двумя равнозначными способами:
Для н = 0 по МассивНовый.ВГраница() цикл Сообщить("МассивНовый[" + н + "] = " + МассивНовый[н] );
КонецЦикла;
Листинг 7.1.6
И по-другому:
Для н = 0 по МассивНовый.Количество() - 1 цикл Сообщить("МассивНовый[" + н + "] = " + МассивНовый[н] );
КонецЦикла;
Листинг 7.1.7
Рекомендуется использовать метод ВГраница, поскольку иной раз Вы можете забыть вычесть единицу из количества, что может привести к ошибкам.
Обход с помощью Для каждого… Цикл
(3). 7.08. Обход с помощью Для каждого… Цикл - для каких данных применяется?
В третьей главе мы с Вами изучили некоторые циклы. В этой изучим новый незнакомый вид цикла Для каждого…Цикл. Мы не проходили этот цикл ранее, поскольку он применим только для коллекций значений и табличных частей.
Данный цикл имеет следующий синтаксис:
Для каждого <Элемент> из <Коллекция> цикл
//операторы Прервать;
//операторы Продолжить;
КонецЦикла
Приведённый оператор предназначен для циклического обхода коллекций. Переменная Коллекция представляет именно ту коллекцию, которую мы обходим. Переменной Элемент присваивается очередное значение элемента коллекции при каждом обходе. Операторы Прервать и Продолжить Вам уже знакомы.
Рассмотрим этот вид цикла на примере обхода массива. Обойдём с помощью данного цикла уже созданный нами массив.
н = 0;
Для Каждого ЭлементМассива из МассивНовый цикл
Сообщить("МассивНовый[" + н + "] = " + ЭлементМассива); н = н + 1;
КонецЦикла;
Листинг 7.1.8
Самостоятельно проверьте работу этого цикла.
В коде выше переменную «н» мы ввели искусственно, чтобы пример был более наглядным. Как Вы уже поняли из примера, переменной ЭлементМассива в каждой итерации цикла присваивается соответствующий элемент массива МассивНовый.
Я рекомендую Вам использовать для обхода массивов в основном второй цикл, потому что в этом случае Вы получаете прямой доступ к элементу коллекции, и Вам не придётся обращаться к нему посредством оператора квадратные скобки. Во всех последующих примерах использования универсальных коллекций будем также применять оператор цикла Для каждого…Цикл.
(3). 7.09. Методы массивов. метод - добавляется новый элемент в конец массива?
Методы массивов
Поскольку массив в языке программирования 1С является объектом, то у него есть собственные методы. Некоторые мы уже разобрали ранее, это Количество и ВГраница.
Сейчас мы рассмотрим остальные методы, которые могут Вам понадобиться.
(3). 7.10. Метод массива «Добавить»
Метод Добавить
С помощью этого метода добавляется новый элемент в конец массива. Метод содержит один параметр, это значение того элемента, который добавляется. Также он может быть и без параметра, тогда будет добавлен элемент со значением Неопределено.
Сделаем новую команду формы, в которой будем изучать метод Добавить: создадим массив из трёх элементов, а потом добавим ещё один и выведем все элементы нового массива в окно сообщений:
&НаКлиенте
Процедура МетодМассиваДобавить(Команда)
Массив1 = Новый Массив(3);
Для н = 0 по Массив1.ВГраница() цикл Массив1[н] = н;
КонецЦикла; Массив1.Добавить(1000);
н = 0;
Для Каждого ЭлМассив1 из Массив1 цикл Сообщить("Массив1["+ н + "] = " + ЭлМассив1 ); н = н +1;
КонецЦикла;
КонецПроцедуры
Листинг 7.1.9
Сохраните обработку и посмотрите на результат.
Теперь создадим вообще пустой массив и перебором добавим десять элементов, а после выведем их в окно сообщений.
Массив2 = Новый Массив;
Для н = 1 по 10 цикл
Массив2.Добавить(Строка(н)+ "* 2 = " + Строка(н*2)); КонецЦикла;
Для Каждого ЭлМассив2 из Массив2 цикл Сообщить(ЭлМассив2);
КонецЦикла;
Листинг 7.1.10
Сохраните обработку и посмотрите на результат. Разберём код из листингов 7.1.9 и 7.1.10.
Первоначально мы создали массив из трёх элементов и заполнили его числами от нуля
до двух, а затем добавили новый элемент и вывели на экран все элементы (листинг 7.1.9). Потом мы создаём массив без элементов, в цикле добавляем элементы в виде строки и выводим их на экран (листинг 7.1.10).
С помощью метода Добавить можно добавлять любой элемент (и даже массив), причём данный элемент будет иметь последний индекс в массиве, это значит, что новый элемент встанет в конец массива.
(3). 7.11. метод вставляет этот элемент по указанному в процедуре индексу
Следующим разберём похожий метод – Вставить.
Метод Вставить
Этот метод похож на предыдущий, но, в отличие от метода Добавить (который добавляет новый элемент в конец массива), метод Вставить вставляет элемент по указанному в процедуре индексу. Все остальные элементы после данного индекса сдвигаются на плюс один. Если указанный в методе индекс заходит за границу массива, то элемент всё равно встанет на указанный индекс, но недостающие элементы от последнего элемента до вставленного заполнятся значением Неопределено.
Синтаксис метода следующий:
Вставить(<Индекс>, Элемент).
Здесь параметр Индекс – индекс, в который значение будет вставлено, Элемент – вставляемое значение.
Создадим новую команду, в обработчике этой команды создадим массив, заполним его в цикле пятью элементами, а потом вставим элемент в середину массива. Но кроме этого, добавим элемент гораздо выше границы массива.
&НаКлиенте
Процедура МетодМассиваВставить(Команда)
Массив = Новый Массив; Для н = 1 по 5 цикл
Массив.Добавить(Строка(н)+ "* 2 = " + Строка(н*2)); КонецЦикла;
Массив.Вставить(2, 100); Массив.Вставить(10,10000);
КонецПроцедуры
Листинг 7.1.11
Выведем на экран элементы массива.
Для Каждого ЭлМассив из Массив цикл
Сообщить(?(ЭлМассив = Неопределено, "Неопределено",ЭлМассив)); КонецЦикла;
Листинг 7.1.12
Сохраните обработку и выполните команду. Вы увидите, что в первом случае элемент вставился в центр массива, а во втором – в конец массива, но между предыдущим крайним и последним элементом появились элементы со значением Неопределено.
Добавлять элементы массива мы научились, теперь рассмотрим, как удалять их из массива.
(3). 7.12 Метод Для удаления конкретного элемента массива
Метод Удалить
Для удаления конкретного элемента массива используется метод Удалить, единственным параметром данного метода является индекс удаляемого элемента. Это значение типа Число (целое и положительное) от нуля и выше. Если указан индекс выше верхней границы массива, то ничего не произойдёт и ошибки не будет.
Запомните: после того как Вы удалите какой-то элемент, все индексы в массиве сместятся, на место удалённого элемента придут те, которые стояли после него, и т.д. Помните об этом, когда захотите удалить несколько каких-нибудь элементов.
Создадим новую команду и в обработчике этой команды создадим массив, который заполним десятью элементами.
&НаКлиенте
Процедура МетодМассиваУдалить(Команда) Массив = Новый Массив;
Для н = 1 по 10 цикл
Массив.Добавить(Строка(н)+ "* 2 = " + Строка(н*2)); КонецЦикла;
КонецПроцедуры
Листинг 7.1.13
Удалим у этого массива первые три элемента сверху.
ИндексУдаления = 1;
Пока ИндексУдаления <= 3 Цикл Массив.Удалить(0);
ИндексУдаления = ИндексУдаления + 1; КонецЦикла;
Листинг 7.1.14
В коде выше сначала мы удаляем три элемента с индексом нуль, поскольку при удалении элемента все индексы смещаются вверх, и каждый последующий элемент в массиве становится первым, и мы его удаляем.
А потом три снизу:
ИндексУдаления = 1;
Пока ИндексУдаления <= 3 цикл Массив.Удалить(Массив.ВГраница()); ИндексУдаления = ИндексУдаления + 1;
КонецЦикла;
Листинг 7.1.15 Мы удаляем все элементы с индексом верхней границы, понятно, что при удалении
элемента верхняя граница уменьшается, и каждый раз в итерации мы удаляем элемент,
имеющий индекс верхней границы.
Выведем итоговый массив в окно сообщений.
Для Каждого ЭлМассив из Массив цикл Сообщить(ЭлМассив);
КонецЦикла;
Листинг 7.1.16
(3). 7.13 Метод массива удаляет все элементы массива
Метод Очистить
Метод Очистить удаляет все элементы массива. Удалим их из массива Массив в обработчике, который сделали в предыдущем подразделе.
Массив.Очистить();
Сообщить("Массив.Количество() = " + Массив.Количество());
Листинг 7.1.17 Сохраните и запустите обработку, и Вы увидите, что количество элементов в массиве
равно нулю. Он очистился.
(3). 7.14 метод устанавливает значение элемента по нужному индексу
Метод Установить
Вы видели из предыдущих примеров, что значения элементам массива мы присваивали с помощью оператора квадратные скобки. У объекта Массив имеется метод аналогичный квадратным скобкам, который называется Установить. Этот метод устанавливает значение элемента по нужному индексу. Рассмотрим синтаксис метода:
Установить(<Индекс>, <Значение>)
Первый параметр – это индекс элемента, которому будет устанавливаться значение.
Второй параметр – значение элемента.
Сделаем пример: создадим новую команду, в обработчике которой создадим массив с количеством элементов, равным десяти, и заполним его чётными числами с помощью метода Установить. А потом всё это выведем в окно сообщений.
&НаКлиенте
Процедура МетодМассиваУстановить(Команда) Массив = Новый Массив(10);
ИндексМассива = 0;
ИндексСчетчика = 1;
Пока ИндексМассива <= Массив.ВГраница() цикл Если ИндексСчетчика % 2 = 0 тогда
Массив.Установить(ИндексМассива,ИндексСчетчика);
ИндексМассива = ИндексМассива + 1; КонецЕсли;
ИндексСчетчика = ИндексСчетчика + 1; КонецЦикла;
Для Каждого ЭлМассива из Массив цикл Сообщить(ЭлМассива);
КонецЦикла;
КонецПроцедуры
Листинг 7.1.18
Данный код должен быть Вам понятен, единственно, что мы вместо квадратных скобок использовали метод Установить.
Мы рассмотрели основные методы массивов, их Вам будет достаточно, чтобы проводить любые манипуляции с этим объектом. А теперь узнаем, что такое многомерные массивы.
Многомерные массивы
(3). 7.15 Многомерные массивы - что это?
Многомерным массивом в языке 1С называется массив, элементами которого являются массивы. Если одномерный массив создавался посредством конструктора с одним параметром, то в многомерном массиве может быть два и больше параметров.
Создадим новую обработку, в которой разберём многомерные массивы. Пример создания многомерного массива с двумя параметрами:
МассивМн1 = Массив(3,2);
В этом примере мы создали массив, у которого будет три элемента, каждый из которых будет массивом, содержащим по два элемента.
Для заполнения многомерного массива необходимо будет заполнить элементы внутренних массивов. Сделаем это в команде на форме новой обработки.
&НаКлиенте
Процедура ЗаполнитьМногомерныйМассив(Команда) МассивМн1 = Новый Массив(3,2);
Для н = 0 По МассивМн1.ВГраница() цикл МассивВнутренний = МассивМн1[н];
Для к = 0 по МассивВнутренний.ВГраница() цикл МассивВнутренний[к] = Строка(н+1)+ "." + Строка(к+1);
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Листинг 7.1.19 В данном коде во внешнем цикле мы получаем элементы основного массива,
напомню, что каждый элемент является массивом. Во внутреннем цикле мы заполняем
непосредственно внутренний массив.
Выведем заполненный массив на экран.
Для Каждого ЭлМассиваВнеш из МассивМн1 цикл СтрокаВывода = "";
Для Каждого ЭлемМассиваВнутр из ЭлМассиваВнеш цикл СтрокаВывода = СтрокаВывода + " " + ЭлемМассиваВнутр;
КонецЦикла; Сообщить(СокрЛ(СтрокаВывода));
КонецЦикла;
Листинг 7.1.20 В этом коде мы получаем каждый элемент массива, который тоже является массивом,
и уже у этого массива выводим элементы на экран. Сохраните обработку и посмотрите, что получилось.
Должен выйти следующий результат:
Рис. 7.1.2
Как Вы видите, вышло три строки, ведь мы задали изначально три внешних массива, и в каждой строке две цифры, которые являются элементами внутренних массивов, каждый из которых состоит из двух элементов.
Многомерные массивы можно создавать, не используя параметры в конструкторе массивов, для этого достаточно установить значению элемента другой массив.
Рассмотрим пример: зададим массив без параметров и будем добавлять элементы массива внутри цикла, причём каждый элемент будет являться массивом.
&НаКлиенте
Процедура МногомерныйМассивБезПараметров(Команда)
Массив = Новый Массив; Для н = 1 по 5 цикл
МассивВн = Новый Массив; Для к = 1 по 7 цикл
МассивВн.Добавить(Строка(н) +"." + Строка(к)); КонецЦикла;
Массив.Добавить(МассивВн); КонецЦикла;
КонецПроцедуры
Листинг 7.1.21 Вы видите, что в данном коде в первом цикле в начале итерации мы создаём новый
массив, а потом заполняем этот массив элементами. После того как заполнили массив внутри
цикла элементами, мы добавляем его во внешний массив в качестве элемента.
Выведите этот массив на экран самостоятельно.
Вы можете создавать массивы какой угодно размерности: трёхмерные, четырёхмерные, или такие, где внутри массива будут массивы с разным количеством элементов, и т.п.
Итак, мы научились работать с массивами. Я не стал Вам давать такие вещи, как сортировка и свёртка массивов, по двум причинам. Во-первых, это общие понятия программирования, они есть в любом учебнике по программированию и к работе с 1С не имеют никакого отношения. Во-вторых, в языке 1С есть более универсальные объекты типа списков значений и таблиц значений, в которых все нужные методы по сортировке, свёртке и т.п. реализованы. Оба этих объекта мы обязательно изучим.
И поэтому если перед Вами стоит задача, в которой имеющиеся данные необходимо будет сортировать или свернуть, то необходимо использовать вышеупомянутые объекты, а не массивы. Тем не менее сами массивы необходимо знать и уметь с ними работать, поскольку многие методы некоторых объектов возвращают при своём исполнении массивы.
(3). 7.16 Часть 2. Структура - что это?
Структура в языке программирования 1С – это коллекция некоторых значений в связке с ключом. Эта связка ключа со значением называется КлючИЗначение. Ключ структуры уникален в рамках конкретной структуры. Причём к значениям структуры можно обращаться как к свойствам объекта, используя название ключа.
(3). 7.17 как создается Объект Структура
Объект Структура создаётся при помощи конструктора Новый.
Структура1 = Новый Структура;
(3). 7.18 Объект Структура - особенности?
Структуру можно создать на всех видах клиентов и в любом контексте.
Сериализуется, то есть можно передать переменную с типом структура с клиентского контекста в серверный. Хоть и в значение можно записывать любой тип, использование типов в этом случае очень сильно зависит от контекста и от вида клиента: мы не можем на клиенте задать в значение тип, который работает только в серверном контексте (например, ДокументОбъект.<>).
(3). 7.19 Работа со структурой. Метод структуры для создания нового элемента
Работа со структурой
Научимся создавать структуру, создавать пару Ключ и значение и читать значения структуры, используя ключи. Для этого создадим обработку, в которой и будем проводить все эксперименты со структурами.
Как создать новую структуру, Вы уже знаете, теперь выясним, как создаются новые элементы этого объекта. Создаются они при помощи метода Вставить.
Вот синтаксис метода:
Вставить(<Ключ>,<Значение>);
Первый параметр – это название ключа устанавливаемого элемента. Второй параметр – непосредственно устанавливаемый элемент.
Параметр Ключ имеет тип значения Строка. На названия ключа структуры распространяются те же правила, как и на названия переменных. Параметр Значение может иметь любой тип.
Обращаю Ваше внимание, что связка Ключ и значение уникальна, поэтому если Вы напишете для одной структуры два метода Вставить с одинаковыми ключами и разными значениями, то всё равно в структуре будет одна связка Ключ и значение, причём значение возьмётся с последнего метода.
Создадим форму, команду и обработчик этой команды на клиенте, а в обработчике создадим простую структуру с двумя парами Ключ и значение.
&НаКлиенте
Процедура СоздатьСтруктуру(Команда)
Структура1 = Новый Структура; Структура1.Вставить("Ключ1",12.3); Структура1.Вставить("Ключ2",33.4);
КонецПроцедуры
Листинг 7.2.1 В этом случае мы не стали думать над названиями ключей, Вы же в процессе работы
можете давать ключам любые названия, которые соответствуют требованиям к названиям
переменных.
Посмотрим в табло отладчика, как выглядит созданная структура (см. рис. 7.2.1).
Рис. 7.2.1
Как видите, в отладке структура представляет собой некоторый список, где напротив каждого ключа есть то значение, которое мы привязали к этому ключу в методе Вставить. Ключ является свойством структуры, и мы можем обращаться к нему напрямую.
Для того чтобы посмотреть, как это работает, допишем наш код:
Сообщить("Структура1.Ключ1 = " + Строка(Структура1.Ключ1)); Сообщить("Структура1.Ключ2 = " + Строка(Структура1.Ключ2));
Листинг 7.2.2
Как видно из кода выше, мы обращаемся к обоим ключам как к свойствам структуры.
По сути, они и есть свойства данной структуры, где хранятся соответствующие значения. Сохраним и запустим обработку. Выполним команду и посмотрим, что получится.
Рис. 7.2.2
В окне сообщений вышли те значения, которые мы привязали к ключам с помощью метода Вставить.
(3). 7.20 добавить пару КлючИЗначение в структуру через конструктор
Не всегда обязательно использовать метод Вставить, чтобы добавить пару КлючИЗначение в структуру, иногда это можно сделать в конструкторе. Тогда конструктор будет иметь следующий синтаксис:
Структура1 = Новый Структура(Ключ, Значение);
Переделаем предыдущий пример:
Структура1 = Новый Структура("Ключ1, Ключ2",12.3,33.4);
Сообщить("Структура1.Ключ1 = " + Строка(Структура1.Ключ1)); Сообщить("Структура1.Ключ2 = " + Строка(Структура1.Ключ2));
Листинг 7.2.3 В этом варианте конструктора все ключи должны задаваться одной строкой, а
значения этих ключей должны быть перечислены через запятую.
Изменить значение ключа
(3). 7.21 Изменить значение ключа - как?
Если нам необходимо изменить значение какого-нибудь ключа, то мы, используя метод Вставить, в котором в качестве первого параметра указываем ключ, значение которого хотим поменять, а в качестве второго параметра – новое значение для данного
ключа.
Переделаем обработку.
&НаКлиенте
Процедура СоздатьСтруктуру(Команда)
Структура1 = Новый Структура("Ключ1, Ключ2",12.3,33.4); Структура1.Вставить("Ключ1",1200);
Сообщить("Структура1.Ключ1 = " + Строка(Структура1.Ключ1)); Сообщить("Структура1.Ключ2 = " + Строка(Структура1.Ключ2));
КонецПроцедуры
Листинг 7.2.4
Сохраните обработку и посмотрите на результат работы.
Количество элементов
(3). 7.22 Количество элементов - метод структуры узнать количество пар «Ключ и значение»
Для того чтобы узнать количество пар Ключ и значение, существует метод
Количество.
Допишем в последнюю команду код, при помощи которого можно посмотреть, какое количество элементов у созданной структуры.
КоличествоЭлементов = Структура1.Количество();
Сообщить("В структуре1 количество элементов = " + КоличествоЭлементов);
Листинг 7.2.5
Обход коллекции
(3). 7.23 Обход коллекции - цикл обхода структуры
Обход структуры осуществляется с помощью уже знакомого нам оператора цикла Для каждого…Цикл.
Доработаем текущий пример: обойдём уже созданную структуру.
Для Каждого ЭлСтруктуры из Структура1 цикл Сообщить(Строка(ЭлСтруктуры.Ключ) + " = " + ЭлСтруктуры.Значение);
КонецЦикла;
Листинг 7.2.6 В этом коде переменная ЭлСтруктуры принимает значение каждого элемента
структуры в зависимости от итерации. Данная переменная является парой Ключ и значение,
поэтому мы можем прочитать у неё ключ и значение, которое соответствует ключу.
Тип значений
(3). 7.24 Тип значений - какие могут быть значения типов структуры
В структуру можно записывать не только примитивные типы, но также любые другие объекты платформы, вплоть до других структур. Причём значения типов разных ключей
структуры могут быть разными. Продемонстрируем это – запишем в структуру массив, ссылку на объект справочника и сам объект справочника. Для этого в последней обработке создадим новую команду, в которой и проделаем все вышеперечисленные манипуляции.
Поскольку мы не можем в клиентском контексте получить доступ к объекту метаданных, то создадим для команды обработчик на клиенте и на сервере без контекста. В этих обработчиках напишем следующий код:
&НаСервереБезКонтекста
Процедура СоздатьСтруктуруСРазнымиЗначениямиНаСервере() Структура1 = Новый Структура;
МассивДат = Новый Массив; Для н = 0 по 4 цикл
МассивДат.Добавить(ТекущаяДата() + 3600*24*н); КонецЦикла;
МаркаFordСсылка = Справочники.МаркиАвтомобилей.НайтиПоНаименованию("Ford Motor",Истина);
Если НЕ МаркаFordСсылка.Пустая() Тогда
МаркаFordОбъект = МаркаFordСсылка.ПолучитьОбъект(); иначе
МаркаFordОбъект = Неопределено; КонецЕсли;
Структура1.Вставить("МассивДат",МассивДат); Структура1.Вставить("МаркаФордОбъект",МаркаFordОбъект); Структура1.Вставить("МаркаФордСсылка",МаркаFordСсылка);
КонецПроцедуры &НаКлиенте
Процедура СоздатьСтруктуруСРазнымиЗначениями(Команда) СоздатьСтруктуруСРазнымиЗначениямиНаСервере();
КонецПроцедуры
Листинг 7.2.7 Как Вы видите, мы вставили абсолютно разные объекты в значения структуры.
Причём обращаясь к значению через ключ, мы получаем доступ непосредственно к самому
объекту. Допишем код в обработке:
Для Каждого СтрокаЭл из Структура1.МассивДат цикл Сообщить(Формат(СтрокаЭл,"ДЛФ=DD"));
КонецЦикла; Сообщить(Структура1.МаркаФордСсылка.Наименование);
Листинг 7.2.8 Сохраним, перезапустим обработку и посмотрим, как она работает (см. рис. 7.2.3).
Рис. 7.2.3
Вы видите, что обращаясь к свойствам структуры посредством ключа, мы обращаемся непосредственно к объекту и можем проделать с ним любые манипуляции.
Обращаю Ваше внимание: если Вы проведёте какие-нибудь манипуляции со значением структуры, то данные манипуляции отобразятся на той переменной, которую Вы записали в это значение.
Для демонстрации вышеприведённого утверждения изменим предыдущий пример: у массива внутри структуры добавим новый элемент и посмотрим, как это отобразится на самом массиве, который мы записали в структуру.
Структура1.МассивДат.Добавить(ТекущаяДата() + 3600*24*5); Для Каждого СтрокаЭл из МассивДат цикл
Сообщить(Формат(СтрокаЭл,"ДЛФ=DD")); КонецЦикла;
Листинг 7.2.9 Сохраните, перезапустите обработку, и Вы увидите, что элемент, который мы
добавили в значение структуры, появился у изначального массива, поскольку в данной
структуре содержится не копия переданного массива, а указатель или ссылка на сам массив, к которому можно обратиться посредством структуры и ключа.
Безошибочное получение значения элемента
(3). 7.25 Безошибочное получение значения элемента - как обратиться к значению ключа, не боясь вызвать ошибку
Если при обращении к ключу структуры будет указано название несуществующего в структуре ключа, то платформа выдаст ошибку. Но есть метод объекта Структура, с помощью которого можно обратиться к значению ключа, не боясь вызвать ошибку в случае промаха.
Этот метод – Свойство.
Метод Свойство является функцией и возвращает Истину, если указанный ключ есть, и возвращает Ложь, если указанного ключа нет.
Рассмотрим синтаксис метода:
Свойство(<ИмяКлюча>,<ЗаписываемоеЗначение>);
ИмяКлюча – название ключа для поиска свойства.
В параметр ЗаписываемоеЗначение будет возвращено найденное значение. В том случае если ключа нет в структуре, то данному параметру присвоится значение Неопределено. Обращаю Ваше внимание, что параметр ЗаписываемоеЗначение где-то должен быть определён. Причём данный параметр также будет являться указателем на первоначальный объект.
Рассмотрим работу этого свойства.
На форме последней обработки создадим новую команду и обработчик этой команды на клиенте. В обработчике создадим структуру и запишем в неё массив дат из предыдущих примеров. Также в начале кода в обработчике объявим новую переменную.
&НаКлиенте
Процедура РаботаСоСвойствомСтруктуры(Команда) Перем МассивДатНайденный;
МассивДат = Новый Массив; Для н = 0 по 4 цикл
МассивДат.Добавить(ТекущаяДата() + 3600*24*н); КонецЦикла;
Структура1 = Новый Структура; Структура1.Вставить("МассивДат",МассивДат);
КонецПроцедуры
Листинг 7.2.10 Запишем в переменную МассивДатНайденный при помощи метода Свойство
структуры массив МассивДат из структуры, а после изменим эту переменную, для того
чтобы убедиться, что изначальный массив, который в структуре, тоже изменится.
Допишем код:
ЕстьМассив = Структура1.Свойство("МассивДат",МассивДатНайденный); Если ЕстьМассив тогда
МассивДатНайденный.Добавить(ТекущаяДата() + 3600*24*7); КонецЕсли;
Для Каждого СтрокаЭл из МассивДат цикл Сообщить(СтрокаЭл);
КонецЦикла;
Листинг 7.2.11
Самостоятельно посмотрите, как работает код выше. Вы увидите, что изначальный массив, который в структуре, тоже изменился. То есть переменная МассивДатНайденный содержит указатель на переменную МассивДат.
Очистка структуры и удаление элементов
(3). 7.26 Очистка структуры и удаление элементов - каким образом можно удалить все пары Ключ и значение? каким образом можно удалить какую-то одну пару?
Узнаем, каким образом можно удалить все пары Ключ и значение или какую-то одну
пару.
Для удаления всех пар используется метод Очистить. Выглядит это так:
Структура1.Очистить();
После данной процедуры никаких пар Ключ и значение в данной структуре не будет. Если необходимо удалить конкретную пару Ключ и значение, используется метод
Удалить с единственным параметром – ключ удаляемого значения.
Структура1.Удалить("МаркаГаз");
Если Вы введёте неправильное название ключа, то ничего не произойдёт, ошибку отладчик не выдаст.
Поэкспериментируйте самостоятельно с данными методами структуры.
В этой части урока мы научились работать со структурами, это очень важный объект базы, поскольку многие методы принимают в качестве параметра структуру с нужными ключами. Это не очень сложный объект для понимания, и если у Вас на начальных этапах возникли трудности, то рекомендую открывать данный объект в отладке, чтобы посмотреть, как он работает, как выглядят ключи и какие значения к этим ключам привязываются.
(3). 7.27 Часть 3. Соответствие - особенности
Соответствие в языке программирования 1С чем-то похоже на Структуру, это тоже коллекция пар Ключ и значение. Но, в отличие от Структуры, в Соответствии, чтобы получить значение по определённому ключу, нужно обращаться к ключу не как к свойству объекта, а через квадратные скобки, и в качестве ключа можно использовать значение любого типа.
(3). 7.28 Работа с соответствием - метод соответствия установления ключа
Структура | Соответствие |
Структура1.Ключ1 | Соответствие1["Ключ1"] |
Соответствие можно создать на всех видах клиентов и в любом контексте.
Сериализируется, то есть можно передать переменную с типом Соответствие с клиентского контекста на серверный.
Хоть и в ключе, и в значении элемента соответствия можно записать переменные любого типа, использование типов в этом случае очень сильно зависит от контекста и от вида клиента: мы не можем в клиентском контексте задать ключ или значение, тип которых работает только в серверном контексте (например, ДокументОбъект.<>).
Работа с Соответствием
Работа с Соответствием чем-то похожа на работу со Структурой. Рассмотрим основные методы объекта Соответствие, разберём, каким образом осуществляется обход Соответствия, и чем кардинально отличается Соответствие от Структуры.
Для этой части создадим новую обработку и форму обработки, в которой будем делать все приведённые ниже примеры.
(3). 7.29 Работа с соответствием - всталение
Метод Вставить
Метод Вставить для Соответствия работает точно так же, как для Структуры.
Метод имеет следующий синтаксис:
Вставить(<Ключ>, <Значение>)
Внешне этот метод не отличается от метода Структуры, с той лишь разницей, что Ключ может иметь любой тип! Это очень важное отличие, с помощью него Вы сможете в процессе работы устанавливать соответствие любых объектов с любыми объектами.
Параметр Значение тоже может принимать любой тип.
Сделаем следующий пример. Создадим соответствие с тремя элементами, у которых будут ключи трёх типов: Строка, Число и Дата, и выведем значения этих ключей в окно сообщений.
&НаКлиенте
Процедура СоответствиеМетодВставить(Команда) Соответствие1 = Новый Соответствие; Соответствие1.Вставить("Ключ1","Ключ тип строка"); Соответствие1.Вставить(1,"Ключ тип число");
Соответствие1.Вставить(Дата(2017,12,10),"Ключ тип дата");
Сообщить(Соответствие1["Ключ1"]); Сообщить(Соответствие1[1]); Сообщить(Соответствие1[Дата(2017,12,10)]);
КонецПроцедуры
Листинг 7.3.1
Мы можем использовать в качестве ключа значение любого типа, что, повторюсь, в некоторых случаях бывает удобно.
Если уже какой-то элемент создан, то мы можем поменять значение этого элемента, достаточно использовать тот же метод Вставить. Единственно, что в этом случае прежнее значение будет потеряно.
Продемонстрируем это. Допишем предыдущий пример: обратимся к элементу структуры при помощи числового ключа и поменяем значение у этого элемента.
Соответствие1.Вставить(1,"Ключ тип ""число"""); Сообщить(Соответствие1[1]);
Листинг 7.3.2
Сохраним, запустим обработку и выполним команду.
Рис. 7.3.1
Поменять имеющееся значение можно, также используя квадратные скобки. Код в листинге 7.3.2 можно переделать.
Соответствие1[1] = "Ключ тип ""число"""; Сообщить(Соответствие1[1]);
Листинг 7.3.3
Результат будет точно такой же.
Обход
(3). 7.30 Обход соответствия - какой цикл?
Научимся обходить Соответствие при помощи знакомого цикла Для Каждого…Цикл.
Создадим новую команду, обработчик команды на клиенте, скопируем в этот обработчик код создания Соответствия и выполним обход:
&НаКлиенте
Процедура СоответствиеОбход(Команда) Соответствие1 = Новый Соответствие;
Соответствие1.Вставить("Ключ1","Ключ тип строка"); Соответствие1.Вставить(1,"Ключ тип число"); Соответствие1.Вставить(Дата(2017,12,10),"Ключ тип дата");
Для Каждого ЭлементСоответствия из Соответствие1 цикл Сообщить("Соответствие1 [" +
Строка(ЭлементСоответствия.Ключ) + "] = " + ЭлементСоответствия.Значение);
КонецЦикла;
КонецПроцедуры
Листинг 7.3.4
Сохраним обработку и посмотрим на результат.
Рис. 7.3.2
Вы видите, что при обходе коллекции мы получаем доступ к элементу коллекции, причём у элемента структуры мы можем обратиться и к ключу, и к значению этого элемента посредством свойств Ключ и Значение.
(3). 7.31 Очистка соответствия - какие методы
Очистка Соответствия
Очистка соответствий осуществляется с помощью метода Очистить, который удаляет все элементы соответствия, и метода Удалить, который удаляет определённый элемент, ключ которого указан в параметре метода.
Синтаксис и работа методов похожи на синтаксис и работу методов структуры.
Соответствие1.Очистить();
Данный метод очищает полностью соответствие. Синтаксис метода Удалить следующий:
Удалить(<Ключ>);
Рассмотрим пример с удалением элемента по ключу. Сделаем на форме новую команду, в этой команде создадим Соответствие, в которое добавим несколько элементов с ключами типа Дата, а потом удалим одну пару КлючИЗначение.
&НаКлиенте
Процедура СоответствиеУдаление(Команда) Соответствие1 = Новый Соответствие;
Соответствие1.Вставить(Дата(2017,12,1), "Число 2");
Соответствие1.Вставить(Дата(2017,12,2), "Число 3");
Соответствие1.Вставить(Дата(2017,12,3), "Число 1");
Соответствие1.Вставить(Дата(2017,12,4), "Число 6"); Соответствие1.Удалить(Дата(2017,12,3));
Для Каждого ЭлементСоответствия из Соответствие1 цикл
Сообщить("Соответствие1["+
Формат(ЭлементСоответствия.Ключ,"ДЛФ=DD") + "] = " + ЭлементСоответствия.Значение);
КонецЦикла;
КонецПроцедуры
Листинг 7.3.5
Проверьте работу команды самостоятельно.
(3). 7.32 каким методом получить значение элемента соответствия, но применение квадратных скобок неосуществимо
Метод Получить
Для того чтобы получить значение элемента соответствия используются квадратные скобки. Но иногда возможны ситуации, когда применение квадратных скобок неосуществимо. В таких случаях мы можем использовать метод Получить, который возвращает любое значение, соответствующее ключу. Если такого ключа нет, то вернётся значение Неопределено.
Рассмотрим работу метода Получить на уже известном нам соответствии с датами в качестве ключей. Создадим новую команду, обработчик команды и скопируем в него код, где мы создаем соответствие, в котором в качестве ключей выступают даты (чтобы много раз не копировать код, создайте функцию, которая будет возвращать заполненное соответствие). А потом с помощью метода Получить получим один из элементов этого соответствия.
&НаКлиенте
Процедура СоответствиеПолучить(Команда) Соответствие1 = Новый Соответствие;
Соответствие1.Вставить(Дата(2017,12,1), "Число 2");
Соответствие1.Вставить(Дата(2017,12,2), "Число 3");
Соответствие1.Вставить(Дата(2017,12,3), "Число 1");
Соответствие1.Вставить(Дата(2017,12,4), "Число 6");
ЭлСоотвествия1 = Соответствие1.Получить(Дата(2017,12,4)); ЭлСоотвествия2 = Соответствие1.Получить(Дата(2017,12,5));
Сообщить(?(ЗначениеЗаполнено(ЭлСоотвествия1),ЭлСоотвествия1,"Неопределено"));
Сообщить(?(ЗначениеЗаполнено(ЭлСоотвествия2),ЭлСоотвествия2,"Неопределено")); КонецПроцедуры
Листинг 7.3.6
Посмотрим, как работает этот метод.
Рис. 7.3.3
В этой части главы мы научились работать с соответствиями. Соответствия чем-то напоминают структуры, но это абсолютно разные коллекции значений, и мы в этом убедились. В своих прикладных задачах Вы можете использовать как соответствия, так и структуры, в зависимости от тех целей, которые перед Вами стоят.
(3). 7.33 Часть 4. Список Значений - что это?
Список значений – это по сути одномерный динамический массив, созданный в рамках платформы 1С для решения некоторых интерфейсных задач. В отличие от простого массива, элементы которого могут быть произвольных типов, у списка значений каждый элемент имеет специальный тип Элемент списка значений. Элемент списка значений содержит следующие данные: само значение (любого типа), представление значения (тип Строка), пометка (тип Булево) и картинка (тип Картинка).
Список значений можно создавать на всех видах клиентов и в любом контексте.
Сериализируется, то есть можно передать переменную с типом Список значений с клиентского контекста на серверный.
Несмотря на то, что в значении элемента списка можно хранить значения любых типов, использование типов очень сильно зависит от контекста и от вида клиента. Мы не можем в клиентском контексте записать в значение элемента списка переменную типа, который используется только в серверном контексте (например, ДокументОбъект.<>).
Как правило, списки значений используются в интерфейсных задачах. Например, это организация выборки какого-нибудь одного значения из списка возможных. На форме для решения таких задач используется элемент формы Таблица.
Таблицы формы и работу с таблицами будем изучать в следующей главе.
Разберём пример, из которого Вам станет понятно, что такое список значений и для каких целей он нужен. Для примера создадим новую обработку, форму обработки, а на форме создадим реквизит с типом СписокЗначений (см. рис. 7.4.1).
Рис. 7.4.1
Несмотря на то, что элементы списка значений имеют тип Элемент списка значений, мы всё равно можем жёстко указать тип, который будут иметь значения этого списка. Укажем тип СправочникСсылка.МаркиАвтомилей. Тип данных значений списка задаётся в свойстве реквизита Тип значения.
Рис. 7.4.2
Список сделали и настроили, поместим созданный реквизит на форму в виде таблицы:
Рис. 7.4.3
На вопрос: «Добавлять колонки или нет?», отвечаем: «Нет». Мы их добавим самостоятельно. После того как мы «перетащим» список значений на форму, на самой форме ничего не появится. Так произошло потому, что мы не добавили колонки. «Перетащим» самостоятельно две колонки: Значение и Пометка. Нужно «тащить» колонки именно в сам элемент СписокЗначений (см. рис. 7.4.4 и 7.4.5).
Рис. 7.4.4
Рис. 7.4.5
Создадим обработчик формы ПриСозданииНаСервере, в котором напишем следующий
код:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Выборка = Справочники.МаркиАвтомобилей.Выбрать(); Пока Выборка.Следующий() Цикл
СписокМарок.Добавить(Выборка.Ссылка,Выборка.Наименование); КонецЦикла;
КонецПроцедуры
Листинг 7.4.1
Сохраним и запустим обработку.
Рис. 7.4.6
Вы видите, что в списке отобразились все элементы справочника Марки автомобилей.
Для этого мы получили выборку из справочника (более подробно выборки мы будем проходить в девятой главе), обошли её циклом, в цикле добавили значения в реквизит формы СписокМарок, который имеет тип Список значений, используя для этого метод Добавить списка значений. В этот метод в качестве параметров мы передали ссылку на элемент справочника с представлением в виде наименования элемента.
Данный пример наглядно показывает, в каких целях можно использовать список значений.
Немного забежали вперёд, теперь вернёмся к порядку. Сначала мы научимся манипулировать списком значения: добавлять, вставлять, удалять, редактировать и сортировать элементы, а потом мы научимся работать со списком значений на форме.
Добавление элементов
Для того чтобы нам начать работать со списком значений, необходимо заполнить его элементами.
(3). 7.34 Добавление элементов в список значений - какие есть способы?
Сделать это можно тремя способами: добавить новый элемент (добавится в конец списка), вставить новый элемент в нужное место и загрузить элементы из массива.
Рассмотрим каждый способ по отдельности.
(3). 7.35 Метод создает новый элемент списка значений и добавляет его в конец списка
Метод «Добавить»
Метод Добавить создает новый элемент списка значений и добавляет его в конец списка.
У этого метода следующий синтаксис:
Добавить(<Значение>, <Представление>, <Пометка>, <Картинка>)
Первый параметр Значение – это может быть объект любого типа, который будет храниться в списке значений.
Второй параметр – это непосредственно то, как данный объект будет представлен пользователю в списке. Имеет тип Строка. Это необязательный параметр, в случае отсутствия представления объект будет показан в обычном виде.
Третий параметр задаёт – будет ли у данного объекта в списке пометка выбора или нет. Имеет тип Булево. Тоже необязательный параметр.
Четвёртый параметр – это картинка, мы не будем разбирать картинки в данной книге, поэтому пропустим его, он тоже является необязательным.
Как Вы поняли из описания параметров, обязательным является только первый параметр.
Рассмотрим пример: сделаем новую обработку, форму у этой обработки, команду на форме, в обработчике команды создадим список значений, в который добавим элементы типа Число, и укажем представления этих чисел.
&НаКлиенте
Процедура СписокЗначенийДобавить(Команда) Список = Новый СписокЗначений; Список.Добавить(100 , "Число 100");
Список.Добавить(0.25, "Число: 1/4"); Список.Добавить(-100, "Число -100"); Список.Добавить(0.5 , "Число 1/2");
КонецПроцедуры
Листинг 7.4.2
Сохраним обработку и посмотрим в отладке, как заполнится список.
Рис. 7.4.7
Как видно из табло, значение и представление отличаются друг от друга. Но при этом, какое бы ни было представление, оно необходимо только для удобства восприятия пользователя. Сами данные хранятся непосредственно в значении. Продемонстрируем это: по аналогии с предыдущей обработкой на форме создадим реквизит СписокНаФорме с типом СписокЗначения (свойство ТипЗначения – число), поместим список на форму в виде таблицы, а также поместим в эту таблицу колонки Значение и Представление (см. рис. 7.4.8).
Рис. 7.4.8
А в процедуре обработчике команды, которую создали ранее, этому реквизиту присвоим созданный объект Список значений.
СписокНаФорме = Список;
Перезапустим обработку, выполним команду и посмотрим, что выйдет в поле списка.
Рис. 7.4.9
Заметьте, в колонке Значение данные отображаются в виде представлений, но если непосредственно зайти в ячейку для нужного значения, то увидим то значение, которое хранится в списке.
(3). 7.36 Метод создает новый элемент списка значений 2)
Рассмотрим следующий способ добавления новых элементов в список значение – с помощью метода Вставить.
Метод «Вставить»
Метод Вставить имеет следующий синтаксис.
Вставить(<Индекс>, <Значение>, <Представление>, <Пометка>, <Картинка>)
Все параметры, кроме параметра Индекс, имеют точно такое же назначение, как и аналогичные параметры у метода Добавить.
Параметр Индекс указывает непосредственно номер позиции, на который устанавливается элемент. Элемент, который был на этом индексе, сдвигается на плюс один, и все последующие элементы – тоже.
Продемонстрируем это, вставим в уже созданный нами ранее список новый элемент на второй индекс или на третье место по порядку.
Список.Добавить(0.5 , "Число 1/2"); Список.Вставить(2,777, "Число 777");//добавили в код СписокНаФорме = Список;
Листинг 7.4.3
Сохраним и перезапустим обработку.
Рис. 7.4.10
Как видите, на третьем месте появился новый элемент. Напомню, что индексы в объектах 1С начинаются с нуля. Имейте всегда это в виду, когда будете делать обход по индексам или получать какое-нибудь значение по индексу.
Метод ЗагрузитьЗначения
(3). 7.37 Метод создает новый элемент списка значений 3)
Рассмотрим еще один метод, каким образом можно добавить элементы в список значений. Это метод ЗагрузитьЗначения. Метод ЗагрузитьЗначения позволяет загрузить значения из одномерного массива в список значений. Все предыдущие элементы списка значений при этом удалятся. Об этом надо всегда помнить.
Сделаем пример. В уже имеющейся обработке создадим новую команду Загрузить из массива, поместим команду на форму в виде кнопки, а также создадим обработчик команды на клиенте.
В процедуре обработчике команды напишем код, в котором сначала заполним массив какими-то данными, а потом загрузим этот массив во вновь созданный список значений и выведем уже знакомым способом на форму в поле списка.
&НаКлиенте
Процедура ЗагрузитьИзМассива(Команда)
Массив = Новый Массив; Массив.Добавить("Иванов И.И"); Массив.Добавить("Петров А.Н"); Массив.Добавить("Кузьмин А.Г."); Массив.Добавить("Сидоров Н.Н");
Список = Новый СписокЗначений; Список.ЗагрузитьЗначения(Массив); СписокНаФорме = Список;
КонецПроцедуры
Листинг 7.4.4
Сохраним, перезапустим обработку и нажмём на вновь созданную кнопку Загрузить из массива. Должен выйти список, как на рис. 7.4.11.
Рис. 7.4.11
Метод ЗагрузитьЗначения очень удобен, когда нужно какие-то данные загрузить полностью в список, и его можно использовать, чтобы не писать лишний код по заполнению списка значений.
Имейте в виду, что этот метод заполняет только значения элементов списка, все остальные параметры (представление, картинка и т.п.) остаются пустыми.
Метод ВыгрузитьЗначения
(3). 7.38 функция возвращает одномерный массив, формируя его значениями из списка
Обратным методу ЗагрузитьЗначения, который заполняет список значений из массива, является метод ВыгрузитьЗначения. Данный метод является функцией и возвращает одномерный массив, формируя его значениями из списка.
Поэкспериментируйте с этим методом самостоятельно.
Элемент списка значений
(3). 7.39 Элемент списка значений - что такое Элемент списка значений?
После того как мы научились добавлять, вставлять и загружать элементы в список значений, узнаем, что вообще такое Элемент списка значений.
Мы уже узнали, что элементы массива – это и есть те значения, которые хранятся в массиве, также мы узнали, что элемент структуры (соответствия) – это есть пара Ключ и значение. А что такое Элемент списка значений?
По сути, элемент списка значений – это отдельный объект, который имеет свойства и методы. Когда мы создаём новый элемент списка значений при помощи метода Добавить, то значения из всех параметров метода Добавить будут записаны в одноимённые свойства элемента списка значений, который будет создан.
Когда список значений заполнен, то он заполнен элементами типа Элемент списка
значений. Мы можем обратиться к любому элементу списка значений и работать с ним самостоятельно как с объектом: обращаться к свойствам этого объекта и использовать его методы. Но объект Элемент списка значений не может существовать самостоятельно без своего родителя – Списка значений.
(3). 7.40 как Обратиться непосредственно к элементу списка значений
Обратиться непосредственно к элементу списка значений можно двумя способами: с помощью оператора квадратные скобки и с помощью метода Получить.
В ранее созданной обработке в процедуре ЗагрузитьИзМассива обратимся к первому элементу списка значений с помощью оператора квадратные скобки (метод Получить предлагаю Вам рассмотреть самостоятельно). Поскольку элементы списка начинаются с нуля, то этот элемент будет идти под индексом 0.
/...
ПервыйЭлемент = Список[0];
Сообщить("ПервыйЭлемент.Значение = " + ПервыйЭлемент.Значение); Сообщить("ПервыйЭлемент.Представление = " + ПервыйЭлемент.Представление);
СписокНаФорме = Список;
Листинг 7.4.5
Перезапустим обработку и выполним команду Загрузить из массива.
Рис. 7.4.12
Как видите, первый элемент содержит значение Иванов И.И., которое мы загрузили из массива. Представление не заполнено, поскольку при загрузке из массива заполняются только значения.
Теперь рассмотрим более внимательно код на листинге 7.4.5 .
Сначала мы получили элемент под индексом 0 списка значений Список. Поскольку полученный элемент является объектом, нам доступны его свойства. Их у элементов списка значений четыре: Значение, Представление, Пометка и Картинка. Нас интересуют только
первые два. Мы обращаемся к этим свойствам, как обычно, через точку.
Мы также можем самостоятельно изменять свойства элементов.
Доработаем пример: заполним представление элемента.
//...
ПервыйЭлемент = Список[0]; ПервыйЭлемент.Представление = "Иванов Иван Иванович";
Сообщить("ПервыйЭлемент.Значение = " + ПервыйЭлемент.Значение); Сообщить("ПервыйЭлемент.Представление = " + ПервыйЭлемент.Представление);
СписокНаФорме = Список;
Листинг 7.4.6
Сохраним, перезапустим обработку, и мы увидим, что изменилось отображение первого элемента в списке.
Рис. 7.4.13
Обращаю Ваше внимание, что отдельно (от списка значений) элемент списка значений как объект существовать не может! Он может существовать только в контексте данного списка значений. Мы не можем его передавать из одного списка значений в другой, кроме того, если уничтожится список значений, то уничтожится и элемент.
(3). 7.41 Обход списка значений - какие способы?
Обход коллекции
Обход списка значений осуществляется двумя способами: с помощью операторов цикла Для Каждого…Цикл или Для…Цикл.
(3). 7.42 Разница в циклах? что рекомендуется?
Оба обхода равнозначны, но рекомендуется применять оператор Для каждого…Цикл, поскольку в таком случае Вы получаете сразу элемент коллекции. А в случае цикла Для … Цикл его придётся получать либо через квадратные скобки, либо используя метод Получить.
Рассмотрим и тот, и другой способ обхода. Допишем код в обработчике команды
Загрузить из массива.
Для Каждого ЭлСписок из Список цикл Сообщить(ЭлСписок.Значение);
КонецЦикла;
Для н = 0 по Список.Количество() - 1 цикл Сообщить(Список[н].Значение);
КонецЦикла;
Листинг 7.4.7
Как видите, оба метода одинаковы, но, с другой стороны, способ с помощью цикла Для…Цикл является более быстрым примерно процентов на 20. Поэтому при обходе больших коллекций значений используйте цикл Для…Цикл.
Работа с элементами списка значений
(3). 7.43 Работа с элементом списка значений. метод списка значений - открывает окно для выбора определенного элемента из списка, и возвращает элемент, который выбрал пользователь, или Неопределено, если пользователь отказался от выбора
Изучим основные методы списка значений, предназначенные для работы с элементами.
В предыдущих редакциях рассматривался метод ВыборЭлемента, но поскольку метод ВыборЭлемента используется только тогда, когда в свойстве конфигурации РежимИспользованияМодальности установлено значение Использовать (что уже встречается крайне редко), то в этот раз разберём более универсальный метод ПоказатьВыборЭлемента.
Метод ПоказатьВыборЭлемента
Метод ПоказатьВыборЭлемента открывает окно для интерактивного выбора определённого элемента из списка и возвращает элемент, который выбрал пользователь, или Неопределено, если пользователь отказался от выбора. В методе ПоказатьВыборЭлемента в качестве параметра используется объект ОписаниеОповещенияОЗакрытии, в котором должна быть указана экспортная процедура, срабатывающая после выбора элемента.
Изучим работу этого метода на простом примере: в последней обработке выберем любой элемент из списка СписокНаФорме и сообщим об этом.
Для этого создадим отдельную команду Выбор элемента и напишем в обработчике команды следующий код:
&НаКлиенте
Процедура ВыборЭлемента(Команда)
Если СписокНаФорме.Количество() = 0 Тогда Возврат;
КонецЕсли;
Описание = Новый ОписаниеОповещения("ПослеВыбораЭлемента",ЭтаФорма);
СписокНаФорме.ПоказатьВыборЭлемента(Описание,"Выберете элемент");
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораЭлемента(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт Если ВыбранныйЭлемент = Неопределено Тогда
Возврат;
КонецЕсли;
Сообщить(ВыбранныйЭлемент.Значение); КонецПроцедуры
Листинг 7.4.8 Поясним этот код. В обработчике ВыборЭлемента используется метод списка
значений ПоказатьВыборЭлемента, у этого метода в качестве параметра указывается объект
ОписаниеОповещения, который мы создаём строкой ранее. Во время создания объекта ОписаниеОповещения в первом параметре конструктора указывается название процедуры, которая сработает после выбора элемента (или отказа выбора). Эта процедура, которую так и назвали ПослеВыбораЭлемента, идёт ниже, она имеет два параметра – ВыбранныйЭлемент и ДополнительныеПараметры, и процедура обязательно должна быть экспортной. Параметр
ВыбранныйЭлемент процедуры ПослеВыбораЭлемента или будет иметь тип Элемент списка значений, если элемент выбран, или он будет равен Неопределено, если ничего не выбрано.
Если что-то выбрано, то мы сможем работать с выбранным элементом, как с элементом списка значений, например, можно получить значение этого элемента, что мы и делаем.
Сохраним, перезапустим обработку, заполним список на форме, а потом выполним команду Выбор элемента. Откроется окно выбора элементов.
Рис. 7.4.14
Выберем любой элемент двойным щелчком мышки, или просто выбрав его и нажав кнопку ОК. Выйдет соответствующее сообщение. Если мы ничего не выберем и нажмём
кнопку Отмена или клавишу Esc клавиатуры, то никакое сообщение не выйдет – это значит, что метод вернул значение Неопределено.
(3). 7.44 метод элемента списка значений возвращает индекс передаваемого в него элемента.
Метод Индекс
Метод Индекс возвращает индекс передаваемого в него элемента.
Доработаем вышеприведённый пример: если элемент выбран, то сообщим его номер по порядку, а это – номер индекса плюс один, если Вы помните.
&НаКлиенте
Процедура ПослеВыбораЭлемента(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт Если ВыбранныйЭлемент = Неопределено Тогда
Возврат;
КонецЕсли;
Номер = СписокНаФорме.Индекс(ВыбранныйЭлемент) + 1;
Сообщить("Выбран: " + ВыбранныйЭлемент.Значение + ", номер: " + Номер); КонецПроцедуры
Листинг 7.4.9
Сохраним, перезапустим обработку, выберем какой-нибудь элемент, и Вы увидите, что в сообщении вышел номер по порядку выбранного элемента.
Рис. 7.4.15
Метод Найти по значению
(3). 7.45 объект Список значений - метод, который позволяет искать элемент по его значению
У объекта Список значений есть один полезный метод, который позволяет искать элемент по его значению. Этот метод называется НайтиПоЗначению. Данный метод является функцией с одним параметром – это непосредственно значение, по которому ведётся поиск элемента. Возвращает функция НайтиПоЗначению либо элемент списка значений, если он найден, либо значение Неопределено – в противном случае.
Изучим работу этого метода. Сделаем новую обработку по аналогии с той, которую делали в начале этой части (с марками автомобилей), на форме обработки создадим список значения СписокМарок с типом значения Ссылка на справочник Марки автомобилей, а также
создадим реквизит формы Марка с типом значения Ссылка на справочник МаркиАвтомобилей (см. рис. 7.4.16). Поместим реквизит и список значений на форму, у списка значений поместим в таблицу колонки Пометка и Значение.
Рис. 7.4.16
При открытии формы будем заполнять список значений марками автомобилей.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) Выборка = Справочники.МаркиАвтомобилей.Выбрать();
Пока Выборка.Следующий() Цикл СписокМарок.Добавить(Выборка.Ссылка,Выборка.Наименование);
КонецЦикла;
КонецПроцедуры
Листинг 7.4.10
При изменении значения в поле Марка будем искать в списке СписокМарок изменённое значение и отмечать его флажком. Перед этим у всех элементов списка мы уберём флажки при помощи метода ЗаполнитьПометки. Метод списка значения ЗаполнитьПометки имеет один параметр типа Булево, после его выполнения все флажки принимают значение указанного параметра.
Создадим процедуру – обработчик события ПриИзменении поля ввода формы Марка
на клиенте, и в процедуре напишем следующий код:
&НаКлиенте
Процедура МаркаПриИзменении(Элемент) СписокМарок.ЗаполнитьПометки(Ложь);
ЭлНайденный = СписокМарок.НайтиПоЗначению(Марка); Если ЭлНайденный <> Неопределено тогда
ЭлНайденный.Пометка = Истина; КонецЕсли;
КонецПроцедуры
Листинг 7.4.11
Разберём этот код. В первой строке мы установили все пометки списка СписокМарок в положение Ложь. В следующей строке мы ищем с помощью изучаемого метода элемент списка СписокМарок. В параметр метода передаётся значение данных из поля ввода Марка.
Если элемент будет найден, то установим у этого элемента в свойство Пометка значение
Истина.
Сохраним обработку, запустим и посмотрим, как она работает.
Рис. 7.4.17
(3). 7.46 метод по работе с элементами - позволяет сместить элемент на определенное количество позиций
Метод Сдвинуть
Последний из интересующих нас методов по работе с элементами списка значений – это метод Сдвинуть. Метод Сдвинуть позволяет сместить элемент на определённое количество позиций.
Рассмотрим синтаксис этого метода.
Сдвинуть(<Элемент>, <Смещение>)
Параметр Элемент – это либо элемент списка значений, либо индекс данного элемента. Смещение – количество позиций, на которое сдвигается элемент. Если число положительное, то элемент сдвигается к концу списка, если отрицательное, то к началу списка.
Доработаем предыдущий пример: создадим новый реквизит на форме Сдвиг (типом значения число(2,0)). И при выборе элемента будем сдвигать его на то число, которое в нём указано.
код.
Рис. 7.4.18
Допишем код в процедуре – обработчике события ПриИзменении поля ввода Марка
Если ЭлНайденный <> Неопределено тогда ЭлНайденный.Пометка = Истина;
Если (СписокМарок.Индекс(ЭлНайденный)
+ 1 + Сдвиг <= СписокМарок.Количество()) и (СписокМарок.Индекс(ЭлНайденный) + 1 + Сдвиг > 0) тогда СписокМарок.Сдвинуть(ЭлНайденный,Сдвиг);
КонецЕсли;
КонецЕсли;
Листинг 7.4.12
В этом коде в качестве условий мы поставили ограничения, чтобы наш Сдвиг не выходил за границы списка значений.
Посмотрите, что получилось.
Сортировки
(3). 7.47 списки значений, методы позволяющие отсортировать элементы внутри данного списка
Разберём одну очень интересную возможность списка значений – это возможность сортировать элементы.
Для списков значений есть два метода, позволяющих отсортировать элементы внутри данного списка. Это сортировка по значению, когда сортируются непосредственно сами элементы в порядке возрастания или убывания. И второй метод – это сортировка по представлению, в этом случае элементы сортируются в алфавитном порядке представлений.
Первый способ сортировки лучше применять, когда в списке находятся примитивные типы (Строка, Число и Дата). Если же в списке находятся элементы справочника или документы, то сортировка по значению не всегда будет правильно выполняться, так как платформа будет сортировать все элементы по внутреннему идентификатору. Хотя очень часто внутренний идентификатор платформы может совпадать с названием элемента, и сортировка будет внешне выполняться правильно, но, как говорится, раз на раз не приходится.
Изучим сортировку на примере: в обработке с предыдущего примера отсортируем список значения СписокМарок по значению и по представлению. Для этого разместим на форме тумблер Сортировка с переключателями По значению и По представлению (реквизит и тумблер создайте самостоятельно, см. рис. 7.4.19). А при изменении этого тумблера будет сортировать СписокЗначения формы, для этого у поля Сортировка создадим обработчик команды ПриИзменении (см. листинг 7.4.13).
Рис. 7.4.19
В том случае если нажат тумблер По представлению, элементы в списке будут сортироваться по представлению, а если По значению – по значению.
Для того чтобы можно было наглядно убедиться, как работает данный метод, мы изменим представления списка Марка с марками автомобилей так, чтобы последний в списке элемент начинался на 01, предпоследний на 02 и т.д.
Допишите в обработчике события формы ПриСозданииНаСервере код следующим образом:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) Выборка = Справочники.МаркиАвтомобилей.Выбрать();
Пока Выборка.Следующий() Цикл СписокМарок.Добавить(Выборка.Ссылка,Выборка.Наименование);
КонецЦикла;
ПоследнийИндекс = СписокМарок.Количество() - 1; Счетчик = 1;
Пока ПоследнийИндекс >= 0 цикл
СписокМарок [ПоследнийИндекс].Представление = Строка(Счетчик) + " " + Строка(СписокМарок [ПоследнийИндекс].Значение);
ПоследнийИндекс = ПоследнийИндекс - 1; Счетчик = Счетчик + 1;
КонецЦикла;
КонецПроцедуры
Листинг 7.4.13
В этом коде мы изменяем представление списка СписокМарок таким образом, чтобы был обратный порядок цифр. Сохраним и перезапустим обработку.
Рис. 7.4.20
Вы видите, что к названиям марок добавились цифры, которые идут в обратном порядке.
Теперь осуществим непосредственно саму сортировку. Внутри обработчика события
ПриИзменении поля ввода Сортировка (тумблер) напишите следующий код:
&НаКлиенте
Процедура СортировкаПриИзменении(Элемент)
Если Сортировка = 0 Тогда СписокМарок.СортироватьПоЗначению();
иначе
СписокМарок.СортироватьПоПредставлению(); КонецЕсли;
КонецПроцедуры
Листинг 7.4.14
Посмотрите самостоятельно, как работает этот код.
Как Вы уже поняли, методы списков значений СортироватьПоПредставлению и СортироватьПоЗначению осуществляют сортировку элементов внутри списка. У этих процедур есть параметр, это способ сортировки: либо по возрастанию, либо по убыванию. Данный параметр задаётся в виде системного перечисления Направление сортировки.
Покажем, как это всё работает: добавим новый тумблер на форму с двумя переключателями: По убыванию и По возрастанию (реквизит ПорядокСортировки, см. рис. 7.4.21). Если нажат тумблер По убыванию, то элементы будут сортироваться по убыванию, в противном случае – по возрастанию.
Рис. 7.4.21
Изменим код в обработчике события кнопки Сортировка.
&НаКлиенте
Процедура СортировкаПриИзменении(Элемент)
Если ПорядокСортировки = 0 Тогда
Направление = НаправлениеСортировки.Убыв; ИначеЕсли ПорядокСортировки = 1 Тогда
Направление = НаправлениеСортировки.Возр; КонецЕсли;
Если Сортировка = 1 Тогда СписокМарок.СортироватьПоЗначению(Направление);
иначе
СписокМарок.СортироватьПоПредставлению(Направление); КонецЕсли;
КонецПроцедуры
Листинг 7.4.15
Посмотрите самостоятельно, как работает этот код.
Вот и всё. Теперь мы с Вами научились сортировать различными способами списки значений, это совсем не сложно и требует очень небольших усилий.
Удаление элементов. Очистка
(3). 7.48 Удаление элементов и очистка списка значений - методы?
Напоследок рассмотрим такой важный вопрос, как удаление элементов и очистка списка значений в целом.
Очистка списка значений выполняется с помощью метода Очистить, который Вам уже знаком по предыдущим коллекциям, поэтому здесь его разбирать не будем.
Рассмотрим подробнее удаление элементов списка значений. Выполняется это с помощью метода Удалить.
Синтаксис метода следующий:
Удалить(<ЭлементСписка>) Удалить(<Индекс>)
Метод Удалить имеет два варианта синтаксиса. В первом варианте синтаксиса единственный параметр – это ЭлементСписка, который нужно удалить. А во втором варианте синтаксиса – это число, которое являтся индексом удаляемого элемента.
Посмотрим, как работает метод Удалить. Для этого разместим в командной панели таблицы кнопку Удалить, при нажатии на которую будет удаляться тот элемент списка на форме, который в данный момент выделен.
Создадим команду формы Удалить, которую поместим на командную панель списка значений. К команде привяжем стандартную картинку Удалить.
Рис. 7.4.22
В процедуре-обработчике команды напишем код, в результате действия которого будет удаляться текущая строка (та, которая выделена курсором). Для того чтобы найти текущую строку, будем использовать свойство ТекущаяСтрока элемента формы Таблица. Данное свойство возвращает индекс строки, на которой в данный момент установлен курсор, то есть он выделен.
&НаКлиенте
Процедура Удалить(Команда)
ИндексДляУдаления = Элементы.СписокМарок.ТекущаяСтрока;
Если ИндексДляУдаления <> Неопределено тогда СписокМарок.Удалить(ИндексДляУдаления);
КонецЕсли;
КонецПроцедуры
Листинг 7.4.16
Разберём код выше.
В первой строке мы получаем индекс текущего элемента, тот, который выделен в данный момент с помощью свойства ТекущаяСтрока элемента формы Таблица.
Проверяем, действительно ли элемент выделен, потому что если элемент не выделен, то свойство вернёт значение Неопределено.
И если переменная ИндексДляУдаления не равна значению Неопределено, то удаляем её с помощью метода Удалить.
Сохраните обработку и посмотрите, как будет работать данная кнопка.
Итак, в этой части мы научились работать со списками значений. Вы поняли, что использовать список значений гораздо удобнее, чем массив, поскольку данный объект обладает рядом несравненных преимуществ перед массивами. К тому же есть специальный элемент формы, предназначенный для вывода данного объекта. Хотя в следующей главе мы с Вами будем рассматривать таблицы значений, которые более удобны и универсальны в работе с данными, всё же знать принципы работы со списками необходимо.
(3). 8.01 Глава 8. Таблицы - какие есть виды?
В этой главе Вы научитесь работать с таблицами в 1С. Под термином «таблица» понимается способ хранения (отображения) данных, при котором эти данные распределяются по однотипным строками и колонкам. При разработке в платформе 1С, как привило, используется два вида таблиц: это таблица значений, которая является одним из объектов универсальных коллекций значений, и непосредственно табличные части документов и справочников. В текущей главе мы научимся работать с таблицами значений и с табличными частями документов и справочников.
(3). 8.02 Часть 1. Таблицы значений - что такое Таблица значений?
Начнем с Таблиц значений.
Таблица значений представляет собой динамический набор значений, имеющий колонки и строки. Информация в таблице значений не хранится в базе данных и доступна только при работе контекста, в котором она была создана. Пользователи могут работать с данными, которые содержатся в таблице значений, посредством элемента формы Таблица, если разработчик свяжет созданную таблицу значений с элементом формы.
Как мы уже определили, вся информация в таблице значений разбита на колонки, причём каждая колонка таблицы должна иметь своё уникальное название. Каких-либо ограничений на количество колонок нет. Количество колонок, как правило, всегда фиксировано и задается разработчиком на этапе создания таблицы значений (хотя можно добавлять колонки и уже существующей таблице). А вот количество строк может меняться. Строки в таблицу значений можно добавлять разными способами. Можно программным способом, в этом случае необходимо использовать методы объекта Таблица значений, а можно интерактивно посредством элемента формы Таблица. Количество строк может быть неограниченно.
В том случае если работа с таблицей значения осуществляется посредством элемента формы Таблица, то у элемента формы Таблица могут быть все колонки, которые имеются у связанной с ним таблицы значений. Причём количество колонок в Таблице на форме может быть меньше, чем непосредственно у таблицы значений, то есть не все колонки из таблицы значений можно отображать в таблице формы. Необязательно выводить таблицу значений на форму, разработчик может использовать её и просто внутри программного модуля для реализации собственных алгоритмов.
У таблиц значений есть ряд полезных методов, которые позволяют сортировать таблицу по определённым колонкам, сворачивать, получать итог по конкретной колонке, осуществлять выборку части строк по определённым параметрам и многое другое. Все эти интересные вещи мы будем изучать в текущей главе.
Обратите внимание, что таблица значений может существовать только либо в серверном контексте, либо в клиентском контексте, который выполняется под толстым клиентом. Под тонким клиентом нельзя ни создать, ни использовать таблицу значений.
В том случае если ваше приложение будет работать или под тонким клиентом, или под веб- клиентом, всегда работайте напрямую с таблицей значения в серверном контексте (под директивой &НаСервере).
Сначала мы научимся работать с таблицей значения в программном модуле без привязки её к таблице на форме, а потом научимся работать с таблицей значения на форме.
(3). 8.03 как создать таблицу значений
Создать таблицу значений в программном модуле несложно, делается это с помощью оператора Новый. Созданная таблица значений существует в рамках того контекста, в котором был написан конструктор.
Выглядит это так:
Таблица1 = Новый ТаблицаЗначений;
Колонки таблицы значений
Мы научились создавать таблицу значений, это совсем не сложно, но это только малая часть работы, поскольку сама по себе таблица значений абсолютно не интересна. Чтобы начать с ней работать, необходимо в неё добавить колонки.
Для добавления колонок используется одно из основополагающих свойств таблиц значений – свойство Колонки.
Колонки таблицы значений - что такое свойство Колонки?
Разберём это свойство. В свойстве Колонки таблицы значений всегда содержится объект, который имеет тип Коллекция колонок таблицы значений, этот объект привязан к таблице значений и не может существовать без неё. Объект Коллекция колонок таблицы значений является, как ясно из названия, коллекцией, и эта коллекция состоит из объектов с типом КолонкаТаблицыЗначений.
С объектом Коллекция колонок таблицы значений мы можем работать, как с любой коллекцией значений: добавлять, удалять, сдвигать и выполнять прочие операции с элементами коллекции. Создавая новый элемент коллекции, мы создаём новый объект с типом КолонкаТаблицыЗначений. Объект с типом КолонкаТаблицыЗначений и есть колонка таблицы значений (как ни странно), у этого объекта нет методов, но есть всего четыре свойства – Имя колонки, Заголовок (данный заголовок выводится в шапке Таблицы), Тип значения (какие данные хранятся в колонке) и Ширина (данное свойство содержит ширину колонки в символах).
И поскольку объект Коллекция колонок таблицы значений – это коллекция, то её, так же, как и любую другую коллекцию, можно обойти с помощью оператора цикла Для каждого…Цикл.
Таблицы значений мы научились создавать, научимся создавать колонки.
Как создавать колонки?
Как же создавать сами колонки? У объекта Коллекция колонок таблицы значений существует два метода по созданию новых колонок. Это методы Добавить и Вставить. Метод Добавить – добавляет новую колонку в конец коллекции, а метод Вставить – вставляет колонку в нужное место по соответствующему индексу.
Для демонстрации создадим простую таблицу значений, которую назовём ФИО, имеющую три колонки – Фамилия, Имя и Отчество. Создадим обработку, форму обработки, какую-нибудь команду на форме, а также обработчики команды на сервере и на клиенте. В обработчиках напишем следующий код:
&НаСервере
Процедура СоздатьКолонкиТаблицыЗначенияНаСервере() ФИО = Новый ТаблицаЗначений; ФИО.Колонки.Добавить("Фамилия"); ФИО.Колонки.Добавить("Имя"); ФИО.Колонки.Добавить("Отчество");
КонецПроцедуры
&НаКлиенте
Процедура СоздатьКолонкиТаблицыЗначения(Команда) СоздатьКолонкиТаблицыЗначенияНаСервере();
КонецПроцедуры
Листинг 8.1.1 В этом коде мы просто создали таблицу значений, а потом добавили у неё три
колонки. Сохраним обработку и запустим её в отладчике, чтобы посмотреть, что собой
представляет коллекция колонок таблицы значений, о которой мы перед этим так долго говорили.
Рис. 8.1.1
В табло мы видим вновь созданную таблицу значений, в свойстве Колонки у этой таблицы значений всего три колонки, которые создали ранее. Раскроем одну из них.
Рис. 8.1.2
У этой колонки всего четыре свойства: Заголовок, Имя, Тип Значения и Ширина.
Заполнено только одно свойство – Имя. Так произошло потому, что мы использовали только один параметр у метода Добавить.
Настало время разобрать синтаксис метода Добавить коллекции колонок таблицы значений.
Добавить(<Имя>, <Тип>, <Заголовок>, <Ширина>)
У метода Добавить четыре параметра, по аналогии с четырьмя свойствами объекта Колонка таблицы значений. Если параметры Имя, Заголовок и Ширина Вам понятны (тип параметров Имя и Заголовок – это строка, а тип параметра Ширина – число), то со вторым параметром Тип, который имеет тип Описание типов, мы сейчас разберёмся.
Описание типов
Как Вы должны помнить из главы, посвящённой конфигурированию, когда мы создаем реквизит у какого-то объекта (будь то справочник, документ, обработка или отчёт), необходимо указать тип у создаваемого реквизита (то же самое справедливо и для реквизитов формы). Причём иногда один реквизит может принимать значения разных типов, если установить флаг Составной в окне Редактирование типа данных.
Рис. 8.1.3
Описание типов - для чего?
Таким образом указывается тип у реквизитов объектов на этапе конфигурирования. Но создавая таблицу значений в программном модуле, мы не можем указать тип у той или иной колонки интерактивно, как для элементов конфигурации, нам необходимо его задать программно. Делается это с помощью переменных, имеющих тип Описание типов. В переменной, которая имеет тип Описание типов, будут указаны все типы, значения которых будет принимать соответствующая колонка таблицы значений.
Рассмотрим синтаксис конструктора, необходимого для создания переменной типа
ОписаниеТипов:
Новый ОписаниеТипов(<Типы>, <КвалификаторыЧисла>, <КвалификаторыСтроки>,
<КвалификаторыДаты>, <КвалификаторыДвоичныхДанных>)
Разберём приведённый конструктор.
Первый параметр Типы – обязательный, он должен быть представлен либо в виде массива, элементы которого являются значениями типа Тип, либо это строка, в которой все типы перечислены через запятую.
Квалификаторы числа, строки, даты и двоичных данных – это объекты, которые задают параметры для соответствующих типов, это может быть: длина строки, длина и точность числа, части даты.
Чтобы понять, как всё это работает, создадим одно описание типа, которое будет содержать в себе тип Число, Дата и Строка. Причём тип будет задаваться двумя способами: с помощью массива и с помощью строки. Сделаем это в той же процедуре, где создавали таблицу значений, только выше.
&НаСервере
Процедура СоздатьКолонкиТаблицыЗначенияНаСервере()
КвЧисл = Новый КвалификаторыЧисла(10,2); КвСтр = Новый КвалификаторыСтроки(100);
КвДаты = Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя);
МассивТипов = Новый Массив(3); МассивТипов[0] = Тип("Строка"); МассивТипов[1] = Тип("Число"); МассивТипов[2] = Тип("Дата");
ОписаниеТипов1 = Новый ОписаниеТипов(МассивТипов,КвЧисл,КвСтр,КвДаты);
//...
Листинг 8.1.2
В данном коде мы получили описание типов с помощью массива.
Рассмотрим вариант задания типов с помощью строки.
ОписаниеТипов2 = Новый ОписаниеТипов("Строка,Число,Дата",КвЧисл,КвСтр,КвДаты);
Листинг 8.1.3 И вариант, когда типом будет ссылка на элемент справочника или на документ.
ОписаниеТипов3 = Новый ОписаниеТипов("СправочникСсылка.МаркиАвтомобилей"); ОписаниеТипов4 = Новый ОписаниеТипов("ДокументСсылка.ПрибытиеВГараж");
Листинг 8.1.4
Разберём вышеприведённый код.
В листинге 8.1.2 в первых трёх строках мы задаём квалификаторы числа, строк и даты. Это простые объекты, и мы не будем останавливаться на них подробно, поясним только, что задаются они с помощью оператора Новый. Конструктор квалификатора числа имеет два параметра – это длина числа и точность. Квалификатор строки имеет также два параметра – длина строки и допустимая длина, а квалификатор даты имеет только один параметр – части даты.
Потом мы создаём массив из трёх элементов и заполняем его переменными, имеющими тип Тип. Переменные создаём при помощи функции Тип.
И в последней строке листинга 8.1.2, а также в строках листингов 8.1.3, 8.1.4 создаём переменные с типом Описание типов. Причём если тип должен быть ссылочным, то необходимо писать либо СправочникСсылка, либо ДокументСсылка.
Если мы укажем переменную ОписаниеТипов1 или ОписаниеТипов2 при создании новой колонки таблицы, эта колонка сможет содержать в себе только три типа данных.
Пытливый читатель спросит: а зачем задавать колонки и задавать в них переменные определённых типов, когда можно просто оставить данный параметр пустым, и значения в колонках будут любых типов?
Да, так можно делать, но есть несколько «но». Во-первых, если Вы задаёте колонки без типа, то данная таблица будет работать примерно в полтора раза медленнее, чем таблица с колонками, имеющими тип. Во-вторых, если Вы будете передавать данную таблицу в запрос, то, в случае колонок без типа, такой запрос не будет работать.
Поэтому если таблица содержит небольшой объём данных и не передаётся в дальнейшем в запрос, то смело можете создавать нетипизированные колонки. В противном случае всегда указывайте тип колонок с помощью объекта Описание типов.
Итак, мы научились создавать описания типов, теперь сконструируем таблицу со следующими колонками: Фамилия (тип Строка с длиной 50), Имя (тип Строка), Отчество, (тип Строка) и Дата рождения (тип Дата). Зададим все параметры метода Добавить.
Для этого создадим новую команду Создать таблицу значений с типами и обработчики к ней.
&НаСервере
Процедура СоздатьТЗСТипамиНаСервере()
КвСтр = Новый КвалификаторыСтроки(50);
КвДаты = Новый КвалификаторыДаты(ЧастиДаты.Дата); ОписаниеТиповСтрока = Новый ОписаниеТипов("Строка",,КвСтр,);
ФИО = Новый ТаблицаЗначений; ФИО.Колонки.Добавить("Фамилия",ОписаниеТиповСтрока,"Фамилия",50); ФИО.Колонки.Добавить("Имя",ОписаниеТиповСтрока,"Имя",50); ФИО.Колонки.Добавить("Отчество",ОписаниеТиповСтрока,"Отчество",50); ФИО.Колонки.Добавить("ДатаРождения",Новый
ОписаниеТипов("Дата",,,КвДаты),"Дата рождения",10); КонецПроцедуры
&НаКлиенте
Процедура СоздатьТЗСТипами(Команда) СоздатьТЗСТипамиНаСервере();
КонецПроцедуры
Листинг 8.1.5
Разберём код выше. Первым делом мы создали квалификаторы строки и даты, для того чтобы потом их использовать в описании типов.
Следующим шагом создаём описание типа для строки. Вы заметили, что мы не стали создавать отдельную переменную, для описания типа Дата.
Потом мы создаём таблицу значений и добавляем колонки, используя все параметры метода Добавить. Надеюсь, Вы обратили внимание на последнюю строку метода СоздатьТЗСТипамиНаСервере (листинг 8.1.5), в которой внутри параметра мы использовали ключевое слово Новый, так допустимо писать, если у Вас нет необходимости использовать созданное значение где-нибудь ещё. Например, мы можем убрать переменные КвСтр и КвДаты и напрямую создавать квалификаторы, когда задаём описание типов.
Тогда наш код будет выглядеть так:
ОписаниеТиповСтрока = Новый ОписаниеТипов("Строка",,Новый КвалификаторыСтроки(50),);
ФИО = Новый ТаблицаЗначений; ФИО.Колонки.Добавить("Фамилия",ОписаниеТиповСтрока,"Фамилия",50); ФИО.Колонки.Добавить("Имя",ОписаниеТиповСтрока,"Имя",50); ФИО.Колонки.Добавить("Отчество",ОписаниеТиповСтрока,"Отчество",50); ФИО.Колонки.Добавить("ДатаРождения",Новый ОписаниеТипов("Дата",,,Новый КвалификаторыДаты(ЧастиДаты.Дата)),"Дата рождения",10);
Листинг 8.1.6 Как видите, использование оператора Новый внутри параметра вполне может
оптимизировать код программы. Но не слишком увлекайтесь этим, поскольку при большом
количестве параметров внутри какой-нибудь процедуры или функции код будет трудно читаемым.
Посмотрим в отладке на колонку Имя нашей таблицы значений (см. рис. 8.1.4).
Рис. 8.1.4
Как видите, у колонки Имя заполнены все свойств.
Итак, мы научились добавлять новые колонки в таблицу значений, осуществляется это с помощью объекта Коллекция колонок таблицы значений. Поскольку данный объект является коллекцией, то каждая колонка имеет свой индекс. И, как следствие, Вы можете осуществить обход коллекции с помощью оператора цикла Для Каждого…Цикл, или получить доступ к свойствам колонки с помощью квадратных скобок.
Например, так:
ФИО.Колонки[0]
Обращаю Ваше внимание, что с помощью свойства таблицы значений Колонки Вы получите доступ только к свойствам колонки (название, заголовок и т.д.), а не к тем данным, которые хранятся в соответствующей колонке.
Метод Вставить
Метод добавления колонки
Используя полученные ранее знания, разберём метод Вставить объекта Коллекция колонок таблицы значений.
Метод Вставить имеет следующий синтаксис:
Вставить(<Индекс>, <Имя>, <Тип>, <Заголовок>, <Ширина>)
Синтаксис метода Вставить похож на синтаксис метода Добавить, но только добавился параметр Индекс, он указывает тот индекс, на место которого будет вставлена новая колонка.
Используем уже созданную нами таблицу, вставив колонку между Отчеством и Датой рождения, которая будет называться ФИО, в этой колонке будет храниться фамилия с инициалами.
Доработаем код из листинга 8.1.6.
ФИО = Новый ТаблицаЗначений; ФИО.Колонки.Добавить("Фамилия",ОписаниеТиповСтрока,"Фамилия",50); ФИО.Колонки.Добавить("Имя",ОписаниеТиповСтрока,"Имя",50); ФИО.Колонки.Добавить("Отчество",ОписаниеТиповСтрока,"Отчество",50); ФИО.Колонки.Добавить("ДатаРождения",Новый ОписаниеТипов("Дата",,,Новый КвалификаторыДаты(ЧастиДаты.Дата)),"Дата рождения",10);
//вставляем колонку ФИО.Колонки.Вставить(3,"ФИО",ОписаниеТиповСтрока,"ФИО",50);
Листинг 8.1.7 Для того чтобы посмотреть, в какое место вставилась Ваша колонка, поставим точку
останова в конце процедуры, запустим отладку и посмотрим на таблицу в табло (см. рис.
8.1.5).
Рис. 8.1.5
Как видите, колонка ФИО встала точно между Отчеством и Датой рождения. На третий индекс по порядку (Вы не забыли, что индексы начинаются с 0?).
На этом мы закончим изучать работу с колонками таблицы значений, так как двух данных методов Вам будет вполне достаточно, чтобы успешно решать задачи с таблицами значений. С остальными методами (они все похожи на методы, которые мы изучали для списка значений) Вы можете ознакомиться самостоятельно, работая с синтакс-помощником. У Вас это не вызовет больших затруднений.
Строки таблицы значений - метод создать новую строку таблицы значений, которая вставляется в конец таблицы значений
Строки таблицы значений
Мы научились создавать колонки таблицы значений. Как Вы поняли, на этапе создания колонок можно задать жёстко, данные какого типа будут храниться в данной колонке. Это надо всегда помнить, поскольку если Вы попробуете записать в колонку значение типа, отличного от указанного, то значение не будет записано.
Научимся добавлять строки в таблицу значения, то есть полноценно с ней работать.
Метод Добавить
Метод «Добавить»
Для того чтобы создать новую строку таблицы значений используется метод Добавить объекта Таблица значений, этот метод не имеет параметров и является функцией, которая возвращает новую строку таблицы значений.
Новая строка таблицы значений создаётся следующим образом:
НоваяСтрока = ФИО.Добавить();
С помощью метода Добавить мы создаём переменную НоваяСтрока, тип значения которой будет Строка таблицы значений. Но просто создать строку недостаточно, нам ещё необходимо заполнить её определённые данные. Как что-то записать в нужную колонку новой строки?
Осуществить это можно двумя способами.
Первый способ:
НоваяСтрока.Фамилия = "Иванов";
Второй способ:
НоваяСтрока[1] = "Иван";
В первом способе мы получаем доступ к колонке как к свойству через точку, во втором – используя оператор квадратные скобки и указывая в них номер индекса колонки. Первый способ является более удобным.
Продолжим работать с последней процедурой, в которой создали таблицу значений и заполнили колонками. Добавим в ней код, который создаёт новую строку таблицы значений и заполняет её.
НоваяСтрока = ФИО.Добавить(); НоваяСтрока.Фамилия = "Иванов"; НоваяСтрока[1] = "Иван"; НоваяСтрока.Отчество = "Петрович"; НоваяСтрока.ДатаРождения = '19800209'; НоваяСтрока.ФИО = НоваяСтрока.Фамилия +" " +
Лев(НоваяСтрока.Имя,1) +"." + Лев(НоваяСтрока.Отчество,1) + ".";
Листинг 8.1.8
Как видно из кода, обращаясь к строке, мы можем как читать данные, так и записывать
их.
А теперь посмотрим, что записалось в таблицу значений. Для этого запустим опять отладку, поставим точку останова в конце процедуры и откроем таблицу в табло (см. рис. 8.1.6).
Рис. 8.1.6
Видно, что в табло у данной таблицы значений уже есть одна строка, и она заполнена теми данными, которые мы только что в неё ввели.
Какие методы имеют строки таблицы значений? Всего их три: метод Владелец – возвращает таблицу значений, которой принадлежит данная строка; метод Установить – записывает данные в нужную колонку строки; метод Получить – читает данные нужной колонки.
Методы Установить и Получить следует применять тогда, когда Вы не можете использовать оператор квадратные скобки или обращаться напрямую через точку.
Разберём вышеприведённые методы.
Метод Установить имеет следующий синтаксис:
Установить(<Индекс>,<Значение>)
Первый параметр – индекс колонки, в которую будет записываться значение, второй параметр – непосредственно записываемое значение.
Добавим ещё одну строку созданной ранее таблицы и занесём все данные в неё с помощью метода Установить.
НоваяСтрока = ФИО.Добавить(); НоваяСтрока.Установить(0,"Васильев"); НоваяСтрока.Установить(1,"Иван"); НоваяСтрока.Установить(2,"Андреевич"); НоваяСтрока.Установить(3,"Васильев И.А."); НоваяСтрока.Установить(4,'19760910');
Листинг 8.1.9
Код написали, а теперь посмотрим, как записались данные в таблицу, также используя
табло.
Рис. 8.1.7
Из табло видно, что у нас появилась ещё одна строка с данными, которые мы внесли с помощью метода Установить.
Следующий метод – метод Получить. Этот метод получает значение нужной колонки у строки. Метод имеет единственный параметр, в котором указывается индекс колонки.
Доработаем наш пример: при помощи метода Получить обратимся к значениям, которые содержатся в колонках вновь созданной строки. Для этого обойдём все колонки созданной только что строки и выведем в окно сообщений названия колонок, а также данные, которые содержатся в колонках.
Для н = 0 по ФИО.Колонки.Количество() - 1 цикл Сообщить(ФИО.Колонки[н].Заголовок + ": " +
Строка(НоваяСтрока.Получить(н)));
КонецЦикла;
Листинг 8.1.10
Разберём код выше. По условиям задания необходимо обойти все колонки, получить названия этих колонок и получить значения, которые хранятся в них. В принципе, это можно было осуществить китайским методом, написав пять раз сообщение, но мы будем решать данную задачу используя цикл Для…Цикл. В этом цикле необходимо перечислить индексы всех колонок, которые есть у таблицы значений. Для этого мы начинаем обход с нуля (все индексы начинаются с нуля), а последним значением будет количество колонок за минусом единицы.
В методе Сообщить сначала мы получаем заголовок колонки, получив нужную колонку по индексу, используя свойство Заголовок этой колонки, а потом с помощью метода Получить получаем значение, которое хранится в данной колонке.
Если сейчас выполним доработанную команду, то выйдут данные, которые хранятся в последней созданной строке таблицы значения.
Рис. 8.1.8
Метод поместить строку в нужное место таблицы значений
Метод Вставить
Если при помощи метода Добавить мы создаём строку, которая вставляется в конец таблицы значений, то для того чтобы поместить строку в нужное место таблицы значений, необходимо использовать метод Вставить. Параметром данного метода является индекс, на который вставляется данная строка.
Добавим с помощью этого метода еще одну строку в нашу таблицу. И поставим её на первое место (индекс 0).
НоваяСтрока = ФИО.Вставить(0); НоваяСтрока.Фамилия = "Петров"; НоваяСтрока.Имя = "Игорь"; НоваяСтрока.Отчество = "Андреевич";
НоваяСтрока.ФИО = НоваяСтрока.Фамилия +" " + Лев(НоваяСтрока.Имя,1) +"." + Лев(НоваяСтрока.Отчество,1) + ".";
НоваяСтрока.ДатаРождения = '19850909';
Листинг 8.1.11
Посмотрите, в какое место таблицы встала данная строка.
Рис. 8.1.9
Как видите, новая строка добавилась на первое место таблицы значений.
Обход строк
Обход строк таблицы - какие операторы цикла? какой рекомендуемый?
Мы научились добавлять новые строки и читать в них значения. Теперь научимся обходить строки таблицы. Это можно осуществлять с помощью операторов цикла Для Каждого...Цикл и Для…Цикл. Осуществим обход созданной ранее и заполненной таблицы и тем, и другим способом.
Начнём с оператора цикла Для Каждого...Цикл.
Для Каждого Стр из ФИО цикл Сообщить(Стр.ФИО + ", дата рождения " +
Формат(Стр.ДатаРождения,"ДЛФ = ДД"));
КонецЦикла;
Листинг 8.1.12
Как видите, с помощью этого способа мы обходим все строки таблицы значений. В переменную Стр в каждой итерации цикла записывается строка таблицы значения по порядку. Тип этой переменной – Строка таблицы значений, поэтому мы можем спокойно обращаться к колонкам таблицы значения, используя точку или квадратные скобки.
Покажем, как осуществить обход, используя оператор Для…Цикл.
Для н = 0 по ФИО.Количество() - 1 цикл Сообщить(ФИО[н].ФИО + ", дата рождения " +
Формат(ФИО[н].ДатаРождения,"ДЛФ = ДД"));
КонецЦикла;
Листинг 8.1.13
В этом цикле нам необходимо получить индексы всех строк, для этого мы осуществляем обход, начиная с нуля и заканчивая значением, которое возвращает метод Количество за минусом единицы.
Когда мы используем квадратные скобки применительно к таблице значений (например, ФИО[н]), то результатом данной операции является строка таблицы под соответствующим индексом, который указан в квадратных скобках. Это мы демонстрируем в только что приведённом примере.
Итак, мы научились обходить таблицы значений, используя два разных оператора цикла. Оба они дают одинаковые результаты. Но первый способ имеет преимущества: во- первых, код более читабельный, во-вторых, первый способ более быстрый по времени.
Поэтому рекомендую Вам для обхода таблиц значений использовать цикл Для Каждого…Цикл.
Поиск по таблице значений
Поиск по таблице значений - какие есть методы?
Довольно часто ставится задача найти в таблице значения строку с каким-нибудь конкретным значением или отобрать строки по определённым заранее заданным параметрам. Осуществляется это с помощью методов Найти и НайтиСтроки.
Метод «Найти» - что осуществляет?
Метод Найти
Метод Найти производит поиск нужного значения в указанных колонках. Этот метод являет функцией и возвращает строку таблицы значений, если в ней присутствует искомое значение, или возвращает Неопределено, если значение не было найдено.
Если имеется несколько строк с искомым значением, то будет возвращена только одна. Поэтому рекомендуется использовать метод Найти для поиска уникальных значений.
Рассмотрим синтаксис функции Найти.
Найти(<Значение>, <Колонки>)
Первый параметр – непосредственно то значение, которое мы ищем, он является обязательным.
Второй параметр имеет тип значения Строка и представляет собой имена колонок, разделённых запятыми. Он может быть не заполнен, тогда поиск осуществляется по всей таблице.
Рассмотрим пример: в уже созданной таблице ФИО будем искать нужную нам фамилию. Для этого на форме создадим реквизит Фамилия с типом Строка (длина 50) и поместим его на форму в виде поля ввода (см. рис. 8.1.10).
При выполнении команды Создать таблицу значений с типами будет осуществляться поиск значения из данного поля в колонке Фамилия. Если оно будет найдено, то выведем в окно сообщений соответствующую информацию.
Рис. 8.1.10
Допишем код в последней команде (СоздатьТЗСТипамиНаСервере) обработки:
Если Не ПустаяСтрока(Фамилия) тогда
СтрокаСФамилией = ФИО.Найти(СокрЛП(Фамилия),"Фамилия"); Если СтрокаСФамилией <> Неопределено тогда
Для н = 0 по ФИО.Колонки.Количество() - 1 цикл
Если ТипЗнч(СтрокаСФамилией[н]) = Тип("Дата") тогда Сообщить(ФИО.Колонки[н].Заголовок + ": " +
Формат(СтрокаСФамилией[н],"ДЛФ = ДД"));
Иначе
Сообщить(ФИО.Колонки[н].Заголовок + ": " + Строка(СтрокаСФамилией[н]));
КонецЕсли;
КонецЦикла;
иначе
Сообщить("В таблице нет записей с фамилией " + Фамилия); КонецЕсли;
КонецЕсли;
Листинг 8.1.14
Разберём вышеприведённый код.
Первым делом мы проверяем, пустая у нас строка или нет, потому что иначе нет смысла искать. Для того чтобы найти строку с искомой фамилией, мы применяем метод Найти, в котором указываем непосредственно искомое значение и название колонки, по которой будет осуществляться поиск.
Метод Найти возвращает найденную строку или значение Неопределено, поэтому мы проверяем переменную, которую вернул метод Найти, на неравенство значению Неопределено и выводим сообщения о данных, которые хранятся в строке, обойдя все колонки по индексу. Конечно же, Вы обратили внимание, что мы проверяем тип данных в колонке, и если тип является типом Дата, то выводим её в специальном формате.
Сохраните обработку и посмотрите, как данный код будет работать.
Только что мы научились осуществлять поиск по какому-то одному значению, но часто возникают ситуации, когда необходимо найти строку или строки по нескольким значениям. Такая операция выполняется при помощи метода НайтиСтроки.
НайтиСтроки - что осуществляет?
Метод НайтиСтроки
Рассмотрим синтаксис метода НайтиСтроки, который является функцией и возвращает массив строк таблицы значений соответствующим условиям поиска.
НайтиСтроки(<Отбор>)
У данного метода всего один обязательный параметр, это – Отбор, который является структурой, её ключи соответствуют названиям колонок таблицы, а значения структуры – искомым значениям.
Повторюсь, что на выходе этой функции мы имеем массив, состоящий из строк, соответствующих установленному отбору, причём в массиве хранятся ссылки на строки. Поэтому если вы поменяете какое-нибудь значение в строке из массива, то оно изменится и в таблице значений. И наоборот, если что-нибудь поменяете в таблице, то автоматически изменится и определённый элемент массива.
Доработаем наш пример: необходимо осуществлять поиск по Фамилии и по Имени. Если строки с такими данными будут найдены, то выведем информацию в окно сообщений. Для этого добавим ещё один реквизит Имя (Строка(20)) на форму. Также у реквизитов Фамилия и Имя установим в свойстве Проверка заполнения значение Выдавать ошибку (см. рис. 8.1.12).
Рис. 8.1.11 | Рис. 8.1.12 |
Код поиска будет следующий:
Если ПроверитьЗаполнение() тогда СтруктураПоиска = Новый Структура;
СтруктураПоиска.Вставить("Имя",СокрЛП(Имя)); СтруктураПоиска.Вставить("Фамилия", СокрЛП(Фамилия)); НайденныеСтроки = ФИО.НайтиСтроки(СтруктураПоиска);
Если НайденныеСтроки.Количество() <> 0 тогда
Для Каждого СтрокаФИО из НайденныеСтроки цикл
Для н = 0 по ФИО.Колонки.Количество() - 1 цикл Если ТипЗнч(СтрокаФИО[н]) = Тип("Дата") тогда
Сообщить(ФИО.Колонки[н].Заголовок + ": " + Формат(СтрокаФИО[н],"ДЛФ = ДД"));
Иначе
Сообщить(ФИО.Колонки[н].Заголовок + ": " + Строка(СтрокаФИО[н]));
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЕсли;
Листинг 8.1.15
Разберём данный код.
Сначала мы при помощи метод ПроверитьЗаполнение() проверяем, есть ли данные в соответствующих реквизитах формы. Если есть, то создаём структуру, которую называем СтруктураПоиска, и добавляем в неё две пары Ключ и значения, причём, как Вы могли заметить, названия ключей соответствуют названиям колонок в таблице. После этого мы используем метод НайтиСтроки, который возвращает некоторый массив строк. Если он заполнен, то выводим информацию в окно сообщений точно так же, как мы это делали в предыдущем примере.
Сохраните обработку и посмотрите, как работает наш новый поиск.
Мы научились осуществлять всевозможный поиск по таблицам значений.
Потренируйтесь с поиском данных в Вашей созданной таблице, такие навыки Вам очень пригодятся в дальнейшей деятельности.
Работа с таблицей значения
Мы научились заполнять таблицу значений и осуществлять поиск по ней. Научимся работать непосредственно с самой таблицей: сворачивать её, копировать, выгружать данные из колонки, загружать данные в колонку, получать итоги по какой-нибудь одной колонке, заполнять всю таблицу одним значением и сортировать.
Свёртка
Работа с таблицей значения. Свертка - какой метод?
Очень часто бывает необходимо свернуть таблицу. Свернуть таблицу – это значит сгруппировать значения по некоторым колонкам, причём так, чтобы все одинаковые строки в какой-нибудь колонке (или в нескольких колонках) должны будут слиться в одну.
Продемонстрируем это наглядно, например, у нас есть таблица следующего вида:
Дата | ФИО | Часы | Сумма |
01.12.12 | Иванов И.И. | 10 | 1000 |
02.12.12 | Иванов И.И. | 8 | 800 |
03.12.12 | Петров Ф.Ф. | 5 | 500 |
04.12.12 | Петров Ф.Ф. | 7 | 700 |
Таблица 8.1.1
В ней имеются колонки с датами, фамилиями, часами и суммами.
Нам необходимо свернуть таблицу по колонке ФИО, причём Часы и Сумма должны быть просуммированы. И на выходе должна получиться следующая таблица:
ФИО | Часы | Сумма |
Иванов И.И. | 18 | 1800 |
Петров Ф.Ф. | 12 | 1200 |
Таблица 8.1.2
Свертка - метод Свернуть()
Как выполнить такую операцию? Для этого необходимо использовать метод Свернуть
объекта Таблица значений.
Свернуть(<КолонкиГруппировок>, <КолонкиСуммирования>)
Первый параметр – это колонки, по которым значения в таблице будут группироваться.
Второй параметр – это колонки, по которым значения будут суммироваться.
То есть касательно нашего примера данная процедура должна выглядеть так:
Таблица.Свернуть("ФИО","Часы,Сумма")
Причём имейте в виду, что данный метод является процедурой, в результате выполнения которой Ваша таблица изменится: те колонки, которые не перечислены в колонках группировки и колонках суммирования, удалятся, данные в них потеряются. Также обращаю внимание, что списки колонок группировки и суммирования не должны пересекаться.
Реализуем приведённую выше задачу на практике. Создадим таблицу значений, заполним её, а потом свернём. Для этих целей создадим новую обработку, форму обработки,
поместим на форму команду и создадим обработчики команды на сервере и на клиенте. В обработчиках напишем следующий код:
&НаСервере
Процедура СворачиваниеТаблицЗначенийНаСервере() КвЧисл = Новый КвалификаторыЧисла(10,2);
ОписаниеТиповЧисло = Новый ОписаниеТипов("Число",КвЧисл,,);
ТаблицаОплат = Новый ТаблицаЗначений; ТаблицаОплат.Колонки.Добавить("Дата",Новый ОписаниеТипов("Дата",,,Новый
КвалификаторыДаты(ЧастиДаты.Дата))); ТаблицаОплат.Колонки.Добавить("ФИО",Новый ОписаниеТипов("Строка",Новый
КвалификаторыСтроки(100))); ТаблицаОплат.Колонки.Добавить("Часы", ОписаниеТиповЧисло); ТаблицаОплат.Колонки.Добавить("Сумма",ОписаниеТиповЧисло);
НоваяСтрока = ТаблицаОплат.Добавить(); НоваяСтрока.Дата = '20121201'; НоваяСтрока.ФИО = "Иванов И.И."; НоваяСтрока.Часы = 10;
НоваяСтрока.Сумма = 1000;
НоваяСтрока = ТаблицаОплат.Добавить(); НоваяСтрока.Дата = '20121202'; НоваяСтрока.ФИО = "Иванов И.И."; НоваяСтрока.Часы = 8;
НоваяСтрока.Сумма = 800;
НоваяСтрока = ТаблицаОплат.Добавить(); НоваяСтрока.Дата = '20121205'; НоваяСтрока.ФИО = "Петров Ф.Ф."; НоваяСтрока.Часы = 5;
НоваяСтрока.Сумма = 500;
НоваяСтрока = ТаблицаОплат.Добавить(); НоваяСтрока.Дата = '20121205'; НоваяСтрока.ФИО = "Петров Ф.Ф."; НоваяСтрока.Часы = 7;
НоваяСтрока.Сумма = 700;
ТаблицаОплат.Свернуть("ФИО","Часы,Сумма");
КонецПроцедуры
&НаКлиенте
Процедура СворачиваниеТаблицЗначений(Команда) СворачиваниеТаблицЗначенийНаСервере();
КонецПроцедуры
Листинг 8.1.16 Не будем разбирать подробно код в данном примере, Вы без труда разберёте его
самостоятельно. Но для того чтобы понять, как работает данный метод, поставим точку
останова на строку свёртки таблицы и посмотрим, какой была таблица до свёртки (рис. 8.1.13) и что с ней стало после свёртки (рис. 8.1.14).
Рис. 8.1.13
Рис. 8.1.14
Как Вы видите, таблица свернулась, и получилась точно такая же таблица, как в таблице 8.1.2.
Ещё один интересный момент: второй параметр в процедуре Свернуть не является обязательным, то есть можно просто сгруппировать таблицу по определённым колонкам, притом вовсе не нужно суммировать значения где-либо. Поэкспериментируйте самостоятельно с этим методом таблиц значений.
копирование таблиц значений имеется два метода
Копирование таблиц и копирование структуры таблиц
Иногда возникает необходимость получить вторую точно такую же таблицу из ранее созданной, то есть скопировать её. Причём иногда нужно, чтобы скопированная таблица содержала все данные, которые были в таблице-оригинале, а иногда – чтобы она была пустой, но имела точно такие же колонки, как и у оригинала. С копированием таблиц значений нам помогут два метода: Скопировать и СкопироватьКолонки.
Скопировать
Копирование таблиц и копирование структуры таблицы - метод создает копию исходной таблицы
Разберём метод Скопировать. Метод Скопировать создаёт копию исходной таблицы.
У этого метода два синтаксиса.
Первый:
Скопировать(<Строки>, <Колонки>)
Этот синтаксис имеет два необязательных параметра. Первый параметр Строки – это массив строк таблицы значений, которые скопируются в новую строку, а второй параметр Колонки – это список колонок для копирования, которые перечислены через запятую.
Второй вариант синтаксиса следующий:
Скопировать(<ПараметрыОтбора>, <Колонки>)
Первый параметр ПараметрыОтбора является структурой, по которой будет осуществлен отбор строк в новую таблицу, по аналогии со структурой для метода Отбор. Второй параметр точно такой же, как и в предыдущем варианте синтаксиса.
Таким образом, если Вы хотите перенести в новую таблицу только часть строк, то Вы должны понять, можно ли получить эти строки отбором по каким-то признакам, или нет.
Если да, то используйте синтаксис с вариантом для параметра отбора. Если нет, то создайте массив, в который добавьте нужные Вам строки, и используйте синтаксис с вариантом для массива.
Создадим на форме новую команду, обработчики этой команды на сервере и на клиенте. Из предыдущей команды создание таблицы ТаблицаОплат вынесем в отдельную функцию под директивой &НаСервереБезКонтекста, которая будет возвращать созданную и заполненную таблицу.
В коде нового обработчика, после получения таблицы ТаблицаОплат, создадим копированием две новые таблицы.
В первую таблицу добавим первую и последнюю строку из таблицы ТаблицаОплат и колонки: Дата, ФИО и Сумма.
Во вторую вставим все строки, где колонка ФИО содержит Иванов И.И., и колонки
ФИО, Часы и Сумма, и сразу свернем её, просуммировав колонки по Часам и Сумме.
&НаСервере
Процедура КопированиеТаблицыЗначенийНаСервере() ТаблицаОплат = СоздатьИЗаполнитьТаблицуОплатНаСервер();
МассивДляТаблицы = Новый Массив; МассивДляТаблицы.Добавить(ТаблицаОплат[0]); МассивДляТаблицы.Добавить(ТаблицаОплат[ТаблицаОплат.Количество() - 1]);
ТаблицаОплат1 = ТаблицаОплат.Скопировать(МассивДляТаблицы,"Дата,ФИО,Сумма"); СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("ФИО","Иванов И.И.");
ТаблицаОплат2 = ТаблицаОплат.Скопировать(СтруктураОтбора,"ФИО, Часы, Сумма");
ТаблицаОплат2.Свернуть("ФИО","Часы,Сумма");
КонецПроцедуры
Листинг 8.1.17
Сохраним обработку и поставим точку останова в конце процедуры, для того чтобы посмотреть, какими стали новые таблицы.
Рис. 8.1.15. ТаблицаОплат1
Рис. 8.1.16. ТаблицаОплат2 Как Вы видите, в них именно те данные, которые мы хотели.
СкопироватьКолонки
Ещё один метод, который создаёт новую таблицу, это метод СкопироватьКолонки.
метод создает таблицу с точно тем же набором колонок, как и у оригинала. Новая таблица абсолютно пустая и не содержит никакой информации из оригинала.
Метод СкопироватьКолонки создаёт таблицу с точно тем же набором колонок, как и у оригинала, но новая таблица абсолютно пустая – в ней нет никаких строк из оригинала.
Синтаксис этого метода следующий:
СкопироватьКолонки(<Колонки>)
Параметр Колонки – это колонки, перечисленные через запятую. Если параметр не указан, то копируются все колонки.
Посмотрим простой пример:
НоваяТаблица = ТаблицаОплат.СкопироватьКолонки("ФИО,Часы,Сумма");
Самостоятельно поработайте с этим методом.
Выгрузка и загрузка данных в таблицу значений - метод, который позволяет выгрузить все значения из колонки в массив?
Выгрузка и загрузка данных в таблицу значений
Научимся выгружать данные из колонки и загружать данные в колонку.
Начнём с выгрузки. У таблиц значения существует метод, который позволяет выгрузить все значения из определённой колонки в массив. Он называется ВыгрузитьКолонку. Рассмотрим синтаксис этого метода.
ВыгрузитьКолонку(<Колонка>)
Данный метод имеет один параметр – это колонка, значения которой мы будем выгружать. Колонку можно представить тремя способами: индекс, название колонки и как саму колонку.
Продемонстрируем, как это выглядит. Как и в предыдущий раз создадим новую команду на форме и в серверном обработчике получим таблицу значения при помощи созданной функции СоздатьИЗаполнитьТаблицуОплатНаСервере, а потом выгрузим колонки:
&НаСервере
Процедура ВыгрузкаКолонокТаблицыЗначенияНаСервере() ТаблицаОплат = СоздатьИЗаполнитьТаблицуОплатНаСервере();
МассивФИО = ТаблицаОплат.ВыгрузитьКолонку("ФИО"); МассивФИО_1 = ТаблицаОплат.ВыгрузитьКолонку(1);
МассивФИО_2 = ТаблицаОплат.ВыгрузитьКолонку(ТаблицаОплат.Колонки.ФИО);
КонецПроцедуры
Листинг 8.1.18
Посмотрите самостоятельно, какие данные выгрузятся в массивы.
как загружать значения в таблицу из массива
Разберём, как загружать значения в таблицу из массива. Для этого необходимо использовать метод таблиц значений ЗагрузитьКолонку.
У этого метода следующий синтаксис:
ЗагрузитьКолонку(<Массив>, <Колонка>)
Первый параметр – это массив данных, которые будут загружаться в колонку, второй параметр – это колонка, представленная в одном из вариантов, которые мы использовали в предыдущем коде.
Данные из массива будут загружаться по индексу, то есть первый элемент массива будет загружен в первую строку, второй – во вторую и так далее. Причём, обращаю внимание, если для колонки определены типы, то данные в массиве должны быть тех же типов, которые определены для колонки. Методу безразлично больше элементов в массиве или меньше, если элементов массива меньше, то будет загружено ровно столько, сколько есть, остальные строки таблицы останутся незаполненными.
Рассмотрим пример: создадим новую команду, в которой получим таблицу оплат, добавим в эту таблицу колонку Порядок, создадим массив, который заполним цифрами от 1 до 5, и загрузим этот массив в колонку Порядок.
&НаСервере
Процедура ЗагрузитьДанныеВКолонкуНаСервере()
ТаблицаОплат = СоздатьИЗаполнитьТаблицуОплатНаСервере(); ТаблицаОплат.Колонки.Добавить("Порядок");
Массив = Новый Массив; Для н = 1 по 5 цикл
Массив.Добавить(н); КонецЦикла;
ТаблицаОплат.ЗагрузитьКолонку(Массив,"Порядок"); КонецПроцедуры
Листинг 8.1.19
Думаю, нет смысла комментировать этот код. Сохраним обработку и посмотрим, как изменилась наша таблица.
Рис. 8.1.17
Вы видите, что новая колонка добавилась и заполнилась нужными нам значениями.
Самостоятельно уменьшите количество элементов массива до трёх и посмотрите, как заполнится новая колонка.
Заполнить значение
Представим, что в таблице оплат мы забыли создать колонку Валюта, которую необходимо заполнить значением Рубли. Как добавить новую колонку мы знаем. Но как заполнить всю колонку одним значением? Для этого используется метод ЗаполнитьЗначения.
Рассмотрим синтаксис данного метода:
ЗаполнитьЗначения(<Значение>, <Колонки>)
Первый параметр – это значение, которым мы будем заполнять колонки. Второй параметр – это список колонок через запятую. Второй параметр необязательный, если он пустой, то значение заполнит собой всю таблицу. Если указано несколько колонок, то значение будет заполнено во всех этих колонках. Если для колонок определены типы, то значение должно быть того же типа, который определён для колонок.
Доработаем наш предыдущий пример: создадим новую колонку Валюта и заполним значение в ней.
ТаблицаОплат.Колонки.Добавить("Валюта"); ТаблицаОплат.ЗаполнитьЗначения("Рубли","Валюта");
Листинг 8.1.20
Получение итогов
Очень часто бывает необходимо получить суммовой итог по какой-нибудь колонке. Например, по таблице ТаблицаОплат подсчитать общую сумму. Для этого нам пригодится метод Итог.
Синтаксис у этого метода простой:
Итог(<Колонка>)
Где параметр Колонка – имя колонки в виде строки.
Посмотрим, как он работает, допишем код в последней команде:
Сообщить("Общая сумма: " + ТаблицаОплат.Итог("Сумма"));
Листинг 8.1.21
Сохраните обработку, и запустите её заново. При выполнении команды
ЗагрузитьДанныеВКолонку должен выйти итог по всей колонке Сумма.
Сортировка
И напоследок научимся сортировать таблицу значений. Делается это достаточно просто, с помощью метода Сортировать.
Метод имеет следующий синтаксис:
Сортировать(<Колонки>)
У метода Сортировать только один параметр, который является обязательным, это список колонок через запятую. После каждого названия колонки можно указывать направление сортировки. Всего два направления – по убыванию и по возрастанию.
Сортировка по убыванию задаётся так:
ТаблицаОплат.Сортировать("ФИО Убыв");
А по возрастанию так:
ТаблицаОплат.Сортировать("ФИО Возр");
Когда сортировка ведётся по убыванию, после названия поля пишется слово «Убыв».
А когда сортировка ведётся по возрастанию, соответственно пишется слово «Возр».
Обращаю Ваше внимание, что сортировка ведётся в порядке очерёдности колонок, которые указаны в параметре, то есть если Вы первым полем указали ФИО, а потом Дата, то сначала произойдёт сортировка всех строк по ФИО, а потом внутри отсортированных строк произойдёт сортировка по Дате.
Потренируйтесь с сортировкой таблиц самостоятельно.
Итак, мы научились работать с таблицами значений, изучили большинство нужных нам методов. Рекомендую Вам, используя синтакс-помощник, ознакомиться с остальными
методами таблиц (они несложные и вполне доступны для понимания) для полного представления всех возможностей данного объекта.
Работа с таблицей значения на форме
Мы узнали, как работать с таблицей значений посредством встроенного языка 1С, то есть программно, в модуле формы (все примеры справедливы также и для других модулей). В заключительной части о таблице значений научимся работать с ней на форме, когда таблица значений представлена в виде реквизита формы и когда этот реквизит размещён на форме в виде Таблицы.
Создадим новую обработку, форму обработки, на форму добавим новый реквизит, тип которого будет ТаблицаЗначений.
Рис. 8.1.18
Но сама по себе таблица значений с отсутствующими колонками бесполезна. Для того чтобы добавить колонку в таблицу значений на форме, необходимо выделить реквизит (нашу таблицу значений) и нажать на кнопку Добавить колонку реквизита в командной панели окна реквизитов (см. рис. 8.1.19).
Рис. 8.1.19
После этих действий будет создана новая колонка таблицы значений, а справа откроется палитра свойств колонки, где можно задать название, заголовок, тип и т.д.
Рис. 8.1.20
Создадим следующие реквизиты таблицы значений ТаблицаОплат:
ДатаВыплаты (тип Дата)
ФИО (тип Строка(50))
Автомобиль (тип СправочникСсылка.Автомобили)
КоличествоЧасов (тип Число(10,1))
ЦенаЧаса (определяемый тип ТипДляЦен, см. стр. 235)
Сумма (определяемый тип ТипДляЦен, см. стр. 235)
Рис. 8.1.21
Мы создали реквизит формы ТаблицаОплат с типом ТаблицаЗначений, с этим реквизитом мы спокойно сможем работать в модуле формы (ниже мы научимся это делать).
Но сейчас нас интересует, как эта таблица значений будет отображаться на форме.
Для отображения таблиц значений на форме используется элемент формы Таблица. Добавим этот элемент на форму (см. рис. 8.1.22).
Рис. 8.1.22
После добавление элемента Таблица на представлении формы ничего не изменится.
Так произошло, потому что наша Таблица ещё не связана с реквизитом формы ТаблицаОплат и у неё не добавлены колонки. Привяжем элемент формы к реквизиту, выбрав нужную таблицу значений в свойстве ПутьКДанным элемента (см. рис. 8.1.23).
Рис. 8.1.23
После выбора будет предложено автоматически заполнить колонки, мы – откажемся для того, чтобы научиться добавлять колонки самостоятельно, поэтому после привязки элемента формы к реквизиту опять ничего не изменится. Чтобы таблица появилась на форме, необходимо добавить хотя бы одну колонку. Добавить колонку в таблицу на форму можно двумя способами. Первый – просто «перетащить» нужную колонку мышкой из реквизита на форму (см. рис. 8.1.24). Тогда колонка сразу отобразится на представлении формы (см. рис. 8.1.25).
Рис. 8.1.24
Рис. 8.1.25
Второй способ – необходимо выделить элемент формы Таблица1, а после добавить новый элемент формы Поле, выполнив команду Добавить (см. рис. 8.1.26). Будет добавлена
новая колонка элемента формы Таблица1, её необходимо связать с колонкой реквизита формы. Делается это в уже знакомом нам свойстве элемента формы ПутьКДанным (см. рис. 8.1.27).
Рис. 8.1.26
Рис. 8.1.27
В результате колонка отобразится на форме. Нужно будет только переименовать имя колонки на более понятное.
Добавьте самостоятельно все колонки (для тренировки сделайте сначала первым способом, а потом – вторым), чтобы получилась картинка как на рис. 8.1.29 (у колонки КоличествоЧасов измените заголовок).
Рис. 8.1.29
Мы научились создавать таблицу на форме, связывать её с реквизитом типа ТаблицаЗначений, добавлять колонки к таблице на форме и связывать их с соответствующими колонками нужной таблицы значений. Теперь освоим несколько приёмов оформления элемента Таблица на форме. И первый приём, который разберём, это группировка колонок.
При помощи группировки колонок можно сделать красивый вид таблицы на форме.
Колонки можно разместить или друг над другом, или в одной ячейке. Для группировки колонок используется элемент формы Группа с видом ГруппаКолонок. К слову, это единственный возможный вид элемента Группа для таблиц.
Для демонстрации возможности группировки колонок, объединим две колонки: ФИО и Автомобиль. Для того чтобы добавить группу колонок, необходимо выделить элемент формы Таблица1 и добавить элемент формы Группа – Группа колонок (см. рис. 8.1.30).
Группа колонок будет добавлена в конец таблицы в виде папки.
Рис. 8.1.31
После того как группа колонок будет добавлена в таблицу, её можно двигать по таблице при помощи кнопок Вверх и Вниз командной панели окна Элементы, а также мышкой «перетаскивать» нужные поля-колонки в группу. В нашем случае должен получиться следующий вид (сгруппируем колонки КоличествоЧасов и Сумма):
Рис. 8.1.32
Всего существует три варианта группировки: Горизонтальная, Вертикальная и В ячейке. Все эти варианты задаются в свойстве Группировка нужной группы (см. рис. 8.1.33).
Рис. 8.1.33
О том, как группируются колонки в случае Горизонтальной и Вертикальной группировки, понятно из названий. Группировку В ячейке целесообразнее применять, когда в таблице размещены колонки, привязанные к связанным реквизитам. Например, у реквизита Автомобиль имеется связанный реквизит ГосНомер. Разместим реквизит ГосНомер в таблице (см. рис. 8.1.34) и сгруппируем поля ввода для автомобиля и гос. номера так, чтобы вид группировки был В ячейке (см. рис. 8.1.35).
Рис. 8.1.34
Рис. 8.1.35
Поле, связанное с основным реквизитом (в нашем случае Автомобиль) должно располагаться первым в группе. Теперь если мы выберем в поле таблицы какой-нибудь автомобиль, то также отобразится и его гос. номер (см. рис. 8.1.36).
Рис. 8.1.36
Можно формировать разноуровневые группировки колонок, «перетаскивая» их мышкой, например, вот так:
Рис. 8.1.37
Мы научились создавать таблицы, заполнять их колонками и даже как-то группировать эти колонки. Этих знаний вполне хватит, чтобы начать работать с таблицами.
Программная работа с таблицей значения на форме
Мы узнали, как создавать реквизиты с типом ТаблицаЗначений, размещать их на форме в виде элемента Таблица и конфигурировать колонки этой таблицы. Осталось научиться работать непосредственно с реквизитом типа ТаблицаЗначений в модуле формы (в клиентском и серверном контексте). Тут есть одна особенность. Поскольку с таблицами значений можно работать только в серверном контексте, то платформа автоматически преобразует объект ТаблицаЗначений в объект ДанныеФормыКоллекция. Этот объект
предназначен для эмулирования коллекций значений при работе с ними в управляемой форме. И он доступен и в серверном, и клиентском контексте (включая тонкий клиент).
Когда мы задаём реквизиту формы какой-нибудь тип, который может работать только в серверном контексте (объект ТаблицаЗначений только один из них, все остальные мы не будем изучать в этой книге), то платформа всегда преобразует его в один из типов данных форм. Причём при работе в любом контексте: и серверном, и клиентском. Ознакомиться с этими объектами Вы сможете самостоятельно в синтакс-помощнике (по пути Интерфейс (управляемый) – Данные формы).
Проверим это утверждение: создадим на форме команду Записать в таблицу, разместим в командной панели таблицы, и для этой команды создадим обработчики на клиенте и на сервере. Поставим точки останова в обеих процедурах – обработчиках и посмотрим в табло, что представляет собой реквизит формы ТаблицаОплат (с типом ТаблицаЗначений) в клиентском (см. рис. 8.1.38) и в серверном (см. рис. 8.1.39) контексте.
Рис. 8.1.38
Рис. 8.1.39
Объект ДанныеФормыКоллекция – это коллекция некоторых значений, для которой доступен обход с помощью цикла Для каждого …. Цикл. Она имеет несколько стандартных
методов типа Добавить, Вставить, Очистить, НайтиСтроки и т.д. Мы не будем подробно разбирать все эти методы, со всеми методами этого объекта Вы сможете ознакомиться в синтакс-помощнике.
Если Вы имеете цель с помощью встроенного языка добавить какую-нибудь строку в реквизит формы с типом ТаблицаЗначений, или, наоборот, удалить, или отредактировать, то нет смысла получать каким-то образом саму таблицу значений (о том, как это сделать, – ниже), можно напрямую работать с объектом ДанныеФормыКоллекция. Сделаем простой пример: в уже созданном нами обработчике добавим при помощи встроенного языка пару строк в реквизит ТаблицаОплат (см. листинг 8.1.22). Для этих целей нам необязательно делать серверный вызов, мы всё можем сделать на клиенте (можете удалить серверную процедуру).
&НаКлиенте
Процедура ЗаписатьВТаблицу(Команда) НовСтр = ТаблицаОплат.Добавить(); НовСтр.ДатаВыплаты = ТекущаяДата(); НовСтр.ФИО = "Иванов И.И."; НовСтр.КоличествоЧасов = 10;
НовСтр.ЦенаЧаса = 500;
НовСтр.Сумма = НовСтр.КоличествоЧасов * НовСтр.ЦенаЧаса;
НовСтр = ТаблицаОплат.Добавить(); НовСтр.ДатаВыплаты = ТекущаяДата(); НовСтр.ФИО = "Петров С.В."; НовСтр.КоличествоЧасов = 20;
НовСтр.ЦенаЧаса = 1000;
НовСтр.Сумма = НовСтр.КоличествоЧасов * НовСтр.ЦенаЧаса; КонецПроцедуры
Листинг 8.1.22 Если мы выполним эту команду, то произойдёт заполнение таблицы на форме (см. рис.
8.1.40).
Рис. 8.1.40
Естественно, Вы заметили, что колонка Автомобиль не заполнена. Это было сделано намеренно, чтобы показать, как изменять реквизит формы с типом ТаблицаЗначений.
Для примера добавим на форму реквизит с типом СправочникСсылка.Автомобили, и разместим его на форме в виде поля ввода (см. рис. 8.1.41), а при изменении этого поля ввода будем перезаписывать колонку Автомобиль в реквизите ТаблицаОплат. Для этого создадим обработчик события ПриИзменении поля ввода (в клиентском контексте, см. рис. 8.1.42). А в обработчике напишем код, в котором будем заполнять колонку Автомобиль реквизита формы ТаблицаОплат (см. листинг 8.1.23).
Рис. 8.1.41
Рис. 8.1.42
&НаКлиенте
Процедура АвтомобильПриИзменении(Элемент) Если ТаблицаОплат.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Для Каждого стрТЗ из ТаблицаОплат Цикл стрТЗ.Автомобиль = Автомобиль;
КонецЦикла;
КонецПроцедуры
Листинг 8.1.23
Мы просто обходим реквизит формы ТаблицаОплат и в каждой итерации цикла заполняем колонку Автомобиль значением из одноимённого поля. Самостоятельно проверьте работу этого метода.
Научимся получать таблицу значений из объекта ДанныеФормыКоллекция и, наоборот, загружать таблицу значений в объект ДанныеФормыКоллекция. Сделать обе операции можно двумя способами. Первый способ: с помощью метода управляемой формы РеквизитФормыВЗначение получить из реквизита таблицу значения, а потом, обработав её, загрузить обратно в реквизит при помощи метода ЗначениеФормыВРеквизит.
Второй способ: получить таблицу значения, используя метод коллекции Выгрузить, а потом, обработав её, загрузить обратно при помощи метода коллекции Загрузить.
Для того чтобы понять, как работают оба способа, сделаем одну задачку: будем сворачивать таблицу значения, суммируя поля КоличествоЧасов и Сумма. Для этого создадим две команды: Свернуть первым способом и Свернуть вторым способом с обработчиками в клиентском и серверном контексте. Для красивого расположения команд в командной панели создадим группу Подменю (см. рис. 8.1.43).
Рис. 8.1.43
И «перетащим» в эту группу обе команды (которые нужно сделать самостоятельно).
Заголовок для группы будет – Сворачивать. Если всё правильно сделали, то должна получиться такая же красивая картинка, как на рис. 8.1.44.
Рис. 8.1.44
В серверном обработчике команды Свернуть первым способом напишем код, в котором будем сворачивать таблицу значений при помощи методов формы (см. листинг 8.1.24), а в серверном обработчике другой команды напишем код, в котором свернём таблицу значений при помощи методов коллекции (см. листинг 8.1.25).
&НаСервере
Процедура СвернутьПервымСпособомНаСервере()
ТаблицаДляСвертки = РеквизитФормыВЗначение("ТаблицаОплат"); ТаблицаДляСвертки.Свернуть("ДатаВыплаты,ФИО,Автомобиль,ЦенаЧаса",
"КоличествоЧасов,Сумма"); ЗначениеВРеквизитФормы(ТаблицаДляСвертки," ТаблицаОплат");
КонецПроцедуры
&НаКлиенте
Процедура СвернутьПервымСпособом(Команда) СвернутьПервымСпособомНаСервере();
КонецПроцедуры
Листинг 8.1.24
&НаСервере
Процедура СвернутьВторымСпособомНаСервере() ТаблицаДляСвертки = ТаблицаОплат.Выгрузить();
ТаблицаДляСвертки.Свернуть("ДатаВыплаты,ФИО,Автомобиль,ЦенаЧаса",
"КоличествоЧасов,Сумма"); ТаблицаОплат.Загрузить(ТаблицаДляСвертки);
КонецПроцедуры
&НаКлиенте
Процедура СвернутьВторымСпособом(Команда) СвернутьВторымСпособомНаСервере();
КонецПроцедуры
Листинг 8.1.25
С методом формы РевизитФормыВЗначение мы знакомы, он создаёт переменную того типа, который указан в реквизите на форме. Таким образом, любую переменную из данных форм при помощи этого метода можно преобразовать в изначальный тип.
А метод ЗагрузитьВРеквизитФормы выполняет обратную функцию: загружает какую-либо переменную в реквизит формы. Причём переменная должна быть того же типа, который указан у реквизита.
С методами коллекции данных формы Выгрузить и Загрузить всё понятно.
Ознакомьтесь с ними самостоятельно в синтакс-помощнике.
На этом наше изучение таблиц значений закончилось, Вы много усвоили и поняли в этой главе, и данная информация очень пригодится для дальнейшей работы.
А работать Вы с ними будете часто, поэтому не бойтесь применять таблицы значений.
Если Вы раньше писали на другом языке программирования (например, Паскаль), то у Вас будет огромное желание использовать массивы, это делать нежелательно, поскольку таблицы значений суть динамический двумерный массив, который гораздо удобнее использовать в своей работе. Замечу, что точно такие же методы, как и методы таблиц значений, имеют многие коллекции значений. Поэтому если Вы хорошо научитесь работать с таблицами значений, то освоить остальные коллекции не составит особого труда.
В предыдущей части этой главы мы научились работать с таблицами значений, в этом разделе разберём, как работать с табличными частями справочников и документов. Из четвёртой главы Вы знаете, что у любого справочника и документа можно сконструировать табличную часть, в которой будут храниться какие-нибудь перечисленные сущности.
Вспомним, как выглядят табличные части справочников и документов.
Для этого в конфигурации, в которой мы работаем и которую создали ранее, развернём справочник Автомобили. Внутри этого справочника имеется элемент узла Табличные части, развернём этот элемент.
Рис. 8.2.1
Внутри узла Табличные части имеется единственная табличная часть – ДополнительныеОпции, у которой только один реквизит – это Опция. В платформе 1С 8.3 у объектов можно создавать несколько табличных частей и неограниченное количество реквизитов в них. Посмотрим, каким образом табличная часть выглядит на форме. Откроем форму элемента справочника (если она создана; если нет, то создайте самостоятельно).
На форме присутствует уже знакомый элемент Таблица с именем ДополнительныеОпции и с двумя колонками (см. рис. 8.2.2). Откроем палитру свойств этого элемента и обратим внимание на свойство ПутьКДанным (см. рис. 8.2.3).
Рис. 8.2.2
Рис. 8.2.3
Обратите внимание, что в свойстве ПутьКДанным указано
Объект.ДополнительныеОпции, раскроем это свойство (см. рис. 8.2.4).
ДополнительныеОпции входит в состав основного реквизита формы Объект, тип которого СправочникОбъект.Автомобили. Если бы у нас была ещё одна табличная часть, она бы тоже присутствовала.
В управляемом приложении принципы работы с табличной частью объекта (документа или справочника) посредством управляемой формы напрямую отличаются. Поэтому мы сначала научимся работать с табличной частью напрямую, получая её из какого-то объекта, а потом – используя управляемую форму.
Работа с табличной частью
Демонстрацию, как работать с табличными частями объектов (мы будем тренироваться на документах), проведём на решении следующей задачи. Оператор на форме обработки забивает в таблицу данные о ценах на топливо разных поставщиков. После того как все данные введены (они могут быть введены хаотично), оператор выполняет команду Создать документы, в результате этих действий будут созданы документы Установка цен на топливо. Причём документов будет создано столько, сколько в целом введено поставщиков в таблицу. Например, в таблице десять строк, в трёх из них – информация по поставщику ТопливоОйл, а в остальных – по поставщику НефтьСэйл. В этом случае должно быть создано два документа Установка цен на топливо. Для каждого поставщика – свой документ.
Для реализации задачи создадим обработку, форму обработки, на форме обработки создадим реквизит ДанныеПоЦенам с типом ТаблицаЗначений, у которой будут следующие поля:
Поставщик (тип СправочникСсылка.Контрагенты)
ТипТоплива (тип СправочникСсылка.ТипыТоплива)
Цена (тип ОпределяемыйТип.ТипДляЦен)
На форме также будет создана команда Создать документы.
Создадим обработчики команды в серверном и клиентском контексте. В серверном контексте реализуем следующий алгоритм:
сгруппируем всех поставщиков в отдельную таблицу;
для каждого поставщика из сгруппированной таблицы создадим отдельный документ
Установка цен на топливо;
заполним табличную часть созданного документа ценами на топливо для соответствующего поставщика;
сохраним и проведём документ.
В листинге к коду ниже даны пояснения, поэтому отдельных комментариев к этому коду не будет.
&НаСервере
Процедура СоздатьДокументыНаСервере(ДатаДокумента)
//получаем таблицу значения с формы, выгрузив её
//из объекта ДанныеФормыКоллекция ТЗ_ДанныеПоЦенам = ДанныеПоЦенам.Выгрузить();
//создаем новую таблиц значения при помощи метода
//Скопировать, причем в этой таблице будет только поставщик ТЗ_Поставщиков = ТЗ_ДанныеПоЦенам.Скопировать(,"Поставщик");
//сворачиваем ТЗ_Поставщиков.Свернуть("Поставщик");
//обходим свернутую таблицу поставщиков
Для каждого стрПоставщик Из ТЗ_Поставщиков Цикл
//создаем новый документ
НовДокумент = Документы.УстановкаЦенНаТопливо.СоздатьДокумент(); НовДокумент.Дата = ДатаДокумента;
НовДокумент.Поставщик = стрПоставщик.Поставщик;
//отбираем цены и типы цен для поставщика конкретного поставщика МассивЦен = ТЗ_ДанныеПоЦенам.НайтиСтроки(Новый
Структура("Поставщик",стрПоставщик.Поставщик));
//обходим отобранные цены
Для каждого стрЦена Из МассивЦен Цикл
//добавляем новые строки в табличную часть документа НовСтрокаТабЧасти = НовДокумент.ЦеныТоплива.Добавить(); ЗаполнитьЗначенияСвойств(НовСтрокаТабЧасти,СтрЦена);
КонецЦикла;
НовДокумент.Комментарий = "#Создан из обработки ввода данных"; Попытка
//проводим документ НовДокумент.Записать(РежимЗаписиДокумента.Проведение)
Исключение
Сообщить(СтрШаблон("Не удалось записать документ установки цен для поставщика %1", Строка(стрПоставщик.Поставщик)));
КонецПопытки;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура СоздатьДокументы(Команда)
//если таблица пустая, то выйдем из клиентского обработчика Если ДанныеПоЦенам.Количество() = 0 Тогда
Возврат;
КонецЕсли;
СоздатьДокументыНаСервере(ТекущаяДата()); КонецПроцедуры
Листинг 8.2.1
Проясним некоторые моменты.
Получить доступ к табличной части документа или справочника достаточно просто: обращение к ней идёт, как к свойству (по имени) у переменной ссылочного или объектного типа (точка, а после название табличной части). После этого мы получаем объект, общее название которого будет ТабличнаяЧасть. Не будем вдаваться в особенности этого объекта, отметим только, что он имеет почти все те же методы, которые мы изучали у таблиц значений: Добавить, Вставить, Итог, НайтиСтроки и т.д., с тем же принципом работы.
Когда мы используем метод Добавить табличной части, то создаётся новая строка табличной части объекта, которую мы впоследствии заполняем при помощи метода глобального контекста ЗаполнитьЗначенияСвойств. Эта процедура заполняет данные в первом параметре по данным из второго параметра. Данные сопоставляются по названиям и по типам.
Проверьте самостоятельно работу этого кода, если Вам не понятен принцип работы с табличными частями, зайдите в отладку и посмотрите на значение переменной НовДокумент.ЦеныТоплива.
Если Вы будете хорошо тестировать этот код, то обнаружите «баг» – ошибку: если мы на форму обработки введём несколько одинаковых строк, то не сможем провести документ.
Рис. 8.2.6
Для устранения «бага» сделаем небольшую интерфейсную доработку формы обработки.
Для того чтобы избежать ситуации, когда у одного поставщика на один вид топлива пользователь может ввести две разных цены, реализуем проверку после ввода значения в
любое поле. Для этого будем использовать событие элемента формы Таблица – ПередОкончаниемРедактирования. Этот обработчик вызывается перед окончанием редактирования строки, и у него имеется параметр Отказ, и если этот параметр принимает значение Истина, то редактирование не будет закончено.
Создадим на форме обработки обработчик ПередОкончаниемРедактирования
элемента формы-таблицы ДанныеПоЦенам, в котором напишем следующий код:
&НаКлиенте
Процедура ДанныеПоЦенамПередОкончаниемРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ЗначениеЗаполнено(ТекущиеДанные.Поставщик) и ЗначениеЗаполнено(ТекущиеДанные.ТипТоплива) и ЗначениеЗаполнено(ТекущиеДанные.Цена) тогда
Отказ = ЕстьСтрокиДляПоставщикаИТоплива(ТекущиеДанные.Поставщик,
ТекущиеДанные.ТипТоплива);
Если Отказ Тогда
Сообщить("Нельзя создавать дубли строк!"); КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Функция ЕстьСтрокиДляПоставщикаИТоплива(Поставщик, ТипТоплива) СтруктураОтбора = Новый Структура; СтруктураОтбора.Вставить("Поставщик",Поставщик); СтруктураОтбора.Вставить("ТипТоплива",ТипТоплива);
МассивОтбора = ДанныеПоЦенам.НайтиСтроки(СтруктураОтбора); Возврат ?(МассивОтбора.Количество() >= 2, Истина, Ложь);
КонецФункции // ЕстьСтрокиДляПоставщикаИТоплива()
Листинг 8.2.2
Разберём этот код. В процедуре-обработчике ДанныеПоЦенамПередОкончаниемРедактирования мы получаем текущие данные строки таблицы формы. Делаем это с помощью параметра обработчика Элемент, в котором содержится ссылка на элемент формы, к которому привязан обработчик. ТекущиеДанные – это свойство таблицы, которое предоставляет доступ к текущим данным строки.
Следующим шагом мы проверяем, все ли колонки текущей строки заполнены. А в функции ЕстьСтрокиДляПоставщикаИТоплива проверяем, есть ли уже строки для текущей комбинации Поставщик-Топливо. С помощью метода НайтиСтроки объекта ДанныеФормыКоллекция мы узнаем, сколько уже есть строк с заданной комбинацией. И если их больше двух (т.е. уже ввели лишнию), то отказываем в окончании редактирования.
Работа с табличной частью на управляемой форме
В начале этой части мы узнали, что табличные части справочников и документов присутствуют на форме в виде уже знакомого Вам элемента формы Таблица. У этого
элемента в свойстве ПутьКДанным указан путь к табличной части объекта через основной реквизит формы Объект. Посмотрим в отладке, какой тип имеет объект вид Объект.<НазваниеТабличнойЧасти>. Для этого мы возьмём форму документа Установка цен на топливо, на которой размещена таблица ЦеныТоплива, связанная с табличной частью документа ЦеныТоплива (см. рис. 8.2.7).
Рис. 8.2.7
Чтобы узнать, какой тип у выражения вида Объект.ЦеныТоплива, установим точку останова в конце события ПриОткрытии и посмотрим на значение этого выражения в отладке (см. рис. 8.2.8).
Рис. 8.2.8
Как видно из рисунка выше, табличная часть доступна посредством уже знакомой нам коллекции ДанныеФормыКоллекция. Поэтому нет никаких особых сложностей по работе с табличной частью на управляемой форме: мы просто изменяем коллекцию, а после сохранения документа эти изменения запишутся непосредственно в табличную часть документа автоматически.
Для того чтобы понять, как это всё работает, выполним несколько простых заданий.
Первое задание будет следующим: создадим на форме команду, и в результате выполнения этой команды по всей табличной части будет устанавливаться одинаковая цена. Цену эту пользователь будет вводить при помощи метода ПоказатьВводЧисла.
Первым делом доработаем форму документа Установка цен на топливо: создадим подменю Заполнить в командной панели таблицы ЦеныТоплива (см. рис. 8.2.9), создадим команду Установить одинаковую цену, которую поместим в подменю Заполнить (см. рис. 8.2.10.
Рис. 8.2.9
Рис. 8.2.10
У команды Установить одинаковую цену создадим обработчик в клиентском контексте, в котором напишем следующий код:
Процедура УстановитьОдинаковуюЦену(Команда)
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВводаЧисла",ЭтаФорма);
ПоказатьВводЧисла(ОписаниеОповещения,0,"Введите новую цену");
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаЧисла(ВведенноеЧисло, ДополнительныеПараметры) Экспорт Если ВведенноеЧисло = Неопределено Тогда
Возврат; //отказались ввести число КонецЕсли;
Для каждого стрЦен Из Объект.ЦеныТоплива Цикл стрЦен.Цена = ВведенноеЧисло;
КонецЦикла; Модифицированность = Истина;
КонецПроцедуры
Листинг 8.2.3 В листинге 8.2.3 пользователь вводит число при помощи немодального метода
ПоказатьВводЧисла, после того как число будет введено (или произойдёт отказ от ввода
числа) этот метод вызовет экспортную процедуру ПослеВводаЧисла. В процедуре ПослеВводаЧисла мы обходим коллекцию Объект.ЦеныТоплива и изменяем каждый элемент коллекции. Чтобы пользователь увидел, что данные на форме изменились, устанавим свойству формы Модифицированность значение Истина.
Самостоятельно сделайте команды, которые будут прибавлять к цене определённое число (вводит пользователь) и вычитать из цены определённое число (тоже вводит пользователь).
С коллекцией данных формы можно делать почти всё что угодно: добавлять строки, удалять строки, очищать всю таблицы и т.д. Реализуем небольшой пример, чтобы показать, как работает добавление строк: будем заполнять табличную часть документу Установка цен на топливо всеми типами топлива. На форме документа сделаем команду Заполнить всеми типами цен, которую разместим в уже созданной группе подменю Заполнить. Для этой команды создадим обработчики на клиенте и на сервере. В серверном обработчике будет следующий код:
&НаСервере
Процедура ЗаполнитьВсемиТипамиЦенНаСервере() Объект.ЦеныТоплива.Очистить();
Выборка = Справочники.ТипыТоплива.Выбрать(); Пока Выборка.Следующий() Цикл
НовТипЦен = Объект.ЦеныТоплива.Добавить(); НовТипЦен.ТипТоплива = Выборка.Ссылка;
КонецЦикла; Модифицированность = Истина;
КонецПроцедуры
Процедура ЗаполнитьВсемиТипамиЦен(Команда) ЗаполнитьВсемиТипамиЦенНаСервере();
КонецПроцедуры
Листинг 8.2.4
В процедуре ЗаполнитьВсемиТипамиЦенНаСервере мы получаем выборку цен (подробно выборки будем изучать в следующей главе), обходим эту выборку и в каждой итерации создаём новую строку коллекции данных формы, у которой точно такие же колонки, как и у табличной части документа, и у реквизита Объект.ЦеныТоплива.
Потренируйтесь с последней командой. Например, можете ввести цену на топливо при помощи уже знакомого Вам немодального метода ПоказатьВводЧисла.
На этом мы закончим изучать работу с табличными частями справочников и документов. Кроме справочников и документов, табличные части могут быть у планов, видов характеристик, обработок и т.д. Принципы работы с табличными частями других метаданных точно такие же, как и при работе с табличными частями документов и справочников.
Мы изучили основы работы с таблицами значений и табличными частями справочников и документов. Все эти объекты на форму выводятся в виде элемента формы Таблица. В заключительной части текущей главы мы изучим некоторые особенности работы с этим элементом.
Работа с подвалом таблицы
У каждой таблицы формы есть возможность вывести подвал – область в нижней части таблицы. Для того чтобы научиться работать с подвалом таблицы, откроем форму документа Отчет о расходе топлива (если её нет, то создайте самостоятельно), откроем палитру свойств таблицы Автомобили и обратим внимание на свойство Подвал (см. рис. 8.3.1). По умолчанию оно всегда выключено.
Рис. 8.3.1
Включим это свойство и обратим внимание на то, что внизу таблицы появится область (см. рис. 8.3.2).
Рис. 8.3.2
Сам по себе подвал не очень интересен, но в нём имеется возможность размещать различную информацию. Зайдём в палитру свойств поля Автомобиль таблицы формы. В этой палитре нас интересуют два свойства – ТекстПодвала и ПутьКДаннымПодвала (см. рис.
8.3.3).
Рис. 8.3.3
В свойстве ТекстПодвала можно размещать какой-либо статичный текст, а в свойстве ПутьДаннымПодвала можно указывать различные динамические данные (например, сумму по всем строкам). Для демонстрации этих возможностей выполним небольшую задачу: на форме документа Отчет о расходе топлива в подвале колонки Автомобиль должен быть текст «Итог по всем автомобилям», а в подвале колонки Количество – общая сумма по всем строкам.
С первым требованием проблем у Вас возникнуть не должно: просто напишем нужный текст в свойстве ТекстПодвала поля Автомобиль (см. рис. 8.3.4).
Рис. 8.3.4
Займёмся колонкой Количество. Откроем палитру свойств этой колонки и нажмём на кнопку «…» свойства ПутьКДаннымПодвала. Откроется окно выбора реквизита (см. рис.
8.3.5).
Рис. 8.3.5
В этом окне два узла – Объект и Элементы. Узел Объект – это основной реквизит формы, можно выбрать любое свойство этого реквизита (например, Дата или Комментарий, см. рис. 8.3.6).
В узле Элементы можно выбрать данные по текущей строке редактируемой таблицы (см. рис. 8.3.7). Например, можно сделать, чтобы в подвале всегда отображался автомобиль той строки, на которой в данный момент установлен курсор.
Рис. 8.3.6
Рис. 8.3.7
Вернёмся обратно к объекту и развернём узел Автомобили. В этом узле нас интересует пункт ИтогКоличество.
Рис. 8.3.8
У таблиц табличных частей справочников и документов имеется возможность получать итоги по всем реквизитом, у которых тип Число.
Выберем этот пункт в свойстве ПутьКДаннымПодвала (см. рис. 8.3.9).
Рис. 8.3.9
Сохраним конфигурацию, обновим базу данных и откроем форму документа Отчет о расходе топлива, чтобы посмотреть, как заполняется подвал формы (см. рис. 8.3.10).
Рис. 8.3.10
А для табличной части документа Установка цен на топливо самостоятельно сделайте подвал, как на рис. 8.3.11 (данные по текущей строке).
Рис. 8.3.11
Текущий элемент
Часто возникает потребность совершить какие-либо операции над текущей строкой
таблицы или получить информацию из текущей строки. Для реализации подобных задач необходимо работать со свойствами ТекущиеДанные и ТекущаяСтрока таблиц.
Свойство ТекущиеДанные имеет тип ДанныеФормыЭлементКоллекции, посредством этого свойства можно получить доступ к данным текущей строки. А свойство ТекущаяСтрока – это идентификатор текущей строки.
На рис. 8.3.12 можно увидеть, какие данные хранятся в обоих свойствах.
Рис. 8.3.12
Обратите внимание, свойство ТекущаяСтрока – это не индекс строки и не её порядковый номер. Как работать с этим свойством, мы узнаем ниже.
Разберём простенький пример, как работать с текущими данными таблицы. Для его реализации создайте обработку, форму обработки, а на форме создадим два реквизита: реквизит ТаблицаАвтомобилей с типом таблица значений (одна колонка Автомобиль (тип СправочникСсылка.Автомобили), в свойство реквизита Проверка заполнения установите значение Выдавать ошибку) и реквизит КоробкаПередач с типом ПеречислениеСсылка.КоробкаПередач (в свойство реквизита Проверка заполнения установите значение Выдавать ошибку). А также команду Поменять коробку передач. При выполнении этой команды будем менять коробку передач у автомобиля в текущей строке.
Рис. 8.3.13
Заполним таблицу значений в обработчике формы ПриСозданииНаСервере (см. листинг 8.3.1).
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Выборка = Справочники.Автомобили.Выбрать(); Пока Выборка.Следующий() Цикл
НовСтр = ТаблицаАвтомобилей.Добавить(); НовСтр.Автомобиль = Выборка.Ссылка;
КонецЦикла;
КонецПроцедуры
Листинг 8.3.1
Создадим обработчик команды Поменять коробку передач в клиентском и в серверном контексте и напишем следующий код.
&НаСервере
Процедура ПоменятьКоробкуПередачНаСервере(Автомобиль)
АвтомобильОбъект = Автомобиль.ПолучитьОбъект(); АвтомобильОбъект.КоробкаПередач = КоробкаПередач; Попытка
АвтомобильОбъект.Записать(); Сообщить("Коробку заменили успешно");
Исключение
Сообщить("Не удалось поменять коробку передач"); КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура ПоменятьКоробкуПередач(Команда)
Если Не ПроверитьЗаполнение() Тогда Возврат;
КонецЕсли;
ТекущиеДанные = Элементы.ТаблицаАвтомобилей.ТекущиеДанные; Если Не ЗначениеЗаполнено(ТекущиеДанные.Автомобиль) Тогда
Сообщить("Не заполнен автомобиль в текущей строке"); Возврат;
КонецЕсли;
ПоменятьКоробкуПередачНаСервере(ТекущиеДанные.Автомобиль); КонецПроцедуры
Листинг. 8.3.2
Вы этот код должны разобрать без проблем.
Перейдём к свойству ТекущаяСтрока. Для чего нужно это свойство? С его помощью мы можем связывать текущие данные элемента формы с данными, которые хранятся в реквизите формы (они не всегда совпадают!) Научимся это делать. Для примера реализуем следующий пример: в документе Установка цен на топливо создадим команду Увеличить
текущую цену в 2 раза и при выполнении команды будем увеличивать цену текущей строки таблицы в 2 раза.
Создадим команду формы документа Установка цен на топливо и разместим её в группе Заполнить командной панели таблицы Цены (см. рис. 8.3.14).
Рис. 8.3.14
У этой команды создадим обработчик на клиенте, при её выполнении будем увеличивать цену текущей строки в 2 раза (см. листинг 8.3.3).
&НаКлиенте
Процедура УвеличитьТекущуюЦенуВ2х(Команда) Идентификатор = Элементы.ЦеныТоплива.ТекущаяСтрока; Если Идентификатор = Неопределено Тогда
Возврат;
КонецЕсли;
ТекущиеДанные = Объект.ЦеныТоплива.НайтиПоИдентификатору(Идентификатор); Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ТекущиеДанные.Цена = ТекущиеДанные.Цена * 2; КонецПроцедуры
Листинг 8.3.3
Разберём этот код.
В первой строке мы получили свойство таблицы формы ТекущаяСтрока, это свойство содержит или идентификатор текущей строки, или значение Неопределено, если нет текущей строки.
Следующим шагом проверяем, не вернуло ли свойство ТекущаяСтрока значение
Неопределено, и если вернуло, то выходим из процедуры.
После мы ищем текущую строку непосредственно у реквизита – табличной части ЦеныТоплива, то есть в данных формы. Делаем мы это при помощи метода НайтиПоИдентификатору знакомого нам объекта ДанныеФормыКоллекция. Этот метод имеет один параметр – это идентификатор строки, которую нужно найти, и возвращает или значение Неопределено, если строка с таким идентификатором в коллекции не найдена, или тип ДанныеФормыЭлементКоллекции, посредством которого мы получаем доступ к элементам конкретного реквизита. Мы на всякий случай проверяем, не вернул ли метод НайтиПоИдентификатору значение Неопределено.
И в последнем шаге мы рекурсивно изменяем значение одного из свойств элемента коллекции.
Самостоятельно поработайте с текущей строкой. Сделайте команды, которые уменьшают текущую цену в 2 раза, вычитают из неё 1 рубль и т.д.
На этом мы закончим изучать работу с таблицами. Мы изучили одну из основных коллекций значений прикладного языка 1С – таблицу значений. Таблицы значений очень часто применяются при разработке тех или иных задач, поэтому данный объект нужно знать и уметь с ним работать. Также нужно понимать, как работает этот объект на управляемой форме. Поскольку таблица значений не может существовать в тонком клиенте, то на форме осуществляется работа с объектом ДанныеФормыКоллекция. Вы узнали, как работать с табличными частями метаданных (документов, справочников и т.д.) и как они отображаются на форме (в виде уже знакомого нам объекта ДанныеФормыКоллекция). А также освоили некоторые приёмы работы с элементом формы Таблица: научились делать подвал и заполнять его данными, а также работать с текущей строкой. Все эти знания пригодятся Вам в практической работе.
9.01 Глава 9. Получение данных. Часть 1. Понятие выборки - что такое Выборка?
В этой главе мы научимся получать данные из базы. Что понимается под получением данных из базы?
В дальнейшем под этим термином будем понимать получение любого набора элементов справочников, документов, записей регистров сведений, накопления и регистров бухгалтерии.
В этой главе мы научимся получать выборки данных для документов и справочников.
С регистрами накоплений и сведений мы будем разбираться в следующей главе.
В превой части этой главы научимся получать данные, используя методы менеджеров объектов, а во второй части научимся получать данные с помощью запросов.
## 9.02 Часть 1. Понятие выборки
Начнём с выборки данных.
Выборка – это специализированный способ перебора чего-либо. В языке программирования 1С существует много видов выборки, мы рассмотрим два из них – это Выборка документов и Выборка справочников.
9.02 Выборка справочников - что это?
Изучим Выборку справочников.
Выборка справочников
Выборка справочников – это объект, который представляет собой специализированный способ перебора элементов справочника. Выборка является динамическим объектом, то есть она не получает все элементы справочника сразу, а получает их порциями, что позволяет достаточно быстро обходить справочники, состоящие из большого количества элементов.
9.03 какими методами можно получить Выборка справочников?
Выборка справочников возвращается двумя методами менеджера справочника, это: Выбрать
и Выбрать иерархически.
Разберём оба этих метода.
Метод Выбрать
Метод Выбрать объекта Справочник менеджер формирует некоторую выборку данных по заданным условиям. Этот метод является функцией и возвращает объект Выборка справочника.
Метод Выборка имеет следующий синтаксис:
Выбрать(<Родитель>, <Владелец>, <Отбор>, <Порядок>)
Все параметры являются необязательными.
Родитель – применим для иерархических справочников. Если он указан, то будут выбраны только те элементы справочника, у которых в свойстве Родитель содержится указанный элемент. Если параметр пуст, то выберутся все элементы справочника. Чтобы выбрать элементы только верхнего уровня, необходимо указать в качестве Родителя пустую ссылку.
Владелец – применим для работы с подчинёнными справочниками. Когда параметр указан, то будет осуществлена выборка всех элементов, которые подчинены указанному владельцу.
Отбор. Вот на этом параметре мы остановимся поподробнее. Параметр Отбор представляет собой структуру, в которой мы можем задать критерий, по которому будет отфильтрована полученная выборка. Ключом элемента структуры должно быть название поля, по которому выборка будет отфильтрована, а значение структуры – непосредственно то значение, по которому должен будет произвестись отбор. В выборках структура должна содержать только один элемент! Отбор можно осуществить только по одному реквизиту.
Обращаю Ваше внимание, что в качестве полей для отбора могут быть заданы только те поля, у которых в свойстве Индексировать установлено либо значение Индексировать, либо Индексировать с дополнительным упорядочиванием. Посмотрим, где это свойствоа находится. Откроем палитру свойств реквизита КоробкаПередач справочника Автомобили и обратим внимание на свойство Индексировать.
Рис. 9.1.1
У этого свойства установлено значение Не индексировать. Поменяем его на значение
Индексировать.
Рис. 9.1.2
Теперь мы реквизит КоробкаПередач справочника Автомобили сможем использовать
в отборах для выборок того же справочника. Таким образом, если мы хотим в выборке осуществить отбор по какому-то реквизиту, то у этого реквизита в свойстве Индексировать должно быть установлено значение Индексировать. Поэтому прежде чем делать какую- нибудь выборку с отбором, обратите внимание на это свойство для отбираемого реквизита. И только после принимайте решение об использовании отбора. Если реквизит не является индексируемым, а Вам всё равно необходимо получить выборку с отбором по этому реквизиту, то необходимо использовать язык запросов. О нём мы поговорим во второй части текущей главы. Существуют всего два реквизита, которые могут свободно быть использованы в отборе без каких-либо условий, это реквизиты Код и Наименование (стандартные реквизиты).
И последний, тоже интересный параметр – это Порядок. Параметром Порядок является строка с именем реквизита, по которому будет упорядочена выборка. В этом параметре свободно могут быть указаны поля Наименование и Код, а также поля примитивных типов (Число, Строка, Дата, Булево), для которых в свойство Индексировать установлено или значение Индексировать, или Индексировать с дополнительным упорядочиванием. Сортировка данных будет осуществлена по возрастанию, но можно провести и сортировку по убыванию, написав в конце строки слово «Убыв».
Например, так:
"Код Убыв"
Также можно и задать сортировку по возрастанию, написав в конце строки слово
«Возр».
"Код Возр"
Итак, все параметры мы изучили, теперь осталось применить это на практике. Для этого сначала сделаем простую выборку справочника Гаражи, а потом выборку с иерархией. Результаты выборки будем выводить в таблицу значений, которая будет реквизитом формы.
На основе данных примеров Вы научитесь работать с выборками.
Создадим новую обработку, форму обработки, на которой создадим реквизит ТаблицаГаражей с типом ТаблицаЗначений. У этой таблицы будет одна колонка – Гараж (тип ссылка на справочник Гаражи). Саму таблицу значений разместим на форме в виде элемента Таблица. Также создадим команду Заполнить таблицу, которую разместим в командной панели таблицы на форме.
Рис. 9.1.3
Создадим обработчики команды Заполнить таблицу, и напишем следующий код:
&НаСервере
Процедура ЗаполнитьТаблицуНаСервере() ВыборкаГаражей = Справочники.Гаражи.Выбрать(); Пока ВыборкаГаражей.Следующий() Цикл
НоваяСтрока = ТаблицаГаражей.Добавить(); НоваяСтрока.Гараж = ВыборкаГаражей.Ссылка;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицу(Команда) ЗаполнитьТаблицуНаСервере();
КонецПроцедуры
Листинг 9.1.1 Разберём код выше. В первой строке процедуры ЗаполнитьТаблицуНаСервере мы
получаем выборку элементов справочника Гаражи при помощи метода Выбрать.
Метод Следующий, который используется во второй строке, нам ещё незнаком. Данный метод получает следующий элемент выборки. Дело в том, что любая выборка представляет собой совокупность элементов, которые были выбраны. Обращаться к этим элементам можно непосредственно через ту переменную, в которую выборка записана. В нашем случае – это переменная ВыборкаГаражей. Но, когда мы только получили выборку с помощью метода Выбрать, выборка ещё не спозиционирована ни на каком элементе.
Поэтому, чтобы спозиционировать выборку на первом элементе, необходимо использовать метод Следующий, потом, чтобы спозиционировать уже на втором элементе, опять нужно использовать метод Следующий, и так далее, пока не наступит конец выборки. Метод Следующий является функцией и возвращает значение Истина, если элемент выбран, и значение Ложь – в том случае, когда достигнут конец выборки. Если нам необходим только первый элемент выборки, достаточно написать вот так:
ВыборкаГаражей = Справочники.Гаражи.Выбрать(); ВыборкаГаражей.Следующий();
После того как элемент выборки выбран, то можно обратиться к нему как к элементу справочника. Как следствие, мы можем получить доступ к значению в реквизите справочника выбранного элемента и можем их использовать в дальнейшей работе. Сама переменная ВыборкаГаражей имеет тип СправочникВыборка.Гаражи, посредством этого типа можно прочитать все реквизиты того элемента, на котором выборка позиционирована.
Рис. 9.1.4
Вот почему в примере выше мы получили ссылку на элемент справочника, обратившись к выборке.
Если бы нам надо было получить наименование элемента справочника или код, то мы тоже легко смогли бы это сделать:
Наименование = ВыборкаГаражей.Наименование; Код = ВыборкаГаражей.Код;
Если в нашем коде поставить точку после переменной ВыборкаГаражей, то появится
контекстная подсказка, в которой перечислены все реквизиты справочника.
Рис. 9.1.5
9.04 как правильно получать реквизит справочника?
Важно! Обращайтесь к реквизиту именно через выборку, а не через ссылку на объект.
Так Вы существенно оптимизируете свой код!
Правильно: ВыборкаГаражей.Наименование. Неправильно: ВыборкаГаражей.Ссылка.Наименование.
У выборки справочника есть ещё один метод – ПолучитьОбъект. С помощью данного метода мы получаем объект того элемента, на котором в данный момент спозиционирована выборка.
ВыборкаСкладов.ПолучитьОбъект();
Этот метод возвращает объект справочника или документа.
Чтобы изучить более подробно метод Выбрать, доработаем справочник Гаражи.
Добавим в него два реквизита, это реквизит ТолькоЛегковыеАвтомобили (тип Булево, неиндексируемый) и реквизит ВремяНачалаРаботыГаража (тип Дата, состав даты – Время, индексируемый).
Рис. 9.1.6
И доработаем форму уже созданной обработки: добавим в таблицу значений новые колонки: Время открытия (тип Булево) и Только легковые автомобили (тип Дата, состав даты – Время). Разместим их в таблице на форме. У колонки Только легковые автомобили
вид – поле флажка (см. рис. 9.1.7).
Рис. 9.1.7
Доработаем код из предыдущего листинга – допишем в конце цикла следующие строки:
НоваяСтрока.ВремяНачалаРаботыГаража = ВыборкаГаражей.ВремяНачалаРаботыГаража; НоваяСтрока.ТолькоЛегковыеАвтомобили = ВыборкаГаражей.ТолькоЛегковыеАвтомобили;
Листинг 9.1.2 Создайте самостоятельно разветвлённую структуру гаражей (с группами и
элементами). Как на рис. 9.1.8.
Рис. 9.1.8
Если мы сейчас запустим обработку и выполним команду, то получится следующий результат (см. рис. 9.1.9).
Рис. 9.1.9
Усложним работу с выборкой. Сначала научимся выбирать элементы только верхнего уровня, а потом – элементы одной конкретной группы.
Выберем элементы только первого уровня. Для этого в первом параметре метода
Выбрать напишем пустую ссылку на элемент справочника.
ВыборкаГаражей = Справочники.Гаражи.Выбрать(Справочники.Гаражи.ПустаяСсылка()); Пока ВыборкаГаражей.Следующий() Цикл
//обход выборки КонецЦикла;
Листинг 9.1.3 Если после этого мы сохраним и перезапустим обработку, то увидим, что будут
выведены все элементы верхнего уровня, включая группы. К сожалению, мы не можем
отобрать с помощью выборки только элементы справочника, поэтому если не нужно появление групп в табличном поле, то можно дописать следующий код:
ВыборкаГаражей = Справочники.Гаражи.Выбрать(Справочники.Гаражи.ПустаяСсылка()); Пока ВыборкаГаражей.Следующий() Цикл
Если ВыборкаГаражей.ЭтоГруппа Тогда Продолжить;
КонецЕсли;
//обход выборки КонецЦикла;
Листинг 9.1.4 Сохраним обработку, перезапустим и посмотрим, какая получилась выборка в этот
раз.
Мы увидим, что заполнятся только элементы справочника.
Научимся делать выборки для конкретного Родителя. Для этого добавим на форму обработки реквизит Гараж с типом СправочникСсылка.Гаражи, разместим его на форме, а у поля выбора установим у свойства ВыборГруппИЭлементов (категория Использование) значение Групп (см. рис. 9.1.10).
Рис. 9.1.10
Создадим новую команду Заполнить таблицу по группе. Для удобства все команды будем размещать в подменю Заполнить (см. рис. 9.1.11).
Рис. 9.1.11
В обработчиках команды Заполнить таблицу по группе напишите следующий код:
&НаСервере
Процедура ЗаполнитьТаблицуПоГруппеНаСервере()
ВыборкаГаражей = Справочники.Гаражи.Выбрать(Гараж);//выборка элементов по группе
Пока ВыборкаГаражей.Следующий() Цикл Если ВыборкаГаражей.ЭтоГруппа Тогда
Продолжить;
КонецЕсли;
НоваяСтрока = ТаблицаГаражей.Добавить(); НоваяСтрока.Гараж = ВыборкаГаражей.Ссылка; НоваяСтрока.ВремяНачалаРаботыГаража = ВыборкаГаражей.ВремяНачалаРаботыГаража; НоваяСтрока.ТолькоЛегковыеАвтомобили = ВыборкаГаражей.ТолькоЛегковыеАвтомобили;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицуПоГруппе(Команда) ЗаполнитьТаблицуПоГруппеНаСервере();
КонецПроцедуры
Листинг 9.1.5
Посмотрим, как будет работать в этот раз обработка (см. рис. 9.1.12).
Заметьте, что если мы выберем группу, у которой внутри есть ещё одна группа (например, группа Автобаза 1, см. рис. 9.1.9), то будут выведены элементы, которые входят в группу выбора, но элементы, входящие в подчинённую группу, не будут выведены (см. рис. 9.1.12).
Рис. 9.1.12
Для того чтобы получить все элементы, включая элементы подчинённых справочников, необходимо использовать метод менеджера справочника ВыбратьИерархически. Синтаксис данного метода точно такой же, как и у метода Выбрать, поэтому мы не будем его разбирать, а просто продемонстрируем, как он работает. Создадим новую команду Заполнить таблицу по группе с иерархией, в которой будет точно такой же код, как и в команде Заполнить таблицу по группе, только метод Выбрать заменим на метод
ВыбратьИерархически (см. листинг 9.1.6).
ВыборкаГаражей = Справочники.Гаражи.ВыбратьИерархически(Гараж); Пока ВыборкаГаражей.Следующий() Цикл
Если ВыборкаГаражей.ЭтоГруппа Тогда Продолжить;
КонецЕсли;
// заполнение таблицы значений КонецЦикла;
Листинг 9.1.6
У нас должен получиться результат, как на рис. 9.1.13.
Рис. 9.1.13
Как видите, данный метод очень удобно использовать, когда работаем с иерархическими справочниками и необходимо получить все элементы данного справочника.
Обращаю Ваше внимание, что сначала будут выбраны группы самого верхнего уровня, потом группы следующего уровня и так далее. И только после этого будут выбраны элементы, начиная с самого нижнего уровня и заканчивая нулевым уровнем. Чтобы убедиться в этом, закомментируйте код, в котором мы отказываемся выводить группы, и посмотрим, что получится, когда в поле ввода нет элемента справочника. Обратите внимание на порядок, в котором вышли строки в таблице значений.
В дальнейшем применительно к справочнику Гаражи будем работать с методом
ВыбратьИерархически.
Научимся работать с отбором.
Создадим отбор гаражей по Времени начала работы гаража. Мы сделали данный реквизит справочника индексируемым, поэтому его можно использовать в отборе.
Поскольку нам необходимо сделать отбор по времени, добавьте на форму обработки реквизит ВремяРаботы (Тип Дата, состав даты – Время), и элемент поле ввода Время
работы (см. рис. 9.1.14).
Рис. 9.1.14
Создадим новую команду Заполнить таблицу с учетом времени, которую разместим на форме к группе Заполнить командной панели таблицы ТаблицаГаражей, а также создадим обработчики команды на сервере и на клиенте, в которых напишем следующий код (см. листинг 9.1.7):
&НаСервере
Процедура ЗаполнитьТаблицуСУчетомВремениНаСервере()
Если Не ЗначениеЗаполнено(ВремяРаботы) тогда
ВыборкаГаражей = Справочники.Гаражи.ВыбратьИерархически(Гараж); иначе
Отбор = Новый Структура; Отбор.Вставить("ВремяНачалаРаботыГаража",ВремяРаботы);
ВыборкаГаражей = Справочники.Гаражи.ВыбратьИерархически(Гараж,,Отбор); КонецЕсли;
Пока ВыборкаГаражей.Следующий() Цикл Если ВыборкаГаражей.ЭтоГруппа Тогда
Продолжить;
КонецЕсли;
//заполнение таблицы значений КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицуСУчетомВремени(Команда) ЗаполнитьТаблицуСУчетомВремениНаСервере();
КонецПроцедуры
Листинг 9.1.7 В этом примере используется иерархическая выборка, эта выборка производится для
всех объектов, включая группы, а Вы уже знаете, что в иерархической выборке сначала
выводится группа, а потом элементы, которые входят в группу. Но отбор в иерархической
выборке тоже применяется для всех элементов, включая группы. Поэтому если у нас в качестве реквизита Гараж ничего не будет указано, то будет произведена выборка по самой верхней иерархии, и если мы зададим отбор для времени 10 часов, то ничего не выйдет, а при отборе времени 6 часов выйдет только элемент справочника Офисная стоянка "Северная".
Почему так получилось? Потому что у нас не выбрались группы первого уровня, из-за того, что у всех групп не заполнен реквизит ВремяНачалаРаботыГаража, следовательно, не выведутся и элементы, которые входят в них. Поэтому список будет или пустой, или заполнен элементам первого уровня. В то же время если мы укажем какую-то группу, то отбор сработает: будут выбраны элементы из указанной группы (но если в указанную группу входят ещё группы, то элементы этих групп не будут выбраны, даже если они удовлетворяют условию отбора).
Теперь попробуем сделать отбор для неиндексируемого поля и посмотрим, что получится.
Изменим код:
Отбор = Новый Структура; Отбор.Вставить("ТолькоЛегковыеАвтомобили",Истина);
ВыборкаГаражей = Справочники.Гаражи.ВыбратьИерархически(Гараж,,Отбор);
Пока ВыборкаГаражей.Следующий() Цикл Если ВыборкаГаражей.ЭтоГруппа Тогда
Продолжить;
КонецЕсли;
//обход выборки КонецЦикла;
Листинг 9.1.8
Запустим обработку и посмотрим, что должно возникнуть. Как видите, сгенерировалась ошибка.
Рис. 9.1.15
Ещё раз повторимся: отбор работает только с индексированными реквизитами.
Рассмотрим последний параметр выборок – Порядок. Выведем все наши элементы, упорядочив их по Времени начала работы гаража. Для этих целей создадим команду Заполнить таблицу с упорядочиванием, которую разместим на форме. В обработчиках команды напишем следующий код:
&НаСервере
Процедура ЗаполнитьТаблицуСУпорядочиваниемНаСервере() ВыборкаГаражей =
Справочники.Гаражи.ВыбратьИерархически(Гараж,,,"ВремяНачалаРаботыГаража"); Пока ВыборкаГаражей.Следующий() Цикл
Если ВыборкаГаражей.ЭтоГруппа Тогда Продолжить;
КонецЕсли;
//обход по выборке КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицуСУпорядочиванием(Команда) ЗаполнитьТаблицуСУпорядочиваниемНаСервере();
КонецПроцедуры
Листинг 9.1.9
Реквизит, по которому осуществляется сортировка, тоже должен быть индексируемым!
Параметр Порядок, так же, как и параметр Отбор, действует на все элементы справочника, включая группы. Поэтому в случае сортировки по иерархии, желательно данный параметр применять, когда осуществляется выборка элементов из какой-то группы.
Рис. 9.1.16
Если необходимо упорядочивание по убыванию, то следует изменить написание последнего параметра, добавив слово «УБЫВ».
ВыборкаГаражей = Справочники.Гаражи.ВыбратьИерархически(Гараж,,,"ВремяНачалаРаботыГаража УБЫВ");
Листинг 9.1.10 Сохраните обработку, перезапустите, и Вы увидите, что элементы упорядочились по
убыванию.
Итак, мы рассмотрели все параметры выборок, кроме второго – Владелец. Создадим новую обработку, на форме этой обработки будет два реквизита: МаркаАвтомобиля (тип СправочникСсылка.МаркиАвтомобилей) и МоделиАвтомобилей (тип ТаблицаЗначений, единственная колонка Модель с соответствующим типом), первый будет размещён на форме в виде поля ввода, а второй – таблицы (см. рис. 9.1.17).
Рис. 9.1.17
Создадим клиентский и серверный обработчики события ПриИзменении поля ввода
МаркаАвтомобиля. В обработчиках события напишем следующий код:
&НаСервере
Процедура МаркаАвтомобиляПриИзмененииНаСервере()
Выборка = Справочники.МоделиАвтомобилей.Выбрать(,МаркаАвтомобиля); МоделиАвтомобилей.Очистить();
Пока Выборка.Следующий() Цикл
НовСтр = МоделиАвтомобилей.Добавить(); НовСтр.Модель = Выборка.Ссылка;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура МаркаАвтомобиляПриИзменении(Элемент) МаркаАвтомобиляПриИзмененииНаСервере();
КонецПроцедуры
Листинг 9.1.11
Сохраним обработку и посмотрим на результат: после выбора определённой марки в таблице на форме должен появиться список моделей этой марки (см. рис. 9.1.18).
Рис. 9.1.18
На этом мы закончим изучать выборку справочников и перейдём к изучению выборок документов.
9.05 Выборка документов - что это?
Выборка документов
Выборка документов, как и в случае выборки справочника, – это объект, который представляет специализированный способ перебора документов. Объект Выборка документов возвращается методом Выбрать менеджера документа.
Метод Выбрать имеет следующий синтаксис:
Выбрать(<ДатаНачала>, <ДатаОкончания>, <Отбор>, <Порядок>)
Все параметры являются необязательными. Разберём параметры метода.
ДатаНачала и ДатаОкончания – это параметры, которые определяют период выбираемых документов. Если они не указаны, то выбираются все документы. Если указана только одна дата (ДатаНачала либо ДатаОкончания), то выбираются документы с этой даты или до этой даты.
Второй и третий параметр (Отбор и Порядок) Вам уже знакомы по выборке справочников, у них точно такой же смысл, и они работают только в отношении реквизита Дата и индексированных реквизитов. Точно так же в отборе можно указать только один реквизит. Метод Выбрать является функцией, которая возвращает выборку документов. У выборки всего два метода, это: ПолучитьОбъект, который возвращает объект выбранного документа, и метод Следующий, который осуществляет позиционирование на следующем элементе.
Рассмотрим пример. Для того чтобы пример был для Вас более наглядным, создадим несколько документов Прибытие в гараж с разными датами, а также сделаем реквизит Автомобиль документа индексируемым.
Создадим новую обработку, в которой будут реквизит ТаблицаДокументов (тип
ТаблицаЗначений) с колонками: Номер (тип Строка), ДатаПрибытия (тип Дата, состав даты
Дата), Автомобиль (тип СправочникСсылка.Автомобили) и ПрибытиеАвтомобиля (тип ДокументСсылка.ПрибытиеВГараж), а также на форме создадим команду Заполнить таблицу, в серверном обработчике которой будем заполнять таблицу значений на форме.
Рис. 9.1.19
&НаСервере
Процедура ЗаполнитьТаблицуНаСервере() ТаблицаДокументов.Очистить();
Выборка = Документы.ПрибытиеВГараж.Выбрать(); Пока Выборка.Следующий() Цикл
НовСтр = ТаблицаДокументов.Добавить(); НовСтр.Номер = Выборка.Номер; НовСтр.ДатаПрибытия = Выборка.ДатаПрибытия; НовСтр.Автомобиль = Выборка.Автомобиль; НовСтр.ПрибытиеАвтомобиля = Выборка.Ссылка;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицу(Команда) ЗаполнитьТаблицуНаСервере();
КонецПроцедуры
Листинг 9.1.12 В этом коде мы получаем выборку документов Прибытие в гараж и осуществляем
обход элементов выборки. Во время обхода создаём новую строку табличного поля, в которую заносим соответствующие данные. Посмотрите, как работает ваша обработка.
Мы рассмотрели самый простой вариант выборки без параметров. Научимся применять даты начала и конца. Для этого на форме обработки создадим реквизит с новым для вас типом СтандартныйПериод (см. рис. 9.1.20).
Рис. 9.1.20
Переменная этого типа имеет три реквизита. Нас интересуют ДатаНачала и
ДатаОкончания, в которых соответственно содержатся начало и конец указанного периода.
Создадим команду формы ЗаполнитьТаблицуСПериодом, разместим на форме (самостоятельно создайте группу команд – подменю в командной панели таблицы), и в серверном обработчике команды напишем следующий код:
&НаСервере
Процедура ЗаполнитьТаблицуСПериодомНаСервере()
ТаблицаДокументов.Очистить(); Выборка =
Документы.ПрибытиеВГараж.Выбрать(Период.ДатаНачала,Период.ДатаОкончания); Пока Выборка.Следующий() Цикл
НовСтр = ТаблицаДокументов.Добавить(); ЗаполнитьЗначенияСвойств(НовСтр,Выборка); НовСтр.ПрибытиеАвтомобиля = Выборка.Ссылка;
КонецЦикла;
КонецПроцедуры &НаКлиенте
Процедура ЗаполнитьТаблицуСПериодом(Команда) ЗаполнитьТаблицуСПериодомНаСервере();
КонецПроцедуры
Листинг 9.1.13 Посмотрите, как отбираются документы по датам. Как Вы должны увидеть, выводятся
документы только из заданного диапазона дат.
Разберём, как работает отбор. Для этого внедрим в обработку возможность установки отбора по реквизиту Автомобиль документа. Для этого создадим новый реквизит под названием Автомобиль (тип СправочникСсылка.Автомобили), и поместим его на форму .
Рис. 9.1.21
Создадим новую команду Заполнить таблицу с отбором, скопируем код из предыдущего листинга, в котором осуществляется заполнение таблицы. Этот код доработаем следующим образом: если ссылка реквизита Автомобиль не пустая (он выбран), то мы создаем новую структуру, название ключа которой будет совпадать с названием реквизита документа Прибытие в гараж, по которому должен быть выполнен отбор, а в значении элемента структуры будет указан выбранный реквизит. Созданную структуру будем использовать в качестве третьего параметра метода Выбрать.
&НаСервере
Процедура ЗаполнитьТаблицуСОтборомНаСервере() ТаблицаДокументов.Очистить();
Если Автомобиль.Пустая() Тогда Выборка =
Документы.ПрибытиеВГараж.Выбрать(Период.ДатаНачала,Период.ДатаОкончания); иначе
Отбор = Новый Структура("Автомобиль",Автомобиль);
Выборка = Документы.ПрибытиеВГараж.Выбрать(Период.ДатаНачала,
Период.ДатаОкончания, Отбор);
КонецЕсли;
Пока Выборка.Следующий() Цикл
НовСтр = ТаблицаДокументов.Добавить(); ЗаполнитьЗначенияСвойств(НовСтр,Выборка); НовСтр.ПрибытиеАвтомобиля = Выборка.Ссылка;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицуСОтбором(Команда) ЗаполнитьТаблицуСОтборомНаСервере();
КонецПроцедуры
Листинг 9.1.14
Посмотрим, как работает отбор (напомню, что реквизит Автомобиль документа должен быть индексируемым).
Рис. 9.1.22
Напоследок рассмотрим работу последнего параметра метода Выбрать – параметра
Порядок.
Перепишем код в последнем листинге: отсортируем документы по реквизиту Дата.
Если Автомобиль.Пустая() Тогда
Выборка = Документы.ПрибытиеВГараж.Выбрать(Период.ДатаНачала,
Период.ДатаОкончания,, "Дата УБЫВ");
иначе
Отбор = Новый Структура("Автомобиль",Автомобиль);
Выборка = Документы.ПрибытиеВГараж.Выбрать(Период.ДатаНачала,
Период.ДатаОкончания, Отбор,
"Дата УБЫВ");
КонецЕсли;
Листинг 9.1.15
Мы добавили Дату в порядок в обоих методах выбора документов. Документы должны быть отсортированы по Дате в обратном порядке.
Замечу, что реквизит, по которому осуществляется сортировка, должен быть индексируемым (или сортировка осуществляется по реквизиту Дата)!
В этой части мы научились выбирать документы и справочники с помощью методов менеджеров. Как Вы поняли, если необходима сложная выборка, например, когда условие ставится по нескольким полям, то данные методы не применимы, для этого необходим язык запросов. Но всё равно про них не нужно забывать, и если необходимо осуществить простую выборку большого числа элементов или документов, то мысль о выборках – это первая мысль, которая должна прийти Вам в голову.
9.06 Часть 2. Работа с запросами. Что такое Запрос в понятии 1С?
В этой части изучим самые основы работы с запросами.
Что такое запрос в понятии 1С? Запрос – это один из механизмов доступа к данным. С помощью запроса разработчик может получить быстрый доступ к данным, а потом как-то их прочитать и проанализировать. Но в отличие от других языков программирования, в 1С с помощью запроса нельзя изменять данные (создавать, редактировать и удалять), то есть запросы предназначены только для получения некоторой выборки из больших объёмов данных. В этой книге работа с запросами дана в самом общем виде, чтобы у Вас имелось представление об этом механизме платформы 1С. Подробно запросы 1С изучаются в моем курсе «Запросы в 1С для начинающих».
Перейдём непосредственно к практической части. Научимся создавать свои собственные запросы.
Получение данных из запроса
9.07 Получение данных из запроса - какой объект для запросов?
Работа с запросами осуществляется посредством объекта Запрос. Создаётся данный объект с помощью оператора Новый.
Запрос = Новый Запрос;
Поставим небольшую задачу: выведем с помощью запроса все элементы справочника Автомобили в таблицу значений. В предыдущей части мы научились это делать при помощи выборки, а теперь проделаем это с помощью запроса.
Создадим обработку, форму обработки, создадим на форме реквизит ТаблицаАвтомобилей (тип ТаблицаЗначений, колонки соответствуют реквизитам справочника Автомобиль, см. рис. 9.2.1) и разместим его в виде таблицы на форме.
Рис. 9.2.1
Создадим команду Заполнить таблицу и поместим её в командную панель таблицы формы ТаблицаАвтомобилей. Для этой команды создадим обработчики на клиенте и на сервере. С запросами мы будем работать только в серверном контексте. В принципе, с запросами можно работать и в клиентском контексте, но Ваше приложение сможет нормально функционировать только в режиме толстого клиента. В режиме тонкого клиента с запросами работать нельзя!
После того как мы создадим объект Запрос, необходимо этому объекту передать текст запроса. Для этого используется свойство Текст объекта Запрос.
&НаСервере
Процедура ЗаполнитьТаблицуНаСервере() ТаблицаАвтомобилей.Очистить(); Запрос = Новый Запрос; Запрос.Текст = ;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицу(Команда) ЗаполнитьТаблицуНаСервере();
КонецПроцедуры
Листинг 9.2.1 Можно написать текст запроса вручную, а можно использовать конструктора запроса.
Мы будем использовать конструктор запроса. Откроем его. Для открытия конструктора
запроса необходимо поместить курсор в то место модуля, где будет текст запроса.
Затем следует воспользоваться командой Конструктор запроса. Эту команду можно найти или в главном меню по пути: Главное меню – Текст – Конструктор запроса, или в контекстном меню. Мы воспользуемся контекстным меню.
Рис. 9.2.3
Выйдет сообщение: «Не найден текст запроса. Создать новый?», мы ответим: «Да».
После ответа откроется окно конструктора запроса.
Конструктор представляет форму с несколькими закладками. Нас пока интересует только первая закладка Таблицы и поля. Эта закладка состоит из трёх списков. Самый левый список называется База данных, в нём отображены все метаданные базы (таблицы).
Из этого списка можно выбрать любой объект, который нас интересует. Поскольку по условию задачи нужно вывести все элементы справочника Автомобили, то выберем этот справочник. Сделаем это, два раза кликнув по соответствующему объекту в списке правой кнопкой мышки, или воспользовавшись командой «>».
Рис. 9.2.5
Справочник Автомобили выбран, и он появился в списке Таблицы. В этом списке отображаются все таблицы, данные которых нужно вывести в запросе. Но наш запрос ещё пустой, потому что нет полей, которые должны быть отображены в нём. Выберем поля. Для этого развернём справочник Автомобиль, и получим список реквизитов и табличных частей справочника.
Чтобы выбрать нужный реквизит, необходимо или дважды по нему кликнуть, или воспользоваться командой «>». Выберем поля Наименование, Год выпуска, ГосНомер, Коробка передач, Марка и Модель.
Рис. 9.2.7
И на этом мы закончим, запрос создан, если мы захотим посмотреть на сам запрос, не выходя из конструктора, то это можно сделать, нажав на кнопку Запрос.
Рис. 9.2.8
Причём в этом же окне можно отредактировать запрос вручную, нажав на кнопку
Редактировать запрос.
Мы ничего редактировать не будем, закроем окно с текстом запроса и нажмём на кнопку ОК конструктора, соответствующий текст появится в модуле (см. листинг 9.2.2).
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| Автомобили.Наименование КАК Наименование,
| Автомобили.ГодВыпуска КАК ГодВыпуска,
| Автомобили.ГосНомер КАК ГосНомер,
| Автомобили.Марка КАК Марка,
| Автомобили.Модель КАК Модель,
| Автомобили.КоробкаПередач КАК КоробкаПередач
|ИЗ
| Справочник.Автомобили КАК Автомобили";
Листинг 9.2.2 В только что созданном запросе три ключевых слова: «ВЫБРАТЬ», «ИЗ» и «КАК».
Ключевое слово «ВЫБРАТЬ» является предложением, после которого указываются поля выборки, которые должны обязательно попасть в результат запроса, эти поля должны быть перечислены через запятую. Это ключевое слово является единственным обязательным в запросе.
Ключевое слово «ИЗ» также является предложением, которое указывает, из какой таблицы-источника будут выбраны данные.
Ключевое слово «КАК» задаёт, каким образом будет называться источник данных в запросе, а также псевдонимы полей.
Запрос написан, но этого ещё мало, чтобы получить данные, необходимо выполнить запрос к базе данных.
Для этого используется метод Выполнить объекта Запрос.
Результат = Запрос.Выполнить();
Листинг 9.2.3 Данный метод является функцией, которая возвращает объект, так и называющийся
Результат запроса, этот объект предназначен для хранения полученных данных.
9.08 метод объекта РезультатЗапроса для проверки, есть ли данные
Но прежде чем начать обрабатывать данные, лучше проверить, есть ли они в принципе, ведь в справочнике Автомобили может и не быть никаких элементов. Для этого используем метод объекта РезультатЗапроса, который называется Пустой.
Если Результат.Пустой() Тогда Возврат;
КонецЕсли;
Листинг 9.2.4
Метод Пустой результата запроса возвращает Истину, если Результат запроса не содержит данных. В этом случае мы просто выходим из процедуры.
Рекомендую Вам всегда перед началом обработки результата запроса проверять его на наличие данных.
Результат получен, он не пустой, теперь нам необходимо вывести данные в таблицу значений. Сделать это можно двумя способами: используя Выборку и используя Выгрузку.
Мы разберём оба этих способа.
Сначала заполним нашу таблицу на форме данными из запроса с помощью Выборки
(см. листинг 9.2.5).
Выборка = Результат.Выбрать(); Пока Выборка.Следующий() цикл
НовСтр = ТаблицаАвтомобилей.Добавить(); НовСтр.Наименование = Выборка.Наименование; НовСтр.ГодВыпуска = Выборка.ГодВыпуска; НовСтр.ГосНомер = Выборка.ГосНомер; НовСтр.Марка = Выборка.Марка;
НовСтр.Модель = Выборка.Модель; НовСтр.КоробкаПередач = Выборка.КоробкаПередач;
КонецЦикла;
Листинг 9.2.5 С выборками Вы уже знакомы, только в данном примере при помощи метода
Выбрать() результат запроса будет – создан объект Выборка из результата запроса. Эту
выборку мы обходим также, как и другие выборки: используем метод Следующий(), чтобы позиционироваться на следующем элементе. В процессе обхода выборки нужно получать значения полей, которые были указаны в запросе в предложении «ВЫБРАТЬ», для этого необходимо обращаться к названию (псевдониму) поля через саму выборку, используя точку (контекстная подсказка в этом случае работать не будет, как в случае других выборок).
Посмотрим, что вернёт запрос.
Рис. 9.2.10
Мы заполняли колонки таблицы значениями, обращаясь к полям запроса в выборке, но
можно сделать и проще, используя уже знакомую процедуру глобального контекста
ЗаполнитьЗначенияСвойств.
Переделаем код:
Пока Выборка.Следующий() цикл
НовСтр = ТаблицаАвтомобилей.Добавить(); ЗаполнитьЗначенияСвойств(НовСтр,Выборка);
КонецЦикла;
Листинг 9.2.6
Как видите, данный метод удобен для написания и экономит время программиста, но он выполняется в два раза дольше. Поэтому в случае больших объёмов данных всегда обращайтесь непосредственно к выборке.
Рассмотрим ещё один способ получения данных из запроса с помощью метода Выгрузить. Тут всё просто: мы выгружаем данные из результата запроса в таблицу значений при помощи метода Выгрузить() и сразу же загружаем их в таблицу значений на форме.
Единственное – название и тип полей в таблице значения на форме должны совпадать с названием и типом полей в запросе.
ТаблицаАвтомобилей.Загрузить(Результат.Выгрузить());
Листинг 9.2.7 Всё должно прекрасно заполниться. Но этот способ ещё медленнее, чем предыдущий,
поэтому используйте его только для небольших объёмов данных.
Итак, мы научились создавать примитивные запросы, получать их результат, и если он заполнен данными, то получать данные разными способами. Теперь мы будем изучать непосредственно сами запросы, мы не будем затрагивать особенности их вывода. В дальнейшем самостоятельно решайте, каким способом Вам получать данные из запроса.
Наиболее оптимальный на данный момент способ – это использование выборок.
9.09 (Работа с секцией «ВЫБРАТЬ»)
Работа с предложением «ВЫБРАТЬ»
Только что мы научились работать с предложением «ВЫБРАТЬ». После него, как Вам уже известно, идёт перечисление полей, которые будут отображены в запросе. Разберём основные конструкции этого предложения.
И первая конструкция – это «РАЗЛИЧНЫЕ».
Создадим на форме обработки новую команду Заполнить таблицу (различные), скопируем в серверный обработчик команды уже созданный нами запрос и изменим его – оставим только два поля. Это поле Марка и Коробка передач (см. листинг 9.2.8, рис. 9.2.11).
&НаСервере
Процедура ЗаполнитьТаблицуРазличныеНаСервере() ТаблицаАвтомобилей.Очистить();
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| Автомобили.Марка КАК Марка,
| Автомобили.КоробкаПередач КАК КоробкаПередач
|ИЗ
| Справочник.Автомобили КАК Автомобили"; Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда Возврат;
КонецЕсли;
Выборка = Результат.Выбрать(); Пока Выборка.Следующий() цикл
НовСтр = ТаблицаАвтомобилей.Добавить(); ЗаполнитьЗначенияСвойств(НовСтр,Выборка);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицуРазличные(Команда) ЗаполнитьТаблицуРазличныеНаСервере();
КонецПроцедуры
Листинг 9.2.8
Посмотрим, как у нас заполнится таблица на форме.
Рис. 9.2.11
Естественно, остальные поля не заполнились, но нам они и не нужны, для тренировки сделаем их невидимыми. Но среди тех строк, что вышли, мы видим повторяющиеся.
Рис. 9.2.12
Директива «РАЗЛИЧНЫЕ» как раз необходима для того, чтобы в результате запроса
не было повторяющихся строк. Поставим её.
Откроем конструктор для имеющегося запроса. Для того чтобы открыть конструктор уже созданного запроса, необходимо поставить курсор в любое место запроса и выполнить команду Конструктор запроса или в меню Текст (Главное меню – Текст), или в контекстном меню.
Рис. 9.2.13
В конструкторе перейдём на закладку Дополнительно и поставим флажок напротив выражения Без повторяющихся.
Рис. 9.2.14
После этого можно смело нажимать кнопку ОК, должен получиться следующий запрос:
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
| Автомобили.Марка КАК Марка,
| Автомобили.КоробкаПередач КАК КоробкаПередач
|ИЗ
| Справочник.Автомобили КАК Автомобили";
Листинг 9.2.9
Как вы видите, после ключевого слова «ВЫБРАТЬ» появилось ключевое слово
«РАЗЛИЧНЫЕ», именно благодаря ему и будут выводиться только уникальные записи. Посмотрим, как работает новый запрос. Останутся только уникальные записи.
Рис. 9.2.15
Следующая конструкция – это конструкция «ПЕРВЫЕ».
Эта конструкция позволяет выводить только несколько первых записей (число может быть любое, в пределах разумного). Эту конструкцию очень удобно использовать тогда, когда нужно вывести только одну запись.
Сейчас мы так и поступим: выведем только одну запись предыдущего запроса. Создадим опять новую команду Заполнить таблицу (первые), в серверный обработчик которой скопируем код из самой первой команды, откроем снова конструктор запроса, перейдём на закладку Дополнительно, в которой и установим флажок рядом со словом
«Первые».
Рис. 9.2.16
В соседнем поле цифру 1 оставим как есть. Нажмём кнопку ОК, запрос приобретёт следующий вид:
Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1
| Автомобили.Наименование КАК Наименование,
| Автомобили.ГодВыпуска КАК ГодВыпуска,
| Автомобили.ГосНомер КАК ГосНомер,
| Автомобили.Марка КАК Марка,
| Автомобили.Модель КАК Модель,
| Автомобили.КоробкаПередач КАК КоробкаПередач
|ИЗ
| Справочник.Автомобили КАК Автомобили ";
Листинг 9.2.10
Как видите, в запросе после ключевого слова «ВЫБРАТЬ» появилось ключевое слово
«ПЕРВЫЕ» и рядом с ней цифра 1. Сохраним, перезапустим обработку и выполним команду. В результате выйдет только одна запись.
Рис. 9.2.17
Условия запроса и передача параметров
Из предыдущей части мы узнали, что в выборке справочников или объектов можно осуществить отбор только по одному, при этом индексируемому, реквизиту. В запросах таких ограничений нет, можно разрабатывать любые выборки данных с любым количеством отборов. Научимся это делать.
Добавим на форму два реквизита – Марка автомобиля и Коробка передач (с соответствующими типами), у обоих реквизитов в свойство Проверка заполнения установим значение Выдавать ошибку. Поместим оба этих реквизита на форму в виде полей ввода.
Рис. 9.2.18
Создадим новую команду Заполнить таблицу с отбором, при выполнении которой будем отбирать все соответствующие заданным условиям автомобили. Создадим клиентский и серверный обработчик, и скопируем в серверный обработчик код из самой первой команды текущей обработки.
В начале процедуры обработчика команды в клиентском контексте напишем код, в котором будем проверять заполнены ли реквизиты, и выходить из процедуры, если один из реквизитов пустой. Для этого будем использовать функцию ПроверитьЗаполение. Эта функция вернет Ложь, если хотя бы один реквизит формы, у которого в свойстве Проверка заполнения значение Выдавать ошибку, будет не заполен.
&НаКлиенте
Процедура ЗаполнитьТаблицуСОтбором(Команда) Если Не ПроверитьЗаполнение() Тогда
Возврат;
КонецЕсли;
ЗаполнитьТаблицуСОтборомНаСервере(); КонецПроцедуры
Листинг 9.2.11 Мы сделали намеренно проверку в клиентском контексте, чтобы лишний раз не
осуществлять серверный вызов.
Дальше необходимо поставить условия для запроса в серверной процедуре команды Заполнить таблицу с отборами. Откроем конструктор уже созданного запроса, который мы скопировали, и перейдём на закладку Условия.
Рис. 9.2.19
В левой части закладки находятся поля, которые можно отобрать. Мы можем ставить условия по всем полям выбранных таблиц.
Выберем два поля: Марка и Коробка передач.
Рис. 9.2.20
После выбора поля строка в таблице справа заполняется автоматически. Разберём таблицу справа.
В колонке Условие расположены непосредственно те поля, на которые необходимо установить отбор. Их в каждой строке можно менять. В следующей колонке расположен Способ сравнения. Он по умолчанию равен Равно. Но можно и поменять на другое сравнение.
Рис. 9.2.21
В последней колонке указывается название параметра, которое будет передано в запрос. Мы также можем поменять его. Если мы поставим флажок в колонку Произвольное, то сможем отредактировать условие вручную.
Рис. 9.2.22
Пока ничего менять не будем, а просто оставим запрос как есть, и нажмём на кнопку
ОК конструктора запроса. После этого запрос станет таким:
Запрос.Текст = "ВЫБРАТЬ
| Автомобили.Наименование КАК Наименование,
| Автомобили.ГодВыпуска КАК ГодВыпуска,
| Автомобили.ГосНомер КАК ГосНомер,
| Автомобили.Марка КАК Марка,
| Автомобили.Модель КАК Модель,
| Автомобили.КоробкаПередач КАК КоробкаПередач
|ИЗ
| Справочник.Автомобили КАК Автомобили
|ГДЕ
| Автомобили.Марка = &Марка
| И Автомобили.КоробкаПередач = &КоробкаПередач";
Листинг 9.2.12
Вы видите, что в тексте запроса добавилось служебное слово – «ГДЕ». Это слово определяет конструкцию, которая нужна для наложения отбора на выборку. Условия отбора перечислены после этого служебного слова. Обратите внимание, что они логически связываются операцией И. Но можно заменить операцию И на ИЛИ, если этого будет требовать задача (правда, не рекомендуется это делать в целях производительности), но в этом случае придётся подправить запрос вручную. Все параметры, которые передаются в запрос извне, начинаются с символа &.
Запрос написан, нам необходимо передать значения наших реквизитов с формы в запрос. Делать это будем, используя метод УстановитьПараметр объекта Запрос.
Запрос.УстановитьПараметр("Марка",МаркаАвтомобиля); Запрос.УстановитьПараметр("КоробкаПередач",КоробкаПередач); Результат = Запрос.Выполнить();
Листинг 9.2.13
Параметры необходимо устанавливать перед тем, как будет выполнен запрос!
Метод УстановитьПараметр имеет два обязательных параметра. Первый – это имя устанавливаемого в запросе параметра, а второй – непосредственно значение данного параметра, которое будет передано в запрос. В нашем случае – это значение реквизита.
Обращаю Ваше внимание, что первый параметр должен в точности совпадать с параметром в запросе, который начинается с символа &, но без этого символа.
В этот раз сообщим пользователю о пустом результате более подробно.
Если Результат.Пустой() Тогда Сообщить("Нет автомобилей с маркой " +
Строка(МаркаАвтомобиля) + " и коробкой передач " + Строка(КоробкаПередач));
Возврат;
КонецЕсли;
Листинг 9.2.14
Сохраним обработку, посмотрим, как она работает.
Рис. 9.2.23
Отборы сработали как надо. Рассмотрим ещё один момент.
Что делать, если нужно сделать отбор сразу по нескольким элементам справочника Марка, например, чтобы вывелись автомобили марки Ford и KIA? Для этого в условии отбора необходимо использовать вид сравнения В.
Изменим обработку – добавим реквизит СписокМарок с типом СписокЗначений (тип значения СправочникСсылка.МаркиАвтомобилей). Этот список будем заполнять при открытии формы всеми марками автомобилей, присутствующими в справочнике, а в запрос будем передавать только те марки, напротив которых стоит отметка.
Добавим список на форму в виде таблицы и «перетащим» колонки Значение и Пометка, также нашу основную таблицу сгруппируем с таблицей списка значений, чтобы они друг относительно друга располагались горизонтально (см. рис. 9.2.24).
Рис. 9.2.24
Создадим обработчик формы ПриСозданииНаСервере, и напишем в нём код, заполняющий список СписокМарок.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) ВыборкаМарка = Справочники.МаркиАвтомобилей.Выбрать(); Пока ВыборкаМарка.Следующий() цикл
СписокМарок.Добавить(ВыборкаМарка.Ссылка,,Ложь); КонецЦикла;
КонецПроцедуры
Листинг 9.2.15 После этого при запуске формы таблица слева должна заполниться марками:
Рис. 9.2.25
Создадим новую команду Заполнить таблицу с отбором по списку, у этой команды создадим клиентский и серверный обработчик. В клиентском обработчике будем выгружать в массив помеченные элементы списка значение СписокМарок. Если массив окажется пустым (то есть нет помеченных элементов), то выйдем из клиентской процедуры, и серверный вызов не произойдёт (см. листинг 9.2.16).
&НаКлиенте
Процедура ЗаполнитьТаблицуСОтборомПоСписку(Команда) МассивМарок = Новый Массив;
Для Каждого ЭлСписка из СписокМарок цикл Если ЭлСписка.Пометка тогда
МассивМарок.Добавить(ЭлСписка.Значение); КонецЕсли;
КонецЦикла;
Если МассивМарок.Количество() = 0 тогда Сообщить("Выберете хотя бы одну марку"); Возврат;
КонецЕсли;
ЗаполнитьТаблицуСОтборомПоСпискуНаСервере(МассивМарок); КонецПроцедуры
Листинг 9.2.16
Данный код прост и понятен и не требует дополнительных пояснений.
Приступим к серверной процедуре. Во-первых, добавим процедуре параметр МассивМарок, поскольку этот массив мы заполняем в клиентской процедуре и нужно как-то его передать в серверную.
&НаСервере
Процедура ЗаполнитьТаблицуСОтборомПоСпискуНаСервере(МассивМарок)
КонецПроцедуры
Листинг 9.2.17
Следующим шагом, как и в прошлый раз, скопируем код из серверного обработчика самой первой команды (ЗаполнитьТаблицуНаСервере()), и переделаем этот код.
Откроем запрос в конструкторе запроса, перейдём на закладку условия, и создадим новое условие, в котором выберете поле Марка, установим вид сравнения В, а название параметра изменим на МассивМарок.
Рис. 9.2.26
Нажмём кнопку ОК конструктора, и должен получиться такой:
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| Автомобили.Наименование КАК Наименование,
| Автомобили.ГодВыпуска КАК ГодВыпуска,
| Автомобили.ГосНомер КАК ГосНомер,
| Автомобили.Марка КАК Марка,
| Автомобили.Модель КАК Модель,
| Автомобили.КоробкаПередач КАК КоробкаПередач
|ИЗ
| Справочник.Автомобили КАК Автомобили
|ГДЕ
| Автомобили.Марка В(&МассивМарок)";
Листинг 9.2.18 Этот вид сравнения отличен от предыдущего, и сам параметр задан в скобках.
Следующим шагом передадим в качестве параметра в запрос Массив марок (это у нас
параметр процедуры), и выведем всё в таблицу на форме.
Запрос.УстановитьПараметр("МассивМарок",МассивМарок); Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат;
КонецЕсли;
Выборка = Результат.Выбрать(); Пока Выборка.Следующий() цикл
НовСтр = ТаблицаАвтомобилей.Добавить(); ЗаполнитьЗначенияСвойств(НовСтр,Выборка);
КонецЦикла;
Листинг 9.2.19
Проверим, как работает такой отбор.
Рис. 9.2.27
Прекрасно видно, что вывелись именно те марки, которые были отмечены флажками. С отборами мы закончили и теперь перейдём к следующему пункту, это
9.10 Упорядочивание - какая закладка?
Упорядочивание.
Упорядочивание
В предыдущей части мы узнали, что в выборках можно получить данные в определённом порядке, то есть упорядоченные, но для этого нужно использовать только индексируемые поля. В запросах тоже есть такая возможность, и она не зависит от индексации.
Для примера получим данные из справочника Автомобили, где упорядочим два поля.
Первое поле – Год выпуска, второе поле – Гос.номер. На форме предыдущей обработки создадим команду Заполнить таблицу с упорядочиванием, в серверный обработчик которой скопируем код из обработчика самой первой команды (ЗаполнитьТаблицу). Откроем конструктор имеющегося запроса и перейдём на закладку Порядок, в которой выберем два поля: ГодВыпуска и ГосНомер (см. рис. 9.2.28).
Рис. 9.2.28
Нажмём кнопку ОК конструктора запросов, и получится следующий запрос:
Запрос.Текст = "ВЫБРАТЬ
| Автомобили.Наименование КАК Наименование,
| Автомобили.ГодВыпуска КАК ГодВыпуска,
| Автомобили.ГосНомер КАК ГосНомер,
| Автомобили.Марка КАК Марка,
| Автомобили.Модель КАК Модель,
| Автомобили.КоробкаПередач КАК КоробкаПередач
|ИЗ
| Справочник.Автомобили КАК Автомобили
|
|УПОРЯДОЧИТЬ ПО
| ГодВыпуска,
| ГосНомер";
Листинг 9.2.20 Видно, что появились новая конструкция «УПОРЯДОЧИТЬ ПО», после этих слов
через запятую перечисляются поля, по которым будет вестись упорядочивание. Перечислить
можно неограниченное количество полей. Также можно указать и обратную сортировку.
Для того чтобы задать обратную сортировку, зайдём снова в конструктор запроса, прейдём на закладку Порядок и поставим у поля ГосНомер сортировку в Убывание.
Рис. 9.2.29
В этом случае получится следующий запрос:
Запрос.Текст = "ВЫБРАТЬ
| Автомобили.Наименование КАК Наименование,
| Автомобили.ГодВыпуска КАК ГодВыпуска,
| Автомобили.ГосНомер КАК ГосНомер,
| Автомобили.Марка КАК Марка,
| Автомобили.Модель КАК Модель,
| Автомобили.КоробкаПередач КАК КоробкаПередач
|ИЗ
| Справочник.Автомобили КАК Автомобили
|
|УПОРЯДОЧИТЬ ПО
| ГодВыпуска,
| ГосНомер УБЫВ";
Листинг 9.2.21
Мы видим, что рядом с полем ГосНомер появилось слово «УБЫВ». Это означает, что конкретное поле будет отсортировано по убыванию.
Посмотрим, как отсортируются данные.
Рис. 9.2.30
Мы видим, что данные отсортированы по Году выпуска, а потом по Гос.номеру
автомобиля.
Работа с полями
9.11 Работа с полями - что такое разыменование полей?
Если какое-нибудь поле имеет ссылочный тип, то можно получить значение реквизита того объекта, на которое оно ссылается. Для этого достаточно обратиться к реквизиту данного объекта через точку. Эта операция называется разыменование полей.
Продемонстрируем. Для этого доработаем последний запрос: выведем код марки автомобиля.
Создадим новую команду Заполнить таблицу с кодом марки и, как обычно, скопируем в серверный обработчик этой команды код из серверного обработчика самой первой команды.
Откроем конструктор запроса, и на закладке Таблицы и поля развернём таблицу Автомобили. Среди полей этой таблицы обратим внимание на поле Марка, нажмём на плюс рядом с ним и развернём его.
Рис. 9.2.31
В выпадающем списке должны появиться все реквизиты, которые есть у справочника
Марка. Выбираем поле Код.
Рис. 9.2.32
После выбора поля Код у поля Марка таблицы Автомобили Вы увидите, что поле Код вышло через вторую точку. И как нам теперь обращаться к новому полю в выборке по результату запроса уже в коде? Точно узнать об этом можно, перейдя на закладку Объединения/Псевдонимы.
Рис. 9.2.33
Левая таблица Объединения нас пока не интересует, а вот на правую таблицу Псевдонимы обратим внимание. В этой таблице с левой стороны указано название поля, а с правой – что это поле представляет собой в запросе. Левую часть мы можем менять по своему усмотрению. Поэтому изменим поле МаркаКод на КодМарки.
Рис. 9.2.34
Добавим новое поле КодМарки в таблицу значений и соответствующую колонку – в таблицу формы, а потом выведем в таблицу КодМарки, результат показан на рис. 9.2.35.
Рис. 9.2.35
Обращаю Ваше внимание: если Вам нужно получить реквизит поля ссылочного типа, то получать его нужно через разыменование полей, а не уже в выборке через точку. Так Вы существенно оптимизируете запрос.
9.12 Объединение запросов - какая закладка?
Объединение запросов
Поставим задачу: необходимо вывести в одну таблицу документы прибытия и выбытия автомобилей. С теми знаниями, которые есть у Вас, эту задачу можно решить только одним способом: сначала с помощью запроса вывести документы прибытия, а потом выбытия. Но такой ход решения, во-первых, трудоёмкий, а во-вторых, этот процесс будет долог по времени, так как понадобится два раза обращаться к базе. Есть гораздо более быстрый способ – использовать объединение таблиц.
Создадим новую обработку, форму обработки, реквизит формы ТаблицаДокументов с типом ТаблицаЗначений, у которого будет единственная колонка Документ (составной тип данных Ссылка на документы прибытия и выбытия). Данный реквизит разместим на форме в виде таблицы (см. рис. 9.2.36).
Рис. 9.2.36
Создадим команду формы Заполнить таблицу с клиентским и серверным обработчиком, в серверном обработчике команды создадим новый запрос, и у свойства Текст запроса вызовем конструктор. В конструкторе выберем документ Прибытие в гараж и его поле Ссылка (см. рис. 9.2.37).
Рис. 9.2.37
Следующим шагом необходимо создать второй запрос с документом Выбытие из гаража. Для этого перейдём в уже знакомую закладку Объединения/Псевдонимы и в левой таблице нажмём кнопку Добавить.
Рис. 9.2.38
Будет создан новый запрос. Причём конструктор сфокусируется на нём автоматически.
Рис. 9.2.39
Справа у конструктора видны закладки запросов. Выберем во втором запросе таблицу
Выбытие из гаража и поле Ссылка этой таблицы.
Рис. 9.2.40
Если мы нажмём на кнопку Запрос, то увидим текст запроса, в котором у нас создано два запроса, объединенные конструкцией «ОБЪЕДИНИТЬ ВСЕ».
Рис. 9.2.41
Слово «ОБЪЕДИНИТЬ» означает, что два запроса объединены и будут в одной выборке. А слово «ВСЕ» значит, что при объединении возможны дубли. Конкретно в этом случае такое невозможно, но бывают запросы, при объединении которых могут быть одинаковые наборы данных. Чтобы они не дублировались, необходимо убрать слово «ВСЕ» после слова «ОБЪЕДИНИТЬ». Закроем окно Запрос, перейдём на закладку Объединения/Псевдонимы и напротив второго запроса поставим флажок в колонке Без дублей.
Рис. 9.2.42
Если мы сейчас посмотрим на запрос, то слово «ВСЕ» исчезнет из текста.
Рис. 9.2.43
Остался последний момент. У нас у таблицы значений единственная колонка имеет название Документ, а в запросе единственное поле имеет псевдоним Ссылка. Для того чтобы можно было использовать метод ЗаполнитьЗначенияСвойств, изменим у поля псевдоним на Документ, сделаем это в той же закладке Объединения/Псевдонимы (см. рис. 9.2.44).
Рис. 9.2.44
Обратите внимание, непосредственно в запросе псевдоним поля задаётся только у первой таблицы.
Рис. 9.2.45
С конструктором мы закончили, нажмём кнопку ОК, и должен получиться следующий запрос:
Запрос.Текст = "ВЫБРАТЬ
| ПрибытиеВГараж.Ссылка КАК Документ
|ИЗ
| Документ.ПрибытиеВГараж КАК ПрибытиеВГараж
|
|ОБЪЕДИНИТЬ
|
|ВЫБРАТЬ
| ВыбытиеИзГаража.Ссылка
|ИЗ
| Документ.ВыбытиеИзГаража КАК ВыбытиеИзГаража";
Листинг 9.2.22
Код по выводу документов в таблицу значений напишите самостоятельно.
Рис. 9.2.46
Пока наша таблица с документами не очень информативная, чтобы немного повысить информативность, добавим в таблицу на форме поле Дата Прибытия Выбытия, в это поле должны попадать даты прибытия автомобиля и даты выбытия автомобиля. Откроем заново конструктор запроса, и в первом запросе у таблицы ПрибытиеВГараж выберем поле Дата прибытия.
Рис. 9.2.47
Следующим шагом перейдём на закладку Объединения/Псевдонимы и переименуем новое поле в ДатаПрибытияВыбытия.
Рис. 9.2.48
Перейдём во второй запрос, и выберем поле ДатаВыбытия.
Рис. 9.2.49
Вернёмся опять на закладку Объединения /Псевдонимы, и мы увидим, что в правой таблице появилась новая запись:
Рис. 9.2.50
Нам этого не надо, поэтому мы во второй строке в колонке Запрос 2 выбираем поле
ДатаВыбытия.
Рис. 9.2.51
Третья строка сразу исчезнет (см. рис. 9.2.52), после этого нажмём кнопку ОК, и получится следующий запрос (см. листинг 9.2.23).
Рис. 9.2.52
Запрос.Текст = "ВЫБРАТЬ
| ПрибытиеВГараж.Ссылка КАК Документ,
| ПрибытиеВГараж.ДатаПрибытия КАК ДатаПрибытияВыбытия
|ИЗ
| Документ.ПрибытиеВГараж КАК ПрибытиеВГараж
|
|ОБЪЕДИНИТЬ
|
|ВЫБРАТЬ
| ВыбытиеИзГаража.Ссылка,
| ВыбытиеИзГаража.ДатаВыбытия
|ИЗ
| Документ.ВыбытиеИзГаража КАК ВыбытиеИзГаража";
Листинг 9.2.23
Как видно из кода запроса, все псевдонимы к полям присваиваются в самом первом запросе. Доработайте самостоятельно обработку, чтобы даты прибытия и выбытия выводились в таблицу формы.
Рис. 9.2.53
Итак, мы научились объединять запросы. Хочу заметить, что объединять можно не только два, но и три, и четыре запроса. Количество их не ограничено. Но псевдонимы всегда будут присваиваться только в первом запросе.
9.13 Соединение таблиц в запросе - какая закладка?
Соединение таблиц в запросе
Разберём поэтапно небольшую задачу. Сначала всё просто: выведем в таблицу на форме все непомеченные на удаление марки автомобилей из одноимённого справочника. Мы это уже умеем делать. Создадим для этой задачи обработку, форму обработки, реквизит формы ТаблицаМарокИМоделей с типом ТаблицаЗначений и с одной колонкой Марка с соответствующими типом. Созданную таблицу значений разместим на форме в виде таблицы. Создадим команду Заполнить таблицу, которую разместим в командной панели таблицы формы.
Рис. 9.2.54
В серверном обработчике команды напишем запрос и обработку запроса, с помощью которого будем выводить в табличное поле все непомеченные на удаление элементы справочника Марка автомобиля, те, у которых значение стандартного реквизита ПометкаУдаления – Ложь.
&НаСервере
Процедура ЗаполнитьТаблицуНаСервере() Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| МаркиАвтомобилей.Ссылка КАК Марка
|ИЗ
| Справочник.МаркиАвтомобилей КАК МаркиАвтомобилей
|ГДЕ
| МаркиАвтомобилей.ПометкаУдаления = ЛОЖЬ"; Результат = запрос.Выполнить();
Если Результат.Пустой() Тогда Возврат;
КонецЕсли; ТаблицаМарокИМоделей.Очистить(); Выборка = Результат.Выбрать(); Пока Выборка.Следующий() Цикл
НовСтр = ТаблицаМарокИМоделей.Добавить(); ЗаполнитьЗначенияСвойств(НовСтр,Выборка);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицу(Команда) ЗаполнитьТаблицуНаСервере();
КонецПроцедуры
Листинг 9.2.24
Обратите внимание, как мы отсекаем помеченные на удаление элементы справочника.
Делаем мы это при помощи уже знакомой директивы ГДЕ, только в этот раз мы не используем параметр, а сразу присваиваем полю определенное значение ЛОЖЬ. Чтобы это
можно было сделать в конструкторе, в строке условия следует установить флаг Произвольный
и написать вручную код: МаркаАвтомобиля.ПометкаУдаления = ЛОЖЬ
Рис. 9.2.55
При сравнении булевых значений можно не использовать непосредственно оператор сравнения «=», а просто в условии указывать нужное поле, тип которого Булево. Если нужно отобрать записи, в которых это поле Истина, то просто в условии прописываем Булево поле МаркаАвтомобиля.ПометкаУдаления. А если наоборот – записи, где это поле Ложь, то необходимо использовать булевой оператор НЕ, тогда условие будет следующего вида: НЕ МаркаАвтомобиля.ПометкаУдаления. Переделаем условие:
Рис. 9.2.56
Получится запрос следующего вида:
Запрос.Текст = "ВЫБРАТЬ
| МаркиАвтомобилей.Ссылка КАК Марка
|ИЗ
| Справочник.МаркиАвтомобилей КАК МаркиАвтомобилей
|ГДЕ
| НЕ МаркиАвтомобилей.ПометкаУдаления";
Листинг 9.2.25
Сохраним обработку и проверим, как работает запрос.
Рис. 9.2.57
Как видите, все марки автомобилей из справочника МаркиАвтомобилей попали в таблицу формы.
Усложним задачу. В четвёртой главе мы создали подчинённый справочнику МаркиАвтомобилей справочник МоделиАвтомобилей, в котором можно указать модели у конкретных марок.
Нам необходимо узнать, у каких из выведенных марок имеются модели в справочнике МоделиАвтомобилей. Как это сделать? Для этого мы соединим таблицу МаркиАвтомобилей с таблицей МоделиАвтомобилей.
Для наглядности добавим ещё одну колонку в таблицу значений – Модель
соответствующего типа, и поместим её на форму (см. рис. 9.2.58).
Рис. 9.2.58
Изменим последний запрос, зайдём обратно в конструктор запроса, развернём ветку Справочники, из этой ветки выберем таблицу МоделиАвтомобилей, дважды щёлкнув по ней мышкой.
Рис. 9.2.59
Таблица выбралась. Теперь у нас в запросе две таблицы. Нужно установить между ними связь. Связь определяет, по каким полям таблицы будут между собой соединены. Если мы не установим связь, то будут выведены записи всех таблиц одновременно, это будет
комбинация всех записей обеих таблиц. Для установки связи перейдём на закладку Связи и удалим имеющуюся связь, так как наша задача – научиться устанавливать связи самостоятельно.
Рис. 9.2.60
Создадим новую связь, нажав кнопку Добавить. Появится строка с пустыми колонками.
Рис. 9.2.61
Выберем таблицу в колонке Таблица 1. Это будет таблица МаркиАвтомобилей.
Рис. 9.2.62
Выберем таблицу в колонке Таблица 2 – МоделиАвтомобилей.
Рис. 9.2.63
Осталось выбрать поля, по которым будет установлено соединение. Со стороны таблицы МаркиАвтомобилей – это будет поле Ссылка, а со стороны таблицы МоделиАвтомобилей – поле Владелец.
Рис. 9.2.64
В этой задаче мы рассмотрим Левое соединение. Это значит, что будут выведены все
записи из левой таблицы и те записи, для которых будет найдено соответствие, из правой. Поэтому мы поставим галочку рядом с таблицей МаркиАвтомобилей, это значит, что будут выведены все записи из данной таблицы.
Рис. 9.2.65
Перейдём в закладку Таблицы и поля, и выберем поле Ссылка из таблицы
МоделиАвтомобилей.
Рис. 9.2.66
Присвоим этому полю псевдоним Модель.
Рис. 9.2.67
На этом мы закончим конструировать наш запрос, сохраним его, нажав кнопку ОК.
Запрос должен выглядеть так:
"ВЫБРАТЬ
| МаркиАвтомобилей.Ссылка КАК Марка,
| МоделиАвтомобилей.Ссылка КАК Модель
|ИЗ
| Справочник.МаркиАвтомобилей КАК МаркиАвтомобилей
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.МоделиАвтомобилей КАК МоделиАвтомобилей
| ПО МаркиАвтомобилей.Ссылка = МоделиАвтомобилей.Владелец
|ГДЕ
| НЕ МаркиАвтомобилей.ПометкаУдаления"
Листинг 9.2.26
Появилось несколько новых директив – это ЛЕВОЕ СОЕДИНЕНИЕ,
которое обозначает, что таблица МаркаАвтомобиля связана с таблицей МоделиАвтомобиля левым соединением, и директива «ПО», после которой идет перечисление полей, по которым связаны таблицы. В нашем случае они связаны по одному полю, но могут быть связаны и по нескольким.
Сохраним обработку, запустим её в программе «1С: Предприятие» и выполним команду Заполнить таблицу.
Рис. 9.2.68
Первое, что нам бросается в глаза, это то, что два раза выведена строка с маркой Ford, так произошло потому, что у марки автомобиля Ford в справочнике Модели автомобилей две модели – Focus и Consul. Поэтому в результат запроса вышла комбинация всех вариантов.
Также обратите внимание на пустые строки в колонке Модель, это значит, что у данных марок нет моделей в справочнике. И поэтому таблица вернула значение Null.
А как нам вывести только те марки, у которых есть модели? Сделать это можно двумя способами.
Первый способ – используя внутреннее соединение. Для этого зайдем обратно в конструктор запроса, перейдём на закладку Связи и уберём флажок напротив таблицы МаркаАвтомобиля.
Когда нет флажков ни слева, ни справа, это значит, что будет использовано внутреннее соединение. Нажмём на кнопку ОК и должен получиться следующий запрос:
"ВЫБРАТЬ
| МаркиАвтомобилей.Ссылка КАК Марка,
| МоделиАвтомобилей.Ссылка КАК Модель
|ИЗ
| Справочник.МаркиАвтомобилей КАК МаркиАвтомобилей
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.МоделиАвтомобилей КАК МоделиАвтомобилей
| ПО МаркиАвтомобилей.Ссылка = МоделиАвтомобилей.Владелец
|ГДЕ
| НЕ МаркиАвтомобилей.ПометкаУдаления"
Листинг 9.2.27 Видно, что директива ЛЕВОЕ СОЕДИНЕНИЕ поменялась на ВНУТРЕННЕЕ
СОЕДИНЕНИЕ. Это значит, что будут выводиться только те записи, для которых
установлена связь, остальные комбинации будут отметены.
Посмотрим, как в этот раз будет сформирована таблица. Сохраним обработку и перезапустим её заново.
Рис. 9.2.69
Мы видим, что вышли только те марки, у которых имеются подчинённые элементы в справочнике МоделиАвтомобилей.
Второй способ вывести только те марки, у которых есть модели – это использовать
Правое соединение.
Мы не сможем настроить его в конструкторе, поэтому просто вручную напишем в запросе:
"ВЫБРАТЬ
| МаркиАвтомобилей.Ссылка КАК Марка,
| МоделиАвтомобилей.Ссылка КАК Модель
|ИЗ
| Справочник.МаркиАвтомобилей КАК МаркиАвтомобилей
| ПРАВОЕ СОЕДИНЕНИЕ Справочник.МоделиАвтомобилей КАК МоделиАвтомобилей
| ПО МаркиАвтомобилей.Ссылка = МоделиАвтомобилей.Владелец
|ГДЕ
| НЕ МаркиАвтомобилей.ПометкаУдаления"
Листинг 9.2.28
Правое соединение означает, что выберутся все записи из таблицы справа и те записи, которые им соответствуют, из левой таблицы. Посмотрите самостоятельно, что будет с записями.
1С не рекомендует использовать правое соединение, а вместо этого применять левое, просто меняя таблицы местами.
Сделайте это самостоятельно и посмотрите, что получится.
Остался ещё один вид соединения – это Полное соединение. Полное соединение - это, по сути, и левое, и правое соединение, то есть объединяются данные таблицы слева и таблицы справа. Причём выводятся записи, и которые удовлетворяют условию, и все остальные.
Для того чтобы разобрать этот вид соединения, разберём следующую задачу. У нас есть документ Прибытие автомобиля и документ Выбытие автомобиля. Соединим эти два документа по полю Автомобиль полным соединением.
Создадим новую обработку, форму, на которой создадим и разместим реквизит Таблица документов с типом ТаблицаЗначений, у этой таблицы будут следующие колонки: Прибытие (ссылка на документ Прибытие в гараж), Выбытие (ссылка на документ Выбытие из гаража), Автомобиль прибытия и Автомобиль выбытия (ссылка на справочник Автомобили).
Рис. 9.2.70
Создадим команду Заполнить таблицу, и для этой команды создадим обработчики на
сервере и на клиенте. В серверном обработчике создадим новый объект Запрос, откроем конструктор запроса и в конструкторе выберем две таблицы – документ Прибытие в гараж и документ Выбытие из гаража.
Рис. 9.2.71
Следующим шагом выберем такие поля: поле Ссылка документа Прибытие в гараж, поле Ссылка документа Выбытие из гаража, поле Автомобиль документа Прибытие в гараж и поле Автомобиль документа Выбытие из гаража.
Рис. 9.2.72
Перейдём на закладку Объединения /Псевдонимы и переименуем поля по названиям колонок в таблице значений, чтобы их можно было заполнить методом ЗаполнитьЗначенияСвойств.
Рис. 9.2.73
Перейдём на закладку Связи и создадим соединения этих документов по полям
Автомобиль и Гараж.
Рис. 9.2.74
Соединение будет полное, поэтому везде в колонках Все поставим флажки.
Рис. 9.2.75
В результате должен получиться такой запрос:
"ВЫБРАТЬ
| ВыбытиеИзГаража.Ссылка КАК Выбытие,
| ПрибытиеВГараж.Ссылка КАК Прибытие,
| ВыбытиеИзГаража.Автомобиль КАК АвтомобильПрибытия,
| ПрибытиеВГараж.Автомобиль КАК АвтомобильВыбытия
|ИЗ
| Документ.ПрибытиеВГараж КАК ПрибытиеВГараж
| ПОЛНОЕ СОЕДИНЕНИЕ Документ.ВыбытиеИзГаража КАК ВыбытиеИзГаража
| ПО ПрибытиеВГараж.Автомобиль = ВыбытиеИзГаража.Автомобиль
| И ПрибытиеВГараж.Гараж = ВыбытиеИзГаража.Гараж"
Листинг 9.2.29 Самостоятельно напишите код, который будет заполнять таблицу на форме.
Сохраните обработку и посмотрите, как она работает.
Рис. 9.2.76
Попробуйте поменять на внутреннее, левое или правое соединение в запросе и посмотрите, что получится.
9.14 Группировка данных - какая закладка?
Группировка данных
Разберём такую интересную возможность в запросах программы 1С, как Группировка данных.
Для наглядности решим следующую задачу: необходимо узнать, сколько километров проехал каждый автомобиль в сумме за какой-либо период.
Для решения будем использовать документ Прибытие в гараж, у которого есть
реквизит Пробег.
Данный пример имеет чисто академический характер. Нельзя получать какое-то агрегатное значение по документам. Для этого нужно использовать регистры накопления!
Для реализации задачи создадим обработку, форму этой обработки, создадим и разместим на форме реквизит Период с типом СтандартныйПериод и реквизит ТаблицаПробега с типом ТаблицаЗначений, у которой будут колонки Автомобиль (тип СправочникСсылка.Автомобили) и Пробег (тип Число(10,2)). Все созданные реквизиты разместим на форме (см. рис. 9.2.77), а также создадим команду Заполнить таблицу, которую разместим в командной панели таблицы формы.
Рис. 9.2.77
У команды Заполнить таблицу создадим серверный и клиентский обработчик, в серверном обработчике команды Заполнить таблицу создадим объект Запрос с пустым текстом, в конструкторе запроса выберем таблицу Прибытие в гараж, поля – Автомобиль и Пробег.
Рис. 9.2.78
Если мы на этом остановимся, то в наш список будет выведено множество автомобилей, среди которых будут встречаться одинаковые, но с разными пробегами, которые соответствуют разным документам прибытия. Нам это не очень интересно, так как
нужно знать общую цифру по каждому автомобилю. Чтобы получить общую сумму пробега по каждому автомобилю, сделаем группировку по полю Автомобиль. Для этого перейдём на закладку Группировка конструктора запроса.
Рис. 9.2.79
В закладке Группировка три таблицы: Общая со всеми полями (слева), Таблица для групповых полей (справа, вверх) и Таблица для суммируемых полей (справа, вниз). Поместим поле Автомобиль в таблицу групповых полей, а поле Пробег в таблицу суммируемых полей.
Рис. 9.2.80
Следующим шагом необходимо выбрать агрегатную функцию в колонке Функция
таблицы суммируемых полей.
Рис. 9.2.81
Это может быть: сумма всех пробегов автомобиля, количество разных пробегов или общее количество, максимальный или минимальный пробег, среднее значение. По условиям задачи выберем функцию Сумма.
Обращаю Ваше внимание, что в поле групповых полей должны быть все поля, которые выбраны в запрос, но которые не выбраны в суммовые поля. Если мы этого не сделаем, то за нас это сделает компилятор при сохранении запроса. Поэтому если Вы выберете ещё и поле Ссылка, то оно тоже попадёт в группировку, и тогда никаких итоговых цифр по автомобилю не будет, поскольку выйдут записи в связке Автомобиль плюс Документ, и по этой связке будут вычислены суммы.
Осталось перейти в закладку Условия и поставить ограничения по дате.
Рис. 9.2.82
На этом закончим с запросом, после нажатия кнопки ОК конструктора запросов получим запрос, который будет выглядеть следующим образом:
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| ПрибытиеВГараж.Автомобиль КАК Автомобиль,
| СУММА(ПрибытиеВГараж.Пробег) КАК Пробег
|ИЗ
| Документ.ПрибытиеВГараж КАК ПрибытиеВГараж
|ГДЕ
| ПрибытиеВГараж.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
|
|СГРУППИРОВАТЬ ПО
| ПрибытиеВГараж.Автомобиль";
Листинг 9.2.30 Как видите, появилась новая директива СГРУППИРОВАТЬ ПО, которая указывает, по
какому полю будет осуществлена группировка. Кроме того, появилась функция СУММА,
которая суммирует значения нужного нам поля.
Осталось написать код, выводящий полученные данные в таблицу.
Запрос.УстановитьПараметр("ДатаНачала",Период.ДатаНачала); Запрос.УстановитьПараметр("ДатаОкончания", Период.ДатаОкончания);
Результат = Запрос.Выполнить(); Если Результат.Пустой() Тогда
Возврат;
КонецЕсли;
Выборка = Результат.Выбрать(); Пока Выборка.Следующий() Цикл
НовСтр = ТаблицаПробега.Добавить(); ЗаполнитьЗначенияСвойств(НовСтр,Выборка);
КонецЦикла;
Листинг 9.2.31
Сохраним обработку и посмотрим на результат.
Рис. 9.2.83
Остальные функции языка запросов 1С
9.15 поле таблицы сравнивается с каким- нибудь предопределённым значением
В конце этой главы рассмотрим остальные функции языка запросов 1С, которые пригодятся в дальнейшей работе. Это будет не полный перечень, но наиболее часто встречаемый.
И первая функция – это функция Значение.
Значение
Иногда необходимо задать условие, в котором поле таблицы сравнивается с каким- нибудь предопределённым значением. Это может быть конкретный элемент перечисления, либо предопределённый элемент справочника, либо пустая ссылка справочника или документа. Для сравнения с предопределённым значением можно использовать функцию Значение.
Для демонстрации работы этой функции рассмотрим все элементы справочника
Автомобили с автоматической коробкой передач.
Создадим обработку, форму обработки, на форму поместим реквизит ТаблицаАвтомобилей с типом ТаблицаЗначений, который содержит две колонки – Автомобиль и КоробкаПередач с соответствующими типами, а также создадим команду Заполнить таблицу, у которой будут обработчики на сервере и на клиенте.
В серверном обработчике команды создадим новый объект Запрос и откроем конструктор запроса. В конструкторе выберем справочник Автомобили и два поля – Ссылка и КоробкаПередач (у поля Ссылка назначим псевдоним Автомобиль), перейдём на закладку Условие, в котором выберем поле КоробкаПередач и поставим флаг Произвольное.
Рис. 9.2.84
Изменим условие следующим образом:
Рис. 9.2.85
Запрос сконструирован, нажимаем кнопку ОК, в результате должен получиться следующий запрос:
ВЫБРАТЬ
Автомобили.Ссылка КАК Автомобиль, Автомобили.КоробкаПередач КАК КоробкаПередач
ИЗ ГДЕ
Справочник.Автомобили КАК Автомобили Автомобили.КоробкаПередач =
ЗНАЧЕНИЕ(Перечисление.КоробкаПередач.Автоматическая)
Листинг 9.2.32
При помощи функции Значение в языке запросов можно указывать предопределённые значения справочников и планов видов характеристик. Например:
Рис. 9.2.86
А также можно указать пустую ссылку, например, мы можем отобрать все элементы справочника Автомобиль, где не указана марка.
Рис. 9.2.87
Синтаксис выражения, которое нужно указать в функции Значение, должен быть следующим:
НазваниеГруппыМетаданных.НазваниеМетаданного.НазваниеЗначения
Где:
НазваниеГруппыМетаданных – название группы метаданных в единственном числе
(Справочник, Перечисление и т.д.);
НазваниеМетаданного – название конкретного объекта метаданных, как указанно в конфигураторе (КоробкаПередач, МаркиАвтомобилей и т.д.);
НазваниеЗначения – название значения, которое может быть у конкретного метаданного, это или название какого-то значения перечисления, или название предопределённого элемента справочника или ПустаяСсылка.
Допишите сами вывод данных в таблицу значений.
Выбор
Функция Выбор аналогична функции Если в языке программирования, она используется в полях, условиях и пр. и имеет следующий синтаксис:
ВЫБОР
КОГДА <Выражение> ТОГДА <Выражение> КОГДА <Выражение> ТОГДА <Выражение>
……
ИНАЧЕ <Выражение> КОНЕЦ
Вы видите, что может быть использовано неограниченное количество условий
КОГДА.
Рассмотрим пример: будем выводить документы Прибытие в гараж вместе со значением реквизита Пробег, и если значение этого реквизита больше 100, то в поле должна отражаться строка Пробег завышен.
Создадим новую обработку, форму, реквизиты (таблица значений Прибытие с колонками ПрибытиеВГараж, Автомобиль и Пробег (у этой колонки установим составной тип: Число и Строка)) и команду с обработчиками.
В конструкторе запроса выберем таблицу ПрибытиеВГараж, поля Ссылка, Автомобиль и Пробег. Для поля Ссылка укажем псевдоним ПрибытиеВГараж.
Рис. 9.2.88
Выделим поле Пробег, и нажмём на кнопку Изменить текущий элемент.
Рис. 9.2.89
Откроется окно Произвольное выражение, в котором напишем условие:
9.16 Выбор
ВЫБОР
КОГДА ПрибытиеВГараж.Пробег > 100 ТОГДА "Пробег завышен"
ИНАЧЕ ПрибытиеВГараж.Пробег КОНЕЦ
Листинг 9.2.33
Рис. 9.2.90
На этом мы закончим с условием, нажмём кнопку ОК окна Произвольное выражение, осталось зайти в закладку Объединения/Псевдонимы, в которой поменяем название этого поля на Пробег (после написания условия название сбросится).
В результате должен получиться следующий запрос.
ВЫБРАТЬ
ПрибытиеВГараж.Ссылка КАК ПрибытиеВГараж, ПрибытиеВГараж.Автомобиль КАК Автомобиль, ВЫБОР
КОГДА ПрибытиеВГараж.Пробег > 100 ТОГДА "Пробег завышен"
ИНАЧЕ ПрибытиеВГараж.Пробег КОНЕЦ КАК Пробег
ИЗ
Документ.ПрибытиеВГараж КАК ПрибытиеВГараж
Листинг 9.2.34
Код вывода в таблицу напишите самостоятельно.
Рис. 9.2.91
Ссылка
9.17 логический оператор для проверки поля на конкретную ссылку
Рассмотрим еще одну функцию языка запроса – Ссылка. Ссылка – это логический оператор для проверки, имеет ли значение в каком-то поле конкретную ссылку. Обычно применяется, когда некоторое поле имеет составной тип.
Для примера выведем все записи журнал документов Прибытие Выбытие автомобилей. Напомню, что этот журнал может содержать документы двух видов: Прибытие в гараж и Выбытие из гаража, и если в записи присутствует документ с типом ДокументСсылка.ПрибытиеВГараж, то напишем текст «Прибытие», а если иначе (ДокументСсылка.ВыбытиеИзГаража) – текст «Выбытие».
Создадим обработку, форму, команду формы, таблицу значений в качестве реквизита формы с двумя колонками: Документ (тип Строка), и Ссылка (составной тип ДокументСсылка.ПрибытиеВГараж и ДокументСсылка.ВыбытиеИзГаража), также создадим в обработчике команды объект Запрос, и откроем конструктор запроса. В конструкторе нужно выбрать таблицу журнал документов Прибытие-выбытие автомобилей и поле Ссылка.
Рис. 9.2.92
Создадим новое поле вручную. Для этого нужно в окне Поля закладки Таблицы и поля
нажать на кнопку Добавить.
Рис. 9.2.93
В открывшемся окне Произвольное выражение напишем следующий код:
ВЫБОР
КОГДА ПрибытиеВыбытиеАвтомобилей.Ссылка ССЫЛКА Документ.ПрибытиеВГараж ТОГДА "Прибытие"
КОГДА ПрибытиеВыбытиеАвтомобилей.Ссылка ССЫЛКА Документ.ВыбытиеИзГаража ТОГДА "Выбытие"
КОНЕЦ
Листинг 9.2.35
Рис. 9.2.94
После того как сохраним поле запроса, не забудем установить новое название поля –
Документ.
Рис. 9.2.95
Сохраним запрос. Самостоятельно напишите код вывода данных в табличное поле.
Должен получиться примерно такой результат.
Рис. 9.2.96
Синтаксис написания выражения после ключевого слова «ССЫЛКА» следующий:
Где:
НазваниеГруппыМетаданных.НазваниеМетаданного
НазваниеГруппыМетаданных – название группы метаданных в единственном числе
(Справочник, Документ и т.д.);
НазваниеМетаданного – название конкретного объекта метаданных, как указанно в конфигураторе (ПрибытиеВГараж, МаркиАвтомобилей и т.д.);
При помощи функции Ссылка можно устанавливать разные условия. Доработаем предыдущий запрос: выведем только документы ВыбытиеИзГаража.
Рис. 9.2.97
Должен получиться следующий запрос:
ВЫБРАТЬ
ПрибытиеВыбытиеАвтомобилей.Ссылка КАК Ссылка, ВЫБОР
КОГДА ПрибытиеВыбытиеАвтомобилей.Ссылка ССЫЛКА Документ.ПрибытиеВГараж ТОГДА "Прибытие"
КОГДА ПрибытиеВыбытиеАвтомобилей.Ссылка ССЫЛКА Документ.ВыбытиеИзГаража ТОГДА "Выбытие"
КОНЕЦ КАК Документ
ИЗ ГДЕ
ЖурналДокументов.ПрибытиеВыбытиеАвтомобилей КАК ПрибытиеВыбытиеАвтомобилей ПрибытиеВыбытиеАвтомобилей.Ссылка ССЫЛКА Документ.ВыбытиеИзГаража
Листинг 9.2.36
Проверьте самостоятельно работу этого запроса.
Есть NULL
Рассмотрим следующую функцию, которая очень полезна в практической работе, – это функция Есть null.
Для рассмотрения этой функции возьмём запрос, в котором мы соединяли таблицу МаркиАвтомобилей с таблицей МоделиАвтомобилей (см. стр. 646). Тогда у нас получился следующий запрос:
ВЫБРАТЬ
МаркиАвтомобилей.Ссылка КАК Марка, МоделиАвтомобилей.Ссылка КАК Модель
ИЗ
Справочник.МаркиАвтомобилей КАК МаркиАвтомобилей
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.МоделиАвтомобилей КАК МоделиАвтомобилей ПО МаркиАвтомобилей.Ссылка = МоделиАвтомобилей.Владелец
ГДЕ
НЕ МаркиАвтомобилей.ПометкаУдаления
Листинг 9.2.37
Как Вы должны помнить, в том случае когда у марки не было моделей, выходили пустые поля. В этих пустых полях находится значение null, то есть отсутствие каких-либо значений. Такое возникает, как правило, при различных соединениях таблиц (левых, правых, полных), когда не найдены соответствия по полям. С помощью функции Есть Null можно это значение обработать.
Скопируем обработку, где мы соединяли таблицы МаркаАвтомобиля и МодельАвтомобиля (у меня эта обработка под названием Глава9Часть2Обработка3, в запросе исправим на левое соединение). В реквизите с типом ТаблицаЗначений для колонки Модель сделаем составной тип (Строка и СправочникСсылка.МоделиАвтомобилей).
Рис. 9.2.98
Откроем конструктор для уже созданного Запрос, на закладке Таблицы и поля в окне Поля выделим поле МоделиАвтомобилей.Ссылка и нажмём на кнопку Изменить текущий элемент.
Рис. 9.2.99
В открывшемся окне напишим следующий код:
ВЫБОР
КОГДА МоделиАвтомобилей.Ссылка ЕСТЬ NULL ТОГДА "Нет моделей у этой марки"
ИНАЧЕ МоделиАвтомобилей.Ссылка КОНЕЦ
Листинг 9.2.38
В результате должен получиться следующий запрос:
ВЫБРАТЬ
МаркиАвтомобилей.Ссылка КАК Марка, ВЫБОР
КОГДА МоделиАвтомобилей.Ссылка ЕСТЬ NULL ТОГДА "Нет моделей у этой марки"
ИНАЧЕ МоделиАвтомобилей.Ссылка КОНЕЦ КАК Модель
ИЗ
ГДЕ
Справочник.МаркиАвтомобилей КАК МаркиАвтомобилей
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.МоделиАвтомобилей КАК МоделиАвтомобилей ПО МаркиАвтомобилей.Ссылка = МоделиАвтомобилей.Владелец
НЕ МаркиАвтомобилей.ПометкаУдаления
Листинг 9.2.39
Сохраним новую обработку и посмотрим на результат её работы.
Рис. 9.2.100
9.18 метод сравнения, который возвращает Истину, если поле содержит значение null, и Ложь - в противном случае
Мы получили гораздо более красивую картинку, чем было раньше. Функция Есть Null
это метод сравнения, который возвращает Истину, если поле содержит значение null, и возвращает Ложь – в противном случае.
ЕстьNULL
Выражение ЕстьNULL возвращает либо Истину, либо Ложь. Но есть ещё функция, которая позволяет нам не использовать директиву ВЫБОР для подобных сравнений. Это функция ЕстьNull.
Заменим в предыдущем запросе директиву ВЫБОР на данную функцию. Для этого откроем заново конструктор запроса, и перейдём в соответствующее поле.
Измените данное поле.
ЕСТЬNULL(МоделиАвтомобилей.Ссылка, "Нет моделей у этой марки")
Листинг 9.2.40 Сохраним обработку и посмотрим на результат. Результат будет тот же самый.
Функция ЕстьNull имеет следующий синтаксис:
ЕСТЬNULL(<Поле для сравнения>, <Значение вместо null>)
9.19 функция проверяет первый параметр, и если он не равен NULL, то возвращает его, иначе возвращает второй параметр
Эта функция проверяет первый параметр, и если он не равен NULL, то возвращает его, иначе – возвращает второй параметр.
Рекомендуется использовать функцию ЕстьNull для замены пустых значений в полях, но метод сравнения ЕстьNull Вам может пригодиться в условиях.
На этом мы закончим изучение языка запросов платформы 1С. Дано довольно много для начинающих, но, надеюсь, Вы с лёгкостью освоите эту главу, так как всё было предоставлено в виде маленьких шагов и на наглядных примерах.
10.01 Глава 10. Регистры сведений и накоплений - связь ресурса и РС
В десятой главе мы разберём работу с регистрами сведений и регистрами накоплений.
Научимся создавать, изменять и удалять записи регистров сведений и накоплений программным способом, получать выборку записей регистров и работать с ними в запросах.
Начнём с регистров сведений.
10.02 Часть 1. Регистры сведений. Работа с записями - что такое регистр сведения?
Если Вы позабыли, то напомню, что регистры сведений в платформе 1С призваны хранить информацию, которая используется в прикладной задаче. Если информация изменятся со временем, тогда регистр должен быть периодическим, в противном случае мы имеем дело с непериодическим регистром сведений. Например, информация о привязке автомобиля к гаражу не изменяется во времени, но информация о ценах на топливо может изменяться каждый день.
Рис. 10.1.1
Рис. 10.1.2
Как видно на картинках выше, во втором случае (рис. 10.1.2) в записях присутствует поле Период, а в первом случае (рис. 10.1.1) данного поля нет. Вспомним, где мы указываем периодичность регистра.
Рис. 10.1.3
Периодичность может быть разная, самая маленькая для подчинённых регистров сведений – в пределах регистратора (на одну секунду может быть несколько документов- регистраторов), самая большая – в пределах года.
Рис. 10.1.4
Для независимых регистров самая маленькая периодичность – в пределах секунды, самая большая – в пределах года.
Рис. 10.1.5
Вся информация в регистрах хранится в определённых разрезах данных, которые называются Измерениями. У регистра должно быть хотя бы одно измерение (практически
регистр сведений можно сделать и без измерений, но работать с таким регистром будет невозможно). Например, у автомобиля может быть только один основной гараж, поэтому в регистре сведений Основной гараж автомобиля только одно измерение – Автомобиль.
Рис. 10.1.6
А информация о ценах на топливо может храниться в двух разрезах – Тип топлива и Поставщик топлива. Поэтому у регистра ЦеныНаТопливо два измерения – ТипТоплива и ПоставщикТоплива.
Рис. 10.1.7
Сами данные хранятся в Ресурсах.
Рис. 10.1.8
Также можно создавать и использовать Реквизиты.
Рис. 10.1.9
Реквизиты, в отличие от ресурсов, являются не более чем справочной информацией и не возвращаются стандартными функциями работы с регистрами сведений.
Строки регистра сведений с определённым значением ресурса для определённого набора измерений называются Записями.
Из назначения регистра сведений выходит, что не может быть двух записей с одинаковым набором измерений (и одинаковым периодом, в случае периодических регистров). Действительно, например, не может быть для одного автомобиля два основных гаража. Если в прикладной задаче это возможно, то необходимо либо добавить ещё одно измерение (например, перечисление Лето-Зима), либо сделать данный регистр периодическим (например, с периодичностью в год).
Теперь изучим, каким образом вносятся записи в регистр сведений. Осуществить это можно двумя способами: вручную и с помощью документов. За то, каким образом вносятся записи в регистр сведений, отвечает свойство Режим записи. В том случае если записи вносятся вручную пользователем, мы имеем регистр сведений с Независимым режимом записи (как это сделано в регистре сведений Основной гараж автомобиля).
Рис. 10.1.10
Когда же записи создаются документом (регистратором), то мы имеем дело с режимом записи Подчинение регистратору (регистр сведений Цены на топливо).
Рис. 10.1.11
Как следствие, в случае независимого регистра Вы можете редактировать любые записи вручную, в противном случае записи будут закрыты от редактирования. Документ, который будет вносить запись в подчинённый регистр сведений, называется Регистратор, записи регистра жёстко подчинены регистратору.
Рис. 10.1.12
Записи подчинённого регистра создаются при проведении документа-регистратора, соответственно, при отмене проведения документа эти записи будут уничтожаться автоматически (если не настроено иначе).
Итак, всю теоретическую информацию вкратце Вы узнали. Самостоятельно создайте независимый периодический регистр сведений (с периодичностью в пределах месяца) Норма расхода с двумя измерениями: Автомобиль (тип СправчоникСсылка.Автмобили, ведущее) и Сезон (для измерения Сезон создайте перечисление Сезоны (Зима-Лето)) и одним ресурсом Норма (тип Число(10,2)). Добавьте его в подсистему НСИ и, кроме полных прав, дайте права роли Диспетчер – чтение/просмотр.
После того как вспомнили, как создаются регистры сведений, и вспомнили, какие их виды существуют, научимся работать с ними.
10.03 Менеджер регистров - какие есть возможности?
Менеджер регистров
Для того чтобы работать непосредственно с регистром сведений: создать новую запись, удалить или редактировать имеющуюся, получать выборку или срез первых (последних) и т.п., необходимо создать Менеджер регистров, а после уже можно проводить различные вышеперечисленные манипуляции с регистром сведений.
10.04 Менеджер регистров - как создаётся?
Менеджер регистров сведений создаётся так же, как и менеджер справочников и документов: используется свойство глобального контекста, только в этот раз – РегистрыСведений.
МенеджерНормаРасход = РегистрыСведений.НормаРасхода; МенеджерОсновнойГараж= РегистрыСведений.ОсновнойГаражАвтомобиля;
Узнаем, как создать новую запись регистра сведений.
10.05 Менеджер записи - какие есть возможности?
Менеджер записи
Для того чтобы программным способом создать, редактировать или удалить конкретную запись независимого регистра сведений, необходимо использовать объект РегистрСведенийМенеджерЗаписи. С помощью менеджера записи можно получить доступ к записи с необходимым набором полей.
10.06 Менеджер записи - как создаётся?
Создаётся менеджер записи с помощью функции менеджера регистров СоздатьМенеджерЗаписи.
Для того чтобы на практике проверить, как работает этот метод, создадим новую обработку, на форме которой будет три реквизита: Автомобиль, Сезон и Норма расхода с соответствующими типами (как у измерений и ресурса регистра сведений НормаРасхода). А также создадим команду СоздатьЗапись, у которой будут обработчики в клиентском и серверном контексте.
Рис. 10.1.13
В серверном обработчике команды создадим менеджер регистра сведений и менеджер записи.
&НаСервере
Процедура СоздатьЗаписьНаСервере()
МенеджерНормаРасход = РегистрыСведений.НормаРасхода; МенеджерЗаписиНР = МенеджерНормаРасход.СоздатьМенеджерЗаписи();
КонецПроцедуры &НаКлиенте
Процедура СоздатьЗапись(Команда)
СоздатьЗаписьНаСервере(); КонецПроцедуры
Листинг 10.1.1
Переменная МенеджерЗаписиНР, которую мы создали, имеет тип РегистрСведенийМенеджерЗаписи, объекты этого типа предназначены для чтения, редактирования и удаления конкретной записи регистра сведений. Мы можем обращаться к измерениям, ресурсам и реквизитам регистра сведений как к свойствам данного объекта.
Присвоим свойствам данного объекта значения реквизитов формы и запишем новую запись, используя метод Запись() объекта РегистрСведенийМенеджерЗаписи.
&НаСервере
Процедура СоздатьЗаписьНаСервере()
МенеджерНормаРасход = РегистрыСведений.НормаРасхода; МенеджерЗаписиНР = МенеджерНормаРасход.СоздатьМенеджерЗаписи();
МенеджерЗаписиНР.Автомобиль = Автомобиль; МенеджерЗаписиНР.Норма = НормаРасхода; МенеджерЗаписиНР.Сезон = Сезон; МенеджерЗаписиНР.Период = ТекущаяДата(); МенеджерЗаписиНР.Записать();
КонецПроцедуры
Листинг 10.1.2
Самостоятельно проверьте, как работает обработка.
Разберём менеджер записей регистра сведений более подробно. Менеджер записи позволяет управлять записью регистра сведений и применим только для независимых регистров. Доступ к записи обеспечивается путем присвоения значений полям объекта, которые соответствуют измерениям, ресурсам и реквизитам регистра. В примере выше это поля – Автомобиль, Норма расхода и Период.
В примере выше мы не выясняем, есть ли уже запись с нужным набором ключевых полей, а просто записываем её, поэтому если такая запись уже есть, то она перезапишется. Самостоятельно проверьте этот факт.
Иногда это не нужно.
Как сделать так, чтобы регистр Норма расхода не перезаписывался при одинаковых измерениях и периоде? Для этого нам понадобятся два метода объекта РегистрСведенийМенеджерЗаписи – это метод Прочитать и метод Выбран.
Метод Прочитать считывает данные регистра по указанным измерениям и периоду, а метод Выбран возвращает Истину, если есть запись с указанными полями, и возвращает Ложь, если такой нет.
Добавим на форму новую команду Создать запись с проверкой, создадим клиентский и серверный обработчики этой команды, и в серверном обработчике будем проверять, есть ли запись по заданному набору полей. Если нет, создадим её.
&НаСервере
Процедура СоздатьЗаписьСПроверкойНаСервере() МенеджерНормаРасход = РегистрыСведений.НормаРасхода;
МенеджерЗаписиНР = МенеджерНормаРасход.СоздатьМенеджерЗаписи();
МенеджерЗаписиНР.Автомобиль = Автомобиль; МенеджерЗаписиНР.Сезон = Сезон; МенеджерЗаписиНР.Период = ТекущаяДата(); МенеджерЗаписиНР.Прочитать();
Если Не МенеджерЗаписиНР.Выбран() тогда МенеджерЗаписиНР.Автомобиль = Автомобиль; МенеджерЗаписиНР.Норма = НормаРасхода; МенеджерЗаписиНР.Сезон = Сезон; МенеджерЗаписиНР.Период = ТекущаяДата(); МенеджерЗаписиНР.Записать();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура СоздатьЗаписьСПроверкой(Команда) СоздатьЗаписьСПроверкойНаСервере();
КонецПроцедуры
Листинг 10.1.3
Прокомментируем код выше. Как и в прошлый раз, мы создаём объект РегистрСведенийМенеджерЗаписи, следующим шагом присваиваем значения ключевым полям и периоду и используем метод Прочитать. Данный метод считывает записи с регистра по указанным ключевым полям (измерениям) и периоду. Если есть записи с указанным набором полей, то метод Выбран() менеджера записи возвращает Истину, иначе – Ложь. В нашем примере, если метод Выбран вернул значение Ложь (записей нет), то мы заново присваиваем значения измерений и ресурсов и записываем.
Проверьте, как работает новый способ записи.
Рассмотрим, как с помощью объекта Менеджер записи удалить запись с определённым набором ключевых полей.
Создадим новую команду на форме обработки с названием Удалить запись, а также серверные и клиентские обработчики команды. В серверном обработчике напишем следующий код:
&НаСервере
Процедура УдалитьЗаписьНаСервере()
МенеджерНормаРасход = РегистрыСведений.НормаРасхода; МенеджерЗаписиНР = МенеджерНормаРасход.СоздатьМенеджерЗаписи(); МенеджерЗаписиНР.Автомобиль = Автомобиль; МенеджерЗаписиНР.Сезон = Сезон;
МенеджерЗаписиНР.Период = ТекущаяДата(); МенеджерЗаписиНР.Прочитать();
Если МенеджерЗаписиНР.Выбран() тогда МенеджерЗаписиНР.Автомобиль = Автомобиль; МенеджерЗаписиНР.Сезон = Сезон; МенеджерЗаписиНР.Период = ТекущаяДата(); МенеджерЗаписиНР.Удалить();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура УдалитьЗапись(Команда) УдалитьЗаписьНаСервере();
КонецПроцедуры
Листинг 10.1.4 В коде выше мы также создаём объект Регистр сведений Менеджер записи и
присваиваем измерениям значения с формы. Используя методы Прочитать и Выбран,
определяем, есть ли запись с указанным набором полей. И если есть, то снова присваиваем
значения с полей и удаляем запись.
Проверьте работу вышеприведённого кода.
10.07 (Набор записей - знакомство) Набор записей - что это?
Итак, мы научились работать с конкретной записью регистра сведений, используя объект Регистр сведений Менеджер записи. Но иногда возникает необходимость получить доступ к определённому набору записей регистра сведений и в этом наборе либо добавить, либо изменить, либо удалить какую-нибудь запись.
Для этого необходимо использовать объект Регистр сведений Набор записей.
Набор записей
В процессе знакомства с набором записей регистра сведений решим следующую задачу: необходимо изменить норму расхода выбранного автомобиля, помножив текущую норму на определённый коэффициент.
Для этого создадим новую внешнюю обработку, на форме которой будут реквизиты Автомобиль (тип СправочникСсылка.Автомобили) и Коэффициент (тип Число(10,2)), а также создадим команду формы Пересчитать норму расхода, у которой будут серверные и клиентские обработчики.
Рис. 10.1.14
В серверном обработчике команды напишем следующий код:
&НаКлиенте
Процедура ПересчитатьНормуРасхода(Команда) ПересчитатьНормуРасходаНаСервере();
КонецПроцедуры
&НаСервере
Процедура ПересчитатьНормуРасходаНаСервере() НормаРасхода = РегистрыСведений.НормаРасхода; НаборНорм = НормаРасхода.СоздатьНаборЗаписей(); НаборНорм.Отбор.Автомобиль.Установить(Автомобиль); НаборНорм.Прочитать();
Если НаборНорм.Количество() > 0 тогда
Для Каждого НормаЗапись из НаборНорм цикл НормаЗапись.Норма = НормаЗапись.Норма*Коэффициент;
КонецЦикла; НаборНорм.Записать();
КонецЕсли;
КонецПроцедуры
Листинг 10.1.5
Разберём строки кода листинга выше.
Первоначально мы создаём набор записей (который является отдельным объектом) при помощи метода СоздатьНаборЗаписей менеджера регистра сведений. Следующим шагом нам нужно сделать так, чтобы в наборе записей были записи, соответствующие только указанному в реквизите формы автомобилю. Делается это с помощью свойства Отбор объекта НаборЗаписей.
Мы не будем вдаваться в подробности работы с отбором, единственно уточним, что в отборе можно обращаться ко всем измерениям регистра сведений, в том числе и к периоду, если регистр периодический. Но если регистр подчинён регистратору, то отбор возможен только по регистратору! В нашем случае мы можем установить отбор на какое-то измерение регистра, для этого нужно обратиться через точку к этому измерению у свойства Отбор. В результате будет получен объект Элемент отбора, этот объект имеет только один метод – Установить, который устанавливает значение отбора.
Можно установить отбор по одному полю, а можно и по нескольким. В случае отбора по нескольким полям логическая связь между полями будет осуществляться с помощью булевой операции «И».
Имейте в виду, что отбор в регистрах сведений можно устанавливать только на равенство!
После того как мы установили отбор, нам необходимо извлечь данные из базы в объект Набор записей, осуществляется это с помощью метода Прочитать. Метод Прочитать считывает записи из базы данных с учётом установленных отборов и записывает их в НаборЗаписей.
Объект Набор записей является коллекцией объектов Запись регистров сведений. Не путать с объектом Менеджер записей регистров сведений: объект Запись регистров сведений не создаётся самостоятельно, в отличие от менеджера записей, а доступ к нему предоставляется другими объектами, в нашем случае это – Набор записей.
Замечу, что до того, как мы выполнили метод Прочитать, наш набор записей был пустой, заполнился он именно в результат выполнения вышеприведённого метода. Поэтому после того, как мы с помощью метода Количество проверили есть ли в принципе записи по данному отбору, мы обходим коллекцию набора записей с помощью цикла: Для Каждого…Цикл. В нашем случае переменная НормаЗапись является объектом Запись регистров сведений. С помощью этого объекта мы получаем доступ ко всем полям записи регистра сведений и можем их изменять на своё усмотрение. После того как мы поменяли все нужные нам записи, соответствующие отбору, необходимо записать набор. Обращаю внимание, что записывается именно набор в целом, а не конкретная запись по отдельности, поэтому мы делаем запись уже вне цикла.
Метод Записать объекта Набор записей имеет следующий синтаксис.
Записать(<Замещать>)
Параметр Замещать должен иметь тип Булево, и если установлено значение Истина, то записи по данному отбору будут удалены и вместо них записаны новые, а если – Ложь, то будут добавлены новые записи. По умолчанию установлено значение Истина.
Посмотрите, как работает обработка. Создайте с помощью предыдущей обработки две записи с одним автомобилем (нормы расхода для зимы и лета соответственно).
Как Вы увидите, написанный Вами код изменяет значение поля Норма расхода сразу по нескольким записям.
Продолжим изучать наборы записей.
С помощью набора записей можно не только изменять имеющиеся записи, но и добавлять новые. Это удобно использовать, когда необходимо добавить сразу несколько записей одновременно. Алгоритм добавления нескольких записей с помощью объекта Набор записей будет работать гораздо быстрее, чем с помощью объекта Менеджер записи.
Чтобы продемонстрировать это, создадим обработку, на форме которой будет реквизит СписокАвтомобилей с типом СписокЗначений (тип значения СправочникСсылка.Автомобили), в этот список будем добавлять нужные нам автомобили, реквизиты Сезон (ссылка на перечисление Сезоны) и Норма расхода (Число (10,2)), а также команду Заполнить нормы расхода. Реквизит СписокАвтомобилей разместим на форме в виде таблицы, добавив всего одну колонку, которая соответствует реквизиту списка Значение.
Рис. 10.1.15
При выполнении команды будем создавать набор записей регистра сведений Норма расхода, где каждая запись будет соответствовать автомобилю из списка с установленным расходом для указанного сезона.
Чтобы нельзя было в списке выбрать одинаковые автомобили, а потом создать несколько записей списка с одинаковыми автомобилями, создадим обработчик события ОбработкаВыбора единственной колонки таблицы (соответствует реквизиту списка Значение). Это событие вызывается после выбора значения в список, но до помещения выбранного значения в элемент управления.
Рис. 10.1.16
У события будет единственный клиентский обработчик команды, в котором напишем следующий код:
&НаКлиенте
Процедура СписокАвтомобилейЗначениеОбработкаВыбора(Элемент,
ВыбранноеЗначение, СтандартнаяОбработка)
Если СписокАвтомобилей.НайтиПоЗначению(ВыбранноеЗначение) <> Неопределено Тогда СтандартнаяОбработка = Ложь;
КонецЕсли;
КонецПроцедуры
Листинг 10.1.6 Данный код не требует дополнительных пояснений, так как работу со списком
значений мы уже проходили.
После того как мы провели всю подготовительную работу, напишем основной код в серверном обработчике команды Заполнить нормы расхода.
&НаСервере
Процедура ЗаполнитьНормыРасходаНаСервере()
Если СписокАвтомобилей.Количество() = 0 тогда Возврат;
КонецЕсли;
НаборЗаписей = РегистрыСведений.НормаРасхода.СоздатьНаборЗаписей(); Для Каждого ЭлСписка из СписокАвтомобилей цикл
Если Не ЗначениеЗаполнено(ЭлСписка.Значение) Тогда Продолжить;
КонецЕсли;
Автомобиль = ЭлСписка.Значение; НоваяЗапись = НаборЗаписей.Добавить(); НоваяЗапись.Автомобиль = Автомобиль; НоваяЗапись.Норма = НормаРасхода; НоваяЗапись.Сезон = Сезон; НоваяЗапись.Период = ТекущаяДата();
КонецЦикла; НаборЗаписей.Записать(Ложь);
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьНормыРасхода(Команда) ЗаполнитьНормыРасходаНаСервере();
КонецПроцедуры
Листинг 10.1.7
Разберём вышеприведённый код. Сначала мы проверяем, есть ли автомобили в списке, и если их нет, то выходим из процедуры. Следующим шагом создаём набор записей, потом мы обходим список значений Автомобили циклом. Внутри цикла с помощью функции Добавить объекта Регистр сведений Набор записей создаётся переменная НоваяЗапись, имеющая тип Регистр сведений Запись. Свойствами данного объекта являются измерения, реквизиты и ресурсы регистра сведений. Поэтому обращаемся к ним напрямую и присваиваем нужные значения. После того как обошли цикл – сохраняем набор записей.
Причём параметр Замещать мы ставим в Ложь, чтобы не удалялись старые записи. У данного решения есть один существенный недостаток – если уже есть запись с такими ключевыми полями, то будет сгенерирована ошибка.
Рис. 10.1.17
Поэтому групповая запись в регистр сведений без использования отборов осуществима только для начального заполнения пустого регистра. В иных случаях необходимо работать с отборами.
Создадим новую команду Заполнить нормы расхода с проверкой, в серверном обработчике которой будет следующий код:
&НаСервере
Процедура ЗаполнитьНормыРасходаСПроверкойНаСервере() Если СписокАвтомобилей.Количество() = 0 тогда
Возврат;
КонецЕсли;
НаборЗаписей = РегистрыСведений.НормаРасхода.СоздатьНаборЗаписей(); Для Каждого ЭлСписка из СписокАвтомобилей цикл
Автомобиль = ЭлСписка.Значение; НаборЗаписей.Отбор.Автомобиль.Установить(Автомобиль); НаборЗаписей.Отбор.Сезон.Установить(Сезон); НаборЗаписей.Отбор.Период.Установить(НачалоМесяца(ТекущаяДата())); НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() = 0 тогда НоваяЗапись = НаборЗаписей.Добавить(); НоваяЗапись.Автомобиль = Автомобиль; НоваяЗапись.Норма = НормаРасхода; НоваяЗапись.Сезон = Сезон; НоваяЗапись.Период = ТекущаяДата(); НаборЗаписей.Записать(Истина);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Листинг 10.1.8 В этом коде мы с помощью отборов получаем определённый набор записи, который
должен соответствовать установленным отборам. И если данных по установленным отборам нет, то создаём новую запись.
Имейте в виду, что после того как мы применили метод Прочитать к набору записей, состав набора изменится согласно установленному отбору.
С помощью набора записей можно не только создавать новые записи, но и удалять имеющиеся. Дополните в форму новую команду Удалить набор записей, при выполнении которой будут удаляться все записи, которые соответствуют автомобилям из списка, сезону и текущему месяцу.
В серверном обработчике команды будет следующий код:
&НаСервере
Процедура УдалитьНаборЗаписейНаСервере()
Если СписокАвтомобилей.Количество() = 0 тогда Возврат;
КонецЕсли;
НаборЗаписей = РегистрыСведений.НормаРасхода.СоздатьНаборЗаписей(); Для Каждого ЭлСписка из СписокАвтомобилей цикл
Автомобиль = ЭлСписка.Значение; НаборЗаписей.Отбор.Автомобиль.Установить(Автомобиль); НаборЗаписей.Отбор.Сезон.Установить(Сезон); НаборЗаписей.Отбор.Период.Установить(НачалоМесяца(ТекущаяДата())); НаборЗаписей.Прочитать();
НаборЗаписей.Очистить(); НаборЗаписей.Записать();
КонецЦикла;
КонецПроцедуры
Листинг 10.1.9 Разберём этот код. Как и в предыдущем алгоритме, мы проходим по списку значений
и внутри цикла производим отбор по автомобилю, после чего считываем данные из базы,
очищаем считанный набор и в конце записываем уже пустой набор данных.
Также можно удалить конкретный элемент набора записей. Изменим наш код: будем с помощью отборов считывать записи по всем автомобилям из списка (со всеми сезонами и периодами), а удалим только те записи, у которых значение измерения Сезон равно реквизиту Сезон формы (создадим отдельную процедуру).
&НаСервере
Процедура УдалитьНаборЗаписей2НаСервере()
Если СписокАвтомобилей.Количество() = 0 тогда Возврат;
КонецЕсли;
НаборЗаписей = РегистрыСведений.НормаРасхода.СоздатьНаборЗаписей(); Для Каждого ЭлСписка из СписокАвтомобилей цикл
Автомобиль = ЭлСписка.Значение; НаборЗаписей.Отбор.Автомобиль.Установить(Автомобиль); НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() = 0 Тогда Продолжить;
КонецЕсли;
МассивНаУдаление = Новый Массив;
Для Каждого Запись из НаборЗаписей цикл Если Запись.Сезон = Сезон Тогда
МассивНаУдаление.Добавить(Запись); КонецЕсли;
КонецЦикла;
Если МассивНаУдаление.Количество() > 0 Тогда
Для н = 0 по МассивНаУдаление.ВГраница() цикл НаборЗаписей.Удалить(МассивНаУдаление[н]);
КонецЦикла; НаборЗаписей.Записать();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Листинг 10.1.10
В том варианте, если есть нужные записи, мы их записываем в массив, который заполняем внутри цикла. После того как массив заполнен, мы обходим его и удаляем каждый элемент массива, который представляет собой запись регистра сведений, с помощью метода Удалить объекта Набор записей.
Проверьте, как работает обработка.
Итак, мы с Вами научились создавать, редактировать и удалять записи независимых регистров сведений. Научимся работать с регистрами сведений, подчинённых регистратору. Рекомендую все манипуляции с подчинёнными регистрами сведений проводить только посредством документов, то есть если необходимо поменять значение какого-нибудь ресурса в регистре, то необходимо сначала поменять значение соответствующего реквизита в документе, после чего перепровести данный документ.
В документе Установка цен на топливо в процедуре Обработка проведения уже создан код, в результате выполнения которого будет создаваться запись в регистре сведений ЦеныНаТопливо. Он был создан, когда мы в четвёртой главе при помощи конструктора создавали движения документа.
Рис. 10.1.18
В этом коде обращение к набору записей регистра сведений ЦеныНаТоплива
осуществляется посредством свойства документа Движения.
Мы присваиваем значение Истина свойству Записывать объекта Регистр сведений Набор записей для того, чтобы при проведении документа создавались записи в регистре сведений.
Обращаю Ваше внимание, что свойство Движения.ЦеныНаТоплива имеет тип Регистр
сведений Набор записей, поэтому для данного свойства можно применять все методы объекта
Набор записей.
В цикле по табличной части документа мы создаём новую запись, используя метод Добавить объекта Регистр сведений Набор записей. И присваиваем значение измерениям и ресурсам.
Как Вы видите, в данном случае метод Записать объекта Набор записей не используется, это за нас сделает платформа 1С. Достаточно установить свойство Записывать в значение Истина.
Резюме
10.08 различия менеджера записи и набора записей
В этой части мы научились работать с регистрами сведений: создавать, редактировать и удалять записи. Вы поняли, что создавать записи можно как с помощью менеджера записи, так и с помощью набора записей.
Менеджер записи подходит, когда необходимо создать одну или несколько записей в регистр без особого контроля.
В то же время набор записей – более универсальный инструмент. Благодаря свойству Отбор данного объекта можно осуществлять любые выборки по любым признакам, что позволит Вам исключить дублирование вновь созданных записей регистров сведений, также Вы сможете редактировать и удалять имеющиеся записи.
10.09 Часть 2. Регистры сведений. Получение данных - метод формирует выборку записей регистров сведений
Во второй части десятой главы мы научимся получать данные из регистров сведений.
Сделать это можно двумя способами: используя методы менеджера регистров сведений и используя язык запросов платформы 1С.
Начнём с методов менеджера регистров.
Выбрать
10.10 метод формирует выборку записей регистров сведений
Первый метод, который мы с Вами разберём, это метод Выбрать. Метод Выбрать
формирует выборку записей регистров сведений.
Этот метод имеет несколько вариантов синтаксиса.
Первый вариант синтаксиса – для периодического регистра сведений.
Выбрать(<НачалоИнтервала>, <КонецИнтервала>, <Отбор>, <Порядок>)
Вариант синтаксиса выше похож на синтаксис метода Выбрать для документов, который мы проходили в восьмой главе. Возвращает он объект Выборка регистров сведений. Все параметры метода Выбрать являются необязательными. Разберём каждый из них.
Первый и второй параметры задают начало и конец интервала времени, за который будут выбираться записи регистра сведений.
Если не будет указан параметр НачалоИнтервала, то выборка будет начинаться с самой первой по времени записи. А если не указан параметр КонецИнтервала, то выборка
будет оканчиваться самой последней по времени записью.
Третий параметр Отбор – это структура, в которой в качестве ключа идёт название поля, по которому будет выполнен отбор, а в качестве значения структуры – значение отбора по этому полю. Отбор может осуществляться только по измерениям и реквизитам, для которых установлен признак Индексировать, либо – признак Ведущие.
Посмотрим, где это устанавливается.
Рис. 10.2.1
Обращаю Ваше внимание на то, что структура может содержать только один элемент. Если необходимо осуществить выборку с отбором по двум или более полям, то необходимо использовать язык запросов.
И последний параметр – это Порядок. Данный параметр имеет тип Строка и может содержать название измерения или реквизита, по которому необходимо осуществить упорядочивание выборки. Название полей можно применять с уже знакомыми Вам словами Возр и Убыв. Это значит, что упорядочивание будет проходить либо по возрастанию, либо по убыванию.
Синтаксис метода Выбрать для непериодического регистра точно такой же, только без параметров начала и конца интервала.
Выбрать(<Отбор>, <Порядок>)
Параметры Отбор и Порядок имеют точно такой же функциональный смысл, как и в предыдущем варианте синтаксиса.
Метод Выбрать является функцией, которая возвращает выборку.
Для закрепления решим небольшую задачку: создадим обработку, форму, на форме создадим реквизит ПоставщикТоплива с соответствующим типом (ссылка на справочник Контрагенты) и реквизит ЦеныНаТопливо, тип которого будет ТаблицаЗначений с колонками Период, ТипТоплива и Цена с соответствующими типами.
Рис. 10.2.2
При выборе поставщика будем заполнять таблицу данными из регистра сведений
Цены на топливо для выбранного поставщика, которые соответствуют текущему году.
Для того чтобы отбор работал, необходимо у измерения ПоставщикТоплива у регистра сведений ЦеныНаТопливо установить свойство Ведущее.
Рис. 10.2.3
В модуле формы обработки напишем серверную процедуру, которая осуществляет выборку из регистра и заполняет таблицу значений.
&НаСервере
Процедура ПолучитьВыборку(ДатаТекущая) ЦеныНаТопливо.Очистить();
МенеджерЦенНаТопливо = РегистрыСведений.ЦеныНаТопливо; Отбор = Новый Структура; Отбор.Вставить("ПоставщикТоплива",ПоставщикТоплива);
Выборка = МенеджерЦенНаТопливо.Выбрать(НачалоГода(ДатаТекущая),
КонецГода(ДатаТекущая), Отбор);
Пока Выборка.Следующий() цикл
НоваяСтрока = ЦеныНаТопливо.Добавить(); НоваяСтрока.Период = Выборка.Период; НоваяСтрока.ТипТоплива = Выборка.ТипТоплива;
НоваяСтрока.Цена = Выборка.Цена; КонецЦикла;
КонецПроцедуры // ПолучитьВыборку(ДатаТекущая)
Листинг 10.2.1
Прокомментируем код выше. В процедуру мы передаём один параметр – это текущая дата. Советую не использовать системную функцию 1С ТекущаяДата() внутри собственных процедур или функций, а передавать её в качестве параметра, это поможет в дальнейшем избежать множества проблем.
Первым шагом мы очищаем таблицу значений. Затем создаём менеджер регистра сведений и новую структуру, которую называем Отбор, у этой структуры единственный элемент с ключом ПоставщикТоплива и со значением, в котором укажем одноимённый реквизит формы. Обратите внимание: название ключа должно совпадать с названием измерения регистра сведений.
Следующим шагом получаем выборку из регистра при помощи метода Выбрать менеджера регистра сведений. У данного метода используем три параметра: начало и конец интервала и структура, по которой будет осуществляться отбор. В конце мы идём по выборке и заполняем нашу таблицу значений.
После того как мы создали процедуру в модуле формы, будем её использовать в событии ПриИзменении элемента формы ПолеВвода, который связан с реквизитом ПоставщикТоплива.
Зайдём с палитру свойств этого элемента и создадим обработчик события
ПриИзменении.
Рис. 10.2.4
В обработчике события и будем вызывать процедуру ПолучитьВыборку.
&НаКлиенте
Процедура ПоставщикТопливаПриИзменении(Элемент) ПолучитьВыборку(ТекущаяДата());
КонецПроцедуры
Листинг 10.2.2
Сохраним обработку и посмотрим, как она работает.
Рис. 10.2.5
10.11 «Срез последних» - что получает?
Как видите, осуществляется выборка записей с нужными нам автомобилями за текущий год. Самостоятельно подправьте обработку, чтобы можно было указывать дату пользователю.
Рассмотрим ещё два метода получения данных, которые будут новыми для Вас. Это –
Срез первых и Срез последних записей.
«Срез последних»
Метод менеджера регистра сведений СрезПоследних получает наиболее поздние записи регистра сведений на указанную дату. Метод СрезПоследних применим только для периодических регистров сведений.
У этого метода имеется следующий синтаксис:
СрезПоследних(<КонецПериода>, <Отбор>)
Первый параметр – дата, на которую берётся срез последних записей регистра. Второй параметр – это отбор, данный параметр аналогичен отбору в выборках.
В отличие от предыдущего метода, метод СрезПоследних возвращает таблицу значений, поля которой соответствуют названиям измерений и ресурсов регистра и имеют соответствующие типы. В этой таблице содержатся наиболее поздние записи регистра сведений.
Возможно, у Вас возникнет вопрос: «Чем этот метод отличается от простой выборки?» Продемонстрируем ответ на этот вопрос на примере: на форме будем вводить дату и осуществлять выборку из регистра ЦеныНаТопливо с конечной датой, равной введённой, и срез последних на введённую дату.
Создадим обработку, форму, на которой создадим реквизит ДатаСреза с типом значения Дата (состав Дата и время) и две таблицы значений: Выборка и СрезПоследних. Колонки этих табличных полей будут соответствовать названиям измерений и ресурсов
регистра сведений ЦеныНаТопливо, а также создадим команду формы Заполнить таблицы, которую разместим в командной панели формы.
Рис. 10.2.6
Внутри серверной процедуры обработчика команды напишем следующий код:
&НаСервере
Процедура ЗаполнитьТаблицыНаСервере() Выборка.Очистить(); СрезПоследних.Очистить();
РегЦеныНаТопливо = РегистрыСведений.ЦеныНаТопливо; ВыборкаИзРегистра = РегЦеныНаТопливо.Выбрать(,ДатаСреза); Пока ВыборкаИзРегистра.Следующий() цикл
НоваяСтрока = Выборка.Добавить(); ЗаполнитьЗначенияСвойств(НоваяСтрока,ВыборкаИзРегистра);
КонецЦикла;
ТЗСрезПоследних = РегЦеныНаТопливо.СрезПоследних(ДатаСреза); СрезПоследних.Загрузить(ТЗСрезПоследних);
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицы(Команда) ЗаполнитьТаблицыНаСервере();
КонецПроцедуры
Листинг 10.2.3 В коде выше мы первоначально получаем выборку из регистра, причём датой
окончания выборки ставим дату среза, затем заполняем таблицу значений формы Выборка.
Следующим шагом получаем срез последних из регистра, и результат сразу загружаем в реквизит формы – таблицу значений СрезПоследних.
Сохраним обработку и посмотрим, что получится.
Рис. 10.2.7
Как видите, в случае выборки вывелись все записи до Даты среза. Но в случае Среза Последних мы имеем только одну запись комбинации полей, наиболее близкую к дате среза. Смысл метода Срез Последних в том, что из имеющегося множества записей с одинаковым набором измерений, разбросанных по датам, выбирается та запись, дата которой меньше даты среза и наиболее близко к ней расположена. Если в регистре есть записи, период которых более поздний, чем дата среза, то они не попадут в результат. Метод возвращает все записи, с любыми комбинациями измерений, дата которых меньше даты среза и наиболее близка к ней.
Поработайте с данной обработкой и посмотрите, какие записи будет возвращать метод в зависимости от того, какая дата указана в поле ввода.
10.12 «Срез первых» - что получает?
«Срез первых»
В отличие от предыдущего метода, СрезПервых возвращает наиболее ранние записи регистра. Этот метод имеет синтаксис, аналогичный синтаксису предыдущего метода:
СрезПервых(<НачалоПериода>, <Отбор>)
Где первый параметр – это начало периода, начиная с которого будут выбираться записи регистра сведений. Второй параметр – Отбор – выполняет ту же функцию, что и в выборках. Данный метод также является функцией, которая возвращает таблицу значений.
Для наглядности доработаем нашу предыдущую обработку: создадим на форме третью таблицу СрезПервых и будем выводить срез первых по реквизиту ДатаСреза в эту третью таблицу.
Рис. 10.2.8
Допишем код в серверном обработчике команды Заполнить таблицы.
ТЗСрезПервых = РегЦеныНаТопливо.СрезПервых(ДатаСреза); СрезПервых.Загрузить(ТЗСрезПервых);
Листинг 10.2.4
Сохраним обработку, перезапустим её и посмотрим на результат.
Рис. 10.2.9
Как Вы видите из результата работы обработки, метод возвращает записи, которые
следуют после даты среза. Причём для определённой комбинации измерений возвращается только одна запись, период которой позже даты среза и наиболее близок к ней. Все последующие записи отбрасываются.
То есть данный метод – полная противоположность методу СрезПоследних. Поэкспериментируйте с новым методом самостоятельно.
Выборка, «срез последних» и «срез первых» в запросе
10.13 Выборка, «срез последних» и «срез первых» в запросе - какие виртуальные таблицы?
Разберём, как получать данные из регистров сведений в запросах. Для этого можно использовать виртуальные таблицы СрезПоследних и СрезПервых. Они применимы только к периодическим регистрам сведений.
Виртуальные таблицы языка запросов – это новое для Вас понятие. Виртуальная таблица не существует в базе данных, она создаётся во время выполнения запроса, а потом уничтожается. Разработчик не может самостоятельно создать какой-либо вид виртуальной таблицы, их перечень всегда ограничен платформой 1С. Например, для периодических регистров сведений можно создать только две виртуальные таблицы, это СрезПоследних и СрезПервых, которые возвращают наиболее поздние и наиболее ранние записи регистров сведений по аналогии с одноимёнными методами менеджера регистра сведений.
Изучим на примере, как работать с виртуальными таблицами в запросах.
Создадим обработку с формой, на форме создадим реквизит ДанныеЗапроса с типом ТаблицаЗначений, названия и типы колонок этой таблицы значений должны совпадать с названиями и типами измерений и ресурса регистра сведений НормаРасхода (плюс колонка Период с типом Дата). Также создадим реквизит формы ДатаСреза с типом Дата (состав Дата и время) В командной панели формы создадим подменю Выполнить запрос, в которое будем помещать различные команды формы.
Первая команда формы будет Простая выборка, для этой команды создадим серверные и клиентские обработчики. В серверном обработчике создадим запрос, который возвращает простую выборку регистра сведений. Для этого в конструкторе запроса найдём регистр сведений НормаРасхода и выберем его, а также выберем поля: Период, Автомобиль, Сезон и Норма.
Рис. 10.2.10
среза.
Зададим условия, чтобы выбирались записи с периодом меньше или равным дате
Рис. 10.2.11
Всё, запрос создан, и он должен иметь следующий вид:
&НаСервере
Процедура ПростаяВыборкаНаСервере() Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| НормаРасхода.Период КАК Период,
| НормаРасхода.Автомобиль КАК Автомобиль,
| НормаРасхода.Сезон КАК Сезон,
| НормаРасхода.Норма КАК Норма
|ИЗ
| РегистрСведений.НормаРасхода КАК НормаРасхода
|ГДЕ
| НормаРасхода.Период <= &ДатаСреза";
КонецПроцедуры
Листинг 10.2.5
Доделайте заполнение таблицы самостоятельно. В моей базе такой состав регистра сведений:
Рис. 10.2.12
И получился следующий результат работы запроса:
Рис. 10.2.13
Данный запрос возвращает те же данные, что и выборка. Вы спросите: «В чём удобство запроса, в отличие от выборки менеджера регистра?». А удобство в том, что Вы практически не ограничены по отбору и сортировке, в отличие от метода менеджера регистра, и можете осуществлять отбор и сортировку даже по неиндексируемым полям и по ресурсам.
Например, можно сделать так:
ВЫБРАТЬ
НормаРасхода.Период КАК Период, НормаРасхода.Автомобиль КАК Автомобиль, НормаРасхода.Сезон КАК Сезон, НормаРасхода.Норма КАК Норма
ИЗ ГДЕ
РегистрСведений.НормаРасхода КАК НормаРасхода
НормаРасхода.Период МЕЖДУ &ДатаНачала И &ДатаОкончания И НормаРасхода.Сезон = &Сезон
И НормаРасхода.Норма >= &Норма
Листинг 10.2.6
Мы ввели отбор по ресурсу и измерению, и это будет корректно работать. Поэтому мой совет: если Вам надо получить быстро простую выборку из регистра сведений без лишних отборов и сортировок, используйте метод менеджера запроса. А если появляются дополнительные требования к выборке, то работайте с языком запросов.
Разберём работу с виртуальными таблицами СрезПоследних и СрезПервых. Развернём ветку Регистры сведений в дереве База данных конструктора запроса. Вы увидите, что у некоторых регистров, помимо самих регистров, есть таблицы, название которых состоит из названия регистра, соединённого посредством точки со словосочетанием СрезПоследних или СрезПервых (рис. 10.2.14).
Это виртуальные таблицы, как уже было сказано, они нигде не хранятся, а вычисляются при выполнении запроса.
Рис. 10.2.14
Для работы с виртуальной таблицей СрезПоследних создадим новую команду Срез последних, создадим обработчики команды в клиентском и серверном контексте. В серверном обработчике создадим пустой запрос и запустим конструктор запроса. В конструкторе выберем таблицу СрезПоследних регистра сведений НормыРасхода.
Рис. 10.2.15
Если выделить виртуальную таблицу, то становится активной кнопка Параметры виртуальной таблицы.
Рис. 10.2.16
После нажатия на эту кнопку откроется форма Параметры виртуальной таблицы.
Рис. 10.2.17
В этой форме можно установить период среза и условия. В поле Период необходимо указывать параметр, в который будет передана какая-нибудь дата.
Рис. 10.2.18
В Условие можно задать ограничение на выборку. Например, мы можем сделать срез последних по всем нормам расхода, у которых сезон – Лето. Причём в качестве полей для условия можно выбирать и измерения, и ресурсы, и реквизиты. Также можно выполнять любую логическую связку: И, ИЛИ, НЕ.
Рис. 10.2.19
Обратите на это внимание, что ограничение на выборку виртуальной таблицы СрезПоследних (как и СрезПервых) нужно делать именно посредством условия виртуальной таблицы. Ограничивать виртуальную таблицу через условия запроса не оптимально с точки зрения производительности!
После того как мы задали условия виртуальной таблицы, выберем все поля виртуальной таблицы и сохраним запрос.
Рис. 10.2.20
В результате должен получиться следующий запрос:
ВЫБРАТЬ
НормаРасходаСрезПоследних.Период КАК Период, НормаРасходаСрезПоследних.Автомобиль КАК Автомобиль, НормаРасходаСрезПоследних.Сезон КАК Сезон, НормаРасходаСрезПоследних.Норма КАК Норма
ИЗ
РегистрСведений.НормаРасхода.СрезПоследних(&ДатаСреза,
Сезон =
ЗНАЧЕНИЕ(Перечисление.Сезоны.Лето)
) КАК НормаРасходаСрезПоследних
Листинг 10.2.7
Создайте самостоятельно обработку этого запроса, и выведите данные в таблицу формы. На моей базе получился такой подобный результат:
Рис. 10.2.21
Виртуальные таблицы СрезПоследних и СрезПервых возвращают тот же результат, что и одноимённые методы менеджера регистра сведений. Только они более удобны в плане отборов, сортировки и т.п.
Небольшое задание. Создайте новую команду Срез первых, в которой при помощи виртуальной таблицы СрезПервых получайте «срез первых» регистра сведений НормаРасхода для сезона Зима.
10.14 когда использовать менеджер регистра сведений, когда запрос?
Резюме
На этом мы закончим изучать способы получения данных из регистров сведений.
Повторюсь: если необходимо получить простую выборку или простой срез, то используйте методы менеджера регистра сведений, в более сложных случаях используйте виртуальные таблицы СрезПервых и СрезПоследних языка запросов платформы 1С. Если имеется необходимость поставить отбор на срез первых или срез последних, то в целях оптимизации производительности необходимо устанавливать в условиях виртуальной таблицы.
10.15 Часть 3. Регистры накопления. Работа с записями - из чего состоит РН?
Освежим и углубим информацию о регистрах накопления, которую Вы получили в четвёртой главе.
Как Вы помните (если не помните, то освежите свою память, пролистав четвёртую главу), регистр накопления предназначен для хранения данных о движении материальных величин. Это может быть прибытие и выбытие материала, автомобилей и т.п., или просто движение денежных средств в кассе предприятия.
Регистр накопления состоит из измерений, ресурсов и реквизитов. По сути, он представляет N-мерную систему координат, в узлах которой хранятся данные. Оси такой системы координат являются измерениями, а данные, которые хранятся в узлах, – ресурсами.
Помимо ресурсов, в узлах могут храниться реквизиты, которые несут на себе роль вспомогательных данных.
Основной задачей регистров накопления является суммирование ресурсов.
Разработчик может получить нужную сумму по любому измерению регистра накопления. Как это осуществить, мы узнаем в следующей части текущей главы.
Существует два вида регистров накопления в платформе 1С: это Регистр остатков и
Регистр оборотов.
Для регистров остатков мы можем получить остатки по регистру на заданный момент времени. У оборотных регистров мы можем только посмотреть, какой был оборот материальных величин за указанный промежуток времени.
Ранее мы уже создали в нашей прикладной задаче два регистра накопления. Это регистры ПробегАвтомобиля и ТопливоВАвтомобилях.
Регистр ПробегАвтомобиля является оборотным регистром.
Рис. 10.3.1
Этот регистр имеет одно измерение Автомобиль (тип СправочникСсылка.Автомобили) и один ресурс Пробег (все ресурсы имеют тип Число, можно только изменять параметры числа).
Рис. 10.3.2
Регистратором регистра ПробегАвтомобиля является документ Прибытие в гараж.
Рис. 10.3.3
Регистр ТопливоВАвтомобилях является регистром остатков.
Рис. 10.3.4
Имеет два измерения – Автомобиль (тип СправочникСсылка.Автомобили), ТипТоплива
(тип СправочникСсылка.ТипыТоплива), и один ресурс Количество.
Рис. 10.3.5
Регистратором этого регистра являются документы Заправка топлива и Отчет о расходе топлива.
Рис. 10.3.6
10.16 Менеджер регистра накопления - что позволяет?
Создавать регистры накопления мы с Вами научились в четвёртой главе, осталось научиться работать с ними.
И первый объект, который изучим, – это Менеджер регистра накопления.
Менеджер регистра накопления
Менеджер регистра накопления позволяет управлять данными конкретного регистра накопления: получать остатки и обороты, получать выборку, создавать набор данных и прочее.
Создать менеджер несложно:
МенеджерПробегАвтомобиля = РегистрыНакопления.ПробегАвтомобиля;
Теперь переменная МенеджерПробегАвтомобиля будет иметь тип Менеджер регистра накопления Пробег Автомобиля.
10.17 Набор записей - что выполняет в РН
Набор записей
Набор записей регистров накопления выполняет те же функции, что и Набор записей регистров сведений, а именно: считывание записей из базы данных по определённому регистратору, а также набор записей позволяет добавлять, изменять и удалять записи в наборе.
Поскольку методы Набора записей регистров накоплений совпадают с методами Набора записей регистров сведений по названию, по смыслу и по работе, то мы не будем подробно на них останавливаться.
Единственно, что если в случае с регистрами сведений отбор можно было устанавливать как по измерениям (для независимых регистров), так и по регистратору (для зависимых), то в случае с регистрами накоплений (которые не могут быть независимыми) отбор можно установить только по регистратору. Но самое главное – Набор записей регистров накоплений работает только с отбором по регистратору: для того, чтобы создать набор записей нужно всегда устанавливать отбор по регистратору.
Для демонстрации создадим обработку, в которой будем перебирать все проведённые документы ПрибытиеВГараж и выполнять запись пробега автомобиля в регистр накопления ПробегАвтомобиля в том случае, если у этого документа записей нет. То есть мы будем проверять, есть ли уже запись по данному регистратору или нет, и если нет, то создадим новую запись.
Как правило, чтобы заполнить регистр накопления, нужно просто провести документ.
Но возможны ситуации, когда нужно сделать запись в регистре накопления, не проводя документ. Такие ситуации редко, но могут встречаться. Например, когда регистр накопления был создан после разработки какого-то документа, причём экземпляры этого документа пользователь уже успел создать. В этом случае перепроводить все документы не всегда имеет смысл (может быть закрыт период, есть вероятность, что другие регистры «поплывут», и т.д.) Поэтому имеется смысл сделать запись в регистре по какому-то документу, не проводя сам документ.
Запись напрямую в регистр накопления на практике следует использовать очень
аккуратно и осторожно! Поскольку, как правило, редко бывает простая запись, а при этом используются различные алгоритмы (проверок, заполнений и т.п.)
Создадим обработку, форму обработки, у формы создадим реквизит Период с типом СтандартныйПериод, который поместим на эту же форму, а также создадим команду формы Заполнить регистр, у этой команды создадим обработчики на сервере и на клиенте. В серверном обработчике создадим объект Запрос, с помощью которого получим выборку всех проведённых документов ПрибытиеВГараж за указанный период (выберем поля Ссылка, Пробег, Дата, Автомобиль).
&НаКлиенте
Процедура ЗаполнитьРегистр(Команда) ЗаполнитьРегистрНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьРегистрНаСервере() Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| ПрибытиеВГараж.Ссылка КАК Регистратор,
| ПрибытиеВГараж.Пробег КАК Пробег,
| ПрибытиеВГараж.Дата КАК Период,
| ПрибытиеВГараж.Автомобиль КАК Автомобиль
|ИЗ
| Документ.ПрибытиеВГараж КАК ПрибытиеВГараж
|ГДЕ
| ПрибытиеВГараж.Проведен
| И ПрибытиеВГараж.Дата МЕЖДУ &ДатаНачала И
&ДатаОкончания"; Запрос.УстановитьПараметр("ДатаНачала",Период.ДатаНачала); Запрос.УстановитьПараметр("ДатаОкончания",Период.ДатаОкончания); Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Сообщить("Нет данных по указанному периоду"); Возврат;
КонецЕсли;
Выборка = Результат.Выбрать(); КонецПроцедуры
Листинг 10.3.1
Следующим шагом перед циклом выборки создадим менеджер регистра накопления
ПробегАвтомобиля и набор записей с помощью метода менеджера СоздатьНаборЗаписей.
МенеджерПробегАвто = РегистрыНакопления.ПробегАвтомобиля; НЗПробегАвто = МенеджерПробегАвто.СоздатьНаборЗаписей();
Листинг 10.3.2 Создадим цикл по выборке, установим внутри цикла отбор по регистратору, и
прочитаем набор данных из базы.
Пока Выборка.Следующий() Цикл Регистратор = Выборка.Регистратор;
НЗПробегАвто.Отбор.Регистратор.Установить(Регистратор); НЗПробегАвто.Прочитать();
КонецЦикла;
Листинг 10.3.3
В цикле проверим, есть ли в полученном наборе данных информация, и если нет, то создадим новую запись и заполним поля этой записи (это всё делаем внутри цикла по выборке).
Если НЗПробегАвто.Количество() = 0 Тогда НоваяЗапись = НЗПробегАвто.Добавить(); ЗаполнитьЗначенияСвойств(НоваяЗапись,Выборка);
КонецЕсли;
Листинг 10.3.4 Заметьте, полям запроса специально присвоили такие же псевдонимы, как и у
названий измерений и ресурсов регистра накопления, чтобы можно было использовать
процедуру ЗаполнитьЗначенияСвойств.
Поскольку мы имеем дело с регистром накоплений, то сохраняем набор записей при каждом обходе цикла. Так необходимо делать и с регистрами сведений, если они имеют регистратор. Сохраняем регистр внутри условия, где проверяем отсутствие записей (листинг 10.3.5).
НЗПробегАвто.Записать(); Сообщить("Записали движения для документа
|" + Выборка.Регистратор);
Листинг 10.3.5 Сохраним обработку, запустим и проверим, появились ли движения у документов
ПрибытиеВГараж по регистру ПробегАвтомобиля. Если всё сделано правильно, записи все
должны создаться как надо, но, возможно, что некоторые записи будут с пустым значением ресурса Пробег. Такое может случиться, если не указан пробег в документе. Самостоятельно подправьте обработку так, чтобы такие записи не создавались (измените запрос).
Создадим команду, которая подчистит записи с пустым пробегом. Команда будет называться Очистить пустые записи регистра, поместим её на форму, и создадим обработчики команды в серверном и клиентском контексте. Внутри серверной процедуры создадим менеджер регистра накопления ПробегАвтомобидля и набор записей данного регистра.
&НаСервере
Процедура ОчиститьПустыеЗаписиРегистраНаСервере() МенеджерПробегАвто = РегистрыНакопления.ПробегАвтомобиля; НЗПробегАвто = МенеджерПробегАвто.СоздатьНаборЗаписей();
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьПустыеЗаписиРегистра(Команда) ОчиститьПустыеЗаписиРегистраНаСервере();
КонецПроцедуры
Листинг 10.3.6
Поскольку набор записей регистров накоплений работает только с отбором по регистратору, нам необходимо выбрать все документы Прибытие в гараж за указанный период. Сделаем это с помощью метода Выбрать менеджера документов Прибытие в гараж.
ВыборкаДокументов = Документы.ПрибытиеВГараж.Выбрать(Период.ДатаНачала,
Период.ДатаОкончания);
Пока ВыборкаДокументов.Следующий() Цикл КонецЦикла;
Листинг 10.3.7
Затем установим внутри цикла для набора записей отбор по регистратору и прочитаем
набор.
Пока ВыборкаДокументов.Следующий() Цикл НЗПробегАвто.Отбор.Регистратор.Установить(ВыборкаДокументов.Ссылка); НЗПробегАвто.Прочитать();
КонецЦикла;
Листинг 10.3.8 В том случае если есть данные для выбранного регистратора, то получим
соответствующую запись.
НЗПробегАвто.Прочитать();
Если НЗПробегАвто.Количество() <> 0 Тогда ЗаписьНабора = НЗПробегАвто.Получить(0);
КонецЕсли;
Листинг 10.3.9 Мы получили запись с помощь метода Получить, этот метод возвращает объект
Запись регистра сведений. Вводимый параметр – это индекс записи. Поскольку у нас
предполагается, что у регистратора только одна запись, то мы просто ввели первый индекс. Если же записей было бы несколько, то необходимо было бы организовать обход по набору.
После того как мы получили запись, проверим, равен ли нулю Расход, и если да, то очистим набор и сохраним набор записей.
Если ЗаписьНабора.Пробег = 0 Тогда НЗПробегАвто.Очистить(); НЗПробегАвто.Записать();
КонецЕсли;
Листинг 10.3.10
Сохраните обработку и посмотрите, как она работает.
Самостоятельно оптимизируйте обработку: выведите с помощью запроса только те документы, у автомобилей которых пустая норма расхода.
10.18 Проведение документа - что позволяют?
Проведение документа
Мы научились создавать записи регистра накоплений независимо, то есть вне документа, а теперь научимся создавать их при проведении документа.
Для этого откроем модуль объекта документа Прибытие в гараж и развернём процедуру ОбработкаПроведения. В процедуре ОбработкаПроведения уже есть код, который мы создали при помощи конструктора движений в четвёртой главе.
Процедура ОбработкаПроведения(Отказ, Режим)
// регистр ПробегАвтомобиля Движения.ПробегАвтомобиля.Записывать = Истина; Движение = Движения.ПробегАвтомобиля.Добавить(); Движение.Период = Дата;
Движение.Автомобиль = Автомобиль; Движение.Пробег = Пробег;
КонецПроцедуры
Листинг 10.3.11 В этом коде осуществляется обращение к набору записей регистра накопления
ПробегАвтомобиля при помощи свойства документа Движения. В этом свойстве хранятся
наборы записей по всем регистрам, по которым документ осуществляет движения. После этого мы свойству Записывать набора записей присваиваем значение Истина, это значит, что после выполнения кода в процедуре ОбработкаПроведения наш набор записей запишется и нет смысла записывать его отдельно при помощи метода Записать(). Также нет смысла специально очищать набор записей, поскольку при создании документа мы установили в свойство Удаление движений значение Удалять автоматически при отмене проведения (вернее, оно установилось автоматически, по умолчанию).
Рис. 10.3.7
Поэтому при отмене проведения все данные очистятся, а при перепроведении – перезапишутся. Хотя некоторые программисты иногда перестраховываются и принудительно очищают набор записей в любом случае.
Движения.ПробегАвтомобиля.Очистить();
Листинг 10.3.12
Сейчас мы самостоятельно напишем проведения по регистру накопления ПробегАвтомобиля, чтобы у Вас закрепилось понимание. Для этого очистим код внутри процедуры проведения и сделаем запрос, в котором получим данные по текущему документу, причём поставим условия, чтобы реквизит Пробег был не пустой. Движения будут осуществляться тогда, когда пробег заполнен!
Процедура ОбработкаПроведения(Отказ, Режим) Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ПрибытиеВГараж.Дата КАК Период,
| ПрибытиеВГараж.Автомобиль КАК Автомобиль,
| ПрибытиеВГараж.Пробег КАК Пробег
|ИЗ
| Документ.ПрибытиеВГараж КАК ПрибытиеВГараж
|ГДЕ
| ПрибытиеВГараж.Ссылка = &Ссылка"; Запрос.УстановитьПараметр("Ссылка",Ссылка);
Результат = Запрос.Выполнить(); Выборка = Результат.Выбрать(); Выборка.Следующий();
//....
КонецПроцедуры
Листинг 10.3.13 В этом запросе мы обращаемся напрямую к проводимому документу, и получим
только один элемент выборки из запроса, поскольку запрос вернёт одну запись, и нет смысла
обходить эту выборку целиком.
Получим набор записей регистра накопления ПробегАвтомобиля, очистим его (хотя отбор и должен очиститься автоматически, но перестрахуемся) и установим в свойство Записывать значение Истина. В этом случае после выполнения процедуры ОбработкаПроведения нужные записи в регистре будут созданы автоматически, и нет смысла их отдельно записывать.
// регистр ПробегАвтомобиля
НЗПробегАвтомобиля = Движения.ПробегАвтомобиля; НЗПробегАвтомобиля.Очистить(); НЗПробегАвтомобиля.Записывать = Истина;
Листинг 10.3.14
Осталось создать новую запись регистра и заполнить её поля данными из запроса.
НовЗапись = НЗПробегАвтомобиля.Добавить(); ЗаполнитьЗначенияСвойств(НовЗапись,Выборка);
Листинг 10.3.15
Обратите внимание, что мы не заполнили свойство записи Регистратор. В этом нет смысла, платформа сама автоматически присвоит записи нужный регистратор (текущий
документ).
Проверьте, как будет проводиться документ после наших изменений.
И напоследок сделаем так, что если значение в поле Пробег пустое, то документ не будет проводиться. Для этого воспользуемся обработчиком ОбработкаПроверкиЗаполнения модуля объекта. Для того чтобы создать его, воспользуемся командой ПроцедурыИФункции меню Текст.
Рис. 10.3.8
В окне Процедуры и функции выберем пункт <ОбработкаПроверкиЗаполнения>. В обработчике, который будет создан, два параметра – Отказ и ПроверяемыеРеквизиты.
Второй параметр является массивом, в котором перечислены все проверяемые реквизиты объекта, это те реквизиты, у которых в свойстве Проверка заполнения установлено значение Выдавать ошибку.
Рис. 10.3.9
В нашем случае оно не установлено, поэтому, чтобы проверка заполнения сработала, добавим в этот массив название реквизита Пробег.
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты) ПроверяемыеРеквизиты.Добавить("Пробег")
КонецПроцедуры
Листинг 10.3.16 Если сейчас мы попробуем провести документ с пустым пробегом, то возникнет
ошибка и документ не будет проведён.
Рис. 10.3.10
Резюме
На этом мы закончим изучение регистров накопления. Мы научились создавать наборы данных, добавлять в них строки и очищать. Рекомендую не злоупотреблять данными знаниями, а применять их только в исключительных случаях. Все записи в регистрах накопления должны создаваться только документами. Как добавлять записи при проведении документа – Вы знаете. В следующей части мы рассмотрим, как получать информацию из регистров накопления.
10.19 Часть 4. Регистры накопления. Получение данных - Метод Выбрать что формирует?
В заключительной части этой главы мы изучим, каким образом в программе 1С можно получать данные из регистров накопления. Точно так же, как и в случае с регистрами сведений, сделать это возможно двумя способами: используя методы менеджера регистров накопления и используя язык запросов.
Сначала рассмотрим методы менеджера регистров накопления. Разберём четыре метода: Выбрать, Выбрать по регистратору, Обороты и Остатки.
Выбрать
Метод Выбрать формирует выборку записей регистра и возвращает объект Выборка регистров накопления.
Метод Выбрать имеет следующий синтаксис:
Выбрать(<НачалоИнтервала>, <КонецИнтервала>, <Отбор>, <Порядок>)
Как Вы уже поняли, этот метод аналогичен методу Выбрать для регистров сведений.
Также он имеет четыре параметра.
Начало интервала – дата, с которой начинается выборка.
Конец интервала – дата, которой оканчивается выборка.
Отбор – структура, которая может содержать только один элемент, по значению которого будет осуществлен отбор в выборке. Название ключа структуры должно совпадать с названием измерения (или реквизита), по которому будет вестись отбор, и у данного измерения признак Индексирование должен быть установлен в значение Индексировать.
Порядок – строка с названием поля, по которому будет отсортирована выборка.
Продемонстрируем работу метода: выведем в таблицу значений все записи регистра накопления Топливо в автомобилях по указанному на форме автомобилю. Для этого необходимо у измерения Автомобиль установить свойство Индексировать.
Рис. 10.4.1
Создадим обработку, форму обработки, на форме разместим два реквизита: реквизит Автомобиль с соответствующим типом и таблицу значений – Топливо в автомобилях. У таблицы значений будут следующие колонки: ПриходРасход (тип значения – ссылка на системное перечисление Вид движения накопления, см. рис. 10.4.2), ТипТоплива (ссылка на справочник ТипыТоплива), Регистратор (у этой колонки тип будет составным: ДокументСсылка.ЗаправкаТоплива и ДокументСсылка.ОтчетОРасходеТоплива) и Количество (Число (10,1)). У реквизита Автомобиль установим в свойство Проверка заполнения значение Выдавать ошибку. А также на форме создадим команду Заполнить таблицу, которая будет размещена в командной панели таблицы формы.
Рис. 10.4.2
Рис. 10.4.3
Рис. 10.4.4
У команды формы создадим клиентский и серверный обработчик. В серверном обработчике команды напишем код, который будет осуществлять выборку с отбором по гаражу и заполнять табличное поле. В выборке не будет ограничений по датам.
&НаСервере
Процедура ЗаполнитьТаблицуНаСервере() ТопливоВАвтомобилях.Очистить(); Отбор = Новый Структура;
Отбор.Вставить("Автомобиль",Автомобиль);
Выборка = РегистрыНакопления.ТопливоВАвтомобилях.Выбрать(,,Отбор); Пока Выборка.Следующий() цикл
НоваяСтрока = ТопливоВАвтомобилях.Добавить(); НоваяСтрока.ПриходРасход = Выборка.ВидДвижения; ЗаполнитьЗначенияСвойств(НоваяСтрока,Выборка);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицу(Команда) Если Не ПроверитьЗаполнение() Тогда
Возврат КонецЕсли;
ЗаполнитьТаблицуНаСервере(); КонецПроцедуры
Листинг 10.4.1
В этом коде мы получили выборку регистра накопления Топливо в автомобилях с установленным отбором по гаражу. Затем в цикле выборки создаём новые строки таблицы значений ТопливоВАвтомобилях и заполняем их.
Посмотрим, как работает новая обработка.
Рис. 10.4.5
Самостоятельно сделайте следующие доработки: разместите на форме стандартный период и из него подставляйте даты в соответствующие параметры метода Выбрать.
10.20 Выбрать по регистратору - что осуществляет?
Выбрать по регистратору
Рассмотрим следующий метод – Выбрать по регистратору. У этого простого метода всего один параметр – ссылка на документ, который может быть регистратором какой-нибудь записи регистра накопления.
Для демонстрации работы метода доработаем предыдущую форму обработки: добавим реквизит Регистратор с составным типом (Документы: Прибытие в гараж и Выбытие из гаража, см. рис. 10.4.6).
Рис. 10.4.6
Создадим новую команду Заполнить таблицу по регистратору. В серверном
обработчике команды будем проверять заполнен Регистратор или нет, если Регистратор не пустой, то выборка будет идти по регистратору, причём в качестве параметра будет
указываться значение из реквизита формы Регистратор. А иначе – всё как было раньше.
&НаСервере
Процедура ЗаполнитьТаблицуПоРегистраторуНаСервере() ТопливоВАвтомобилях.Очистить();
Если ЗначениеЗаполнено(Регистратор) тогда Выборка =
РегистрыНакопления.ТопливоВАвтомобилях.ВыбратьПоРегистратору(Регистратор); иначе
Если Не ЗначениеЗаполнено(Автомобиль) тогда Возврат;
КонецЕсли;
Отбор = Новый Структура; Отбор.Вставить("Автомобиль",Автомобиль);
Выборка = РегистрыНакопления.ТопливоВАвтомобилях.Выбрать(,,Отбор); КонецЕсли;
Пока Выборка.Следующий() цикл
НоваяСтрока = ТопливоВАвтомобилях.Добавить(); ЗаполнитьЗначенияСвойств(НоваяСтрока,Выборка); НоваяСтрока.ПриходРасход = Выборка.ВидДвижения;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьТаблицуПоРегистратору(Команда) ЗаполнитьТаблицуПоРегистраторуНаСервере();
КонецПроцедуры
Листинг 10.4.2
Проверьте, как работает данный метод.
10.21 Обороты - что позволяет?
Мы рассмотрели общие методы, которые также есть и в регистрах сведений. Ниже мы будем рассматривать те методы, которые присущи только регистрам накопления. И начнём с метода Обороты.
Обороты
Метод Обороты позволяет получить обороты регистра накопления за заданный период.
Что понимается под словом «обороты»? Для примера рассмотрим регистр Пробег автомобиля. Из этого регистра нам нужно узнать, какой пробег был у определённого автомобиля, скажем, за месяц или за неделю. Это можно сделать, просуммировав все записи регистра по нужному автомобилю за какой-то период. Эта сумма и будет оборотом регистра накопления по конкретному автомобилю.
Необязательно суммировать вручную, можно воспользоваться методом менеджера регистра накопления Обороты. При помощи этого метода можно получить как оборот по конкретному автомобилю, так и общий оборот – по всем автомобилям, по которым прошли движения.
Обороты можно получать как по оборотным регистрам, так и по регистрам остатков. В первом случае будет выводиться сумма оборота по какому-нибудь измерению, а во втором случае – общая сумма прихода и расхода.
Закончим с теорией, рассмотрим работу метода Обороты на практике. Начнём с синтаксиса.
Обороты(<НачалоПериода>, <КонецПериода>, <Отбор>, <Измерения>, <Ресурсы>)
Первые два параметра – НачалоПериода и КонецПериода – не должны вызвать у Вас вопросов.
Отбор – это структура, которая содержит значения измерений, по которым нужно отобрать обороты. Если он указан, то обороты будут подсчитаны только по указанному значению измерений. Например, это могут быть обороты по определённому типу топлива (для регистра ТопливоВАвтомобилях), или по определённому автомобилю (для этого же регистра), или по определённому типу топлива и определённому автомобилю (для того же регистра). Имена ключей структуры должны совпадать с именами измерений регистра.
Измерения – это строка, в которой перечислены измерения через запятую, по которым следует разворачивать обороты. Например, для регистра ТопливоВАвтомобилях можно указать ТипТоплива, тогда будут подсчитаны обороты только по автомобилям (второе измерение).
Ресурсы – это строка, в которой перечислены через запятую ресурсы, по которым будут подсчитаны обороты, то есть именно они будут просуммированы.
Метод Обороты возвращает таблицу значений, которая содержит колонки с измерениями, указанными в параметре Измерения (названия этих колонок совпадают с
названиями измерений), и колонки с ресурсами (названия ресурсов указаны в параметре Ресурсы). Для оборотных регистров будет одна колонка на ресурс с названием ресурса. А для регистров остатков будет по две колонки на ресурс, которые будут иметь следующие названия:
"<Имя ресурса>Приход" и "<Имя ресурса>Расход"
Для экспериментов создадим обработку. На форме обработки создадим реквизит Автомобиль (тип ссылка на справочник Автомобили) и реквизит Период с типом СтандартныйПериод. У обоих реквизитов установим проверку заполнения.
Ещё создадим две таблицы значений.
В первой таблице ОборотыПоТопливу будем выводить обороты по топливу для выбранного в реквизите Автомобиль автомобиля (в таблице будет три колонки – ТипТоплива, Прибыло, Убыло). Получать обороты по топливу будем из регистра накопления ТопливоВАвтомобилях.
Во второй таблице ОборотыПоПробегу будем выводить пробег выбранного автомобиля (в таблице будет две колонки Автомобиль, Пробег). Пробег автомобиля будем получать из регистра накопления ПробегАвтомобиля.
На созданной форме добавим элемент Группа – страницы (со страницами ГруппаРасходТоплива и ГруппаПробег), и разместим две таблицы значений в разных страницах.
Создадим две команды: Заполнить расход и Заполнить пробег с серверными и клиентскими обработчиками, которые разместим в командных панелях соответствующих таблиц формы.
Рис. 10.4.7
Рис. 10.4.8
Рис. 10.4.9
В серверном обработчике команды Заполнить расход напишем код, в котором будем получать обороты по автомобилю из регистра накопления ТопливоВАвтомбилях, и заполнять по полученному результату таблицу значений.
&НаСервере
Процедура ЗаполнитьРасходНаСервере() ОборотыПоТопливу.Очистить(); Отбор = Новый Структура;
Отбор.Вставить("Автомобиль",Автомобиль);
МенТоплВАвто = РегистрыНакопления.ТопливоВАвтомобилях; ТаблицаОборотов = МенТоплВАвто.Обороты(Период.ДатаНачала,
Период.ДатаОкончания, Отбор,
"ТипТоплива"); Для Каждого СтрОборот из ТаблицаОборотов цикл
НоваяСтрока = ОборотыПоТопливу.Добавить(); НоваяСтрока.ТипТоплива = СтрОборот.ТипТоплива; НоваяСтрока.Прибыло = СтрОборот.КоличествоПриход; НоваяСтрока.Убыло = СтрОборот.КоличествоРасход;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьРасход(Команда)
Если Не ПроверитьЗаполнение() Тогда Возврат;
КонецЕсли; ЗаполнитьРасходНаСервере();
КонецПроцедуры
Листинг 10.4.3
Разберём код выше.
Первым делом мы создаём структуру, название ключа которой совпадает с названием измерения, позже она будет указана в третьем параметре метода Обороты. Вторым шагом мы получаем с помощью метода Обороты менеджера регистра накопления ТопливоВАвтомобилях таблицу оборотов. В этот метод передаются следующие параметры: начало и конец периода, структуру для отбора, созданную ранее, а в четвёртом параметре указывается строка с надписью ТипТоплива. Это значит, что обороты будут подсчитаны только по измерению ТипТоплива.
После того как мы получили обороты, заполняем таблицу значений формы Обороты по топливу данными из полученной таблицы.
Обратите внимание на название полей ресурсов в таблице оборотов.
Сохраним новую обработку и посмотрим, какой результат получится касательно таблицы
Обороты по топливу.
Рис. 10.4.10
Мы получили информацию, сколько конкретного топлива было заправлено в выбранный автомобиль и о каком количестве топлива отчитались. Проверьте её самостоятельно.
Подсчитаем обороты по пробегу. Напишем в серверном обработчике команды Заполнить пробег следующий код:
&НаСервере
Процедура ЗаполнитьПробегНаСервере() ОборотыПоПробегу.Очистить(); Отбор = Новый Структура;
Отбор.Вставить("Автомобиль",Автомобиль); МенПробег = РегистрыНакопления.ПробегАвтомобиля;
ТаблицаОборотов = МенПробег.Обороты(Период.ДатаНачала,
Период.ДатаОкончания, Отбор,
"Автомобиль"); Для Каждого СтрОборот из ТаблицаОборотов цикл
НоваяСтрока = ОборотыПоПробегу.Добавить(); НоваяСтрока.Автомобиль = СтрОборот.Автомобиль; НоваяСтрока.Пробег = СтрОборот.Пробег;
КонецЦикла КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьПробег(Команда)
Если Не ПроверитьЗаполнение() Тогда Возврат;
КонецЕсли; ЗаполнитьПробегНаСервере();
КонецПроцедуры
Листинг 10.4.4
Прокомментируем код выше. Сначала мы создаём структуру для отбора, название ключа которой совпадает с названием измерения, ниже мы укажем её в третьем параметре. После этого, используя метод Обороты менеджера регистра накопления ПробегАвтомобиля, получаем обороты этого регистра по измерению Автомобиль для указанного выше отбора. И в конце заполняем таблицу значений ОборотыПоПробегу.
Посмотрите, как работает данный код, и проверьте, правильные ли данные выведены в табличное поле.
Рис. 10.4.11
10.21 Остатки - по чему можно получать остатки?
Последний метод менеджера регистров накоплений, который мы рассмотрим в данной части, это метод Остатки.
Остатки
Метод Остатки применим только к регистрам остатков, поэтому его работу мы будем рассматривать на примере регистра накопления ТопливоВАвтомобилях.
Вкратце разберём, что такое Остатки. Если у нас в автомобиль было залито десять литров топлива, а было истрачено два (по ним есть отчёт), то оставшиеся восемь литров топлива – это и будет остаток топлива по автомобилю. Остаток может быть положительным, а может – и отрицательным. Если, например, залито три литра топлива, а истрачено пять, то остаток будет минус два литра топлива по автомобилю. Фактически это невозможно, но
программа позволяет такое делать, и на практике часто это встречается, особенно когда не ведётся контроль отрицательных остатков и есть привычка в оперативном учёте заводить документы задним числом. Что, конечно же, неправильно и должно пресекаться!
Для регистров накопления можно получать остатки по всем измерениям, которые есть, также можно получать остатки по комбинации измерений. Например, в случае регистра ТопливоВАвтомобилях можно получить остаток по измерению ТипТоплива, тогда будут аккумулироваться остатки по всем автомобилям, и мы узнаем, сколько вообще осталось топлива каждого типа во всех автомобилях. Если же мы получим остатки по измерению Автомобиль, то мы узнаем, сколько в каждом автомобиле топлива всех типов. Также можно получить остаток по комбинации измерений Автомобиль – ТипТоплива, в этом случае мы будем знать, сколько осталось в каждом автомобиле топлива всех видов.
Рассмотрим синтаксис метода Остатки регистра накопления.
Остатки(<МоментВремени>, <Отбор>, <Измерения>, <Ресурсы>)
Момент времени – это дата, на которую мы будем подсчитывать остатки. К примеру, количество топлива в автомобиле на начало месяца и на текущий день может быть разное, тогда эту дату необходимо указывать. Если она не указана, то берутся остатки на максимальную дату движений в регистре (самые последние).
Отбор – это структура, которая содержит значение измерения, по которому должен осуществиться отбор. Если она есть, то остаток будет подсчитан только для указанного в отборе измерения. Например, это может быть остаток по конкретному типу топлива или конкретному автомобилю.
Измерения – это строка, где через запятую перечислены измерения, по которым будут подсчитаны остатки. Если указано несколько измерений, например, Автомобиль и ТипТоплива, то будут подсчитаны остатки по всем типам топлива и по всем автомобилям.
Ресурсы – это строка, в которой через запятую перечислены ресурсы, для которых нужно получить остатки.
Данный метод возвращает таблицу значений со следующими колонками: колонки, указанные в третьем параметре (если не указан, то все измерения), и колонки, которые указаны в четвёртом параметре (если не указан, то все ресурсы).
Для демонстрации работы метода Остатки создадим обработку с формой, на которой разместим таблицу значений. В этой таблице будут выводиться остатки по всем типам топлива. Также предусмотрим возможность отбора по определённому типу топлива (создадим отдельный реквизит). На форме будет создана команда Заполнить остатки, при выполнении которой и будет заполняться таблица значений на форме Остаток по типам топлива.
Рис. 10.4.12
В обработчике команды напишем следующий код:
&НаСервере
Процедура ЗаполнитьОстаткиНаСервере() ТаблицаОстатков.Очистить();
МенТопливоВАвто = РегистрыНакопления.ТопливоВАвтомобилях; Если Не ЗначениеЗаполнено(ТипТоплива) тогда
Остатки = МенТопливоВАвто.Остатки(,,"ТипТоплива",); иначе
Отбор = новый Структура; Отбор.Вставить("ТипТоплива",ТипТоплива);
Остатки = МенТопливоВАвто.Остатки(,Отбор,"ТипТоплива",); КонецЕсли;
Для Каждого СтрокаТабл из Остатки цикл НоваяСтрока = ТаблицаОстатков.Добавить();
НоваяСтрока.ТипТоплива = СтрокаТабл.ТипТоплива; НоваяСтрока.Остаток = СтрокаТабл.Количество;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗаполнитьОстатки(Команда) ЗаполнитьОстаткиНаСервере();
КонецПроцедуры
Листинг 10.4.5
В данном случае мы не стали устанавливать момент времени, предполагая, что нам нужны текущие остатки.
В том случае если поле ТипТоплива пустое, то используем метод Остатки только с одним параметром, это третий параметр, в котором перечислены измерения. Мы указываем измерение ТипТоплива, поскольку, по условиям задачи, нам необходимо получить остатки
только в разрезе типа топлива.
Когда же поле ТипТоплива не пустое, то создаём структуру, в которой указываем выбранный тип топлива. Эту структуру указываем в качестве второго параметра.
После этого мы заполняем таблицу остатков, предварительно очистив её.
Проверим работу метода.
Рис. 10.4.13
Рис. 10.4.14
Допишите данную обработку: пусть выходят остатки в разрезе автомобилей и типов топлива (добавьте новую колонку Автомобиль в таблицу значений с соответствующим типом).
Мы изучили методы менеджера регистров накопления, теперь перейдём к языку запросов. С помощью языка запросов платформы 1С можно получить выборку записей регистра накопления, мы на этом не будем останавливаться, так как здесь всё по аналогии с регистрами сведений. Мы же изучим основы использования виртуальных таблиц, с помощью них можно получить остатки, обороты и остатки с оборотами.
Рассмотрим первую виртуальную таблицу Остатки.
Виртуальная таблица Остатки
Виртуальная таблица языка запросов 1С Остатки может быть создана у регистров накопления, имеющих вид Остатки. Она также, как и метод Остатки менеджера регистра накопления, возвращает остаток ресурса в разрезе определённых измерений
Для демонстрации работы этой виртуальной таблицы разберём следующую задачу: в обработке, на форме создадим реквизиты: Топливо, Автомобиль, Дата (состав Дата и время) и Остаток топлива с соответствующими типами, а также команду Получить остаток. Всё
это разместим на форме (у поля ОстатокТоплива установить свойство ТолькоПросмотр). При выполнении команды будем получать на указанную в поле дату остаток из регистра накопления ТопливоВАвтомобилях по указанному типу топлива и указанному автомобилю.
Рис. 10.4.15
В серверном обработчике команды создадим пустой запрос и откроем конструктор запроса. В таблице База данных развернём дерево регистров накопления и обратим внимание на таблицу Топливо в автомобилях Остатки.
Рис. 10.4.16
Выберем её. Зададим отбор по автомобилю и типу топлива. Для этого нажмём на кнопку Параметры виртуальной таблицы (таблица должна быть выделена).
Рис. 10.4.17
Откроется окно Параметры виртуальной таблицы.
Рис. 10.4.18
Внесём дату, на которую мы будем получать остатки, в поле Период в виде параметра
&Дата, в этот параметр мы и передадим дату остатков перед выполнением запроса.
Рис. 10.4.19
Раскроем поле Условие и установим отбор по автомобилю и типу топлива.
Рис. 10.4.20
10.22 Виртуальная таблица Остатки - каким образом накладывать отбор?
В поле Условие параметров виртуальной таблицы Остатки регистров накоплений мы можем накладывать любые условия на измерения регистра, также можно передать в это поле параметры запроса, чтобы наложить определённые ограничения на выборку данных.
При работе с виртуальными таблицами всегда накладывайте ограничения, используя именно параметры виртуальной таблицы. Неправильно накладывать ограничения посредством директивы ГДЕ языка запросов! Это существенно скажется на производительности!
Сохраним установленные параметры. У таблицы остатков выберем только одно поле –
КоличествоОстаток, установив псевдоним этому полю – Остаток.
Рис. 10.4.21
Переименуем таблицу, чтобы запрос был читаемым. Для этого нужно выделить саму таблицу, кликнуть правой кнопкой мышки и в открывшемся контекстном меню выбрать пункт Переименовать таблицу…
Рис. 10.4.22
Рис. 10.4.23
После переименования таблицы нажмём кнопку ОК конструктора запроса, должен получиться следующий запрос:
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| ОстаткиТоплива.КоличествоОстаток КАК Остаток
|ИЗ
| РегистрНакопления.ТопливоВАвтомобилях.Остатки(
| &Дата,
| Автомобиль = &Автомобиль
| И ТипТоплива = &ТипТоплива) КАК ОстаткиТоплива";
Листинг 10.4.6
Установим параметры запроса.
Запрос.УстановитьПараметр("Дата",Дата); Запрос.УстановитьПараметр("Автомобиль",Автомобиль); Запрос.УстановитьПараметр("ТипТоплива",ТипТоплива);
Листинг 10.4.7
А также получим и выведем результат запроса.
Результат = Запрос.Выполнить(); Если Результат.Пустой() Тогда
ОстатокТоплива = 0; КонецЕсли;
Выборка = Результат.Выбрать(); Выборка.Следующий(); ОстатокТоплива = Выборка.Остаток;
Листинг 10.4.8
Поскольку у данного регистра всего два измерения, и по обоим мы установили отбор, то на выходе запроса должна быть только одна запись, так как не может быть двух разных остатков для одного типа топлива в одном автомобиле на один момент времени.
Поэтому мы просто получили следующий элемент выборки, он же первый, и вывели информацию об остатке.
Проверьте, как работает данная обработка.
Рис. 10.4.24
10.23 Виртуальная таблица Обороты - где можно применять?
Виртуальная таблица Обороты
Следующая виртуальная таблица, которую мы рассмотрим, называется Обороты. Это единственная виртуальная таблица, которая используется и у оборотных регистров, и у регистров остатков.
Для демонстрации работы виртуальной таблицы создадим обработку, на форме которой получать для выбранного автомобиля пробег по дням за указанный период.
На форме обработки создадим следующие реквизиты: Автомобиль (тип СправочникСсылка.Автомобили), Период (тип СтандартныйПериод) и таблицу значений Пробег по дням (с колонками Период и Пробег). А также на форме создадим команду Получить пробег, которую разместим в командной панели таблицы формы.
Рис. 10.4.25
В серверном обработчике команды создадим пустой запрос, и запустим конструктор запроса, в котором развернём дерево регистров накопления. Обратите внимание на виртуальную таблицу ПробегАвтомобиля.Обороты.
Рис. 10.4.26
Выберем её. Следующим шагом нам необходимо установить параметры. Для этого нажмём на кнопку Параметры виртуальной таблицы. Обращаю Ваше внимание, что сама таблица должна быть выделена курсором и иметь синий фон.
Рис. 10.4.27
Зайдём в параметры и установим начало периода и конец периода.
Рис. 10.4.28
Для этого мы используем методы КонецПериода и НачалоПериода, являющиеся методами языка запроса платформы 1С 8 и возвращающими начало или конец периода в зависимости от второго параметра. Если указан день, это будет начало или конец дня, если указан месяц – начало или конец месяца и т.д.
Дальше необходимо установить периодичность. Периодичность – это то, с какой детальностью будут выводиться записи. Если мы, к примеру, установим периодичность Месяц, то выйдут обороты по автомобилям за месяц. Если установим периодичность Год – то за год. Также можно установить периодичность Запись, тогда будут выведены обороты по всем записям регистра накопления. Или периодичность Регистратор, тогда тоже будет периодичность по записям, но только с группировкой по регистратору. Нас интересуют обороты за день. Поэтому установим периодичность День.
Осталось задать условия.
Рис. 10.4.29
Рис. 10.4.30
У таблицы выберем поля Период и ПробегОборот. Полю ПробегОборот присвоим псевдоним Пробег, а саму таблицу переименуем в ПробегАвто.
Рис. 10.4.31
Отсортируем результат, который выдаст виртуальная таблица по периоду.
Рис. 10.4.32
Сохраним запрос. Должен получиться запрос такого вида:
ВЫБРАТЬ
ПробегАвто.Период КАК Период, ПробегАвто.ПробегОборот КАК Пробег
ИЗ
РегистрНакопления.ПробегАвтомобиля.Обороты(НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ),
КОНЕЦПЕРИОДА(&КонецПериода, ДЕНЬ), День,
Автомобиль = &Автомобиль) КАК ПробегАвто
УПОРЯДОЧИТЬ ПО
Период
Листинг 10.4.9
Передадим в запрос параметры.
Запрос.УстановитьПараметр("НачалоПериода",Период.ДатаНачала); Запрос.УстановитьПараметр("КонецПериода",Период.ДатаОкончания); Запрос.УстановитьПараметр("Автомобиль",Автомобиль);
Листинг 10.4.10
Получим выборку и заполним таблицу значений.
Выборка = Запрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл
НовСтр = ПробегПоДням.Добавить(); ЗаполнитьЗначенияСвойств(НовСтр,Выборка);
КонецЦикла;
Листинг 10.4.11
Осталось проверить, как работает обработка.
Рис. 10.4.33
Вы видите, что вывелся пробег автомобиля за каждый день, когда была запись в регистре. Зайдём обратно в запрос и изменим в виртуальной таблице периодичность на Неделю.
Рис. 10.4.34
Посмотрим, какие данные будут на выходе.
Рис. 10.4.35
Запрос сгруппировал все данные по неделе.
Таким образом, делаем вывод, что параметр Периодичность, по сути, определяет уровень группировки данных по строкам в разрезе дат. Посмотрим, что будет, если его вообще обнулить: зайдем в запрос и очистим период в параметрах.
Рис. 10.4.36
Из списка полей сразу же убралось поле Период.
Сохраним запрос, обработку и посмотрим на результат.
Рис. 10.4.37
Таблица вернёт общий итог за весь выбранный период.
И ещё момент. Мы рассмотрели работу виртуальной таблицы Обороты на примере оборотного регистра. Регистры остатков тоже могут работать с данной таблицей, только помимо ресурсного поля с приставкой Оборот появляются поля с приставками Приход и Расход.
Рис. 10.4.38
10.24 (Виртуальная таблица Остатки и обороты)
Напоследок рассмотрим виртуальную таблицу – ОстаткиИОбороты.
Виртуальная таблица Остатки и обороты
Сделаем обработку, в которой будем выводить в таблицу поля с данными по заправке топлива в автомобиль и расходу этого топлива, а также остатки на начало и конец периода.
Разместим на форме обработки следующие реквизиты: Период, Автомобиль и таблицу значений ТопливоВАвтомобиле (с колонками: ТипТоплива, Остаток на начало, Заправка, Расход, Остаток на конец). Создадим команду Заполнить таблицу, которую разместим в командной панели таблицы формы.
Рис. 10.4.39
В серверном обработчике команды создадим объект Запрос и зайдём в конструктор запроса. В конструкторе раскроем дерево регистров накопления. Обратите внимание на таблицу Остатки и обороты Топливо в автомобиле.
Рис. 10.4.40
Выберем эту таблицу и установим параметры для неё: начало периода, конец периода и условие отбора по автомобилю. А саму таблицу назовём ДвижениеТопливаАвто.
Рис. 10.4.41
Выберем следующие поля: ТипТоплива, Количество начальный остаток, Количество приход, Количество расход и Количество конечный остаток, и дадим им псевдонимы по аналогии с названием колонок в таблице значений на форме.
Должен получиться следующий запрос:
ВЫБРАТЬ
ДвижениеТопливаАвто.ТипТоплива КАК ТипТоплива, ДвижениеТопливаАвто.КоличествоНачальныйОстаток КАК ОстатокНаНачало, ДвижениеТопливаАвто.КоличествоПриход КАК Заправка, ДвижениеТопливаАвто.КоличествоРасход КАК Расход, ДвижениеТопливаАвто.КоличествоКонечныйОстаток КАК ОстатокНаКонец
ИЗ
РегистрНакопления.ТопливоВАвтомобилях.ОстаткиИОбороты(НАЧАЛОПЕРИОДА(&ДатаНачала, ДЕНЬ),
НАЧАЛОПЕРИОДА(&ДатаОкончания, ДЕНЬ), , , Автомобиль = &Автомобиль) КАК
ДвижениеТопливаАвто
Листинг 10.4.12 Осталось заполнить параметры и вывести результат в таблицу значений.
Запрос.УстановитьПараметр("ДатаНачала",Период.ДатаНачала); Запрос.УстановитьПараметр("ДатаОкончания",Период.ДатаОкончания); Запрос.УстановитьПараметр("Автомобиль",Автомобиль);
Выборка = Запрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл
НовСтр = ТопливоВАвтомобиле.Добавить(); ЗаполнитьЗначенияСвойств(НовСтр,Выборка);
КонецЦикла;
Листинг 10.4.13
Сохраним обработку, запустим и посмотрим, что получилось.
Рис. 10.4.42
Как видите, вышло количество топлива в автомобиле на начало периода, на конец периода и сколько было топлива в течение периода заправлено, а сколько израсходовано.
А теперь попробуем всё посмотреть в разрезе документов. Для этого добавим колонку Документ в таблицу значений (составной тип документы Заправка топлива и Отчет о расходе топлива) и вынесем её в таблицу формы.
Рис. 10.4.43
Следующим шагом откроем снова конструктор созданного запроса, зайдём в параметры виртуальной таблицы и в параметре Периодичность установим значение Регистратор.
Рис. 10.4.44
После этого в полях таблицы появится поле Регистратор.
Рис. 10.4.45
Выберем это поле и присвоим ему псевдоним Документ. В результате должен получиться такой запрос:
ВЫБРАТЬ
ДвижениеТопливаАвто.ТипТоплива КАК ТипТоплива, ДвижениеТопливаАвто.КоличествоНачальныйОстаток КАК ОстатокНаНачало, ДвижениеТопливаАвто.КоличествоПриход КАК Заправка, ДвижениеТопливаАвто.КоличествоРасход КАК Расход, ДвижениеТопливаАвто.КоличествоКонечныйОстаток КАК ОстатокНаКонец, ДвижениеТопливаАвто.Регистратор КАК Документ
ИЗ
РегистрНакопления.ТопливоВАвтомобилях.ОстаткиИОбороты(НАЧАЛОПЕРИОДА(&ДатаНачала, ДЕНЬ),
НАЧАЛОПЕРИОДА(&ДатаОкончания, ДЕНЬ), Регистратор, ,
Автомобиль = &Автомобиль) КАК
ДвижениеТопливаАвто
Листинг 10.4.14
Сохраните запрос, обработку и посмотрите, как она работает.
Рис. 10.4.46
Как видите, запрос вывел нужную нам информацию, но, к сожалению, появились ненужные строки конца и начала периода, без регистратора. Они не очень информативны и мешают воспринимать информацию. Для этого нам необходимо вернуться обратно в Параметры виртуальной таблицы. И установить в параметр МетодДополнения значение Движения.
Рис. 10.4.47
Сохраним запрос, обработку и посмотрим, что получится в этот раз.
Рис. 10.4.48
Мы видим, что границы периода убрались и информация предоставляется в удобном для понимания виде.
На этом мы закончим изучать способы получения информации из регистров накопления, как Вы поняли, их немало. Для регистров накопления действует то же правило: если необходима простая информация, то удобнее использовать методы менеджера регистров, а если необходимо получить более сложную периодическую информацию, то лучше использовать запросы. У языка запроса 1С гораздо больше возможностей, чем у методов менеджеров регистра. В этой главе мы разобрали только общие моменты использования виртуальных таблиц регистров сведений и накопления.
11.01 Глава 11. Вывод информации. Часть 1. Печатные формы. Макет - для чего необходим Макет? Сколько видов макетов?
Одиннадцатую, последнюю главу этой книги мы посвятим различным способам вывода информации пользователю. Мы научимся создавать и заполнять печатные формы документов, выводить информацию о деятельности предприятия с помощью простых отчётов и СКД. А также узнаем, что такое динамический список и как с ним работать.
Начнём с печатных форм.
11.02 Часть 1. Печатные формы
Практически во всех прикладных задачах необходимо привязать к определённому документу какую-то печатную форму. Печатная форма представляет собой некоторый бланк, который пользователь сможет распечатать после записи или проведения документа. В этой части мы научимся создавать примитивные печатные формы.
Макет
11.03 Вывод печатных форм осуществляется при помощи
Вывод печатных форм осуществляется при помощи макетов. Всего существует девять типов макетов, но мы с Вами в этой книге рассмотрим два – табличный документ и макет системы компоновки данных (СКД). Макеты могут быть общими и подчинёнными какому- нибудь объекту. Общие макеты расположены в ветке Общие макеты дерева конфигурации (см. рис. 11.1.1).
А макеты, подчинённые какому-либо объекту, расположены в ветке Макеты объекта, которому они подчинены.
Рис. 11.1.2
Создадим макет табличного документа для документа Прибытие в гараж нашей конфигурации. Для этого необходимо выделить ветку Макеты документа (см. рис. 11.1.3), кликнуть правой клавишей мышки и в открывшемся контекстном меню выполнить единственную команду Добавить.
Рис. 11.1.3
Откроется окно конструктора макетов. В открывшемся конструкторе мы ничего не меняем, но обращаем внимание, что тип макета выбран Табличный документ.
После нажатия кнопки Готово конструктора макета, будет создан макет табличного документа под названием Макет.
Рис. 11.1.5
Макет табличного документа представляет собой таблицу наподобие таблицы Excel.
Она также состоит из строк, столбцов и ячеек. Каждая ячейка имеет свои уникальные свойства. Кликнем правой клавишей мышки по ячейке и в выпадающем меню выполним команду Свойства. В результате справа откроется палитра свойств выделенной ячейки.
Рис. 11.1.6
Внутрь любой ячейки можно поместить текст. Для этого необходимо либо написать нужный текст в свойстве Текст ячейки, либо написать текст напрямую в ячейке. Напишем в ячейке второй колонки второго столбца текст: «Прибытие автомобиля №».
Рис. 11.1.7
Вы видите, что текст не уместился на одной ячейке, а сразу перешёл на вторую, и появились две линии по краям ячейки – горизонтальная и вертикальная. Эти линии ограничивают область, которая будет выводиться на экран (на печать).
Строка Прибытие автомобиля… будет выведена на печать не полностью. Чтобы такого не произошло, объединим ячейки и заодно увеличим шрифт. Чтобы объединить ячейки, необходимо сначала выделить нужные ячейки (нажать левую кнопку мышки и вести по ячейкам курсор с нажатой кнопкой).
Рис. 11.1.8
Затем вызовем нажатием правой клавиши мышки контекстное меню и выполним в этом меню команду Объединить (также команда доступна по следующему пути: Главное меню – Таблица – Ячейки).
Рис. 11.1.9
В результате ячейка станет одна.
Рис. 11.1.10
Изменим величину шрифта на 14 (ячейка должна быть выделена).
Рис. 11.1.11
Ячейка увеличилась, и текст опять не помещается. Снова объединим ячейки с двумя соседними. Для этого нужно снять имеющееся объединение, также выделив ячейки и нажав на кнопку Объединить или в контекстном меню, или в меню Главное меню – Таблица – Ячейки, и заново объединить в этот раз четыре ячейки.
Рис. 11.1.12
Всё, что вы напишете в данной таблице, будет, при определённых условиях, выведено в печатную форму!
Введём текст «Номер» в следующую ячейку после объединённой (крайнюю объединённую колонку сделаем более узкой), и изменим шрифт на 14.
Следующим шагом нам необходимо подготовиться к тому, чтобы в дальнейшем можно было передать номер и дату документа прибытия в макет (как это делается, мы изучим немного позже). Что для этого нужно сделать? Нужно сделать нескольких простых шагов. Первое – изменим свойство Заполнение ячейки. Откроем палитру свойств ячейки: выделим её, кликнем правой клавишей мышки, выйдет контекстное меню, в котором выполним команду Свойства.
Рис. 11.1.14
Справа откроется палитра свойств выделенной ячейки, в палитре обратим внимание на свойство Заполнение.
Рис. 11.1.15
Изменим значение этого свойства на значение Параметр.
Обратим внимание, слово Номер выделится треугольными скобками.
Рис. 11.1.17
Добавим ещё и ячейку с датой (словом Дата), а потом у ячейки со словом Дата также установим в свойство Заполнение значение Параметр.
Рис. 11.1.18
И сразу же установим формат даты, удобный для восприятия. Сделаем это напрямую в макете. Откроем палитру свойств ячейки Дата и перейдём в свойство Формат.
Рис. 11.1.19
Установим какой-нибудь удобный формат даты.
У многих может возникнуть вопрос: а можно ли передать параметр внутрь текста? Да, можно, для этого необходимо устанавливать в свойство Заполнение ячейки значение Шаблон.
Напишем в нашем макете через строку следующий текст: «Автомобиль [Автомобиль] прибыл в [Гараж] [ДатаПрибытия]». Поставим 12 шрифт и объединим ячейки.
Рис. 11.1.21
Перейдем в палитру свойств объединённой ячейки и установим в свойство Заполнение
значение Шаблон.
Рис. 11.1.22
Все слова, которые находятся в квадратных скобках (Автомобиль, Гараж, ДатаПрибытия), будут переданы в виде параметров.
Для ячеек можно установить границы в виде различных линий. Делается это с помощью свойств ячейки Граница слева, Граница сверху, Граница справа, Граница снизу.
Рис. 11.1.23
Поставим на несколько нижних ячеек Граница снизу, а также напишем текст под
ними:
Рис. 11.1.24
Текст «Ответственный» и «Подпись» сдвинут влево. Сделаем этот текст по центру ячейки. Для этого сначала объединим ячейки под чертой, а потом выделим объединённую ячейку и в свойство ГоризонтальноеПоложение установим значение Центр.
Рис. 11.1.25
Точно так же сделаем для подписи.
Рис. 11.1.26
В целом макет готов, но это ещё не всё. Для того чтобы было удобнее выводить макет, принято использовать области. Зададим область, которую назовём Основная.
Для этого выделим те ячейки, которые мы хотим поместить в область (мы выделим все строки в границе печати).
Рис. 11.1.27
Выполним команду Назначить имя в меню Имена (по пути Главное меню – Таблица, область должна оставаться выделенной).
Рис. 11.1.28
Имя у области Основная.
Рис. 11.1.29
После назначения области макет приобретёт следующий вид:
Рис. 11.1.30
Всё, мы создали самый примитивнейший макет. Теперь нам нужно создать команду
ПечатьДокумента, в которой реализуем вывод табличного документа на экран. Это будет команда документа ПрибытиеВГараж. Для её создания необходимо выделить ветку Команды соответствующего документа в дереве метаданных, вызвать контекстное меню и выполнить команду Добавить.
Рис. 11.1.31
11.04 чем запрос лучше объектного получения данных?
Команда будет создана, назовем её Печать документа, группу укажем Командная панель формы.Важное, тип параметра команды – ДокументСсылка.ПрибытиеВГараж и режим использования параметра – Одиночный (это значит, что можно будет только один документ распечатать).
Рис. 11.1.32
В модуле созданной команды (если закрыли, то открыть её можно, используя команду
Открыть модуль команды, см. рис. 11.1.33) напишем функцию Печать().
Рис. 11.1.33
&НаСервере
Функция Печать(СсылкаНаДокумент) Экспорт Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ПрибытиеВГараж.Номер КАК Номер,
| ПрибытиеВГараж.Дата КАК Дата,
| ПрибытиеВГараж.Автомобиль КАК Автомобиль,
| ПрибытиеВГараж.Гараж КАК Гараж,
| ПрибытиеВГараж.ДатаПрибытия КАК ДатаПрибытия
|ИЗ
| Документ.ПрибытиеВГараж КАК ПрибытиеВГараж
|ГДЕ
| ПрибытиеВГараж.Ссылка = &Ссылка"; Запрос.УстановитьПараметр("Ссылка",СсылкаНаДокумент); Выборка = Запрос.Выполнить().Выбрать(); Выборка.Следующий();
Макет = Документы.ПрибытиеВГараж.ПолучитьМакет("Макет"); ОбластьОсновная = Макет.ПолучитьОбласть("Основная"); ОбластьОсновная.Параметры.Номер = Выборка.Номер; ОбластьОсновная.Параметры.Дата = Выборка.Дата; ОбластьОсновная.Параметры.Автомобиль = Выборка.Автомобиль; ОбластьОсновная.Параметры.Гараж = Выборка.Гараж; ОбластьОсновная.Параметры.ДатаПрибытия = Выборка.ДатаПрибытия;
ТабДокумент = Новый ТабличныйДокумент; ТабДокумент.Вывести(ОбластьОсновная); Возврат ТабДокумент;
КонецФункции
Листинг 11.1.1
Разберём код выше.
Во-первых, получение данных из запроса должно выполняться в серверном контексте, поэтому процедура работает под директивой &НаСервере.
При помощи запроса мы получаем информацию из реквизитов объекта. Конечно, Вы можете спросить, почему мы использовали запрос, а не обратились напрямую к этим реквизитам. Сделано это в целях повышения производительности. Потому что при выполнении запроса мы только один раз обращаемся к базе данных, а после получаем данные уже из запроса, которые хранятся в объекте выбора. Иначе мы каждый раз будем обращаться к базе данных, чтобы получить значение того или иного реквизита.
После запроса и выборки мы получаем макет с помощью метода менеджера документа ПолучитьМакет. В качестве параметра мы передали название макета, которое указано в конфигураторе.
В следующей строке мы получаем область, которую задали в макете, указав её название. Обращаю Ваше внимание, что можно и не задавать имя области, а просто указать диапазон ячеек. Но на начальном этапе, да и в дальнейшем, лучше всё делать через имена областей, такой подход делает код более комфортным для доработки и чтения.
Теперь нам нужно заполнить параметры области, которые мы задали в макете.
Делается это с помощью свойства области Параметры.
Данное свойство представляет объект Параметры макета табличного документа,
который является коллекцией параметров макета.
К параметрам макета можно обращаться через квадратные скобки, а проще – напрямую, как в данном примере.
Мы заполнили макет и параметры его области. Но сам по себе макет бесполезен. Его необходимо вывести. Делается это с помощью объекта Табличный документ. Данный объект предназначен для вывода табличных форм на экран. Он создаётся с помощью оператора Новый.
С помощью метода Вывести табличного документа добавляем основную область макета в табличный документ. Прежде чем вывести сам табличный документ, его необходимо скомпоновать из имеющихся в макете областей. Дело в том, что областей может быть несколько, некоторые из них могут повторяться, а некоторые, наоборот, отсутствовать при определённых условиях. Поэтому с помощью данного метода табличного документа и формируется результирующий документ.
Мы не можем сейчас вывести табличный документ на экран, поскольку функция в модуле команды создана в серверном контексте. А табличный документ должен показываться на компьютере пользователя, то есть в клиентском контексте. Поэтому мы возвращаем созданный и заполненный табличный документ, чтобы его использовать в дальнейшем.
При создании команды автоматически в модуле команды была создана процедура ОбработкаКоманды. Именно эта процедура и сработает при выполнении команды. Заметьте, у процедуры имеется параметр ПараметрКоманды. В этот параметр команды будет передана ссылка на документ, к которому мы применим эту команду. Ссылка будет передана по двум причинам. Во-первых, в свойстве Тип параметра команды указана ссылка на документ, к которому «привязана» эта команды, а во-вторых, в свойстве Режим использования команды указано значение Одиночный (если было бы указано значение Множественный, то в переменной ПараметрКоманды был бы массив ссылок).
Рис. 11.1.34
Напишем в обработчике команды следующий код:
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды) ТабДок = Печать(ПараметрКоманды);
ТабДок.Показать(); КонецПроцедуры
Листинг 11.1.2
В коде выше мы получаем табличный документ из функции Печать модуля команды, которую сделали выше (см. листинг 11.1.35). После этого мы с помощью метода Показать выводим табличный документ на экран.
Сохраним конфигурацию и посмотрим, как будет выходить наша печатная форма. Во-первых, команда печати документа появится в командной панели документа.
Рис. 11.1.35
Во-вторых, при выполнении этой команды, будет сформирован табличный документ.
Рис. 11.1.36
Дата прибытия во второй строке печатной формы выходит не очень красиво. Сделайте вывод даты прибытия в более удобном формате.
Более подробно работа с командами объекта даётся в книге «Основы разработки в 1С: Такси».
Макет с несколькими областями
Мы только что научились выводить макет с одной областью на печать. В реальности такие ситуации достаточно редки. Часто документы содержат табличную часть, которую
тоже необходимо вывести в макет в виде какой-либо таблицы.
Создадим макет табличного документа для документа Установка цен на топливо, при помощи этого макета будем выводить все виды топлива с ценами, которые указаны в табличной части документа.
Развернём документ УстановкаЦенНаТопливо в дереве конфигурации и создадим пустой макет с типом Табличный документ.
Рис. 11.1.37
В этом макете создадим область с пятью строками, которую назовём Шапка (как создавать новые области см. стр. 740).
Рис. 11.1.38
Напишем в первой ячейке второй строки следующий текст:
Цены на топливо поставщика [Поставщик] от [Дата]
Увеличим шрифт, установим у свойства Заполнение значение Шаблон, объединим ячейки по всей длине строки и установим в свойство Отступ текста объединенной ячейки значение 5.
Рис. 11.1.39
Всё. Шапку документа мы создали. Дальше нам необходимо создать шапку табличной части. Для этого создадим новую область, которую так и назовём ШапкаТаблицы.
Рис. 11.1.40
В первой ячейке напишем текст «№», и обведём ячейку границей.
Рис. 11.1.41
Последующие пять ячеек объединим в одну, напишем в них текст «Тип топлива», затем обведём объединённую ячейку границами. В последней ячейке текст будет «Цена», и тоже объединим её границей. Для всех ячеек увеличим шрифт до 12, и горизонтальное положение для всех установим Центр.
Рис. 11.1.42
Подсказка: если какое-то свойство распространяется на несколько ячеек, то можно выделить их все и установить нужное свойство. Оно установится для всех выделенных ячеек.
Дальше необходимо создать область, в которую будут выводиться непосредственно данные из документа. Новую область назовем Таблица.
Рис. 11.1.43
В первой ячейке напишем текст «Номер», сделаем эту ячейку параметром (свойство
Заполнение – Параметр), обведём её, горизонтальное положение для неё будет Право.
Следующие пять ячеек объединим, пишем текст «ТипТоплива», и также делаем эту объединённую ячейку параметром (свойство Заполнение – Параметр). Горизонтальное положение для неё будет Право.
В последней ячейке напишем текст «Цена», сделаем её параметром. Горизонтальное положение для неё будет Право. Всем ячейкам установим 12 шрифт.
Рис. 11.1.44
Теперь создадим подвал таблицы, в котором выведем общее количество строк в документе. Для этого добавляем новую область, которую так и назовём – ПодвалТаблицы.
Рис. 11.1.45
Сверху ограничим область жирной линией. Для этого выделим всю область подвала от номера до цены, откроем палитру свойство выделенных ячеек и установим границу, сверху которой поставим толщину равную 2.
Рис. 11.1.46
Объединим ячейки в подвале под заголовком Тип топлива, и напишем в них следующий текст:
Всего [КолТипов] типов топлива
Сделаем эту объединённую ячейку шаблоном, выделим жирным и установим для неё
12 шрифт.
Рис. 11.1.47
Нам осталось сделать подвал документа. Создадим новую область, которую назовём
Подвал. И разместим в этой области подписи и расшифровку.
Рис. 11.1.48
Всё, макет мы создали, осталось сделать возможность вывода на просмотр. Сделаем это по аналогии с выводом предыдущего макета: создадим команду документа Печать.
Рис. 11.1.49
В модуле команды документа создадим функцию ПечатьРеестраЦен(), которая будет выполняться в серверном контексте.
&НаСервере
Процедура ПечатьРеестраЦен(СсылкаНаДокумент)
КонецПроцедуры
Листинг 11.1.3
Первым делом нам необходимо получить параметры шапки документа и табличной части. В целях производительности мы будем получать эти параметры, используя запросы.
И первым запросом мы получим параметры шапки. Создадим объект Запрос, откроем конструктор запроса, в котором выберем таблицу Установка цен на топливо и поля Дата и Поставщик.
Рис. 11.1.50
Перейдём на закладку Условие и установим условие:
Рис. 11.1.51
Запрос создан, нажмём кнопку ОК и сохраним его, передадим в запрос параметры и сделаем выборку.
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| УстановкаЦенНаТопливо.Дата КАК Дата,
| УстановкаЦенНаТопливо.Поставщик КАК Поставщик
|ИЗ
| Документ.УстановкаЦенНаТопливо КАК УстановкаЦенНаТопливо
|ГДЕ
| УстановкаЦенНаТопливо.Ссылка = &Ссылка"; Запрос.УстановитьПараметр("Ссылка",СсылкаНаДокумент);
Шапка = Запрос.Выполнить().Выбрать(); Шапка.Следующий();
Листинг 11.1.4 Следующим шагом создадим табличный документ и получим макет из менеджера
документа.
ТабДокумент = Новый ТабличныйДокумент;
Макет = Документы.УстановкаЦенНаТопливо.ПолучитьМакет("Макет");
Листинг 11.1.5
Сразу же создадим все области, которые есть в макете.
ОблШапка = Макет.ПолучитьОбласть("Шапка"); ОблШапкаТабл = Макет.ПолучитьОбласть("ШапкаТаблицы"); ОблТаблица = Макет.ПолучитьОбласть("Таблица"); ОблПодвалТаб = Макет.ПолучитьОбласть("ПодвалТаблицы"); ОблПодвал = Макет.ПолучитьОбласть("Подвал");
Листинг 11.1.6
Названия областей в кавычках, передаваемые в параметр метода
ПолучитьОбласть, должны совпадать с названиями областей в макете.
После того как области созданы, мы будем их заполнять, если у них есть параметры, и последовательно выводить в результирующий табличный документ.
Заполним параметры области Шапка. Для этого воспользуемся методом Заполнить объекта ПараметрыМакетаТабличногоДокумента. Данный метод заполняет параметры из значений свойств переданного объекта. В качестве параметра в этот метод будем передавать выборку Шапка, которую мы получили с помощью метода Выбрать результата запроса. И которую мы позиционировали на первом элементе выборки при помощи метода Следующий.
ОблШапка.Параметры.Заполнить(Шапка); ОблШапка.Параметры.Дата = Формат(Шапка.Дата,"ДЛФ=DD");
Листинг 11.1.7
Один параметр мы заполнили вручную. Это Дата.
Теперь выведем область Шапка в результирующий табличный документ. А также выведем область Шапка таблицы, так как в ней нет никаких параметров.
ТабДокумент.Вывести(ОблШапка); ТабДокумент.Вывести(ОблШапкаТабл);
Листинг 11.1.8
Сначала всегда заполняем область, а потом выводим её в табличный документ!
Далее необходимо вывести все типы цен и цены, которые есть в табличной части. Сделаем мы это благодаря одной особенности областей: их можно выводить в табличный документ неограниченное количество раз.
Но перед этим получим данные из табличной части документа. Создадим новый
запрос и откроем конструктор запроса, в котором выбирем табличную часть документа Установка цен на топливо (переименуем эту таблицу в ЦеныТоплива) и поля НомерСтроки, ТипТоплива и Цена.
Рис. 11.1.52
Перейдём на закладку Условие и установим условие:
Рис. 11.1.53
Переименуем поле НомерСтроки в просто Номер.
Рис. 11.1.54
Сохраним запрос, установим параметры и получим выборку.
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| ЦеныТоплива.НомерСтроки КАК Номер,
| ЦеныТоплива.ТипТоплива КАК ТипТоплива,
| ЦеныТоплива.Цена КАК Цена
|ИЗ
| Документ.УстановкаЦенНаТопливо.ЦеныТоплива КАК ЦеныТоплива
|ГДЕ
| ЦеныТоплива.Ссылка = &Ссылка"; Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент); Выборка = Запрос.Выполнить().Выбрать();
Листинг 11.1.9 Создадим цикл обхода выборки. И внутри этого цикла будем заполнять параметры
области Таблица и выводить её в результирующий документ.
Пока Выборка.Следующий() Цикл ОблТаблица.Параметры.Заполнить(Выборка); ТабДокумент.Вывести(ОблТаблица);
КонецЦикла;
Листинг 11.1.10 После цикла заполним параметры подвала таблицы. И выведем подвал таблицы и
общий подвал.
ОблПодвалТаб.Параметры.КолТипов = Выборка.Количество(); ТабДокумент.Вывести(ОблПодвалТаб); ТабДокумент.Вывести(ОблПодвал);
Листинг 11.1.11 И поскольку у нас ПечатьРеестраЦен – это функция, то мы вернём табличный
документ.
Возврат ТабДокумент;
Листинг 11.1.12 Функцию модуля команды, которая формирует и заполняет табличный документ,
сделали. Применим эту функцию в обработчике ОбработкаКоманды модуля созданной
команды документа.
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды) ТабДокумент = ПечатьРеестраЦен(ПараметрКоманды); ТабДокумент.Показать();
КонецПроцедуры
Листинг 11.1.13
В результате должен получиться примерно такой результат:
Рис. 11.1.55
Как Вы видите, печатная форма вышла в том виде, в каком мы и хотели.
В этой части мы научились создавать примитивные печатные формы для документов, заполнять их и выводить на экран. Вы теперь знаете, как создавать макеты, заполнять их и передавать параметры как непосредственно в ячейку, так и в шаблон. Также Вы можете выводить печатную форму любого документа как с табличной частью, так и без неё. Эти знания очень пригодится Вам в дальнейшей работе.
В предыдущих главах мы любую информацию выводили в таблицы на форме обработки. Для пользователя получать информацию в такой форме немного неудобно. Естественно, есть более удобный способ получать информацию о хозяйственной деятельности предприятия. Для этого необходимо использовать такие объекты конфигурации, как Отчёты. Можно создавать отчёты как объект конфигурации, а можно создавать и внешние отчёты.
В этой части мы научимся создавать простые отчёты при помощи табличного документа и при помощи СКД. В этой книге не ставится цель научить Вас делать различные сложные отчёты, а просто даются базовые понятия, чтобы Вы понимали, как это работает, и в дальнейшем уже смогли углубить свои знания и умения.
Простые отчеты
Для демонстрации возможности работы с отчётами создадим простой отчёт по запросу из второй части девятой главы, в этом запросе мы получали список автомобилей. Отчёт
будем выводить в табличном документе.
Создадим внешний отчёт (аналогично созданию внешней обработке), отчёт назовём
«Глава 11 часть 2 отчет 1».
Рис. 11.2.1
Рис. 11.2.2
Создадим форму отчёта.
На этой форме создадим реквизит, который назовём ТабличныйДокумент (заголовок
Отчет), тип у этого реквизита будет Табличный документ.
Рис. 11.2.4
«Перетащим» реквизит на форму. Будет создан элемент формы Поле с новым для Вас видом – Поле табличного документа.
Рис. 11.2.5
Создадим команду Печать, которую разместим в командной панели формы.
Переключимся с формы на редактор отчёта, в котором создадим макет этого внешнего отчёта.
Рис. 11.2.7
Оставим по умолчанию название макета – Макет, и тип макета – Табличный документ.
Рис. 11.2.8
В новом макете табличного документа создадим четыре области. Первую область назовём Шапка, вторую – ШапкаТаблицы, третью – СтрокиТаблицы, четвёртую – Подвал.
В первой колонке второй строки области Шапка напишем текст: «Список автомобилей», установим у текста 14 шрифт, объединим шесть ячеек и отцентрируем текст.
В шапке таблицы в каждой ячейке напишем: «№», «Название», «Год выпуска», «Гос. номер», «Марка» и «Модель». Обведём ячейки шапки таблицы границами, установим 12 шрифт, отцентрируем текст и раздвинем колонки, чтобы все названия влезли.
В области Строки таблицы напишем в ячейках следующий текст: «Номер»,
«Название», «ГодВыпуска», «ГосНомер», «Марка» и «Модель», установим для каждой ячейки в свойство Заполнение значение Параметр, обведем ячейки и установим для них 12 шрифт.
Рис. 11.2.10
Для ячейки Название области СтрокаТаблицы установим в свойство РазмещениеТекста значение Переносить. Теперь если название авто будет не влезать в ширину колонки, то оно перенесётся на другую строку.
Рис. 11.2.11
А у ячейки ГодВыпуска установим формат даты.
Рис. 11.2.12
В подвале проведём жирную черту. Чтобы она выходила на нижней границе таблицы, выделим верхние ячейки подвала, перейдём в палитру свойств всех выделенных ячеек (можно открыть общее свойство для нескольких ячеек) и установим для них верхнюю границу с двойной толщиной.
Рис. 11.2.13
Макет готов, осталось написать вывод информации в созданный макет. Делать мы это будем в обработчиках команды Печать, которую создали ранее на форме отчёта. Создадим обработчики команды на сервере и на клиенте. И в серверном обработчике напишем код, который будет выводить информацию об автомобилях в табличный документ.
&НаСервере
Процедура ПечатьНаСервере() ТабличныйДокумент.Очистить();
ОтчетОбъект = РеквизитФормыВЗначение("Отчет"); Макет = ОтчетОбъект.ПолучитьМакет("Макет");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка"); ОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ШапкаТаблицы"); ОбластьСтрокиТаблицы = Макет.ПолучитьОбласть("СтрокиТаблицы"); ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
ТабличныйДокумент.Вывести(ОбластьШапка); ТабличныйДокумент.Вывести(ОбластьШапкаТаблицы);
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
| Автомобили.Наименование КАК Название,
| Автомобили.ГодВыпуска КАК ГодВыпуска,
| Автомобили.ГосНомер КАК ГосНомер,
| Автомобили.Марка КАК Марка,
| Автомобили.Модель КАК Модель
|ИЗ
| Справочник.Автомобили КАК Автомобили
|ГДЕ
| НЕ Автомобили.ПометкаУдаления";
Выборка = Запрос.Выполнить().Выбрать(); Номер = 1;
Пока Выборка.Следующий() Цикл ОбластьСтрокиТаблицы.Параметры.Заполнить(Выборка); ОбластьСтрокиТаблицы.Параметры.Номер = Номер; ТабличныйДокумент.Вывести(ОбластьСтрокиТаблицы); Номер = Номер + 1;
КонецЦикла; ТабличныйДокумент.Вывести(ОбластьПодвал);
КонецПроцедуры
&НаКлиенте
Процедура Печать(Команда) ПечатьНаСервере();
КонецПроцедуры
Листинг 11.2.1
В этом коде мы обращаемся к реквизиту формы с типом ТабличныйДокумент напрямую и первым делом его очищаем. Потом получаем Макет нашего отчёта, используя метод ПолучитьМакет объекта ВнешнийОтчет, который мы получили, используя метод РеквизитФормыВЗначение, обратившись к основному реквизиту формы Отчет.
Рис. 11.2.14
Дальнейший код Вам должен быть знаком и не должен вызывать каких-либо затруднений: мы получаем области макета и выводим их в табличном документе. Заметьте, в данном случае мы не показываем табличный документ, как делали в предыдущих примерах. Вся нужная информация отобразится на поле в форме.
Рис. 11.2.15
Отчёты на СКД
Что такое СКД? СКД – это инструмент платформы 1С, который позволяет гибко и динамически получать данные из базы, а потом или реализует вывод этих данных в отчёте, или подготавливает их для дальнейшего использования.
Научимся делать самые простые отчёты на СКД. В этом труде не будем подробно вдаваться в основы работы на СКД, а разберём только самые азы, чтобы было в дальнейшем с чего начинать. Если Вы захотите углубить знания по СКД, то сможете найти соответствующую литературу, курсы и т.д. А после этой книги весь узконаправленный материал Вами легче усвоится.
Для тренировки сделаем внешний отчёт по примеру десятой главы, где мы в запросе получали обороты по регистру накопления ТопливоВАвтомобилях.
Создадим внешний отчёт и сохраним его на жёстком диске. В редакторе отчёта необходимо нажать на кнопку Открыть схему компоновки данных (см. рис. 11.2.16), после нажатия откроется конструктор макета, в котором уже будет выбран тип макета Схема компоновки данных.
Рис. 11.2.16 | Рис. 11.2.17 |
Нажмём кнопку Готово, и откроется конструктор СКД.
Рис. 11.2.18
С этим конструктором и будет осуществляться наша основная работа. Первым шагом необходимо создать набор данных. Всего в СКД существует три набора данных – Запрос, Объект и Объединение. В первом варианте мы укажем какой-то запрос, по которому будет из базы данных получена информация. Во втором варианте нужно указать конкретный объект. Этот вариант применяется, когда мы работаем с СКД в программном коде, тогда мы можем передать в СКД различные объекты (например, таблицу значений). И в третьем варианте мы можем объединить несколько разных наборов (к примеру, два набора запроса). Мы разберём только один вид набора данных – запрос.
Рис. 11.2.19
После добавления набора данных – запрос, внизу появится поле запроса, а вверху – таблица полей, которая пока пустая. Можно запрос написать вручную, а можно создать при помощи конструктора, мы создадим запрос с помощью конструктора, для этого нажмём на кнопку Конструктор запроса.
Рис. 11.2.20
В результате откроется уже знакомый Вам конструктор запроса, в этом запросе мы
выберем виртуальную таблицу Обороты регистра накопления ТопливоВАвтомобилях и выберем поля Автомобиль, ТипТоплива, КоличествоПриход и КоличествоРасход.
Рис. 11.2.21
Откроем окно Параметры виртуальной таблицы, в которой зададим только периодичность День. Параметры НачалоПериода и КонецПериода задавать не нужно, платформа сама их определит. Различные отборы в условии нужно задавать, когда мы хотим делать конкретный жёсткий отбор, в иных же случаях делать это не нужно. Все отборы можно делать в СКД.
Рис. 11.2.22
Всё. Больше ничего делать не будем, нажмём кнопку ОК конструктора запроса, и наша форма конструктора СКД изменится: в нижнем окне появится текст запроса. А в верхнем – поля этого запроса. Обратите внимание на флаг Автозаполнение. Поля в верхней части появились, потому что он выставлен. Если этот флаг снять, то верхняя таблица с полями очистится.
Рис. 11.2.23
Поработаем с верхней таблицей. Исправим наименования полей Количество Приход и Количество Расход на Приход и Расход соответственно. Тем самым мы изменим только отображение полей в отчёте. А в самом конструкторе СКД мы будем работать с теми названиями, которые пришли из запроса. Для того чтобы изменить названия, установим флаг во второй колонке и вручную исправим.
Рис. 11.2.24
Следующим шагом установим поля, которые будут суммироваться. В СКД можно настраивать получение итогов по любому нужному полю. Например, мы можем узнать, сколько любого топлива было залито в конкретный автомобиль, или, наоборот, сколько конкретного топлива было израсходовано всеми автомобилями. Для этого нам нужно определить поля, которые будут суммироваться, делается это на закладке Ресурсы.
В этой закладке мы выберем два поля – КоличествоПриход и КоличествоРасход, и установим для них выражение Сумма.
Рис. 11.2.25
Перейдём на закладку Параметры, Вы увидите, что СКД автоматически подставило начало периода и конец периода.
Рис. 11.2.26
Но работать через две даты на форме неудобно и непрактично. Сделаем один параметр с типом СтандартныйПериод. Для этого добавим в таблице параметров новый параметр, назовём его Период и тип ему назначим СтандартныйПериод.
Рис. 11.2.27
Теперь нам нужно сделать так, чтобы данные стандартного периода были переданы в параметры НачалоПериода и КонецПериода. Для этого будем использовать поле таблицы Выражение. В этом поле прописывается выражение, которое может принять тот или иной параметр. Мы передадим в качестве параметра свойств ДатаНачала и ДатаОкончания объекта СтандартныйПериод. И поставим флажки Ограничения доступности у полей НачалоПериода и КонецПериода, чтобы пользователь их не видел.
Рис. 11.2.28
Всё. Само ядро будущего отчёта мы сделали. Именно эти три закладки – Набор данных, Ресурсы и Параметры – определяют, какие данные и как будут появляться в наших отчётах (есть ещё закладки Связи наборов данных и Вычисляемые поля, которые тоже влияют на состав данных, но мы их не будем затрагивать).
Осталось настроить вид, как наш отчёт будет выводиться пользователю. Для этого перейдём на закладку Настройки.
Рис. 11.2.29
Сделаем так, чтобы поле Период отображалось на форме. Выделим строку с параметром Период закладки Параметры, расположенной в нижней части окна, и нажмём на кнопку Свойства элементов пользовательских настроек. В открывшемся окне установим флаг Включать в пользовательские настройки. После этого на форме отчёта (она сформируется автоматически) появится нужное поле. Для того чтобы данные брались сразу, можно установить флаг рядом с параметром Период.
Рис. 11.2.30
Сделаем возможность установки отбора по автомобилю. Для этого перейдём на закладку Отбор и выберем поле Автомобиль.
Рис. 11.2.31
Если мы не установим флаг в строке отборов, то по умолчанию отбор не будет работать (что нам, в принципе, и нужно). Но очень удобно, если возможность установки отбора будет на форме, так же, как и период. В этом нам поможет всё та же кнопка Включать в пользовательские настройки. Выделим строку отбора с автомобилем, нажмём на кнопку Включать в пользовательские настройки, а в открывшемся окне установим флаг Включать в пользовательские настройки.
Рис. 11.2.32
Осталось настроить вид отображения пользователю. Переключим внимание на верхнее окно. Зададим в нём две группировки – Автомобиль и ТипТоплива. Чтобы создать группировку, следует нажать на кнопку Добавить и выбрать вариант Новая группировка…
Рис. 11.2.33
В открывшемся окне Группировка выберем поле Автомобиль.
Рис. 11.2.34
Поскольку нам нужно сделать две группировки Автомобиль – ТипТоплива, то добавим группировку ТипТоплива, которая будет подчинена уже добавленной группировке Автомобиль.
Для этого выделим добавленную группировку, вызовем контекстное меню, в котором выполним команду Новая группировка…
Рис. 11.2.35
В качестве новой группировки выберем группировку ТипТоплива.
Должна получиться следующая иерархия:
Рис. 11.2.36
Теперь сделаем так, чтобы в нашем отчёте отображались поля КоличествоПриход и КоличествоРасход. Для этого выделем головную группировку Отчет, в нижнем окне перейдём на закладку ВыбранныеПоля и «перетащим» поля КоличествоПриход и КоличествоРасход.
Рис. 11.2.37
Всё. Сохраним отчёт и запустим его в пользовательском режиме.
Рис. 11.2.38
Первым делом обратим внимание, что у нас на форме есть поля Период и Автомобиль, так получилось потому, что мы установили флажки Включать в пользовательские настройки у соответствующих полей в настройках отчёта. Причём у поля Период уже установлен флаг (значит, данные будут браться), а у поля Автомобиль – нет. Это потому, что мы поставили (или убрали) флаг у соответствующего поля (см. рис. 11.2.39).
Рис. 11.2.39
Сформируем отчёт.
Рис. 11.2.40
Сформируем отчёт с отбором по автомобилю.
Рис. 11.2.41
На этом мы закончим изучать СКД. Понятно, что этой информации мало, чтобы полностью овладеть этим интересным механизмом. Но её достаточно, чтобы начать делать простые отчёты. В дальнейшем Вы сможете углубить свои знания при помощи различной литературы, статей и т.д. по этой теме.
Рассмотрим последний способ вывода информации, который мы изучим в этой книге,
динамические списки.
Что такое динамический список? Динамический список – это специальный тип, при помощи которого на форме можно отображать любые произвольные данные. Он позволяет делать сортировку этих данных, отбор, группировку, условное оформление и т.д.
Разработчик может указать какую-то определённую таблицу, из которой будут браться необходимые данные, или самостоятельно написать нужный запрос.
Когда мы работали с запросами, то мы запросы загружали в таблицу значений на форме. Можно эти лишние движения не делать, а напрямую выводить данные из того же запроса в динамический список.
Что интересно, мы, сами того не зная, уже сталкивались с динамическими списками, когда создавали формы списков справочников или документов. При автоматическом создании формы списка, будь то справочника или документа, платформа всегда размещает динамический список на форме.
Откроем форму списка документа Прибытие в гараж, и мы увидим, что у нас в реквизитах размещён динамический список (кстати, это основной реквизит).
Рис. 11.3.1
Откроем палитру свойств реквизита Список.
Рис. 11.3.2
У нас заполнено свойство ОсновнаяТаблица и снят флаг ПроизвольныйЗапрос. Это значит, что при выводе списка платформа будет автоматически заполнять его данными из указанной таблицы. Если же мы поставим флаг ПроизвольныйЗапрос, то необходимо будет написать запрос к базе данных на языке запросов 1С, по которому будут выводиться данные в таблицу.
В качестве основной таблицы можно выбрать любую таблицу любого объекта, который есть в базе. Для этого достаточно нажать кнопку выбора (кнопка «…»), и откроется форма выбора таблицы (см. рис. 11.3.3).
Рис. 11.3.3
Таким образом, в качестве основной таблицы можно выбрать любую таблицу, которая есть в базе (включая виртуальные таблицы).
Если же установить флаг Произвольный запрос, то свойство Основная таблица
уберётся из списка свойств (см. рис. 11.3.4).
Рис. 11.3.4
Но если мы нажмём гиперссылку свойства Настройка списка, то откроется форма, в которой мы увидим окно запроса и опять свойство Основная таблица (см. рис. 11.3.5).
Рис. 11.3.5
В случае произвольного запроса мы можем изменить набор данных, который должен отображаться в динамическом списке. Но в этом случае всё равно рекомендуется указывать основную таблицу, необходимо это делать для того, чтобы платформа могла определить, какая информация в этом динамическом списке главная, а какая второстепенная, и исходя из этого настроить стандартные команды. В том случае, если у Вас несколько таблиц в запросе и они связаны каким-то соединением, то всё равно рекомендуется всегда указывать основную таблицу, потому что в противном случае производительность основного списка будет желать лучшего.
Обратите внимание на свойство Динамическое считывание данных, которое есть и в свойствах динамического списка, когда указана основная таблица (см. рис. 11.3.2), и в том случае, когда указан произвольный запрос (см. рис. 11.3.6). Если это свойство установлено, то считывание данных происходит порциями, то есть выбираются только те данные, которые необходимы для отображения на экране. В целях улучшения производительности лучше всегда это свойство устанавливать.
Добавим в имеющийся динамический список поля ГосНомер и ГодВыпуска реквизита
Автомобиль (сделайте это сами, воспользовавшись кнопкой Конструктор запроса).
Рис. 11.3.6
Рис. 11.3.7
Сохраним эту настройку списка, обновим конфигурацию и посмотрим, как отобразится список документов ПрибытиеВГараж (удалите имеющийся элемент формы Список и добавьте новый, расположите колонки, как Вам больше нравится).
Попробуем использовать динамический список как замену таблицы значений в наших тренировках с запросами. Для этого реализуем обработку, в которой создадим динамический список, выводящий список автомобилей.
Создадим новую обработку и форму обработки, а на форме создадим реквизит Список
с типом ДинамическийСписок.
Рис. 11.3.9
Установим свойство ПроизвольныйЗапрос, и в настройках списка сделаем запрос по таблице Автомобили, не забыв указать её в качестве основной таблицы и не забыв поставить флаг Динамическое считывание данных.
Сохраним эту настройку, и у нас сразу же нужные поля появятся в списке.
Рис. 11.3.11
«Перетащим» динамический список на форму, он отобразится в виде элемента
Таблица (самостоятельно сделайте удобное для Вас расположение полей).
Рис. 11.3.12
Сохраним обработку, откроем её в пользовательском режиме «1С: Предприятия».
Рис. 11.3.13
Как видите, выводить данные при помощи динамических списков гораздо удобнее.
На этом мы закончим изучать работу с динамическими списками. Эта часть носит больше ознакомительный характер, чтобы Вы знали, что такой инструмент имеется и его очень удобно использовать. Больше информации о работе с динамическими списками есть в книге «Основы разработки в 1С: Такси. Разработка в управляемом приложении за 12 шагов».
Мы изучили основные механизмы вывода информации на экран в системе
«1С:Предприятия». Их довольно много, и мы разобрали только основные из них. Вся информация этой главы носит ознакомительный характер, цель которой дать Вам первоначальное представление о различных способах отображения информации. В дальнейшем в процессе работы (учёбы) Вы сможете углубить Ваши знания.
Поздравляю!
Вы дочитали до конца эту книгу. Если Вы осилили весь материал, прорешали все примеры и задачи, то у Вас есть отличные шансы начать успешно программировать в среде 1С. Главное – не останавливаться на достигнутом! Постоянно двигайтесь вперёд, постоянно получайте новые для Вас знания и умения. И постоянно занимайтесь программированием и разработкой. Если после прочтения этой книги Вы не будете применять эти знания на практике, то всё, что Вы изучили, забудется через полгода.
Я очень надеюсь, что материал этой книги пригодится Вам в практическом применении, что Вы станете программировать, возможно, устроитесь работать программистом 1С (пусть даже стажёром) и начнёте свой профессиональный рост.
У Вас всё получится!
Русский язык | Английский язык |
Если Тогда ИначеЕсли Иначе КонецЕсли Для Каждого Из По Пока Цикл КонецЦикла Процедура Функция КонецПроцедуры КонецФункции Перем Перейти Возврат Продолжить Прервать И Или Не Попытка Исключение ВызватьИсключение КонецПопытки Новый Выполнить | If Then ElsIf Else EndIf For Each In To While Do EndDo Procedure Function EndProcedure EndFunction Var Goto Return Continue Break And Or Not Try Except Raise EndTry New Execute |
Не найдено
глава7
#Метод «ВыбратьЭлемент»
глава8
как заполнить всю колонку одним значением?
Получение итогов - как подсчитать, какова общая сумма?
Сортировка таблицы значений - какой метод? какие есть варианты?
Работа с таблицей значения на форме - отображения таблиц значений на форме используется элемент формы?
Группировка колонок - какой элемент формы?
(Программная работа с таблицей значения на форме)
(Часть 2. Табличные части справочников и документов)
(Работа с табличной частью)
(Работа с табличной частью на управляемой форме)
Часть 3. Элемент формы «Таблица». Работа с подвалом таблицы - какое свойство включить?
Работа с подвалом таблицы?
(Текущий элемент)
глава11
чем запрос лучше объектного получения данных?
Макет с несколькими областями - как обвод границей?
(Часть 2. Отчеты)
####Простые отчеты
####Отчеты на СКД
Часть 3. Динамические списки - Что такое динамический список?
Забывание