Текст
                    А. П. Габец, Д. И. Гончаров, Д. В. Козырев, Д. С. Кухлевский, М. Г. Радченко
ПРОФЕССИОНАЛЬНАЯ
РАЗРАБОТКА В СИСТЕМЕ
1С:ПРЕДПРИЯТИЕ 8
ПАБЛИШИНГ
Москва
ООО «1С-Паблишинг»
[^ППТЕР
Москва • Санкт-Петербург • Нижний Новгород  Воронеж
Ростов-на-Дону  Екатеринбург  Самара  Новосибирск
Киев • Харьков  Минск
2006

ББК 32.973.23-018.2 УДК 004.382.7 П84 Габец А. П., Гончаров Д. И., Козырев Д. В., Кухлевский Д. С., Радченко М. Г. П84 Профессиональная разработка в системе 1С:Предприятие 8 (+CD) / Под ред. М. Г. Радченко. — М.: «1С-Паблишинг»; СПб.: Питер, 2006. — 808 с.: ил. ISBN 5-9677-0268-7 ISBN 5-91180-076-4 Издание посвящено углубленному изучению вопросов создания, оптимизации и под- держки прикладных решений на платформе системы 1С:Предприятие 8. В нем рассматри- вается архитектура системы и прикладных решений, описывается структура и реализа- ция прикладных механизмов. Значительное внимание уделяется организации хранения данных и обеспечению эффективной работы прикладных решений. Также описываются методические подходы к созданию и поддержке прикладных решений, рассматриваются механизмы системы, которые используются для реализации этих задач. Книга рассчитана на разработчиков, обладающих некоторым навыком создания и мо- дификации прикладных решений в системе 1 С: Предприятие 8 и желающих повысить свой профессиональный уровень. Также она будет интересна IT-специалистам, не занимаю- щимся разработкой, но желающим получить представление о возможностях системы, ее идеологии, архитектуре и реализации конкретных механизмов. В помощь разработчикам прикладных решений книга содержит компакт-диск с демонстра- ционными конфигурациями и кодом примеров, описанных в книге. Код примеров пред- ставлен в виде файлов шаблонов текстов, которые могут быть использованы при разра- ботке конфигураций. Книга дополняет, но не заменяет штатную документацию к программному продукту, входящую в комплект поставки, и позволяет более эффективно использовать возможно- сти программы. ББК 32.973.23-018.2 УДК 004.382.7 Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав. Полное или частичное копирование материалов книги без письменного разрешения фирмы «1С-Паблишинг» запрещается. ISBN 5-9677-0268-7 ISBN 5-91180-076-4 © ООО «1С-Паблишинг», 2006 © Оформление, ООО «1С-Паблишинг», 2006 © Оформление, ЗАО Издательский дом «Питер», 2006
Введение Об авторах Андрей Габец Андрей Габец имеет высшее техническое образование, ра- ботает в московской компании «Аналит», которая явля- ется партнером фирмы «1С». Он специализируется на ре- шении задач оперативного учета, руководит внедрениями «торговых» прикладных решений, отвечает за подготовку специалистов компании по направлению оперативного учета. В то же время Андрей преподает в 1 С-Учебном центре №3. Этот учебный центр — совместный проект фир- мы «1С» и компании «Аналит». Андрей является автором и преподавателем целого ряда учебных курсов, в том числе: ♦ Конфигурирование в системе 1С:Предприятие 8.0. Ре- шение оперативных задач (сертифицированный курс); ♦ 1С:Предприятие 8.0. Внедрение и адаптация конфигу- рации Управление торговлей (сертифицированный курс). Помимо своей преподавательской деятельности Андрей известен читателям как соавтор книги «1 С:Предприятие 8.0. Простые примеры разработки». В книге «Профессиональная разработка в системе 1С:Пред- приятие 8.0» Андрей выступил как автор следующих глав: ♦ глава 6, «Хранение информации»; ♦ глава 7, «Документы, последовательности»; ♦ глава 8, «Реализация задач учета движения средств». Дмитрий Гончаров Дмитрий Гончаров имеет высшее техническое образова- ние и работает в московской компании «Аналит». Он ру- ководит внедрениями прикладных решений в области торговли и медицины. Специализируется на решении задач оперативного учета, интеграции с другими инфор- мационными системами. Является автором нескольких тиражных прикладных решений, выпущенных как компа- нией «Аналит», так и компанией «Аналит» совместно с фирмой «1С». Помимо работы с клиентами компании, Дмитрий препо- дает в 1С-Учебном центре № 3 и, кроме этого, принимает экзамены 1С:Специалист по платформе и прикладным решениям 1 С:Предприятия 8.0 как в Москве, так и на вы- ездных аттестациях. Он является автором и преподавате- лем целого ряда учебных курсов, в том числе: ♦ Введение в конфигурирование в системе 1 С:Предпри- ятие 8.0. Основные объекты (сертифицированный курс); ♦ Использование запросов в системе 1С:Предприятие 8.0 (сертифицированный курс); ♦ Введение в конфигурирование в системе 1С:Предпри- ятие 8.0 (дистанционный курс); ♦ Средства интеграции и обмена данными в системе 1 С:Предприятие 8.0 (сертифицированный курс); ♦ Web-расширение. Дмитрий также известен читателям как соавтор книги «1С:Предприятие 8.0. Простые примеры разработки». Для книги «Профессиональная разработка в системе 1 С: Предприятие 8.0» Дмитрий подготовил следующие главы: ♦ глава 11, «Механизм бизнес-процессов»; ♦ глава 12, «Использование механизма анализа данных и прогнозирования»; ♦ глава 14, «Интеграция с другими информационными системами»; ♦ глава 15, «Создание распределенных информационных систем»; ♦ глава 16, «Web-расширение». Дмитрий Козырев Дмитрий Козырев имеет высшее экономическое образова- ние по специальности «Бухгалтерский учет» и работает в московской компании «Аналит». Он отвечает за внедрения бухгалтерских прикладных решений и подготовку специа- листов компании по направлению бухгалтерского учета. Сейчас Дмитрий преподает в 1С-Учебном центре № 3. Он является автором ряда учебных курсов, в том числе: ♦ Конфигурирование в системе 1С:Предприятие 8.0. Ре- шение бухгалтерских задач (сертифицированный курс); ♦ 1С:Предприятие 8.0. Внедрение и адаптация конфи- гурации Бухгалтерия предприятия (сертифицирован- ный курс). Для этой книги Дмитрий подготовил главу 9 «Реализа- ция задач бухгалтерского учета». Дмитрий Кухлевский Дмитрий Кухлевский имеет высшее экономическое обра- зование по специальности «Финансы и кредит». Дмит- рий работал в московской компании «РГ-Софт», которая является партнером фирмы «1С». Его специализация — решение задач расчета заработной платы. Сейчас Дмитрий преподает в 1 С:Учебном центре № 1, ко- торый является подразделением фирмы «1С». Дмитрий — автор и преподаватель таких курсов, как: ♦ Конфигурирование подсистем расчета зарплаты и управ- ления персоналом в прикладных решениях для 1С:Пред- приятия 8.0; ♦ Бюджетирование в прикладном решении Управление производственным предприятием (интернет-курс).
Для этой книги Дмитрий подготовил главу 10, «Реализа- ция сложных периодических расчетов». Максим Радченко Максим Радченко имеет высшее техническое образование, работает в фирме «1С». Его основной специализацией яв- ляется методика использования платформы 1С:Предпри- ятия 8.0 для создания прикладных решений. Максим является автором книги «1С:Предприятие 8.0. Практическое пособие разработчика. Примеры и типовые приемы». Кроме этого, под его редакцией была выпущена книга «1 С: Предприятие 8.0. Простые примеры разработ- ки» (авторы Андрей Габец и Дмитрий Гончаров). Книга, которую вы держите в руках, также выпущена под редакцией Максима Радченко. Кроме того, Максим выступил в этой книге еще и в роли автора следующих глав: ♦ Введение; ♦ глава 1, «Архитектура 1С:Предприятия»; ♦ глава 2, «Функциональность 1С:Предприятия»; ♦ глава 3, «Использование встроенного языка»; ♦ глава 4, «Работа с данными»; ♦ глава 5, «Клиент -серверный вариант работы»; ♦ глава 13, «Средства построения отчетов»; ♦ глава 17, «Поставка прикладных решений»; ♦ глава 18, «Методология разработки»; ♦ Приложение. Благодарности Написание такой книги, как эта, всегда требует совмест- ных усилий. В создании этой книги также приняло уча- стие кроме собственно авторов большое количество спе- циалистов. Выражаем признательность всем, кто высказал свои за- мечания по тем или иным разделам книги — Александру Алексееву, Александру Безбородову, Александру Вино- градову, Андрею Волкову, Геннадию Дамье, Одею Деруту, Дмитрию Зарецкому, Сергею Копиенко, Максиму Лейбо- вичу, Евгению Митрошкину, Сергею Мурзину, Сергею Нуралиеву, Константину Рупасову, Павлу Чикову и Анд- рею Чичерину. Хочется поблагодарить Одея Дерута, Дмитрия Русанова и Виталия Филиппова, которые оказали помощь авторам в разборе сложных вопросов по реализации и функцио- нированию системы. При создании книги использовались с разрешения фир- мы «1С» материалы информационно-технологического сопровождения и материалы докладов партнерских кон- ференций. Мы выражаем признательность авторам этих материалов и выступлений. Отдельно хочется поблагодарить Константина Рупасова за материал по методике тестирования и оптимизации па- раллельности работы прикладных решений. Также мы благодарим Евгения Медведева, Сергея Позд- някова, Константина Рупасова и Павла Чикова, которые выступили в качестве «бета-тестеров» некоторых глав и разделов книги. Наконец, мы хотим выразить признательность тем, кто помогал нам в подготовке издания этой книги. Андрею Баратынскому — за разработку дизайна оформления кни- ги. Наталии Моисеенко — за организацию работы с изда- тельством и типографией. Ирине Ульяновой — за органи- зационную помощь. Светлане Юткиной — за помощь в технической подготовке материала. От редактора Идея этой книги заключается в том, чтобы собрать воеди- но и систематизировать наиболее важную информацию, которая может понадобиться разработчику прикладных решений 1С:Предприятия 8.0. Уровень изложения мате- риала предполагает, с одной стороны, что разработчик уже знаком с системой 1С:Предприятие 8.0, а с другой стороны — что в этой книге он сможет найти ответ даже на довольно сложные вопросы, возникающие в процессе разработки. В одной книге, пусть даже такой большой, невозможно охватить абсолютно все ситуации, которые могут возник- нуть при разработке прикладных решений. Однако на по- давляющее большинство вопросов, возникающих перед разработчиками, книга дает ответы. Причем книга будет одинаково интересна как начинающим разработчикам, так и более «продвинутым». Как правило, прикладные разработчики имеют достаточ- но четко определенную специализацию, сосредоточивая свои усилия на решении задач одной предметной облас- ти. Это видно даже по составу авторов этой книги. Вместе с этим, довольно часто возникают ситуации, когда прихо- дится осваивать «смежные» прикладные области для того, чтобы внести небольшие исправления в существую- щее решение или, наоборот, создать новую подсистему. Поэтому книга, помимо собственно глубокого изложения прикладных механизмов, содержит общие сведения как о самих механизмах, так и об автоматизируемой предмет- ной области. Благодаря этому разработчик, хорошо зна- комый с системой, но специализирующийся, например, на решении задач оперативного учета, всегда сможет бы- стро разобраться с задачами начисления заработной пла- ты и понять работу механизмов, которые используются для решения этих задач.
При написании этой книги мы стремились, чтобы она стала «серьезным инструментом для серьезных разработчиков», книгой, к которой всегда можно обратиться в случае затруд- нений и которую просто интересно прочитать, чтобы узнать что-то новое о хорошо известной предметной области или познакомиться с новым взглядом на привычные вещи. От себя лично и от всех авторов этой книги хочу поже- лать вам успехов в изучении системы 1 С:Предприятие и повышения вашего профессионального мастерства! Максим Радченко Особенности книги Существует ряд особенностей, отличающих эту книгу от других книг, посвященных системе 1 С:Предприятие 8.0. Прежде всего, это освещение вопросов, которые обычно остаются в тени, когда речь идет о прикладных разработ- ках. Например, такие вопросы, как общая концепция сис- темы, описание используемых таблиц и принципы хране- ния информации системы. При описании тех или иных прикладных механизмов ав- торы стремились дать общее представление о механизме, его месте в системе, рассказать идеологию его работы. По мнению авторов, это поможет разработчику строит эффек- тивные решения исходя из понимания идеологии работы механизма, выбирать те или иные варианты реализации, основываясь на знании принципов работы механизма. Довольно много внимания в книге уделено методологи- ческим вопросам разработки прикладных решений, когда прикладное решение создается коллективом разработчи- ков. Рассматривается использование механизма групповой разработки. Также излагается методика настройки произ- водительности прикладного решения, рассматриваются конкретные шаги и инструменты, используемые на каж- дом из уровней, которые следует использовать в обычной практике. Также, для отдельных случаев, когда требуется индивидуальная настройка прикладного решения, изла- гается простейшая методика настройки производитель- ности, используя средства, предоставляемые SQL Server. Применительно к вопросам методологии создания при- кладных решений рассматриваются механизмы интерна- ционализации, содержащиеся в системе, их влияние и ис- пользование в каждом из элементов системы. Этот раздел дает целостное представление о всех средствах интерна- ционализации, которые содержит 1С:Предприятие 8.0. При подготовке материала этой книги были использова- ны самые различные источники информации: ♦ опыт преподавания на учебных курсах по платформе и прикладным решениям 1С:Предприятия 8.0; ♦ опыт внедрения прикладных решений; ♦ опыт, накопленный разработчиками фирмы «1С»; ♦ материалы информационно-технологической поддерж- ки (ИТС); ♦ материалы форума партнеров-разработчиков на http:// partners.v8.lc.ru; ♦ общение на партнерских семинарах, проводимых фир- мой «1С». Как читать книгу Главы книги составлены таким образом, чтобы можно было читать их как подряд, так и выборочно. Чтение книги по порядку позволяет получить целостное представление о системе и ее возможностях, постепенно переходя от общих архитектурных решений к более кон- кретным прикладным механизмам и их реализации. В то же время книгу можно читать отдельными главами, если требуется изучить работу какого-то конкретного прикладного механизма или понять принципы работы системных механизмов. Книга содержит достаточно подробное оглавление, что позволяет обращаться к отдельным разделам книги в тех случаях, когда нужно разобраться в конкретных особен- ностях работы того или иного механизма или просто ос- вежить их в памяти. Структура книги Книга состоит из 18 глав и приложения, которые охваты- вают практически всю функциональность системы 1С:Пред- приятие. Главы 1 и 2 носят общий характер и посвящены системе 1С:Предприятие в целом. В главе 1 рассказывается об архитектуре 1С:Предпри- ятия — о том, из каких частей состоит система, какие ар- хитектурные решения использованы при построении тех или иных элементов системы. Глава 2 содержит обзор функциональности, предостав- ляемой технологической платформой 1С:Предприятия.
Отдельно рассматриваются возможности прикладных ре- шений, рассказывается о средствах разработки, содержа- щихся в технологической платформе, а также описыва- ются средства администрирования информационных баз 1 С:Предприятия. В главе 3 рассматриваются общие вопросы, касающиеся использования встроенного языка технологической плат- формы. Объясняется структура прикладного решения, мо- дули, которые может содержать конфигурация, а также рассматриваются возможности работы с метаданными сред- ствами встроенного языка. Глава 4 рассказывает об общих принципах и особенностях работы с данными с точки зрения системы 1С:Предпри- ятие. Рассматривается два основных подхода к представле- нию данных системой: объектные и необъектные данные. Рассказывается о типах данных, которые использует сис- тема. Описываются принципы использования транзакций в 1 С:Предприятии, также рассматривается использование системой транзакций базы данных и уровни блокировок, устанавливаемые в различных режимах работы системы. В главе 5 книги излагаются особенности применения клиент-серверного варианта работы, сервера 1С:Пред- приятия. Описывается механизм управления исполнени- ем кода на сервере и на клиенте. Главы книги, с 6 по 10, посвящены описанию конкретных прикладных механизмов, которые содержит система. Об- щим для этих глав является то, что помимо собственно прикладной функциональности, предоставляемой теми или иными механизмами, рассматривается их реализа- ция, описываются алгоритмы формирования виртуаль- ных таблиц запросов и рассматриваются вопросы дости- жения оптимальной производительности при работе с этими механизмами. Глава 6 излагает общий взгляд на вопросы хранения раз- личной информации в системе 1С:Предприятие. В зависи- мости от логической структуры информации, ее назначе- ния, могут использоваться те или иные средства системы. В частности, в главе подробно рассматривается использо- вание регистров сведений и планов видов характеристик. Глава 7 рассматривает работу с документами, журналами документов и последовательностями. В главе подробно рассматриваются различные особенности использования документов, а также важные моменты, на которые следует обращать внимание при работе с последовательностями. Глава 8 целиком посвящена вопросам организации учета движения различных средств с использованием регист- ров накопления. Подробно рассматриваются приемы и особенности получения данных из регистров с использо- ванием различных виртуальных таблиц. Глава 9 рассматривает вопросы организации бухгалтер- ского учета с использованием системы 1С:Предприятие. Изложение для примера опирается на требования к веде- нию бухгалтерского учета, принятые в России, однако не менее подробно рассматриваются и более широкие воз- можности бухгалтерских механизмов, которые есть в сис- теме. Полное понимание этих возможностей позволяет эффективно использовать бухгалтерские механизмы для решения, например, задач управленческого учета или для автоматизации бухгалтерского учета в других странах. В главе 10 описываются возможности системы по органи- зации сложных периодических расчетов. Основное при- менение эти механизмы находят, как правило, в задачах расчета заработной платы, однако могут быть использо- ваны и в других областях. В главе 11 речь идет о механизме бизнес-процессов, реа- лизованном в системе. Рассматривается его назначение и конкретные примеры использования. Глава 12 посвящена описанию механизмов анализа данных и прогнозирования. Эти механизмы, как правило, использу- ются для получения аналитической информации, при фор- мировании отчетов для специалистов-аналитиков. Глава 13 описывает средства системы, используемые для формирования отчетов. В первой части главы подробно рассматривается устройство и возможности использова- ния построителя отчета на конкретных примерах. Вторая часть главы посвящена описанию текстового и таблично- го документа как основных средств для отображения по- лученных данных. Главы книги с 14 по 16 посвящены различным способам интеграции информационных баз системы 1 С: Предпри- ятие с другими информационными системами, в том чис- ле и не основанными на 1С:Предприятии. Глава 14 описывает различные способы взаимодействия 1С:Предприятия с «внешним миром». Рассматривается работа с текстовыми файлами, с файлами DBF, с XML- документами. Описываются возможности использова- ния интернет-технологий, взаимодействия по прото- колам HTTP, FTP, работа с электронной почтой. Также рассматриваются примеры использования обмена сооб- щениями на основе технологий MSMQ и WebSphere MQ. В конце главы излагаются возможности системы по ис- пользованию технологий COM, Automation, ActiveX и ActiveDocument. В 15 главе описываются механизмы обмена данными, со- держащиеся в системе 1С:Предприятие. Подробно рас- сматривается универсальный механизм обмена данными и механизм распределенных информационных баз. Рас- сматриваются различные сценарии обмена. В главе 16 речь идет о Web-расширении. В начале главы дается краткое описание используемых технологий. Да- лее рассматриваются примеры создания веб-приложений и веб-сервисов, описываются особенности использования различных механизмов Web-расширения. Заключительные главы, 17 и 18, посвящены вопросам ин- дустриальной разработки и сопровождения прикладных решений. В главе 17 рассматриваются механизмы поставки и под- держки прикладных решений, и механизм создания комплектов поставки. Приводятся примеры различных сценариев поддержки прикладных решений, примеры создания комплектов поставки. В заключительной 18 главе излагаются методологиче- ские вопросы создания прикладных решений. Дается об- щий взгляд на прикладное решение затем более подробно рассматриваются различные этапы: проектирование, групповая разработка, оптимизация производительности, создание многоязычных прикладных решений. Излагает- ся общая методика и алгоритм оптимизации производи- тельности, дается целостный взгляд на средства интерна- ционализации, содержащиеся в системе. Приложение содержит сведения о размещении данных системы 1С:Предприятие, особенностях хранения значе- ний составного типа и построении индексов.
Что находится на компакт-диске К книге прилагается компакт-диск, который содержит материалы, предназначенные для самостоятельного изу- чения и использования. Прежде всего, это три демонстрационные конфигурации, которые используются в ходе изложения различных глав книги: ♦ конфигурация «Хранение информации и учет движе- ния средств» используется для иллюстрации материа- ла, изложенного в главах с 6 по 8; ♦ конфигурация «Бухгалтерский учет» используется для иллюстрации материала, изложенного в главе 9; ♦ конфигурация «Сложные периодические расчеты» ис- пользуется для иллюстрации материала, изложенного в главе 10. Все демонстрационные конфигурации содержатся на ком- пакт-диске в виде дистрибутивов. После запуска испол- няемого файла шаблоны конфигураций устанавливаются в текущий каталог шаблонов. Конфигурации созданы в версии 1С:Предприятия 8.0.14. Также компакт-диск содержит все фрагменты листингов, приведенных в книге. Использование этих фрагментов может быть полезным как при чтении книги, так и в даль- нейшей работе. Поэтому фрагменты оформлены в виде файла шаблонов текста 1 С:Предприятия — DevEnc.st. Этот файл может быть подключен к любой конфигура- ции с помощью команды Сервис ► Шаблоны текста ► Дей- ствия ► Файлы шаблонов ► Добавить (рис. 0.1). Фрагменты кода сгруппированы по главам, для каждого фрагмента кода в качестве строковой последовательности, которая будет заменяться при вводе текста, указывается номер листинга, содержащего соответствующий фрагмент кода. Замена строковой последовательности может произ- водиться автоматически, если установлен режим автозаме- ны, или вручную, с помощью комбинации клавиш Ctrl + Q. Режим автозамены устанавливается командой Сервис ► Параметры ► Тексты ► Модулей ► Автозамена. Также любой шаб- лон текста может быть просто перенесен мышью в произ- вольное место модуля. Рис. 0.1. Шаблоны текста листингов Скажите нам, чтобы думаете В процессе подготовки этой книги мы прилагали значи- тельные усилия для того, чтобы устранить возможные не- точности и опечатки, однако не можем гарантировать их отсутствие на 100%. Мы понимаем, сколько негативных эмоций может доста- вить пример, который не работает, например, потому, что в имени переменной допущена ошибка. Поэтому обнару- женные неточности мы публикуем по адресу http://v8.lc.ru/ book/DevEnc/Erratum.htm. На этой же странице расположена форма, с помощью ко- торой вы можете сообщить нам информацию об обнару- женных неточностях, а также ваши впечатления об этой книге и пожелания по ее совершенствованию. Мы ценим обратную связь с читателями и с благодарно- стью примем как слова критики, так и слова одобрения, и учтем их в работе над будущими изданиями. От издателей Ваши замечания, предложения и вопросы отправляйте по адресам publishing@lc.ru (издательство «1С-Паблишинг»), а также comp@piter.com (издательство «Питер», компью- терная редакция). Мы будем рады узнать Ваше мнение! Подробную инфор- мацию о книгах серии «1 С: Библиотека» вы найдете на сайте фирмы «1С»: www.lc.ru и сайте издательства «Питер»: www.piter.com.
Глава 1. Архитектура 1С:Предприятия Говоря о системе 1 С:Предприятие в широком смысле, можно сказать, что она представляет собой совокупность четырех составляющих (рис. 1.1): ♦ технологической платформы; ♦ прикладных решений различного масштаба и различ- ной направленности, созданных на основе технологиче- ской платформы; ♦ методологии создания прикладных решений; ♦ информационно-технологической поддержки пользо- вателей и разработчиков. Рис. 1.1. Структура ^Предприятия Такая архитектура продиктована, прежде всего, теми зада- чами, которые призвана решать система 1С:Предприятие. Во-первых, система должна обеспечивать высокий уро- вень адаптируемости прикладных решений под требова- ния заказчика. Во-вторых, система должна обеспечивать изменение гото- вого прикладного решения разработчиком, не участвовав- шим в его создании. Это особенно важно для прикладных решений в сфере экономических задач, где существенная часть разработчиков не создает собственные прикладные решения, а дорабатывает и развивает существующие ти- повые решения. В-третьих, система должна обеспечивать эффективное использование компьютерных технологий и платформ, не требуя, при этом, глубоких специальных знаний от разработчика. В-четвертых, система должна обеспечивать стандартиза- цию разработки. Таким образом, можно сказать, что 1С:Предприятие пе является универсальным средством программирования. Система обладает достаточно широкими возможностями, однако ее архитектура и конкретная реализация механиз- мов и технологий платформы продиктована, прежде все- го, необходимостью решения специализированных задач по созданию бизнес-приложений и требованиями, предъ- являемыми к самой системе. Платформа и прикладные решения Основным концептуальным решением, отличающим сис- тему 1 С:Предприятие 8.0 от универсальных средств про- граммирования, является четкое разделение на платфор- му и прикладное решение. Прикладное решение 1С:Предприятия является самостоя- тельной сущностью и может выступать в качестве отдель- ного программного продукта. Однако создание, моди- фикация и собственно функционирование прикладного решения невозможны без использования технологий и механизмов платформы. Поэтому платформа поставляет- ся с каждым комплектом 1С:Предприятия. Средства разработки в составе платформы Прикладные решения 1С:Предприятия являются откры- тыми. Благодаря этому клиент с помощью разработчика, или собственными силами, может модифицировать и на- страивать любое прикладное решение «под себя». Для модификации прикладных решений не требуется ис- пользовать какие-либо отдельные программные продук- ты — все средства разработки входят в состав технологи- ческой платформы. Можно сказать, что платформа состоит из двух состав- ляющих (рис. 1.2): Рис. 1.2. Структура технологической платформы ^Предприятия ♦ среда исполнения; ♦ среда разработки. Таким образом, обеспечивается высокий уровень адапти- руемости прикладных решений под требования заказчика.
Метаданные — способ описания прикладного решения Прикладное решение 1С:Предприятия не пишется в пря- мом смысле слова на языке программирования. При созда- нии прикладных решений 1 С:Предприятия используется более абстрактная технология — технология метаданных. Метаданные представляют собой иерархическую струк- туру объектов, полностью описывающую все прикладное решение. Среда исполнения 1С:Предприятия исполняет, «проигрывает» метаданные, аналогично тому, как опера- ционная система исполняет код привычной программы. Отличительной особенностью технологии метаданных является использование визуального конструирования прикладного решения. Вместо кропотливого написания кода разработчик просто добавляет визуальными средст- вами новый объект метаданных в прикладное решение и получает сразу же описания нужных типов, структур дан- ных, описаний наборов прав, связи между объектами, ин- формацию об особенностях их поведения, визуального представления и т. д. Метаданные и встроенный язык Все прикладное решение представляется не в виде строк с инструкциями на языке программирования, а в виде - иерархической структуры объектов метаданных. При этом разработчик использует встроенный язык и язык за- просов для того, чтобы описать специфические алгорит- мы поведения тех или иных объектов конфигурации в различные моменты исполнения прикладного решения. Использование встроенного языка при разработке при- кладных решений ограничено в основном решением тех задач, которые действительно требуют алгоритмического описания, например расчета налогов, проверки корректно- сти введенных данных и пр. Основная же структура при- кладного решения описывается структурой метаданных. Почти все объекты метаданных содержат модули, в кото- рых и могут быть описаны алгоритмы на встроенном язы- ке. Эти модули будут вызываться средой исполнения в конкретные, заранее определенные моменты работы при- кладного решения — события. Таким образом, можно ска- зать, что использование встроенного языка в прикладных решениях носит событийный характер. Подсистемы Платформа 1С:Предприятия 8.0 позволяет выделить в при- кладном решении отдельные части — подсистемы, — в совокупности представляющие все прикладное реше- ние. Подсистемы могут иметь иерархическую структуру, то есть одна подсистема может включать в себя несколько других подсистем. Каждый объект метаданных, описывающих данное при- кладное решение, может быть отнесен к одной или не- скольким подсистемам. Таким образом, в терминах подсис- тем можно описать всю структуру прикладного решения. В дальнейшем это описание может быть использовано в различных средствах разработки, например для автомати- ческого формирования прав на основе подсистем или для автоматического построения интерфейсов пользователей. Создание прикладных решений на основе модели Важной особенностью системы 1 С: Предприятие являет- ся то, что для описания структуры прикладного решения разработчик использует не произвольные, а строго опре- деленные объекты метаданных. Платформа 1С:Предприятия содержит ограниченный набор прототипов (шаблонов) объектов конфигурации. Среди этих шаблонов есть, например, шаблон справоч- ника, документа, регистра накопления, бизнес-процесса и т. д. Каждый такой шаблон (прототип) содержит определен- ную базовую реализацию объекта конфигурации (рис. 1.3). Когда разработчик создает новый объект конфигурации, этот объект наследует базовую реализацию прототипа: ♦ платформа «знает», какие таблицы (состав полей, коли- чество таблиц, их взаимная связь) нужно будет создать в хранилище данных при сохранении конфигурации; ♦ сразу же добавляются новые типы встроенного языка, позволяющие работать с данными создаваемого объек- та, причем состав этих типов может быть разным для различных шаблонов (прототипов); Рис. 1.3. Состав прототипа (шаблона) объекта конфигурации
♦ сразу же создается набор прав, которые будут использо- ваться для данного объекта, причем наборы прав также мо- гут быть различными для разных шаблонов (прототипов), поскольку различается их базовая функциональность; ♦ определяются стандартные действия, которые система может выполнять с данными этого объекта конфигурации и т. д. Благодаря этому разработчик, не производя никаких до- полнительных действий, тут же может запустить при- кладное решение и работать с только что добавленным объектом — базовая реализация объекта, унаследованная от прототипа (шаблона), обеспечит выполнение всех не- обходимых типовых действий. Таким образом, несмотря на то, что каждое прикладное решение обладает собственной «индивидуальностью», все они созданы по определенной модели, с использова- нием объектов конфигурации, которые обладают одина- ковой базовой реализацией. Такой подход значительно упрощает модификацию прикладных решений разработ- чиками, которые не участвовали в их создании. Объектные и необъектные данные В 1С:Предприятии принято разделять все прикладные данные на те, которые имеют объектную природу (объ- ектные данные), и на данные, не имеющие таковой при- роды (необъектные данные). Примерами объектных данных могут служить данные справочников, документов. Необъектными данными яв- ляются, например, данные регистров. Подобное деление определяет два различных подхода к работе с данными. Данные, имеющие объектную приро- ду, хранятся в базе данных в виде объектов. Например, объектами является элемент справочника или конкрет- ный документ. Каждый объект «ценен» для системы уже одним фактом своего существования и имеет уникаль- ный идентификатор — ссылку. Могут измениться любые данные объекта, но это будет все тот же объект. Удалив объект, его нельзя создать заново. Даже если для нового объекта будут установлены те же данные, это будет уже другой объект с точки зрения 1 С: Предприятия, обладаю- щий другим уникальным идентификатором. Данные, имеющие необъектную природу, хранятся в базе данных в виде записей. Каждая запись полностью описы- вается значениями своих полей и не имеет какого-либо уникального идентификатора. Поэтому для 1С:Предпри- ятия собственно факт существования записи не важен. Можно удалить запись, а затем создать новую, с такими же значениями полей — состояние базы данных, с точки зре- ния логики прикладного решения, от этого не изменится. Подробнее об объектных и необъектных данных можно прочитать в разделе «Объектные и необъектные данные», с. 36. Три способа представления данных Для всех прикладных данных (как объектных, так и не- объектных) 1С:Предприятие поддерживает три способа представления данных (рис. 1.4): ♦ хранение в базе данных; ♦ представление во встроенном языке; ♦ отображение в формате XML. Рис. 1.4. Три способа представления данных В базе данных информация хранится в виде объектов базы данных или в виде отдельных записей (в зависимо- сти от ее природы — объектной или необъектной). Данные, хранимые в базе данных, могут быть считаны в объекты встроенного языка для их просмотра или изме- нения и записаны обратно в базу данных. В то же время объекты встроенного языка могут быть сериализованы в/из элементы/ов XML. Представление данных в формате XML используется при обмене данны- ми в распределенных информационных базах, а также может использоваться при взаимодействии с другими информационными системами. Важно отметить, что все три способа представления данных используют одну и ту же систему понятий, благодаря чему от разработчика не требуется специальных усилий для пре- образования данных из одного представления в другое. Сквозная типизация Важной особенностью работы с данными является то, что в 1С:Предприятии реализована общая система типов встроен- ного языка, полей баз данных и интерфейса. Иными слова- ми, разработчик одинаковым образом определяет поля базы данных, переменные встроенного языка, реквизиты форм, и одинаковым образом работает с ними (рис. 1.5).
База данных Встроенный язык Система типов Интерфейс В результате разработчику не приходится заботиться о преобразованиях между типами данных, поддерживае- мыми той или иной СУБД, типами, поддерживаемыми встроенным языком, и типами, используемыми для по- строения интерфейсных решений. Подробнее о типах данных, используемых системой 1С:Предприятие, можно прочитать в разделе «Система типов», с. 47. Рис. 1.5. Общая система типов Поддержка составных типов данных Важной особенностью модели данных 1С:Предприятия является возможность использования реквизитов объ- ектов метаданных, имеющих составной тип. Например, врасходной накладной в качестве покупателя может быть указано либо юридическое лицо из справочника органи- заций, либо физическое лицо из справочника частных лиц. Соответственно, при проектировании базы данных разработчик может определить реквизит, который будет хранить значение любого из этих типов. Подробнее о составном типе можно прочитать в разделе «Составной тип данных», с. 68. Смешанный подход к манипулированию данными 1С:Предприятие обеспечивает два способа доступа к дан- ным — объектный (для чтения и записи) и табличный (только для чтения). В объектной модели разработчик оперирует объектами встроенного языка. В этой модели обращения к объекту, например документу, происходят как к единому целому — он полностью загружается в память, вместе с вложенными таблицами, к которым можно обращаться средствами встроенного языка как к коллекциям записей и т. д. При манипулировании данными в объектной модели обеспечивается сохранение целостности объектов, кэши- рование объектов, вызов соответствующих обработчиков событий и т. д. В табличной модели все множество объектов того или иного класса представляется как совокупность связанных между собой таблиц, к которым можно обращаться при помощи запросов — как к отдельной таблице, так и к не- скольким таблицам во взаимосвязи. В этом случае разработчик получает доступ к данным сразу нескольких объектов, что очень удобно для анализа больших объемов данных, например при создании отче- тов. Однако в силу того, что данные, выбираемые таким способом, содержат не все, а лишь некоторые реквизиты анализируемых объектов, табличный способ доступа не позволяет изменять эти данные. Сочетание табличного и объектного доступа к данным по- зволяет, с одной стороны, сделать разработку прикладных решений простой и наглядной, а с другой стороны — полу- чать сколь угодно сложные выборки данных и использо- вать возможности агрегирования полученных данных. Встроенныйязык Встроенный язык имеет много общих черт с другими языками, такими как Pascal, Java Script, Basic, что облег- чает его освоение начинающими разработчиками. Однако он не является прямым аналогом какого-либо из перечис- ленных языков. Вот лишь некоторые, наиболее значимые особенности встроенного языка: ♦ мягкая типизация (тип переменной определяется ти- пом значения, которое она содержит, и может изме- няться в процессе работы); ♦ отсутствие программного описания прикладных типов (они создаются при добавлении объектов метаданных); ♦ не требуется предварительное описание процедур/функ- ций, если их вызов выполняется раньше их описания; ♦ событийная ориентированность встроенного языка; ♦ поддерживается обработка исключительных ситуаций; ♦ все операторы имеют как русское, так и английское на- писание, которое можно использовать одновременно; ♦ используется интерпретатор с предварительной ком- пиляцией (перед исполнением модули, содержащие текст на встроенном языке, преобразуются во внутрен- ний код); ♦ кэширование скомпилированных модулей в памяти.
Язык запросов Язык запросов основан на SQL, но при этом содержит значительное количество расширений, ориентированных на отражение специфики финансово-экономических за- дач и на максимальное сокращение усилий по разработке прикладных решений. Важной особенностью языка запросов является то, что он предоставляет доступ к данным только на чтение и ис- пользует те же типы данных, что и встроенный язык. Можно перечислить наиболее существенные возможно- сти, реализуемые языком запросов: ♦ обращение к подчиненным полям через точку. Если поля какой-либо таблицы имеют ссылочный тип (хранят ссылки на объекты другой таблицы), разработчик мо- жет в тексте запроса ссылаться на них через «.», при этом количество уровней вложенности таких ссылок система не ограничивает; ♦ обращение к вложенным таблицам (например, табличным частям документов и элементов справочников). К вло- женным табличным частям можно обращаться и как к от- дельным таблицам, и как к целым полям одной таблицы; ♦ автоматическое упорядочивание. Режим автоматиче- ского упорядочивания позволяет выводить информа- цию в наиболее правильном («естественном») порядке; ♦ многомерное и многоуровневое формирование итогов. Итоги и подитоги формируются с учетом группировки и иерар- хии, обход уровней может выполняться в произвольном порядке с подведением подитогов, обеспечивается кор- ректное построение итогов по временным измерениям; ♦ поддержка виртуальных таблиц. Виртуальные таблицы, предоставляемые системой, позволяют получить прак- тически готовые данные для большинства прикладных решений без необходимости составления сложных за- просов. Например, такая виртуальная таблица может предоставить данные по остаткам товаров в разрезе пе- риодов на какой-то момент времени. При этом виртуаль- ные таблицы максимально используют хранимую ин- формацию, например ранее рассчитанные итоги и т. д; ♦ стандартные SQL-операции. В языке запросов поддер- живаются стандартные для SQL операции, такие, как объединение (Union), соединение (Join) и т. д. Прикладные решения, независимые от используемого хранилища данных Платформа изолирует разработчика от понятий и подроб- ностей более низкоуровневых технологий. При создании прикладных решений разработчик 1С:Предприятия не об- ращается к базе данных напрямую. Непосредственно он ра- ботает с платформой Ю.Предприятия. При этом он может: ♦ описывать структуры данных в конфигураторе; ♦ манипулировать данными с помощью объектов встро- енного языка; ♦ составлять запросы к данным, используя язык запро- сов. Платформа 1 С: Предприятия обеспечивает операции ис- полнения запросов, описания структур данных и манипу- лирования данными, транслируя их в соответствующие команды. Это могут быть команды SQL Server в случае клиент-серверного варианта работы, или команды собст- венной СУБД для файлового варианта работы. Файловый и клиент-серверный варианты работы 1С:Предприятие может работать в двух вариантах: ♦ файловый; ♦ клиент-серверный. И в том и в другом варианте все прикладные решения ра- ботают полностью идентично, что позволяет выбирать один или другой вариант работы без изменения сущест- вующего прикладного решения. Файловый вариант работы рассчитан на персональную работу одного пользователя или работу небольшого ко- личества пользователей в локальной сети. В этом вариан- те все данные информационной базы (конфигурация, база данных, административная информация) располага- ются в одном файле (рис. 1.6). Рис. 1.6. Файловый вариант работы Такой вариант работы обеспечивает легкость установки и эксплуатации прикладного решения. При этом для ра- боты с информационной базой не требуются дополни-
тельные программные средства, достаточно иметь опера- ционную систему и ЮПредприятие. Клиент-серверный вариант предназначен для использо- вания в рабочих группах или в масштабе предприятия. Он реализован на основе трехуровневой архитектуры «клиент-сервер» (рис. 1.7). Рис. 1.7. Клиент-серверный вариант работы На одном из компьютеров работает сервер ЮПредпри- ятия. Программа, работающая у пользователя, взаимо- действует с сервером 1 С:Предприятия, а сервер при необ- ходимости обращается к базе данных SQL Server. При этом физически сервер Ю.Предприятия и SQL Server мо- гут располагаться как на одном компьютере, так и на раз- ных. Это позволяет администратору при необходимости распределять нагрузку между серверами. Подробнее о клиент-серверном варианте работы можно прочитать в разделе «Клиент-серверный вариант рабо- ты», с. 79. Сервер 1С:Предприятия Сервер 1С:Предприятия является приложением СОМ+, которое преобразует запросы, поступающие от клиент- ского приложения, в запросы на языке Transact SQL, передает их SQL Server, получает от него результат вы- полнения запроса, преобразует его и передает обратно клиентскому приложению. Кроме этого, на сервере 1С:Предприятия сосредоточено выполнение различных общих функций платформы: ♦ чтение и сохранение конфигураций и настроек пользо- вателя; ♦ операции над базой данных, включая ограничения дос- тупа к данным; ♦ хранение значений параметров сеанса; ♦ ведение журнала регистрации; ♦ поддержка оперативной отметки времени; ♦ другие функции (управление объектными блокировка- ми, идентификаторы и т. п.). Сервер 1С:Предприятия является сервером без состоя- ния (stateless), то есть он не хранит данные о сеансах и их состоянии, а просто передает информацию. Выполнение встроенного языка на клиенте и сервере По умолчанию встроенный язык исполняется всегда на клиенте. Но при работе в клиент-серверном варианте раз- работчик может организовать выполнение различных процедур и функций общих модулей и модулей объектов также и на сервере приложения. Для этого используются свойства модулей и операторы препроцессора. Передача выполнения встроенного языка на сервер 1С:Предприятия позволяет, например, сложные алгорит- мы расчета выполнять не на клиентской машине, а на бо- лее мощном сервере, что увеличивает общую производи- тельность прикладного решения. Высокоуровневая модель интерфейса В платформу 1С:Предприятия включен целый ряд меха- низмов, ориентированных на быструю разработку эрго- номичного пользовательского интерфейса. В них реали- зована собственная оконная модель, система форм, набор элементов управления и т. д. Использование информации из метаданных Интерфейсные механизмы 1 С: Предприятия широко ис- пользуют информацию из метаданных для того, чтобы ав- томатизировать процесс разработки интерфейса и умень- шить необходимость детальной настройки, выполняемой разработчиком. Расширения форм и элементов управления ЮПредприятие использует механизм расширений форм и элементов управления. Расширения содержат набор свойств, методов и событий, которыми дополняется стан- дартное поведение элементов управления и формы после того, как они связываются с данными. В зависимости от того, какой тип данных отображает элемент управления или форма, платформа будет использовать то или иное расширение. Такой подход позволяет реализовывать индивидуальные особенности поведения формы и элементов управления при работе с различными типами данных.
Автоматическое формирование командного интерфейса Наряду с возможностью явного указания команд, кото- рые должны входить в состав командных панелей форм и элементов управления, платформа поддерживает авто- матическое формирование командного интерфейса. При этом используется два вида информации. Во-первых, ис- пользуются команды, характерные для данного элемента управления или формы, а во-вторых, используются ко- манды, определяемые тем расширением, которое исполь- зуется совместно с элементом управления или формой. Таким образом, командный интерфейс наряду с команда- ми, общими для данного элемента управления или фор- мы, содержит и индивидуальный набор команд, опреде- ляемый конкретным типом данных, с которыми связан элемент управления или форма. Генерация форм по умолчанию Важной особенностью системы 1 С:Предприятие являет- ся механизм форм по умолчанию. Этот механизм освобо- ждает разработчика от необходимости создания всех воз- можных форм для каждого из объектов прикладного решения. Разработчику достаточно создать новый объект прикладного решения, а система сама сгенерирует в нуж- ные моменты работы пользователя необходимые формы по умолчанию для работы с данными, содержащимися в этом объекте. Таким образом, разработчику нужно созда- вать собственные формы объектов прикладного решения лишь в том случае, если они должны иметь отличия (дру- гой дизайн или специфическое поведение) от форм, гене- рируемых системой по умолчанию. Собственная модель оконной системы Оконная система, используемая в ЮПредприятии, ори- ентирована на обеспечение высокой эргономичности при работе с прикладными решениями и содержит специаль- ные возможности, не поддерживаемые классической Win- dows-моделью. Окна, используемые в прикладных решениях, могут иметь несколько разных состояний, которые определяют пове- дение этих окон: ♦ обычные окна; ♦ свободные окна; ♦ прикрепленные окна; ♦ прячущиеся окна; ♦ «склеенные» окна; ♦ сложенные окна с закладками. Кроме этого, оконная система 1С:Предприятия предлага- ет собственную схему максимизации обычных окон, ко- торая заменяет собой стандартную для приложений Win- dows схему. В 1 С:Предприятии максимизация одного окна не влечет за собой максимизацию всех обычных окон. Также в ЮПредприятии поддерживается специальный режим отображения окна — режим рабочего стола. В этом режиме открытое окно занимает все свободное простран- ство главного окна приложения, не имеет заголовка окна и не отображается в списке открытых окон. Такой режим может быть использован для создания специализирован- ных рабочих мест (например, рабочего места кассира). Поддержка различных хранилищ данных В различных вариантах работы (файловый или клиент- серверный) ЮПредприятие использует различные хра- нилища данных. В файловом варианте работы все данные информацион- ной базы хранятся в одном файле — !Cv8.1CD. Этот файл имеет специальный формат, поддерживаемый сис- темой ЮПредприятие. В клиент-серверном варианте работы все данные хранят- ся в базе данных SQL Server. Бесспорным преимуществом файловой базы данных яв- ляется простота ее использования и обслуживания, одна- ко она не рассчитана на интенсивную конкурентную работу большого числа пользователей и хранение значи- тельных объемов данных. В то же время использование базы данных SQL Server по- зволяет обеспечить большую пропускную способность системы, хранение значительных объемов данных и надеж- ность использования. Оборотной стороной этих преиму- ществ является более сложное, по сравнению с файловой базой данных, обслуживание и необходимость использо- вания дополнительного программного обеспечения (в ка- честве сервера баз данных используется MS SQL Server). Обновление прикладных решений Одним из важных архитектурных решений ЮПредпри- ятия является наличие механизмов обновления приклад- ных решений. Эти механизмы обеспечивают синхрони- зацию изменений, сделанных поставщиком прикладного решения с изменениями, внесенными при внедрении на конкретном предприятии. Они предоставляют мощные
функции сравнения и анализа изменений, а также средст- ва управления их синхронизацией. Администратор или разработчик может детально настроить синхронизацию обновлений вплоть до отдельных объектов, отдельных свойств и отдельных процедур модулей. Например, если специалист, отвечающий за сопровожде- ние прикладного решения на предприятии, отметит объ- екты, которые намерен поддерживать самостоятельно, они не будут в дальнейшем обновляться при установке очередного обновления от поставщика. Если объекты не- обходимо объединить, то для упрощения синхронизации изменений можно настроить приоритеты такого объеди- нения. В то же время если прикладное решение не изме- нялось у клиента, то обновление может быть выполнено в полностью автоматическом режиме. Подробнее об этих механизмах можно прочитать в разде- ле «Механизм поставки и поддержки прикладных реше- ний», с. 652. Интернационализация Механизмы интернационализации, заложенные в техноло- гическую платформу 1С:Предприятия, позволяют исполь- зовать различные языки как при разработке прикладного решения, так и при работе пользователей прикладного решения. Кроме этого, на уровне технологической плат- формы поддерживаются национальные стандарты пред- ставления дат, чисел и т. д. Благодаря этому в 1 С: Предприятии возможно создание многоязычных прикладных решений, в которых различные пользователи работают с одной и той же информацион- ной базой, используя интерфейсы на различных языках. Подробнее о многоязычных прикладных решениях мож- но прочитать в разделе «Многоязычные прикладные ре- шения», с. 764.
Глава 2. Функциональность ^Предприятия Обзор функциональности прикладных решений Значительная часть функциональности прикладных ре- шений, создаваемых на платформе 1С:Предприятие, оп- ределяется теми возможностями, которые содержит базо- вая реализация используемых объектов конфигурации. Не претендуя на полное и глубокое изложение, рассмот- рим лишь основные функциональные возможности неко- торых объектов конфигурации. Многие из упомянутых объектов и механизмов более подробно рассматриваются в других разделах этой книги. Кроме этого, рассмотрим также и некоторые «общие» объекты технологической платформы, не реализующие конкретной прикладной специфики, но обеспечивающие важные функциональные возможности для прикладных решений. Справочники Справочники описывают каталоги, содержимое которых более или менее постоянно. Это может быть, например, перечень выпускаемой продукции, список клиентов ком- пании, перечень валют и т. д. Справочники обеспечивают поддержку иерархических структур, позволяют относить данные к отдельным объектам и их группам, предостав- ляют ряд других сервисных возможностей. Многоуровневая иерархия, поддерживаемая справочни- ками, включается простой активизацией соответствую- щего свойства в метаданных. При этом поддержка иерархии распространяется сразу на все аспекты использования прикладного объекта. Например, прототип (шаблон) справочника обеспечивает поддержку необходимых свойств и методов в объектной модели манипулирования данными (определение уровня объекта, контроль зацикливания иерархии и т. д.). В ин- терфейсных механизмах реализуется представление дан- ных в виде иерархического списка или дерева с навигаци- ей по уровням и интерактивным изменением иерархии. В механизмах отчетов обеспечивается формирование иерархических документов такого рода и получение мно- гоуровневой иерархии итогов в любых отчетах, в которых объекты этого типа выступают в качестве параметров для группировки. Подробнее об использовании справочников можно про- читать в главе 6 «Хранение информации», с. 91. Документы Документы отражают в системе события, происходящие в жизни предприятия: поступление материалов, перечис- ление денег через банк, прием сотрудника на работу и т. д. Прототип (шаблон) документа обеспечивает их отра- жение в различных учетных механизмах, поддерживает контроль последовательности обработки событий, реали- зует сквозную нумерацию объектов разного типа и т. д. Одним из важных функциональных механизмов системы является механизм проведения документов. Он предлага- ет разработчику стандартную модель организации связи между информацией о событиях, происходящих на пред- приятии, и различными учетными механизмами. Любая вводимая пользователем в виде документов информация может отражаться в любых учетных механизмах (плани- ровании, управленческом учете, бухгалтерском учете и т. д.). Разработчик должен только указать в свойствах метадан- ных связь между документами и учетными механизмами, а также описать алгоритм проведения документа. Все необходимые действия по проведению и отмене про- ведения система будет выполнять автоматически. При этом системой предоставляются дополнительные возмож- ности, такие как поддержка отражения событий в реальном времени, поддержка восстановления последовательности отражения событий, происходящих на предприятии, при изменении их задним числом и т. д. В результате предо- ставляется единая модель связи исходных данных и учет- ных механизмов, которая не просто облегчает разработку, но и обеспечивает единообразное предсказуемое поведе- ние всех прикладных решений, что существенно облегча- ет их освоение и поддержку. Подробнее об использовании документов можно прочи- тать в главе 7 «Документы и последовательности», с. 136. Механизм характеристик Механизм описания характеристик позволяет организо- вать хранение свойств объектов (справочников, докумен- тов и т. д.), которые еще не известны на момент разработ- ки прикладного решения. Таким образом, например, для номенклатуры пользователь сможет самостоятельно вво- дить новые свойства: цвет, размер, габариты, мощность и т. д. Для каждой группы номенклатуры может быть соз- дан свой набор свойств: для холодильников — объем мо- розильной камеры, число компрессоров, уровень шума; для компьютеров — объем оперативной памяти, объем жесткого диска; для одежды — размер, рост, цвет. В дальнейшем на основе этих характеристик можно стро- ить отчеты, анализировать объемы продаж, получать дру- гую информацию для принятия решений. Подробнее об использовании механизма характеристик можно прочитать в разделе «Хранение дополнительных характеристик произвольного типа. Использование пла- на видов характеристик», с. 131.
Механизм сведений Механизм хранения сведений, реализованный в платфор- ме 1С:Предприятия, позволяет хранить в прикладном ре- шении произвольные данные в разрезе нескольких изме- рений. Например, можно хранить курсы валют в разрезе валют или цены предприятия в разрезе номенклатуры и типа цен. Кроме этого может быть задана различная периодичность хранения сведений, что позволяет хранить не только сами значения, но и историю их изменения. Подробнее об использовании механизма сведений можно прочитать в разделе «Хранение информации в регистрах сведений», с. 107. Механизм учета движения средств Механизм учета движения средств (финансов, товаров, материалов и т. д.) позволяет автоматизировать такие на- правления, как складской учет, взаиморасчеты, планиро- вание. Основу этого механизма составляют регистры на- копления. Регистр накопления образует многомерную систему из- мерений и позволяет «накапливать» числовые данные в разрезе нескольких измерений. Например, в таком реги- стре можно накапливать информацию об остатках това- ров в разрезе номенклатуры и склада или информацию об объемах продаж в разрезе номенклатуры и подразделе- ния компании. Подробнее об использовании механизма учета движения средств можно прочитать в главе 8 «Реализация задач учета движения средств», с. 177. Механизм бухгалтерского учета Механизмы бухгалтерского учета позволяют реализовать систему двойной записи бухгалтерского учета. Они не на- вязывают разработчику собственно принципов ведения бухгалтерского учета и позволяют создавать модели уче- та, применимые как в России, так и в других странах. Можно перечислить следующие основные возможности, реализуемые механизмами бухгалтерского учета: ♦ ведение многоуровневых планов счетов с произвольной иерархией, в которых поддерживается фиксированная или переменная разрядность кодов счетов; ♦ ведение аналитического учета в нескольких разрезах и уровнях; ♦ ведение учета одновременно по нескольким планам счетов; ♦ ведение консолидированного учета по нескольким юридическим лицам; ♦ возможность указания для отдельных разрезов анали- тики произвольного числа видов учета, таких как коли- чественный, суммовой, валютный учет и т. д. Подробнее об использовании механизма бухгалтерского учета можно прочитать в главе 9 «Реализация задач бух- галтерского учета», с. 240. Механизм сложных периодических расчетов Механизм сложных периодических расчетов позволяет реализовывать различные модели расчета заработной пла- ты. Работа механизма основана на двух составляющих. С одной стороны механизм сложных периодических рас- четов содержит средства для описания различных видов расчета, которые будут использоваться в прикладном ре- шении. Например, это могут быть такие виды расчета, как оклад, алименты, штраф и т. д. Помимо собственно описа- ния этих видов расчета, существует возможность задать правила, по которым одни виды расчета будут влиять на другие виды расчета. С другой стороны, этот механизм предоставляет возмож- ность хранения промежуточных данных, которые исполь- зуются для выполнения расчетов, и конечных результа- тов расчетов. Расчет зарплаты является наиболее типичным примене- нием данного механизма, но сам механизм не имеет ори- ентации именно на эту задачу и успешно используется для решения других задач, требующих описания перио- дических расчетов со сложными взаимосвязями, напри- мер расчета дивидендов, стоимости коммунальных услуг И т. д. Подробнее об использовании механизма сложных перио- дических расчетов можно прочитать в главе 10 «Реализа- ция сложных периодических расчетов», с. 315. Механизм бизнес-процессов Механизм бизнес-процессов позволяет описывать, созда- вать и управлять выполнением бизнес-процессов в при- кладных решениях. Целью этого механизма является автоматизация цепочек связанных операций, направлен- ных на достижение общей цели, обычно в контексте орга- низационной структуры, определяющей функциональные роли и связи. Этот механизм включает средства для описания в при- кладном решении схем бизнес-процессов и их ролевой маршрутизации, для формирования заданий, выполняю- щихся в каждой точке маршрута, для управления бизнес- процессом и организации его связи с другими функция- ми прикладного решения. Важно отметить, что данный механизм предлагает гото- вую стратегию автоматизации совместной деятельности работников предприятия. Для описания простейших биз- нес-процессов достаточно визуального задания схемы маршрута и указания условий ветвления в их узловых точках. Все остальные действия выполняются системой автоматически. При реализации сложных бизнес-процес- сов усилия разработчика требуются в основном для тес- ной их увязки с функциями прикладного решения. Подробнее об использовании механизма бизнес-процес- сов можно прочитать в главе 11 «Механизм бизнес-про- цессов», с. 363.
Механизм анализа данных и прогнозирования Механизм анализа данных и прогнозирования позволяет реализовывать в прикладных решениях инструменты для выявления закономерностей, которые обычно скрывают- ся за большими объемами информации. Например, проанализировав данные о продажах товаров, можно выявить группы товаров, которые обычно покупа- ются вместе, и при очередной покупке рекомендовать кли- енту дополнительные товары, исходя из найденных зако- номерностей и тех товаров, которые клиент уже выбрал. Этот механизм поддерживает выполнение нескольких типов анализа данных, таких как общая статистика, по- иск ассоциаций, дерево решений, поиск последовательно- стей, кластерный анализ. Подробнее об использовании механизма анализа данных и прогнозирования можно прочитать в главе 12 «Исполь- зование механизма анализа данных и прогнозирования», с. 398. Интеллектуальные механизмы подготовки отчетов Важным механизмом системы, обеспечивающим значи- тельную часть функциональности создания и использо- вания отчетов, является построитель отчета. Он предо- ставляет возможность динамического создания отчета как программными, так и интерактивными средствами. В основе работы построителя отчета лежит текст запроса, исходя из которого построитель отчета предоставля- ет пользователю возможность интерактивной настройки всех основных параметров, содержащихся в тексте запро- са. Например, пользователь может выбрать все или толь- ко некоторые исходные поля, может включать в состав полей поля «через точку» от данного поля, может нало- жить ограничения на значения некоторых полей и т. д. Полученные в результате выполнения этого запроса, дан- ные выводятся в табличный документ с использованием всех его интерактивных возможностей: сводных таблиц, диаграмм, сводных диаграмм и т. д. Для формирования табличного документа построитель отчета использует макет, генерируемый автоматически. Средствами встроенного языка этот макет может быть - изменен и оформлен одним из доступных вариантов оформления. Также разработчик может использовать собственный макет, на основании которого будет форми- роваться итоговый документ. Также при формировании табличного документа воз- можно использование условного оформления. Этот меха- низм позволяет оформлять отчет динамически, в зависи- мости от значений, выводимых в отчет. Для настройки доступны цвет текста, цвет фона, шрифт, формат значе- ния, выделение отрицательных чисел и другие оформи- тельские свойства. Разработчик может настроить механизм расшифровки итогового табличного документа таким образом, что для получения детальных сведений по какому-либо результату отчета будет вызываться этот же или другой построитель отчета с нужными параметрами запроса. Таким образом, построитель отчета позволяет не только формировать отдельные отчеты, но и связать воедино це- лый набор отчетов, обеспечивая получение необходимой информации во всех требуемых разрезах. Это дает поль- зователю возможность получать любые аналитические данные без изменения прикладного решения и привлече- ния разработчиков. Подробнее о средствах построения отчетов можно прочи- тать в главе 13 «Средства построения отчетов», с. 413. Табличный документ, географическая схема, диаграммы, диаграмма Ганта Технологическая платформа 1С:Предприятия содержит целый ряд объектов, которые позволяют представлять итоговую информацию в удобном для пользователя виде, обеспечивая при этом, в большей или меньшей степени, интерактивное взаимодействие. Одним из мощных средств презентации любой информа- ции и вывода ее на печать является табличный документ. Он обеспечивает не только эффективную подготовку пе- чатных документов, но и просмотр их на экране в удоб- ном для пользователя виде. Перечислим основные воз- можности табличного документа: ♦ оформление отчета, включая тип и размер шрифта, цвет текста и фона, тип и цвет рамки, рисунки и т. д.; ♦ использование группировок (как вертикальных, так и горизонтальных), с помощью которых можно отражать промежуточные итоги; ♦ поддержка механизма расшифровок, когда при щелчке на строке или ячейке отчета формируется более деталь- ный отчет или открывается объект базы данных; ♦ использование примечаний, содержащих дополнитель- ную информацию о данных, расположенных в ячейке или области документа; ♦ поддержка сводных таблиц, которые позволяют отобра- зить многомерные данные в виде плоской таблицы с вложенными заголовками; ♦ поддержка диаграмм различного вида для наглядного представления экономической информации в графиче- ском виде; ♦ возможность сохранения табличного документа в раз- личных форматах и др. Для представления итоговых данных в разрезе их гео- графического положения в 1С:Предприятии использу- ется специальный объект — географическая схема. Она позволяет создавать отчеты, иллюстрирующие, напри- мер, объемы продаж тех или иных товаров в различных регионах страны. Также географическая схема может быть использована просто для отображения тех или иных географических данных, например схемы проезда к офису или маршрута движения транспортного сред- ства.
Еще одним объектом, используемым для графического представления данных, являются диаграммы. Платформа 1С:Предприятия поддерживает работу с различными ви- дами диаграмм, в том числе: ♦ график (обычный, по шагам, с областями и т. д.); ♦ гистограмма (обычная, с накоплением, объемная и т. д.); ♦ круговая (обычная и объемная); ♦ биржевая (обычная и «свеча»); ♦ изометрическая (обычная, непрерывная и т. д.); ♦ поверхностная (каркасная, выпуклая, вогнутая поверх- ность, сотовая и др.); ♦ радарная (с областями, с накоплением, нормированная и др.); ♦ измерительная диаграмма. Диаграммы акцентируют внимание пользователя на ди- намике изменения данных и помогают быстро произ- водить относительное сравнение данных. Кроме этого, специализированные виды диаграмм могут отражать за- кономерности, обычно скрытые за большими объемами данных. Одним из специальных видов диаграмм, поддерживае- мых платформой, является диаграмма Ганта. Она содер- жит набор интервалов, расположенных на оси времени, и отражает использование объектами (точками) ресурсов (серий). Этот вид диаграммы широко используется для визуализации хода выполнения задач, планирования ре- сурсов, графика рабочего времени и других данных, кото- рые представляются не конкретными числовыми значе- ниями, а набором временных интервалов. Диаграмма Ганта имеет гибкую структуру данных. Как точки, так и серии представляют собой иерархические коллекции, что позволяет, например, представить проект как набор связанных, иерархических задач. Поддерживается возможность установки связей между различными интервалами диаграммы, таким образом, окон- чание одного интервала может быть связано с началом следующего интервала диаграммы. Также поддерживает- ся возможность интерактивного перемещения и растяги- вания интервалов диаграммы в режиме 1С:Предприятие при помощи мыши. Средства интеграции и механизмы обмена данными Система 1С:Предприятие является открытой системой благодаря тому, что технологическая платформа предо- ставляет возможности для интеграции практически с лю- быми внешними программами и оборудованием на осно- ве общепризнанных открытых стандартов и протоколов передачи данных. В системе 1С:Предприятие имеется целый набор средств, с помощью которых можно: ♦ создавать, обрабатывать и обмениваться данными раз- личных форматов; ♦ осуществлять доступ ко всем объектам системы 1С:Пред- приятие, реализующим ее функциональные возможно- сти; ♦ поддерживать различные протоколы обмена; ♦ поддерживать стандарты взаимодействия с другими подсистемами; ♦ разрабатывать собственные интернет-решения. Механизмы обмена данными позволяют создавать рас- пределенные информационные системы на основе: ♦ 1С:Предприятия 8.0; ♦ других информационных систем, не основанных на 1С:Предприятии 8.0. Обмен данными в системе 1 С.'Предприятие реализуется благодаря использованию ряда средств технологической платформы, которые разработчик может применять как по отдельности, так и в различных комбинациях, в зави- симости от конкретной решаемой задачи. Такой подход позволяет обеспечить гибкость механизмов обмена и их «настраиваемость» на решение как можно большего кру- га задач. Подробнее о средствах интеграции можно прочитать в главе 14 «Интеграция с другими информационными системами», с. 528. Механизмы обмена данными более подробно описаны в главе 15 «Создание распределенных информационных систем», с. 571. Web-расширение Одним из средств интеграции, позволяющим расширить сферу применения 1С:Предприятия, является Web-рас- ширение. Данный программный продукт позволяет орга- низовать доступ через веб-интерфейс к функциональности прикладных решений новых категорий пользователей, в том числе и тех, у которых на компьютерах не установ- лена платформа 1С:Предприятия. Это могут быть мо- бильные пользователи, сотрудники территориально уда- ленных подразделений, посетители интернет-магазинов и веб-порталов. Web-расширение позволяет встраивать доступ к данным 1С:Предприятия в существующие веб-сайты и веб-при- ложения и создавать готовые веб-приложения и веб- сервисы, использующие информационную базу 1 (^Пред- приятия. Механизмы Web-расширения могут использоваться для решения задач нескольких уровней, в различных комби- нациях с другими системами: ♦ реализация веб-доступа к информационной базе 1 С:Предприятия; ♦ встраивание прикладной функциональности 1 С:Пред- приятия в существующие сайты; ♦ организация доступа к данным 1С:Предприятия для ре- шения других задач; ♦ организация программного доступа к 1С:Предприятию из других систем. Подробнее о Web-расширении можно прочитать в главе 16 «Web-расширение», с. 606.
Обзор функциональности средств разработки Состав средств разработки достаточно широк и разнооб- разен. Это позволяет выполнять полный цикл действий, начиная от создания конфигурации и заканчивая получе- нием тиражируемого дистрибутива прикладного реше- ния, не прибегая к помощи каких-либо продуктов сторон- них производителей (рис. 2.1). Набор прототипов Средства Средства объектов метаданных разработки ......... -► Метаданные Справочная система Поставка и поддержка v Создание Констрикторы 4- -р оистрив>гввот -> Окна конфигурации Смнтакс-помощник Редакторы Отладчик Глобальный поиск и замена Шаблоны текстов Сравнение/объедынение конфигураций Групповая разработка ' Рис. 2.1. Состав средств разработки Проверка конфигурации Выгрузка/загрузка Файлов конфигурации Внешние обработки —► _ Редактирование ’ текстов интерфейсов Перечислим основные средства, используемые при разра- ботке прикладных решений 1 С: Предприятия. Метаданные и инструменты для их редактирования Прежде всего, это, конечно же, сами метаданные и инст- рументы для их редактирования — окно конфигурации, окно редактирования объекта конфигурации и панель свойств. С помощью этих инструментов выполняется до- бавление, удаление объектов конфигурации, изменение их свойств, установка связей с другими объектами конфигу- рации и пр. Окно редактирования объекта конфигурации позволяет выполнять, в числе прочего, последовательную установку свойств объекта, что удобно (особенно для на- чинающих разработчиков), так как позволяет задать в первую очередь те свойства объекта, которые могут опре- делять наличие или отсутствие других свойств объекта. Палитра свойств также предоставляет возможность из- менять свойства объекта и получать быстрый доступ к информации, связанной с данным объектом. Палитра свойств удобна в использовании для опытных разработ- чиков, а также тогда, когда необходимо просмотреть или изменить одноименные свойства у различных объектов конфигурации. Конструкторы и редакторы В состав средств разработки входит довольно большое количество конструкторов и редакторов. Конструкторы позволяют автоматизировать и облегчить создание неко- торых часто используемых элементов прикладного реше- ния, модификация которых может быть формализована. Как правило, эти элементы прикладного решения могут быть созданы и без использования конструктора, но кон- структор позволяет сделать это быстрее и легче. Например, текст запроса может быть полностью написан самим разработчиком. Для этого разработчик должен хо- рошо знать синтаксис языка запросов и понимать назна- чение различных предложений языка запросов. В то же время текст запроса можно создать с помощью конструк- тора запросов. При этом используется визуальное конст- руирование запроса, когда с помощью мыши нужно вы- брать и перетащить нужные таблицы, поля, установить связи между ними и т. д. После нажатия кнопки ОК конст- руктор запроса создаст синтаксически верный текст за- проса. Можно перечислить, например, следующие конструкто- ры, присутствующие в интерфейсе разработки и админи- стрирования: ♦ конструктор запросов; ♦ конструктор выходной формы; ♦ конструктор движений регистров; ♦ конструктор печати; ♦ конструктор ввода на основании; ♦ конструктор форм объектов конфигурации; ♦ конструктор меню; ♦ конструктор форматной строки. Редакторы позволяют создавать и изменять элементы прикладного решения, модификацию которых затрудни- тельно формализовать или для которых подобная форма лизация не имеет практического смысла. Например, конструктор форм объектов конфигурации позволяет создать некоторую типовую форму объекта, разместить на ней необходимые поля, назначить источни- ки данных и т. д. Этот процесс легко формализуется и по- тому может быть выполнен конструктором. Однако даль- нейшее редактирование формы, как правило, является процессом творческим и формализации не поддается. По- этому платформа предоставляет в распоряжение разра- ботчика редактор форм, с помощью которого он придает форме нужный вид, располагает дополнительные элемен- ты управления, настраивает, при необходимости, привязки и т. д. в соответствии с конкретным назначением формы.
Можно перечислить, например, следующие редакторы, реализованные в интерфейсе разработки и администри- рования: ♦ редактор форм; ♦ редактор текстов и модулей; ♦ редактор табличных документов; ♦ HTML-редактор; ♦ редактор интерфейсов; ♦ редактор картинок. Синтакс-помощник Синтакс-помощник позволяет получать справку по ис- пользованию конструкций встроенного языка, свойствам, методам и событиям объектов встроенного языка (как по- ставляемых непосредственно платформой, так и созда- ваемых наследованием от прототипов объектов конфигу- рации), а также справку по составу таблиц, являющихся источниками данных в языке запросов. Синтакс-помощ- ник может быть использован как самостоятельно, так и в связке с редактором текстов и модулей. Находясь в тек- сте модуля, можно, используя сочетание клавиш, перейти к описанию соответствующего свойства, метода, функции и т. д. в синтакс-помощнике, а конструкции встроенного языка, описанные в синтакс-помощнике, в свою очередь, могут быть перенесены в текст модуля с помощью мыши. Отладчик и режим замера производительности Среди средств разработки, используемых наиболее часто и интенсивно можно отметить также отладчик и режим замера производительности. Отладчик позволяет проана- лизировать работу прикладного решения, выполнить ос- тановку в указанном месте кода на встроенном языке, просмотреть значения переменных, состояние используе- мых объектов в определенные моменты работы, вы- полнить фрагмент кода «по шагам» и т. д. Режим замера производительности используется для того, чтобы про- анализировать эффективность выполнения участка кода, узнать время, затраченное на выполнение каждой из строк этого участка кода (как абсолютное, так и относи- тельное, в процентах к общему времени выполнения все- го участка). Таким образом, можно определить операто- ры, выполнение которых занимает основное количество времени, и попытаться оптимизировать используемый алгоритм. Подробнее об использовании режима замера производительности можно прочитать в разделе «Режим замера производительности 1С:Предприятия», с. 736. Проверка конфигурации Режим проверки конфигурации позволяет выявить ошиб- ки, которые не являются критичными для функциониро- вания прикладного решения в принципе, но наличие ко- торых может существенно снизить скорость работы при- кладного решения или даже привести к возникновению ошибок при р’аботе в некоторых специальных режимах. Использование этого режима не является обязательным, но может оказаться очень полезным, например, для про- верки конфигурации перед поставкой заказчику, перед выпуском тиражного решения, для проверки после мас- сированного удаления объектов или после объединения конфигураций. Сравнение/объединение конфигураций Механизм сравнения/объединения конфигураций позво- ляет выполнять, например, детальный анализ отличий между разными версиями одного и того же прикладного решения. Также с помощью этого механизма можно вы- полнять переход от одной версии прикладного решения к другой версии того же самого или другого прикладного решения. При этом разработчик имеет возможность за- дать различные правила объединения для различных эле- ментов прикладного решения, указывая, какой элемент должен быть взят из новой версии, какой оставлен без из- менений, а какие элементы, например, должны быть объ- единены и содержать как старый, так и новый варианты. После нажатия кнопки Выполнить платформа автоматиче- ски выполнит объединение в соответствии с правила- ми, заданными разработчиком. Использование механизма сравнения/объединения конфигураций позволяет избе- жать ручной модификации конфигурации (и связанного с этим большого количества ошибок), при переносе изме- нений из одной конфигурации в другую, а также значи- тельно ускорить этот процесс. Редактирование текстов интерфейса Платформа 1С:Предприятия позволяет создавать много- язычные прикладные решения, в которых каждый из пользователей может работать с интерфейсом на своем родном языке. Для того чтобы помочь разработчику при создании многоязычных прикладных решений, в состав средств разработки входит механизм редактирования текстов интерфейса. Этот механизм позволяет находить и группировать все вхождения той или иной строки в кон- фигурации и «в одно нажатие» заменить его или доба- вить аналог этой строки на другом языке. Кроме этого, механизм позволяет переносить строки на разных языках из одного прикладного решения в другое. Подробнее о механизме редактирования текстов интерфейса можно прочитать в разделе «Редактирование текстов интерфей- са», с. 772. Групповая разработка прикладных решений Механизм групповой разработки позволяет вести и вер- сионировать разработку прикладных решений группе разработчиков, внося изменения в конфигурацию одно- временно, по мере выполнения каждым из них своего участка работы. Подробнее о механизме групповой разра- ботки можно прочитать в разделе «Групповая разработка прикладных решений», с. 690.
Поставка и поддержка прикладных решений Механизм поставки и поддержки прикладных решений служит для автоматизации процесса поддержки разра- ботчиками прикладного решения, используемого пользо- вателем. Задача поставки и поддержки заключается в соз- дании новых версий прикладного решения и обновления той версии прикладного решения, которая находится у пользователей. Подробнее о механизме поставки и поддержки можно прочитать в разделе «Механизм поставки и поддержки прикладных решений», с. 652. Создание дистрибутивов Механизм создания дистрибутивов позволяет разработчи- ку создать комплект поставки — набор файлов, предназна- ченных для установки на компьютере пользователя. Ком- плект поставки включает в себя программу установки Setup.exe и набор файлов поставки, сжатых в архив. Для установки прикладного решения пользователю достаточно запустить на своем компьютере программу установки, вхо- дящую в комплект поставки, и следовать инструкциям, по- являющимся на экране. Программа установки имеет стан- дартный интерфейс и помогает пользователю установить все компоненты прикладного решения. Подробнее о меха- низме создания дистрибутивов можно прочитать в разделе «Механизм создания комплектов поставки», с. 668. Обзор функциональности средств администрирования Средства администрирования, входящие в состав ин- терфейса разработки и администрирования, позволяют управлять составом пользователей информационной базы, осуществлять регламентные операции по ее обслу- живанию и выполнять другие административные дейст- вия (рис. 2.2). Рис. 2.2. Состав средств администрирования Перечислим основные средства, используемые для ад- министрирования информационных баз 1С:Предпри- ятия. Список пользователей Платформа 1 С: Предприятия позволяет вести список пользователей, которым разрешена работа с данной ин- формационной базой. Этот список не является частью прикладного решения, а создается отдельно, в каждой конкретной организации, в которой используется при- кладное решение. Существует возможность добавлять, удалять пользователей системы, назначать им различные виды аутентификации, набор ролей, доступных в систе- ме, основной интерфейс, язык пользователя и пр. Система прав доступа Для каждого конкретного прикладного решения система 1 С: Предприятие позволяет описать наборы прав, соот- ветствующие должностям пользователей или виду дея- тельности. Структура прав определяется конкретным при- кладным решением. Все права, поддерживаемые системой 1С:Предприятие, можно разделить на две большие группы: основные и ин- терактивные. Основные права описывают действия, вы- полняемые над элементами данных системы или над всей системой в целом, и проверяются всегда, независимо от способа обращения к данным. Интерактивные права опи- сывают действия, которые могут быть выполнены поль- зователем интерактивно. Соответственно проверяются они только при выполнении интерактивных операций стандартными способами, причем в клиент-серверном ва- рианте все проверки прав (кроме интерактивных) выпол- няются на сервере. Ограничение прав на уровне записей и полей Среди действий над объектами, хранящимися в базе дан- ных, есть действия, отвечающие за чтение или изменение
информации, хранящейся в базе данных. К таким дейст- виям относятся: ♦ чтение — получение записей или их фрагментов из таб- лицы базы данных; ♦ добавление — добавление новых записей без изменения существующих; ♦ изменение — изменение существующих записей; ♦ удаление — удаление некоторых записей без внесения изменений в оставшиеся. Для этих действий могут быть заданы дополнительные условия на данные (ограничение доступа к данным). В этом случае над конкретным объектом, хранимым в базе данных, может быть выполнено запрошенное дейст- вие только в том случае, если ограничение доступа к дан- ным для данных этого объекта принимает значение Истина. Аналогичные условия могут быть заданы и для таблиц ба- зы данных, не имеющих объектной природы (регистров). Ограничение доступа к данным представляет собой усло- вие, описанное на языке, который является подмножеством языка запросов. Это условие применяется для каждой за- писи таблицы базы данных, над которой выполняется операция. При просмотре списков и формировании отчетов существует возможность обеспечить отображение только тех данных, доступ к которым пользователю разрешен. Журнал регистрации Для хранения информации о событиях, происходящих в информационной базе, система 1С:Предприятие ведет журнал регистрации. Администратор информационной базы имеет возможность настроить уровень событий, ко- торые будут отображаться в журнале регистрации (на- пример, только ошибки или ошибки, предупреждения и информация). Просмотр журнала регистрации может быть выполнен с помощью специального фильтра, позво- ляющего отбирать информацию по большому количеству критериев. Также журнал регистрации может быть пол- ностью или частично выгружен в формат XML для про- граммного анализа. Подробнее об использовании журна- ла регистрации можно прочитать в разделе «Журнал регистрации 1С:Предприятия», с. 734. Загрузка/выгрузка информационной базы Команды загрузки/выгрузки информационной базы по- зволяют сохранить информационную базу в файл на дис- ке, или загрузить информационную базу из файла. Эти команды используются, например, для того, чтобы пере- нести базу из файлового варианта в клиент-серверный и обратно. Консоль сервера ЮПредприятия Консоль сервера ЮПредприятия используется при ра- боте в клиент-серверном варианте и позволяет выпол- нять такие действия, как: ♦ мониторинг серверов 1 С:Предприятия; ♦ просмотр списка информационных баз; ♦ управление списком администраторов серверов ЮПред- приятия; ♦ создание и удаление информационных баз; ♦ мониторинг соединений пользователей с информаци- онными базами; ♦ отключение пользователей от информационной базы. Консоль сервера ЮПредприятия реализована в виде подключаемого модуля ММС (Microsoft Management Console) и может быть использована на компьютерах, на которых установлено соответствующее программное обеспечение (для операционных систем Windows 2000/ XP/Server 2003 это программное обеспечение является стандартным).
Глава 3. Использование встроенного языка Введение Как уже говорилось выше, прикладное решение 1 С: Пред- приятия представляет собой определенную структуру метаданных, которая исполняется технологической плат- формой. В то же время технологическая платформа со- держит в себе интерфейс разработки и администрирова- ния, позволяющий создавать новые и модифицировать существующие прикладные решения. Разработка прикладного решения заключается, по боль- шому счету, в двух основных действиях: визуальном кон- струировании объектов конфигурации и описании специфи- ческого поведения системы с использованием встроенного языка и языка запросов. Создание нового прикладного решения начинается с добав- ления новой информационной базы в список баз 1 С:Пред- приятия. При этом платформа создает некую «базовую» структуру метаданных, которая уже представляет собой работоспособное прикладное решение. В соответствии с этой структурой метаданных платформа также создает ряд информационных структур (таблиц), обеспечивающих работу этой конфигурации и хранение данных. Информа- ционные структуры создаются в том варианте работы, ко- торый выбран пользователем (например, файловый или клиент-серверный). Таким образом, разработчик начинает создание приклад- ного решения не «с нуля», а с некоторой «базовой» струк- туры метаданных (пустой конфигурации), которую он может изменять в соответствии со своими потребностями. Следующим шагом в разработке прикладного решения является, как правило, создание структур для хранения данных. Отличительной особенностью разработки в сис- теме ЮПредприятие является то, что платформа изоли- рует разработчика от физических деталей хранения дан- ных, предлагая более высокий уровень абстракции - уровень объектов метаданных. Другими словами, разра- ботчик добавляет в структуру метаданных нужные ему объекты, определяет, например, какие реквизиты и таб- личные части будет содержать тот или иной объект. Платформа же анализирует изменения, выполняемые разработчиком, и создает в информационной базе соот- ветствующие информационные структуры, позволяющие хранить и эффективно использовать данные. В результа- те с точки зрения разработчика процесс создания при- кладного решения в файловом варианте или в клиент- серверном выглядит совершенно одинаково, так как он не оперирует физическими таблицами базы данных, а имеет дело с более абстрактными сущностями — объектами ме- таданных. Таким образом, вся структура хранимых дан- ных описывается средствами визуального конфигуриро- вания и не может быть изменена в процессе работы прикладного решения (в реальном режиме времени). Та- кой подход позволяет платформе контролировать целост- ность информационной базы и данных, которые в ней хранятся. Платформе «известно» о назначении того или иного объекта конфигурации, она «знает», в каких табли- цах должны храниться данные этого объекта, и «обладает информацией» о том, как эти данные должны взаимодей- ствовать с данными других объектов конфигурации. Та- ким образом, ограничивая разработчика в динамической модификации структуры информационной базы, она значительно облегчает задачу создания и модификации прикладного решения, избавляя разработчика от необхо- димости самостоятельно контролировать правильность таблиц информационной базы и их связей. Другим положительным моментом такого подхода явля- ется то, что структура прикладного решения становится «прозрачной» и «легко читаемой». Любому разработчи- ку, не принимавшему непосредственного участия в разра- ботке данного решения, достаточно взглянуть на структу- ру объектов метаданных, чтобы понять, в общих чертах, как оно «устроено». Открыв конфигуратор, он увидит привычный набор объектов метаданных, назначение каж- дого из которых ему хорошо известно. Ограниченный набор объектов конфигурации, которые может использовать разработчик, является еще одной особенностью прикладных решений ЮПредприятия. Платформа поддерживает фиксированный набор про- тотипов объектов метаданных (например, справочник, документ, регистр накопления, бизнес-процесс и т. д.). Разработчик не имеет возможности каким-либо образом создать собственный объект конфигурации (например, просто таблицу, содержащую набор колонок). Он может только добавить в прикладное решение новый объект конфигурации, соответствующий одному из прототипов, поддерживаемых системой (например, регистр сведений, обладающий набором реквизитов). Такой подход позво- ляет создать среду описания прикладных решений, со- стоящую из логических сущностей, одинаковых для всех прикладных решений (рис. 3.1). Добавление новых объектов конфигурации в прикладное решение сразу же позволяет использовать их для ввода и модификации информации. Технологическая платформа «знает», как работать с данными того или иного объекта конфигурации, и в определенные моменты работы при- кладного решения самостоятельно может сгенерировать нужные формы для работы с данными. Таким образом, все объекты конфигурации, которые мо- жет использовать разработчик, обладают некоторым базо- вым поведением, которое реализуется платформой без участия разработчика. В простейшем варианте создание функционального и работоспособного прикладного решения возможно исключительно средствами визуального конст- руирования, без написания какого либо текста программы.
Прикладное решение 1С:Предприятия "Обычное" прикладное решение _______Конфигурация Справочник Номенклатура Справочник Клиенты Регистр накопления Цены -----► Бизнес-процесс Получение товаров Уровень объектов метаданных Атализ структуры метаданных Технологическая платформа Рестру ктуризаци я информационной базы Информационная база Уровень физических таблиц базы данных Рис. 3.1. Сравнение логических уровней приложения Платформа проанализирует состав объектов конфигура- ции и обеспечит все необходимые функции для работы с ними. Однако реальные задачи, решаемые с помощью системы 1С:Предприятие, всегда требуют наличия в прикладном решении некоторых алгоритмов, специфичных для авто- матизируемой области. Это могут быть, например, раз- личные алгоритмы расчета себестоимости, контроля ос- татков, распределения средств и т. д. Также возникает необходимость в создании специфических форм, обла- дающих нестандартным поведением, поскольку удобное визуальное представление информации является одной из наиболее важных задач для любого прикладного решения. В этом случае разработчик имеет возможность использо- вать встроенный язык 1С:Предприятия для того, чтобы определить поведение прикладного решения, отличное от стандартного. С помощью встроенного языка разработ- чик может «вмешиваться» в работу прикладного реше- ния: выполнять какие-либо алгоритмы, обрабатывать и модифицировать данные, изменять или вообще отменять стандартные действия системы в зависимости от тех или иных результатов работы. Ключевым моментом здесь является то, что подобное «вмешательство» возможно не всегда, а только в опреде- ленные моменты работы прикладного решения. Таким образом, встроенный язык не является неким универ- сальным языком программирования, с помощью которо- го создаются прикладные решения, а служит лишь для описания особенных алгоритмов работы прикладного ре- шения. Модули конфигурации Для размещения текста программы на встроенном языке предназначены модули прикладного решения (например, модуль приложения, общие модули, модули объектов, мо- дули форм и т. д.). Эти модули располагаются в различных местах конфигурации и имеют различное назначение. Большинство модулей «привязано» к определенным объектам конфигурации или к самому прикладному ре- шению. Такие модули вызываются в определенные мо- менты работы прикладного решения (например, мо- дуль приложения, который запускается при запуске системы в режиме 1 С: Предприятие, или модуль объек- та справочника Номенклатура, который запускается при создании объекта (элемента) справочника). Таким образом, если модуль содержит некоторый код, то этот код будет выполнен и работа прикладного решения продолжена. В таких модулях могут располагаться про- цедуры обработки событий, определенных для различных объектов прикладного решения. Эти процедуры также будут выполняться при наступлении соответствующего события.
Глобальный контекст Экспортируемые функции и процедуры Общий модуль Модуль приложения Модуль внешнего соединения Экспортируемые переменные, функции, процедуры Экспортируемые переменные, функции, процедуры Модуль объекта Модуль формы Экспортируемые переменные, функцию, процедуры Экспортируемые переменные, функции, процедуры Рис. 3.2. Контексты прикладного решения Наряду с модулями, вызываемыми в процессе работы прикладного решения, существуют общие модули, кото- рые сами по себе не вызываются в процессе работы при- кладного решения. Они служат лишь для размещения в них текстов функций и процедур, которые могут вызы- ваться из других модулей прикладного решения. Таким образом, код, располагающийся в общих модулях, будет исполнен только тогда, когда к нему будет выпол- нено явное обращение из другого модуля конфигурации или из командного интерфейса. Каждый модуль связан с остальной частью конфигура- ции, и эта связь называется контекстом выполнения мо- дуля. Контекст определяет набор доступных для модуля объектов, переменных, процедур и функций. Для всех программных модулей доступен (с некоторыми ограничениями, которые будут рассмотрены далее) гло- бальный контекст задачи. Он образуется значениями свойств и методов глобального контекста, а также сис- темными перечислениями и системными наборами зна- чений. В общем виде связь контекстов различных моду- лей представлена на следующей схеме (рис. 3.2). Общий модуль В конфигурации может быть определено произвольное количество общих модулей, в том числе и ни одного. Кон- текст общего модуля образуется глобальным контекстом и локальным контекстом самого общего модуля, то есть процедурами и функциями, определенными внутри об- щего модуля (рис. 3.3). Поскольку общий модуль не исполняется системой непо- средственно, в нем отсутствует раздел описания перемен- ных и раздел основной программы. Общий модуль может содержать только определения процедур и функций. Если процедуры или функции общего модуля определе- ны как экспортируемые, то они становятся частью гло- бального контекста и будут доступны другим модулям прикладного решения (за некоторыми исключениями, о которых будет сказано далее). Поскольку общий модуль не «привязан» к какому-либо объекту конфигурации, а относится ко всему прикладному решению, имена экспортируемых переменных, процедур и функций должны быть различными в разных общих модулях. В противном случае будет выдана синтаксиче- ская ошибка, так как глобальный контекст будет содер- жать повторяющиеся имена. Модуль приложения В конфигурации всегда существует единственный модуль приложения. Контекст модуля приложения (рис. 3.4) об- разуется: ♦ глобальным контекстом, в том числе экспортируемыми функциями и процедурами общих модулей (если для этих модулей установлено хотя бы одно из свойств Кли- ент или Сервер); ♦ локальным контекстом самого модуля приложения. Глобальный контекст Глобальный контекст Экспортируемые функции и процедуры Экспортируемые функции и процедуры Общий модуль Общий модуль Модуль приложения Рис. 3.3. Контекст общего модуля Рис. 3.4. Контекст модуля приложения
Модуль приложения выполняется при запуске системы в режиме 1 С: Предприятие или при обращении к прило- жению как к Autoniation-серверу. Этот модуль пред- назначен для отработки действий, связанных с сеансом работы конечного пользователя. Помимо описания пере- менных и основной программы, модуль приложения мо- жет содержать описание процедур-обработчиков собы- тий, связанных с сеансом пользователя и прикладным решением в целом. Если переменные, процедуры или функции модуля при- ложения определены как экспортируемые, то они будут доступны другим модулям прикладного решения (за не- которыми исключениями, о которых будет сказано да- лее), за исключением общих модулей, в которых они дос- тупны не будут. Основными событиями, которые могут обрабатываться в модуле приложения, являются события начала и окон- чания работы приложения. Последовательность их вызо- ва представлена на рис. 3.5. Рис. 3.5. Последовательность вызова событий модуля приложения Событие ПередНачаломРаботыСистены возникает при запуске системы в режиме ЮПредприятие до открытия главного окна. Обрабатывая это событие, разработчик имеет воз- можность отказаться от запуска системы в случае, если какие-либо условия не выполнены. Следует учитывать, что поскольку это событие вызывается в тот момент, ко- гда главное окно программы еще не открыто, будет недос- тупен ряд действий, требующих наличия главного окна (например, выдача сообщений, открытие форм и т. д.). Событие ПриНачалеРаботыСистены возникает при запуске сис- темы в режиме ЮПредприятие после открытия главного окна. В обработчике этого события разработчик уже не может отказаться от запуска системы, зато может выпол- нить действия, которые обязательно должны быть выпол- нены при начале работы пользователя системы (например, открыть форму, содержащую справочную информацию и т. д.). Событие ПередЗавершениемРаботыСистемы возникает при за- вершении работы системы в режиме ЮПредприятие до закрытия главного окна. Обрабатывая это событие, раз- работчик имеет возможность отказаться от завершения работы в случае, если какие-либо условия не выполнены. Событие ПриЗавершенииРаботыСистемы возникает при завер- шении работы системы в режиме 1 С: Предприятие после закрытия главного окна. В обработчике этого события разработчик уже не может отказаться от закрытия прило- жения, но может выполнить действия, которые обяза- тельно должны быть выполнены при окончании работы пользователя. Следует учитывать, что поскольку это событие вызывается в тот момент, когда главное окно программы уже закрыто, будет недоступен ряд действий, требующих наличия главного окна (например, выдача сообщений, открытие форм и т. д.). Модуль внешнего соединения В конфигурации всегда существует единственный мо- дуль внешнего соединения. Контекст модуля внешнего соединения (рис. 3.6) образуется: ♦ глобальным контекстом, в том числе экспортируемыми функциями и процедурами общих модулей (если для этих модулей установлено хотя бы одно из свойств Внешнее соединение или Сервер); ♦ локальным контекстом самого модуля приложения. Глобальный контекст Экспортируемые функции и процедуры Общий модуль Модуль внешнего соединения Рис. 3.6. Контекст модуля внешнего соединения Модуль внешнего соединения выполняется при обраще- нии к приложению как к COM-серверу (в режиме внеш- него соединения). В режиме внешнего соединения запус- кается не полноценное приложение ЮПредприятия, а «облегченный» вариант приложения, в котором недос- тупны все функции, так или иначе связанные с организа- цией пользовательского интерфейса. Поэтому в режиме внешнего соединения вместо модуля приложения испол- няется модуль внешнего соединения. Этот модуль пред- назначен для отработки действий, связанных с сеансом работы с приложением ЮПредприятия. Если переменные, процедуры или функции модуля внеш- него соединения определены как экспортируемые, то они будут доступны другим модулям объектов (за некоторы- ми исключениями, о которых будет сказано далее), за ис- ключением общих модулей, в которых они доступны не будут. Помимо описания переменных и основной программы, модуль внешнего соединения может содержать описание двух процедур-обработчиков событий, связанных с нача- лом и завершением работы: ПриНачалеРаботыСистены и При- ЗавершенииРаботыСистемы. Последовательность их вызова представлена на рис. 3.7. При работе в модуле внешнего соединения следует пом- нить о том, что ряд объектов встроенного языка, про- цедур и функций глобального контекста будут не- доступны для использования, так как СОМ-сервер 1 С:Предприятия не содержит «интерфейсной» части приложения.
Рис. 3.7. Последовательность вызова событий модуля внешнего соединения Например, в режиме внешнего соединения нельзя ис- пользовать такие объекты, как диаграмма, табличный до- кумент, недоступны функции для вызова диалога ввода данных и т. д. Точная информация о возможности ис- пользования объектов, процедур и функций в модуле внешнего соединения находится в документации, в опи- сании конкретных объектов, процедур и функций. Модуль объекта Каждый прикладной объект конфигурации, данные кото- рого могут быть модифицированы в режиме ^Предпри- ятие, имеет свой модуль. Этот модуль исполняется при создании объекта встроенного языка, который позволяет модифицировать данные объекта конфигурации. Соот- ветствующий объект встроенного языка создается, на- пример, при вводе нового объекта, при копировании, при получении данных существующего объекта и т. д. Для различных объектов конфигурации этот модуль имеет разное название (табл. 3.1). Контекст модуля объекта (рис. 3.8) образуется: ♦ глобальным контекстом, в том числе экспортируемыми функциями и процедурами общих модулей (в зависи- мости от места создания объекта, о чем будет сказано далее); ♦ экспортируемыми переменными, процедурами и функ- циями модуля приложения или модуля внешнего со- единения (в зависимости от места создания объекта, о чем будет сказано далее); ♦ свойствами и методами объекта встроенного языка, контекст которого расширяется модулем; ♦ реквизитами объекта конфигурации, которому «при- надлежит» модуль; ♦ локальным контекстом самого модуля объекта. Глобальный контекст Модуль приложения Экспортируемые функции и процедуры Ч Экспортируемые переменные, функции, процедуры Общий модуль Модуль объекта Рис. 3.8. Контекст модуля объекта Если переменные, процедуры или функции модуля объ- екта определены как экспортируемые, то они будут дос- тупны в качестве свойств и методов соответствующих объектов встроенного языка. Например, пусть в модуле справочника ТиповыеАнкеты определена экспортная процедура (листинг 3.1). Таблица 3.1. Название модуля объекта для различных объектов конфигурации Объект конфигурации Название модуля Объект встроенного языка, который расширяется модулем Константа Модуль менеджера значения КонстантаМенеджерЗначения.<имя> Справочник Документ Отчет Обработка План видов характеристик План счетов План видов расчета План обмена Бизнес-процесс Задача Модуль объекта СправочникОбъект.<имя> ДокументОбъект.<имя> ОтчетОбъект.<имя> ОбработкаОбъект.<имя> ПланВидовХарактеристикОбъект.<имя> ПланСчетовОбъект.<имя> ПланВидовРасчетаОбъект.<имя> ПланОбменаОбъект.<имя> БизнесПроцессОбъект.<имя> ЗадачаОбъект.<имя> Последовательность Регистр сведений Регистр накопления Регистр бухгалтерш! Регистр расчета Перерасчет Модуль набора записей ПоследовательностьНаборЗаписей.<имя> РегистрСведенийНаборЗаписей.<имя> РегистрНакопленияНаборЗаписей.<имя> РегистрБухгалтерииНаборЗаписей.<имя> РегистрРасчетаНаборЗаписей.<имя> ПерерасчетНаборЗаписей.<имя>
Листинг 3.1. Экспортная процедура в модуле справочника Процедура Печать О Экспорт // Алгоритм вывода на экран печатной формы анкеты // ... КонецПроцедуры // Тогда возможен следующий вызов этой процедуры, на- пример, из модуля внешней обработки (листинг 3.2). Листинг 3.2. Пример вызова экспортной процедуры объекта справочника Анкета = Справочники.ТиповыеАнкеты. НайтиПоКодуСООООГ) .ПолучитьОбьектО; Анкета.ПечатьО; Помимо описания переменных и основной программы, модуль объекта может содержать описание процедур-об- работчиков событий, связанных с данным объектом кон- фигурации. Состав этих событий различен для разных объектов, однако есть два события, которые вызываются для всех объектов — ПередЗаписью и ПослеЗаписи. Последо- вательность их вызова представлена на рис. 3.9: Транзакция записи Рис 3.9. Последовательность вызова событий модуля объекта (например, при открытии формы элемента справочника) либо явно получаться средствами встроенного языка (лис- тинг 3.3). Листинг 3.3. Пример получения формы Форма = Справочники.Номенклатура.ПолучитьФориуСпискаО; Контекст модуля формы (рис. 3.10) образуется: ♦ глобальным контекстом, в том числе экспортируемыми функциями и процедурами общих модулей (если для этих модулей установлено хотя бы одно из свойств Или - ент или Сервер); ♦ экспортируемыми переменными, процедурами и функ- циями модуля приложения; ♦ свойствами и методами объекта, который назначен ос- новным реквизитом формы, включая экспортируемые переменные, процедуры и функции, определенные в мо- дуле этого объекта; ♦ свойствами и методами расширения формы, определяе- мого основным реквизитом формы; ♦ свойствами и методами объекта Форма встроенного языка; ♦ реквизитами формы, которой «принадлежит» модуль; ♦ локальным контекстом самого модуля формы. Глобальный контекст Экспортируемые функции и процедуры Общий модуль Модуль приложения Экспортируемые переменные, функции, процедуры Модуль объекта Экспортируемые переменные, функции, процедуры Модуль формы J Событие ПередЗаписью вызывается при записи данных, по- сле начала транзакции записи, но перед непосредствен- ной записью данных в базу данных. В обработчике этого события разработчик имеет возможность отказаться от записи данных, если, например, не выполнены требуемые условия. Событие ПриЗаписи вызывается после того, как была вы- полнена запись данных в базу данных, но до окончания транзакции записи. В обработчике этого события разра- ботчик также может отказаться от записи данных, если, например, в результате записи этих данных в базу нару- шаются какие-либо условия. Модуль формы Каждая форма, определенная в конфигурации, имеет свой собственный модуль. Этот модуль исполняется при соз- дании объекта Форма встроенного языка. Этот объект может создаваться при открытии формы прикладного объекта Рис. 3.10. Контекст модуля формы Если переменные, процедуры или функции модуля фор- мы определены как экспортируемые, то они будут дос- тупны в качестве свойств и методов соответствующих объектов Форма встроенного языка. Помимо описания переменных и основной программы, модуль формы может содержать описание процедур-об- работчиков событий, связанных с формой. Основными событиями, которые могут обрабатываться в модуле форы, являются события открытия и закрытия окна формы. По- следовательность их вызова представлена на рис. 3.11. Событие ПередОткрытиен возникает при открытии формы до показа ее окна пользователю. Изменения значений ре- квизитов формы, выполняемые в этом обработчике, не будут приводить к установке модифицированности фор- мы, поэтому здесь можно выполнять установку началь- ных значений и инициализацию необходимых рекви- зитов.
Рис. 3.11. Последовательность вызова событий модуля формы В обработчике этого события разработчик имеет возмож- ность отказаться как от открытия формы, так и от выпол- нения стандартных действий при открытии формы, если, например, не выполнены требуемые условия. Набор стан- дартных действий, выполняемых после события ПередОт- крытием и до события ПриОткрытии, различен для разных форм, и определяется расширением формы, соответст- вующим основному реквизиту формы. Например, для формы объекта справочника после события ПередОткрыти- ен будет выполняться процедура генерации нового кода справочника (если это необходимо) и, соответственно, будет вызван обработчик события ПриУстановкеНовогоКода. Событие ПриОткрытии возникает при открытии формы до показа ее окна пользователю. Это событие предназначено для выполнения действий, которые необходимо выпол- нить лишь в том случае, когда форма наверняка будет от- крыта. В отличие от события ПередОткрытиен, изменение значений реквизитов формы в этом обработчике будет приводить к установке модифицированности формы. Событие ПередЗакрытиен возникает при закрытии формы до закрытия окна формы. В обработчике этого события разработчик имеет возможность отказаться как от закры- тия формы, так и от выполнения стандартных действий при закрытии формы, если, например, не выполнены тре- буемые условия. Набор стандартных действий, выпол- няемых после события ПередЗакрытиен, также различен для разных форм, и определяется расширением формы, соответствующим основному реквизиту формы. Напри- мер, если документ был модифицирован, одним из стан- дартных действий будет запрос сохранения изменений перед закрытием формы. Событие ПриЗакрытии возникает при закрытии формы по- сле закрытия окна формы. В обработчике этого события можно описывать алгоритмы, которые должны быть вы- полнены только в случае, когда форма будет наверняка закрыта. Компиляция модулей При запуске прикладного решения выполняется загрузка метаданных и компиляция программных модулей, кото- рые содержатся в метаданных. Первоначально компили- руются не все модули прикладного решения, а только те, которые необходимы для начала работы. Компиляция же большинства остальных модулей выполняется по мере вызова соответствующих объектов. Причем, после того, как модуль, например, экземпляра объекта справочника Номенклатура, скомпилирован, он помещается в кэш моду- лей. При создании следующего экземпляра объекта спра- вочника Номенклатура компиляция выполняться не будет — скомпилированный ранее модуль будет получен из кэша. Следует заметить, что некоторые модули прикладного ре- шения могут содержаться в конфигурации уже в виде скомпилированного образа. Для этого используются воз- можности механизма поставки, о которых подробнее мож- но прочитать в разделе «Настройка поставки», с. 659. В этом случае конфигурация физически не содержит ис- ходного текста модуля (только скомпилированный об- раз), поэтому при создании объектов, содержащих такие модули, компиляция, естественно, не выполняется. Воз- можность включения модуля в виде скомпилированного образа является элементом защиты интеллектуальной собственности, и элементом защиты логической целост- ности конфигурации от изменения ее пользователем. Она не влияет на скорость работы прикладного решения, так как дальнейшая работа с такими модулями также осу- ществляется через кэш модулей. Также может существовать и третья ситуация, когда ком- пиляция модуля не выполняется, а используется скомпи- лированный образ. Некоторые модули (например, моду- ли объекта) могут быть закрыты паролем (команда Текст ► Установить пароль). В этом случае конфигурация будет со- держать зашифрованный текст модуля. Сам пароль, с помо- щью которого текст был зашифрован, в конфигурации не хранится. Поэтому для того, чтобы этот модуль мог исполняться, одновременно с шифрованием модуля создает- ся его скомпилированный образ, который и используется при работе прикладного решения в режиме ЮПредприятие. В отличие от поставки без исходного текста, в этом слу- чае разработчик, зная пароль, может просматривать и/или модифицировать исходный текст модуля в режиме кон- фигуратора. Компиляция модулей и режимы исполнения встроенного языка В общем случае компиляция модулей выполняется в не- скольких контекстах: в контексте сервера и контексте клиента, то есть компилируется свой экземпляр модуля на стороне клиента и/или на стороне сервера. Если ис- пользуется файловый вариант работы, то оба эти контек- ста «сливаются» и, фактически, в контексте клиента бу- дут скомпилированы все модули конфигурации. Поэтому далее мы будем рассматривать работу приложения имен- но в клиент-серверном варианте, когда контексты клиен- та и сервера отличаются друг от друга.
Исполнение модулей также может происходить в не- скольких режимах. Модули, скомпилированные на сто- роне сервера, всегда исполняются в одном и том же режи- ме — режиме сервера. В отличие от них модули, скомпилированные на стороне клиента, могут исполнять- ся в одном из двух режимов: в режиме клиента или в ре- жиме внешнего соединения. Каждый из режимов исполнения имеет свои особенно- сти, которые в общем виде приведены в табл. 3.2. Как видно из приведенной таблицы, не все модули могут быть скомпилированы в любых контекстах и не все ском- пилированные модули могут быть исполнены в любых режимах. Далее будет подробно рассмотрена компиляция модулей прикладного решения в различных контекстах и возмож- ность использования инструкций препроцессору для вы- полнения условной компиляции. Что же касается исполнения встроенного языка, то система позволяет выполнить синтаксический контроль модулей прикладного решения в различных режимах исполне- ния — для этого предназначена команда Конфигурация ► Проверка конфигурации... Особенности исполнения встроенного языка на сервере и механизм передачи исполнения с клиента на сервер подробно рассматриваются в разделе «Организация вы- полнения кода на сервере или на клиенте», с. 86. Компиляция общих модулей Экземпляры общих модулей компилируются в соответствии со значениями свойств Клиент, Сервер и Внешнее соединение этих модулей. Если для общего модуля установлено только свой- ство Клиент, то экземпляр этого модуля будет скомпилирован только на стороне клиента. Если установлено только свойст- во Сервер — то только на стороне сервера (рис. 3.12). Компиляция общего модуля (Клиент = Истина) 1 С.Предприятие СОМ-соединение Сервер Клиент Сервер • Клиент Общий модуль Компиляция общего модуля (Сервер = Истина) Таблица 3.2. Режимы исполнения встроенного языка Компьютер клиента Компьютер сервера Исполняемое приложение Клиентское приложение СОМ-соединение Сервер 1С:Предприятия Режим запуска системы 1С:Предприятие Интерактивный запуск в режиме 1С:Предприятие или запуск в качестве Automation-сервера (V8. Application) Запуск в качестве СОМ- сервера (V8.COMConnector) Присутствует в любом режиме запуска, но имеет смысл только в клиент- серверном варианте работы Режим исполнения встроенного языка Клиент Внешнее соединение Сервер Модуль, исполняемый после запуска системы Модуль приложения Модуль внешнего соединения Отсутствует. Может быть исполнен код общего модуля и только в том случае, если исполнение передано с клиента на сервер Использование общих модулей Если установлено свойство Клиент Если установлено свойство Внешнее соединение Если установлено свойство Сервер Использование объектов встроенного языка Любые объекты Некоторые объекты. Если объект не может быть использован в режиме внеш- него соединения, в докумен- тации для него указано: «Не используется в модуле внешнего соединения» Некоторые объекты. Если объект не может быть использован на сервере, в документации для него указано: «Недоступен на сервере» 1С:Предприятия» Использование форм Любые формы Не используются Не используются Передача объектов на сервер и обратно Могут быть переданы только некоторые объекты, для которых в документации указано: «Возможен обмен с сервером»
Если для общего модуля установлены свойства Клиент и Сервер одновременно, то экземпляры этого общего мо- дуля будут скомпилированы как на стороне клиента, так и на стороне сервера (рис. 3.13). Если для общего модуля установлено свойство Внешнее соединение, то экземпляр этого модуля будет скомпилиро- ван на стороне клиента только в случае запуска 1 (^Пред- приятия в сеансе внешнего соединения (при обращении к нему как к COM-серверу) (рис. 3.14). Если для общего модуля установлены свойства Сервер, Клиент и Внешнее соединение, то экземпляр этого модуля всегда будет компилироваться как на стороне сервера, так и на стороне клиента (рис. 3.17). Компиляция общего модуля (Клиент = Истина. Сервер = Истина) 1 С.Предприятие С ОМ-соединение Клиент Клиент Компиляция общего модуля (Сервер - Истина, Клиент = Истина. Внешнее соединение = Истина) клиенте и в сеансе внешнего соединения Сервер Общий модуль Сервер Рис. 3.13. Компиляция общего модуля для исполнения на сервере и клиенте Компиляция общего модуля (Внешнее соединение = Истина) 1 С:Предприятие Сервер ! Клиент С ОМ-соединение Сервер Клиент Общий модуль Рис. 3.14. Компиляция общего модуля для исполнения в сеансе внешнего соединения Компиляция модуля приложения и модуля внешнего соединения Модуль приложения и модуль внешнего соединения все- гда компилируются только на стороне клиента. Модуль приложения компилируется в случае, если выполняется запуск конфигурации в режиме 1 С:Предприятие или приложение запускается в качестве Automation-сервера. Модуль внешнего соединения компилируется в случае, если приложение запускается в качестве СОМ-сервера (рис. 3.18). Если для общего модуля установлены свойства Сервер и Внешнее соединение, то на стороне сервера всегда будет компилироваться экземпляр этого модуля, а на стороне клиента — только в сеансе внешнего соединения (рис. 3.15). Компиляция модуля приложения и модуля внешнего соединения 1 (^Предприятие С ОМ-соединение Сервер Клиент Сервер Клиент Компиляция общего модуля (Сервер = Истина. Внешнее соединение = Истина) 1 С: Предприятие С ОМ-соединение Сервер Клиент Сервер Клиент Модуль приложения Модуль внешнего соединения Рис. 3.18. Компиляция модуля приложения и модуля внешнего соединения Общий модуль Общий модуль Общий модуль Таким образом, можно сказать, что модуль внешнего со- единения выполняет функции модуля приложения в се- ансе СОМ-соединения. Рис. 3.15. Компиляция общего модуля для исполнения на сервере и в сеансе внешнего соединения Если для общего модуля установлены свойства Клиент и Внешнее соединение, то экземпляр этого модуля будет все- гда компилироваться на стороне клиента (рис. 3.16). Компиляция общего модуля (Клиент = Истина. Внешнее соединение = Истина) 1 СПредлриятме С О М-соединение Сервер Клиент Сервер Клиент Общий модуль Общий модуль Рис. 3.16. Компиляция общего модуля для исполнения на стороне клиента и в сеансе внешнего соединения Компиляция модуля объекта Экземпляр модуля объекта компилируется в процессе ра- боты прикладного решения, и компиляция может быть выполнена как на стороне клиента, так и на стороне сер- вера. Это определяется тем, в каком контексте происхо- дит обращение к объекту. Если обращение к объекту выполняется, например, в моду- ле приложения, то экземпляр объекта будет создан на сто- роне клиента и, соответственно, экземпляр модуля объекта будет также скомпилирован па стороне клиента (рис. 3.19). Если же обращение к объекту выполняется в процедуре общего модуля, для которого установлено свойство Сервер, то объект будет создан на сервере и там же будет скомпи- лирован экземпляр модуля этого объекта (рис. 3.20).
Сервер Рис. 3.19. Компиляция модуля объекта на стороне клиента Рис. 3.20. Компиляция модуля объекта на стороне сервера Чтобы убедиться в том, что объект действительно созда- ется на сервере или клиенте, можно добавить в модуль объекта справочника Номенклатура следующие строки (лис- тинг 3.4). Листинг 3.4. Использование инструкций условной компиляции #Если Сервер Тогда Сообщить("Объект создан на сервере”); #ИначеЕсли Клиент Тогда Сообщить ("Объект создан на клиенте’’): #КонецЕсли В этом примере использованы инструкции препроцессо- ру, о которых более подробно рассказывается в разделе «Использование инструкций препроцессору». Следует помнить, что не все объекты могут быть исполь- зованы на сервере или в сессии СОМ-соединепия. Точ- ная информация о возможности использования объектов, процедур и функций на сервере и в модуле внешнего со- единения находится в документации, в описании кон- кретных объектов, процедур и функций. Компиляция модуля формы Модуль формы всегда компилируется только на стороне клиента и только в режиме ЮПредприятие, поскольку объект форма не доступен на сервере и в режиме внешне- го соединения. Использование инструкций препроцессору В тексте модулей конфигурации, которые могут компи- лироваться как на стороне сервера, так и на стороне кли- ента (общие модули и модули объектов), допускается ис- пользование инструкций препроцессору. Инструкции препроцессору позволяют указывать, в каком контексте будет скомпилирован тот или иной фрагмент кода (на сервере, на клиенте, во внешнем соединении). Например, если в модуле объекта разместить предыду- щий текст (листинг 3.4), то в том случае, когда экземпляр модуля объекта компилируется на клиенте, он будет со- держать текст: Сообщить("Объект создан на клиенте"): Если же этот объект будет создаваться на стороне серве- ра, тогда модуль объекта будет содержать следующий текст: Сообщить("Объект создан на сервере"); Таким образом, например, можно получить информацию о том, на какой стороне (сервера или клиента) выполня- ется данный участок кода. Работа с метаданными Встроенный язык 1С:Предприятия позволяет работать с метаданными. Одним из концептуальных моментов этой работы является то, что доступ к метаданным предостав- ляется только на чтение. Таким образом, средствами встроенного языка разработчик не может модифициро- вать метаданные. Изменение структуры метаданных воз- можно только средствами визуального конструирования в режиме конфигуратора. Для доступа к метаданным из встроенного языка исполь- зуется объект ОбъектМетаданныхКонфигурация, который дос- тупен через свойство глобального контекста Метаданные. Этот объект предоставляет доступ как к свойствам самой конфигурации, так и к отдельным коллекциям объектов метаданных, которые описывают различные виды при- кладных объектов, определенных в прикладном решении. Например, для доступа к коллекции объектов метадан- ных, описывающих документы, можно использовать сле- дующий код (листинг 3.5). Листинг 3.5. Доступ к коллекции метаданных МетаданныеДокументов = Метаданные.Документы; А для того, чтобы получить доступ к объектам конфигу- рации, описывающим справочники, можно использовать такой вызов (листинг 3.6). Листинг 3.6. Доступ к коллекции метаданных МетаданныеСправочников = Метаданные.Справочники; Элементами таких коллекций являются объекты мета- данных, которые позволяют получить доступ как к специ- фическим свойствам объектов, так и к свойствам, общим для различных объектов метаданных.
Например, можно получить описание реквизитов объек- та, табличных частей объекта и их реквизитов, описания форм, макетов объекта и т. д. (листинг 3.7). Листинг 3.7. Получение описаний реквизитов объектов метаданных // Для объекта метаданных Документ.АккредитивПереданный // можно получить: // описание реквизита ВалютаДокумента Объект = Метаданные.Документы.АккредитивПереданный. Реквизиты.ВалютаДокумента; // описание табличной части РасшифровкаПлатежа Объект = Метаданные.Документы.АккредитивПереданный. ТабличныеЧасти.РасшифровкаПлатежа; // описание реквизита табличной // части ДоговорКонтрагента Объект = Метаданные.Документы.АккредитивПереданный. ТабличныеЧасти.РасшифровкаПлатежа. Реквиз иты.ДоговорКонтрагента; Реквизиты, табличные части объекта метаданных также представляют собой коллекцию объектов метаданных, состоящих из объектов метаданных, описывающих от- дельный реквизит или отдельную табличную часть. В качестве примера на следующей схеме представлена связь объектов, описывающих реквизиты и табличные части объекта метаданных Документ.АккредитивПередан- ный (рис. 3.21). Рис. 3.21. Описание реквизитов и табличных частей документа
Таким образом, в большинстве случаев, значение некото- рого свойства объекта метаданных может быть получено по следующей цепочке программных объектов (рис. 3.22). Рис. 3.22. Цепочка объектов описания метаданных Такой подход позволяет упростить и унифицировать ра- боту с метаданными, обращаясь к свойствам и методам одних и тех же программных объектов. Объекты метадан- ных имеют различный набор свойств, перечень которых можно узнать при помощи команды Конфигурация | Отчет по конфигурации.... Кроме этого, все коллекции объектов метаданных допускают обращение к элементам коллек- ции по имени или индексу. Также показанные на схеме объекты имеют набор следующих методов (рис. 3.23). Рис, 3.23. Методы объектов описания метаданных Объект ОбъектМетаданныхКонфигурация содержит два метода, которые позволяют найти объект метаданных, описываю- щий некоторое значение или тип. Полученное таким об- разом значение может быть использовано для того, чтобы найти его в некоторой коллекции объектов метаданных (метод Содержит О объекта КоллекцияОбъектовМетаданных) или сравнить с конкретным объектом метаданных. Например, в процессе перебора движений документа тре- буется определить, к какому именно виду регистров отно- сится данная запись регистра. В этом случае для записи можно найти соответствующий объект метаданных и за- тем определить, в какую из коллекций объектов метадан- ных, описывающих регистры, входит полученный объект метаданных (листинг 3.8). Листинг 3.8. Пример использования метода СодержитО // В качестве примера выбирается первая // запись из первого набора записей, // содержащегося в движениях документа Движения = Документы. АвансовыйОтчет. НайтиПоНомеруС"ТК000009", '20040101000000'). ПолучитьОбъектО .Движения[0]; Движения.Прочитать(); ОбъектМетаданных = Метаданные. НайтиПоТипу(ТипЗнч(Движения[0])); Если Метаданные.РегистрыНакопления. Содержит(ОбъектМетаданных) Тогда СообщитьСЭто движения по регистру накопления"); ИначеЕсли Метаданные.РегистрыСведений. Содержит(ОбъектМетаданных) Тогда СообщитьСЭто движения по регистру сведений"); ИначеЕсли Метаданные.РегистрыБухгалтерии. Содержит(ОбъектМетаданных) Тогда СообщитьСЭто движения по регистру бухгалтерии"); ИначеЕсли Метаданные.РегистрыРасчета. Содержит(ОбъектМетаданных) Тогда СообщитьСЭто движения по регистру расчета"); КонецЕсли; Поскольку метаданные имеют иерархическую структуру, объект, полученный методом НайтиПоТипуО, не всегда мо- жет находиться в первом уровне иерархии нужной кол- лекции объектов метаданных. В этом случае можно ис- пользовать метод Родитель О объекта метаданных для того, чтобы получить объект, находящийся на нужном уровне иерархии. Например, если некоторая универсальная процедура об- рабатывает табличные части справочников по одному ал- горитму, а табличные части документов — по другому, то проанализировать принадлежность табличной части оп- ределенному виду метаданных можно следующим обра- зом (листинг 3.9). Листинг 3.9. Пример использования метода РодительО // В качестве примера получается табличная часть Товары // документа АвансовыйОтчет ТабличнаяЧасть = Документы.АвансовыйОтчет. НайтиПоНомеруС"ТК000009", '20040101000000').ПолучитьОбъект(). Товары; ОбъектМетаданных = Метаданные. НайтиПоТ ипу (ТипЗнч (Т абличнаяЧасть)). Родитель (); Если Метаданные.Справочники. Содержит(ОбъектМетаданных) Тогда СообщитьСЭто табличная часть справочника"); ИначеЕсли Метаданные.Документы. Содержит(ОбъектМетаданных) Тогда СообщитьСЭто табличная часть документа"); КонецЕсли; Как уже говорилось выше, коллекция объектов метадан- ных позволяет обращаться к объектам по имени или ин- дексу. Кроме этого, коллекция поддерживает итератор Для Каждого..., с помощью которого, например, может быть организован перебор всех элементов справочников, содержащихся в конфигурации (листинг 3.10). Листинг 3.10. Использование итератора Для Каждого Для Каждого Справочник из Метаданные.Справочники Цикл Сообщить (Сим волы. ПС + Справочник. ПолноеИмяО); МенеджерСправочника = Справочники[Справочник.Имя]; Выборка = МенеджерСправочника.Выбрать!); Пока Выборка.Следующий() Цикл Сообщить(Выборка.Наименование); КонецЦикла; КонецЦикла;
Глава 4. Работа с данными Объектные и необъектные данные Все данные, которые хранятся в базе данных 1С:Пред- приятия, можно разделить на две категории: объектные и необъектные данные. Поскольку природа этих данных различна, различаются и способы работы с объектными и необъектными данными. К объектным данным относятся данные справочников, документов, планов видов характеристик, планов счетов, планов видов расчета, бизнес-процессов, задач, планов обмена. К необъектным данным относятся данные регистров сведений, регистров накопления, регистров расчета, пе- рерасчетов, регистров бухгалтерии и последователь- ностей. Также к необъектным данным относятся кон- станты. С точки зрения системы, объектные данные состоят из отдельных объектов, каждый из которых обладает внут- ренним уникальным идентификатором, благодаря нали- чию которого к некоторой совокупности значений, храня- щихся в базе данных, можно обращаться как к единому целому — объекту. Например, объектом является элемент справочника или документ. Каждый объект, помимо того, что он является совокупностью значений некоторых по- лей, имеет также определенную значимость сам по себе. Например, элемент справочника ФизическиеЛица — это некое физическое лицо, которое имеет набор характери- зующих его значений: имя, фамилия, отчество, паспорт- ные данные и т. д. У него может поменяться, например, фамилия, или паспортные данные, но при этом он оста- нется тем же самым физическим лицом — объектом, — с точки зрения системы. Удаление какого-либо объекта из системы приводит к тому, что состояние базы данных, с точки зрения прикладного решения, изменяется. Да- же создав новый элемент справочника ФизическиеЛица с теми же самыми значениями реквизитов, мы получим уже другое состояние базы данных, поскольку это будет уже другой объект с другим уникальным идентифика- тором. В отличие от объектных данных, необъектные данные не имеют собственной ценности и полностью описываются значениями своих полей. Необъектные данные представ- ляют собой записи, которые хранятся в базе данных. Для записей не поддерживаются внутренние уникальные иден- тификаторы. Удалив некоторую запись и создав новую, с точно такими же значениями полей, мы получим то же самое состояние базы данных, которое было до удаления записи. Рассмотрим работу с объектными и необъектными дан- ными более подробно. Объектные данные Модель хранения данных К объектным данным в 1С:Предприятии относятся дан- ные следующих объектов конфигурации: ♦ Справочник; ♦ Документ; ♦ План видов характеристик; ♦ План счетов; ♦ План видов расчета; ♦ План обмена; ♦ Бизнес-процесс; ♦ Задача. Для каждой объектной сущности конфигурации система создает набор связанных между собой таблиц, в которых и будут храниться данные этого объекта. Количество и состав таблиц различны для каждого объекта метадан- ных. Структура хранения объектных данных всегда состоит из основной таблицы и, возможно, нескольких других таб- лиц (по одной таблице на каждую табличную часть объ- екта). Например, для документа Доверенность, который имеет некоторый набор реквизитов и табличную часть То- вары (рис. 4.1), в базе данных будут созданы две таблицы. Рис. 4.1. Документ Доверенность
Таблица документа будет содержать поля для каждого реквизита документа, а для табличной части будет созда- на отдельная таблица, содержащая поля для всех рекви- зитов табличной части документа (рис. 4.2). Таблица документа -Доверенность* номер организация ФизЛицо 0x803650505450303011DA147DCE8D66E9 09.08.2004 12:00:00.000 TKD00003 Торговьй дом "Комплексный" Бахшиев П. И. тически такое значение представляет собой внутренний идентификатор, который хранится в поле Ссылка таблиц базы данных. Например, справочник Валюты хранится в базе данных в таблице, которая, помимо служебных колонок, содер- жит отдельные колонки для каждого реквизита справоч- ника, заданного в конфигураторе. Поле Ссылка — это одно из служебных полей. Значение этого поля позволяет од- нозначно отличить один элемент справочника от другого (проще говоря, одну валюту от другой) (рис. 4.3). товара Табличная часть "Товары" документа “Доверенность" Ссыпка Единица по классификатору Количество 0x803650505450303011DA147DCE8D66E9 1 Ассорти (конфеты) упак 10 0x803650505450303011DA147DCE8DB6E9 2 Барбарис (конфеты) кг 10 0x803650505450303011DA147DCE8D66E9 3 Белочка (конфеты) кг 10 0x803650505450303011DA147DCE8D66E9 4 Грильяж (конфеты) кг 10 Рис. 4.2. Таблицы документа Доверенность Отличительной особенностью этих таблиц является то, что каждая из них содержит поле Ссылка, в котором хранится внутренний идентификатор, соответствующий каждому из документов. Таким образом, объект документа представля- ет собой совокупность записи основной таблицы и строк табличных частей, относящихся к этому документу. Основная таблица объектных данных также содержит обя- зательное поле, в котором хранится текущая версия объек- та. Значение этого поля изменяется при каждой записи данных объекта в базу данных. Благодаря использованию этого поля обеспечивается оптимистическая блокировка объектных данных. Подробнее про оптимистическую бло- кировку объектных данных можно прочитать в разделе «Оптимистическая блокировка», с. 44. Для работы с объектными данными во встроенном языке существует два основных типа: ссылка и объект. Рассмот- рим каждый из них более подробно. Ссылка Значение ссылочного типа (СправочникСсылка.<имя>, Доку- нентСсылка.<иня> и т. д.) используется везде, где требуется однозначно идентифицировать объект базы данных. Фак- Ссылка Пометка удаления Код Наименован. Наименование полное 0x848A00112F43529A11D955BCBD72D8F9 Ложь Ложь 810 руб. Российский рубль 0x848A00112F43529AHD955eCBD72D8FA Ложь Ложь 840 USD Доллар США 0x848AQ0112F43529A110955В CCS CF4923 Ложь Ложь 978 EUR ЕВРО Ох848А00112F43529A11D955BD0E617614 Ложь Ложь 792 TRL Турецкая лира 0х848А00112F43529A11D9558D0E617615 Ложь Ложь 001 у.е. Условная единица Рис. 4.3. Поле Ссылка Значение ссылки может, например, выбираться в полях ввода, храниться в полях других таблиц базы данных и т. д. Например, поля Организация и ФизЛицо документа Доверенность будут хранить ссылки на элементы справоч- ников «Организации» и ФизическиеЛица (рис. 4.4). Значения ссылочного типа можно сравнивать между со- бой. Важным моментом является то, что для каждого объ- екта метаданных во встроенном языке создается свой тип ссылки. Таким образом, например, ссылка на справочник Организации никогда не будет равна ссылке па справочник ФизическиеЛица, поскольку это значения разных типов. Однако две ссылки на справочник Организации могут быть равны между собой, и это будет выполняться только в том случае, если это ссылки на один и тот же объект базы данных (рис. 4.5). Ссылки, указывающие на один и тот же объект базы дан- ных, будут равны между собой независимо от того, каким образом они получены. Например, ссылка на валюту с ко- дом 810 (рубли), полученная через менеджер справочни- ка Валюты, будет равна ссылке на эту валюту, полученную из выборки справочника Валюты (листинг 4.1). Таблица справочника "Организацкм" Рис 4.4. Хранение ссылок в полях базы данных
Объект СправочникСсы л ка. Организации Объект СправочникСсылка. Организации Рис. 4.5. Сравнение объектов Ссылка Листинг 4.1. Сравнение объектов Ссылка Ссылка! = Справочники.Валюты.НайтиПоКодуС'ВЮ"); ВыборкаВалют = Справочники.Валюты.Выбрать О; Пока ВыборкаВалют.Следующий() Цикл Если Ссылка! = ВыборкаВалют.Ссылка Тогда Сообщить!"" + ВыборкаВалют.Код + ” ” + ВыборкаВалют. Наименование); КонецЕсли; КонецЦикла; Типы ссылок имеют значение по умолчанию — так назы- ваемую пустую ссылку. Пустая ссылка — это значение ссылки, которому не соответствует ни один объект в базе данных. Фактически такой внутренний идентификатор выглядит следующим образом: 00000000-0000-0000-0000-000000000000 Так как тип ссылки создается для каждого объекта мета- данных, то, например, пустые ссылки на разные справоч- ники, никогда не будут равны между собой (листинг 4.2). Листинг 4.2. Сравнение пустых ссылок ПустаяСсылкаНоненклатура = Справочники.Номенклатура. ПустаяСсылкаО; ПустаяСсылкаКонтрагенты = Справочники.Контрагенты. ПустаяСсылкаО; Если ПустаяСсылкаНоненклатура <> ПустаяСсылкаКонтрагенты Тогда Сообщить("Ссылки не равны."); КонецЕсли; Ссылка позволяет обращаться к свойствам объекта базы данных, а также получать сам объект. При этом выполня- ется чтение информации из базы данных, поскольку сама ссылка не содержит этих данных. Подробнее об этом можно прочитать в разделе «Объект», с. 39 . Представление ссылочных значений Поскольку ссылочные значения могут выбираться в поле ввода и использоваться в других элементах интерфейса системы, существует механизм формирования представ- лений ссылочных значений. Благодаря этому механизму пользователь может оперировать не безличными внут- ренними идентификаторами, которые содержит ссылка, а вполне определенными и понятными ему данными, идентифицирующими объекты базы данных. При добавлении объектов конфигурации система само- стоятельно определяет правила формирования представле- ний ссылочных значений, и от разработчика не требуется никаких специальных действий. Однако при необходи- мости, он может внести изменения в правила формирова- ния представлений для ссылок на некоторые типы объек- тов базы данных. Например, для элементов справочников, видов характе- ристик, счетов, видов расчетов и узлов планов обмена представление ссылок может быть задано либо в виде кода, либо в виде наименования (рис. 4.6). Рис. 4.6. Задание представления справочника Для задач разработчик может выбрать между представле- нием ссылок в виде номера или наименования (рис. 4.7). Рис. 4.7. Задание представления задачи
А для документов и бизнес-процессов система предостав- ляет только единственное неизменяемое представление ссылочных значений в виде совокупности синонима до- кумента или бизнес-процесса и его даты. Например: «Приходная накладная от 03.05.2004 15:35:27». Контроль ссылочной целостности ЮПредприятие предоставляет разработчику возможность контролировать ссылочную целостность базы данных, однако использование этой возможности не является обязательным. С точки зрения платформы в базе данных вполне могут содержаться неразрешимые ссылки (то есть ссылки на объекты, которых не существует в базе дан- ных), и это не является ошибкой. Необходимость поддер- жания ссылочной целостности базы данных определяет- ся логикой прикладного решения, и ситуация, когда база данных содержит ссылки на несуществующие объекты, может быть вполне допустимой для данного конкретного прикладного решения. Вопрос о необходимости контроля ссылочной целостно- сти возникает при удалении данных из базы данных. Сис- тема позволяет гибко использовать возможности контро- ля ссылочной целостности как при интерактивном, так и при программном удалении объектов. Интерактивное удаление объектов может быть выполне- но двумя способами. Во-первых, объект может быть удален непосредственно из базы данных, и в этом случае не будет выполняться ника- ких проверок ссылочной целостности, и последующее восстановление объекта будет невозможно. Возможность непосредственного интерактивного удаления регулирует- ся правом Интерактивное удаление. Во-вторых, интерактивное удаление может быть выпол- нено с использованием механизма контроля ссылочной целостности. В этом случае удаление выполняется в два этапа: сначала пользователь устанавливает пометку уда- ления для тех объектов, которые он собирается удалить, а затем выполняет процедуру удаления помеченных объ- ектов. При этом сначала будет выполнен поиск ссылок па удаляемые объекты в других данных, а затем для объек- тов, ссылки на которые отсутствуют, будет выполнено удаление. При удалении объектов средствами встроенного языка также существует возможность использовать или не ис- пользовать контроль ссылочной целостности. Непосред- ственное удаление объектов может быть выполнено мето- дом объекта Удалить(), в то время как пометка на удаление может быть установлена с помощью метода объекта Уста- новитьПометкуУдаленияО. Последующий поиск помеченных на удаление объектов может быть выполнен при помощи функции глобального контекста НайтиПомеченныеНаУдале- ние(), а их удаление — глобальной процедурой УдалитьОбъ- ектыО, которая позволяет удалять объекты как с контро- лем ссылочной целостности, так и без. При этом следует учитывать, что удаление с контролем ссылочной целост- ности выполняется в монопольном режиме. При необходимости может быть выполнен отдельно только поиск ссылок на удаляемые объекты — для этого используется функция глобального контекста НайтиПо- СсылкамО, которая возвращает список найденных ссылок на переданные ей объекты. Особенности использования пометки удаления Для того чтобы отличить объекты, помеченные на удале- ние, от других объектов базы данных, таблицы, хранящие данные этих объектов, содержат специальное поле Помет- каУдаления. Значение этого поля может быть установлено двумя способами. Во-первых, может использоваться интерактивная уста- новка пометки удаления или программное выполнение метода объекта УстановитьПонеткуУдаления(). В этом случае, кроме собственно установки значения этого поля, будет выполнен ряд дополнительных действий, состав которых зависит от типа помечаемого объекта. Например, для справочника будет установлена пометка удаления для всех подчиненных элементов этого справочника и подчи- ненных справочников, для документа будет выполнена отмена проведения и т. д. Также будет вызвано событие объекта ПередЗаписькК), поскольку будет выполняться сохра- нение измененного свойства ПонеткаУдаления этого объекта. Во-вторых, значение поля ПонеткаУдаления может быть уста- новлено путем непосредственной установки свойства По- меткаУдаления объекта и последующей его записи. В этом случае никаких дополнительных действий выполняться не будет, однако следует учитывать особенности работы некоторых объектов. Например, документ не может быть одновременно проведен и помечен на удаление, поэтому, если требуется пометить на удаление проведенный доку- мент, предварительно следует установить его свойство Проведен в значение Ложь или выполнить отмену проведе- ния документа (Записать(РежинЗаписиДокунента.0тненаПрове- дения)). Объект Тип объекта служит, прежде всего, для модификации (чтения и изменения) данных, содержащихся в объекте базы данных. Остальные объекты встроенного языка по- зволяют только читать информацию базы данных. Как уже говорилось ранее, объект представляет собой со- вокупность записи основной таблицы и строк табличных частей, относящихся к этому объекту. Например, рас- смотрим документ ЗаказПоставщику, имеющий три таб- личных части (рис. 4.8). Конфигурация » X ДйЬви. > t t | Ц u.« ЗаказПоставщику I ; Bg Реквизиты В =:ji Табличные части I I i E Товары * В Ш! ВозвратмаяТара Е Услуги ф В Q Формы ! | В Q Макеты v Рис. 4.8. Документ ЗаказПоставщику Объект документа (ДокументОбъект.ЗаказПоставщику) будет представлять собой совокупность значений полей основ- ной таблицы документа и полей каждой из таблиц, в ко- торых хранятся данные его табличных частей (рис. 4.9). Тип объекта используется при создании новых объектов, для редактирования и удаления существующих объектов. Кроме этого, тип объекта используется для отображения
и редактирования всех данных объекта в форме объекта. Также этот тип используется при редактировании строки списка объекта. Значения этого типа, так же как и значения ссылок, мож- но сравнивать между собой. Однако в отличие от ссылок, значения этого типа будут равны между собой только тогда, когда они являются одним и тем же экземпляром про- граммного объекта. Например, если в следующем примере (листинг 4.3) в пе- ременную 0бъект1 получить экземпляр программного объ- екта, соответствующий элементу справочника Номенклатура, и затем значение этой переменной присвоить переменной 0бъект2, то значения этих переменных будут равны. Листинг 4.3. Сравнение объектов 0бъект1 = Справочники.Номенклатура.НайтиПоКоду(1). ПолучитьОбъектО; Объект2 = Объект1; Сообщить(Объект1 = 0бъект2); Если же в переменные 0бъект1 и 0бъект2 получить экзем- пляры объекта, соответствующие одному и тому же эле- менту справочника Номенклатура, то значения этих пере- менных не будут равны, несмотря на то, что в них считан один и тот же объект базы данных и совпадают все дан- ные этого объекта (листинг 4.4). Листинг 4.4. Сравнение объектов 0бъект1 = Справочники.Номенклатура.НайтиПоКодуШ. ПолучитьОбъектО; Объект2 = Справочники.Номенклатура.НайтиПоКоду(1). ПолучитьОбъектО ; Сообщить(0бъект1 = 0бъект2); Значение типа объект может быть получено несколькими способами. Во-первых, значение этого типа может быть получено че- рез менеджер объекта, с использованием соответствую- щего метода (например, для справочников это метод Соз - датьЭлементО, для документов — СоздатьДокументО и т. д.). При этом будет создан новый экземпляр программного объекта, которому не соответствует ни один объект в базе данных. В дальнейшем, когда будет выполнена запись этого объекта, появится и новый объект в базе данных (рис. 4.10). Данные объекта Рис. 4.10. Создание нового объекта Во-вторых, значение этого типа может быть получено из ссылки, путем выполнения метода ПолучитьОбъектО. В этом случае будет создан экземпляр программного объекта и выполнено чтение данных из базы данных (или из кеша). При этом считываются значения всех реквизитов объекта и значения всех реквизитов всех его табличных частей (рис. 4.11). Рис. 4.11. Получение объекта В-третьих, значение этого типа может быть получено из выборки, путем выполнения метода с аналогичным на- званием — ПолучитьОбъектО. В этом случае также будет создан экземпляр программного объекта, однако чтения из базы данных выполняться не будет, так как выборка считывает из базы данных все данные объектов, и данные созданного экземпляра объекта будут заполнены непо- средственно из программного объекта выборки (рис. 4.12). Рис. 4.12. Получение объекта В связи с тем, что тип объекта позволяет модифициро- вать данные, он имеет (помимо свойств и методов) целый
ряд событий, позволяющих разработчику определять собственный алгоритм обработки выполняемых дейст- вий. Среди основных событий, поддерживаемых этим ти- пом, можно перечислить следующие события. ПередЗаписью — это событие возникает перед записью объ- екта в базу данных, до того, как начата транзакция записи. В обработчике этого события можно проанализировать необходимость (или возможность) выполнения записи данных и отказаться от нее, если какие-либо условия не выполняются. ПриЗаписи — это событие возникает после того, как данные записаны в базу данных, но до того, как окончится тран- закция записи. В обработчике этого события можно вы- полнять те действия, которые обязательно должны быть выполнены только в том случае, если объект записан. ПриКопировании — это событие возникает у нового объекта данных в том случае, если он создается путем копирова- ния (интерактивного или программного) существующего объекта данных. В обработчике этого события можно предусмотреть, например, алгоритм заполнения реквизи- тов создаваемого объекта по умолчанию. ОбработкаЗаполнения — это событие также возникает у но- вого объекта данных в том случае, если он создается путем ввода на основании (интерактивного или программного) существующего объекта данных. В отличие от копирова- ния, когда создаваемый и исходный объекты имеют оди- наковые типы, при вводе на основании новый объект, как правило, имеет тип отличный от типа объекта-основания. Например, новый документ может быть введен на основа- нии элемента справочника и т. д. Поэтому в обработчике этого события, как правило, предусматривается некото- рый алгоритм, позволяющий выполнять начальное за- полнение реквизитов нового объекта в зависимости от типа объекта-основания. ПередУдалением — это событие возникает перед непосредст- венным удалением объекта из базы данных. В обработчи- ке этого события можно предусмотреть выполнение ка- ких либо действий перед удалением объекта, а также, при необходимости, отменить удаление объекта, если не вы- полняются какие-либо условия. Кэширование представлений и объектов При работе с объектными данными (как программно, так и интерактивно) система выполняет кэширование считы- ваемых данных в оперативной памяти. Для этого исполь- зуется кэш объектов. При любых интерактивных дейст- виях и при программном доступе к объектным данным с использованием объектной модели прежде всего система будет выполнять обращение к кэшу объектов для того, чтобы получить запрашиваемые данные. Кэш объектов состоит из двух частей: транзакционного кэша и обычного кэша. В зависимости от того, происхо- дит ли чтение в рамках транзакции или нет, будет выпол- няться обращение к той или иной части кэша (рис. 4.13). В кэш объектов считываются два «вида» данных: либо все данные объекта целиком, либо значения полей, необходи- мые для формирования представления ссылки на данный объект. Значения полей, необходимые для получения представ- ления ссылки, считываются тогда, когда возникает необ- ходимость отобразить ссылку на объект в каком-либо элементе интерфейса, а также при явном или неявном преобразовании ссылочной переменной к типу Строка. В остальных случаях выполняется полное чтение всех данных объекта, в том числе и тогда, когда выполняется обращение к какому-либо реквизиту объекта через точку от ссылки. Чтение данных К Транзакция \ Да активна7 / Кэш объектов Обычный кз ш Рис. 4.13. Обращение к кэшу объектов Эту особенность нужно учитывать при проектировании структуры объектов метаданных. Так, например, если предполагается хранение в информационной базе карти- нок, образов файлов или больших текстовых данных, то рекомендуется создавать для этого отдельные структуры хранения (например, справочники или регистры сведе- ний), а не включать эту информацию в состав реквизитов или табличных частей объектов, которым эта информа- ция соответствует. Это позволит избежать считывания и записи больших объемов данных при работе с этими объ- ектами. Обычный кэш Если при обращении к обычному кэшу требуемых дан- ных в нем нет, то выполняется чтение данных объекта из базы данных и сохранение их в кэше. Уникальным иден- тификатором для кэша в данном случае будет являться ссылка на объект базы данных. Поэтому данные каждого считанного объекта могут существовать в кэше в одном из двух видов: либо все данные объекта, либо представле- ние объекта. Таким образом, если мы обратимся к кэшу для получения представления объекта и в кэше есть информация для на- шей ссылки, данные будут взяты из кэша (если в кэше весь объект, нужное представление будет получено из данных объекта). Если в кэше нет информации для на- шей ссылки — из базы данных в кэш будут считаны толь- ко поля, необходимые для формирования представления объекта. Если мы обратимся к кэшу для получения реквизита объ- екта (через точку от ссылки) и в кэше есть информация для нашей ссылки, дальнейшие действия будут зависеть от того, какие именно данные находятся в кэше. Если в кэше весь объект — значение реквизита будет получено из кэша. Если в кэше представление объекта — оно будет удалено из кэша и в кэш будут считаны все данные объек- та. Если же при получении реквизита объекта в кэше нет
информации для нашей ссылки — из базы данных будут считаны все поля объекта. Считанные данные будут находиться в кэше до тех пор, пока не наступит одно из четырех событий: ♦ считанные данные будут вытеснены из кэша другими считанными данными других объектов (переполнение кэша); ♦ при очередном обращении к кэшу окажется, что счи- танные данные были изменены в базе данных; ♦ закончится интервал времени в 20 минут; ♦ данные будут изменены в базе данных. Все считанные данные помещаются в последовательную очередь, и, поскольку объем кэша ограничен, наиболее старые данные будут вытесняться из кэша последними считанными данными. При повторном обращении к кэшу за данными уже счи- танного объекта будет анализироваться интервал време- ни, прошедший с момента появления данных в кэше. Если обращение происходит в пределах 20 секунд после поступления данных в кэш, данные считаются верными (валидными). Если интервал превысил 20 секунд, будет выполняться проверка на то, что версия данных, храня- щихся в кэше, соответствует версии данных, находящих- ся в базе данных. В случае если окажется, что версии дан- ных не совпадают (то есть произошло изменение данных в базе данных), данные, находящиеся в кэше, будут уда- лены из него и выполнено повторное считывание данных из базы данных. Начиная с этого момента, начнется от- счет следующего 20-секундного интервала валидности этих данных. Кроме всех вышеперечисленных событий, считанные дан- ные будут удалены из кэша по истечении 20 минут после их последнего считывания из базы данных. Рассмотрим последовательное выполнение двух операто- ров (листинг 4.5), где Номенклатура — это ссылка на объ- ект справочника, а Наименование и ВидНоменклатуры — ре- квизиты справочника Номенклатура. Листинг 4.5. Последовательное обращение к реквизитам объекта А = Номенклатура.Наименование; В = Номенклатура.ВидНоменклатуры; На выполнение второго оператора будет тратиться гораз- до меньше времени, поскольку в первом случае (с боль- шой долей вероятности) будет выполняться обращение к базе данных и чтение всех данных объекта, а во втором — чтение из оперативной памяти (кэша объектов). Транзакционный кэш Если обращение к данным происходит в рамках транзак- ции, то оно переадресуется транзакционному кэшу. Тран- закционный кэш, по сути, представляет собой ту же последовательную очередь, что и обычный кэш, за исклю- чением того, что все данные, находящиеся в транзакцион- ном кэше, являются валидными (гарантированно акту- альными). При считывании данных в транзакционный кэш устанавливается блокировка на данные в базе дан- ных, поэтому они гарантированно не могут быть измене- ны до окончания транзакции. Транзакционный кэш хранит считанные данные до тех пор, пока они не будут вытеснены более поздними счи- танными данными, или пока не закончится транзакция. По окончании транзакции транзакционный кэш очищает- ся, однако действия, выполняемые при этом, зависят от состояния завершения транзакции. Если транзакция завершена успешно (Commit), данные всех объектов, содержащиеся в транзакционном кэше, пе- реносятся в обычный кэш, а транзакционный кэш очища- ется (рис. 4.14). Рис. 4.14. Успешное завершение транзакции Если был выполнен отказ от изменений (Rollback), то просто очищается транзакционный кэш (рис. 4.15). Рис. 4.15. Откат транзакции Оптимизированная запись объектов При записи объектов базы данных (программной или ин- терактивной) выполняется оптимизация записи измене- ний в базу данных. Так, например, если не менялись значения реквизитов са- мого объекта, то будет записана только минимальная ин- формация об изменении (версия объекта). Если не менялись строки табличной части, то табличная часть записываться не будет. Если менялись только отдельные строки табличной части или добавлялись новые строки, то будут записаны только измененные и добавленные строки. Однако если менялся порядок строк или строки удалялись, то будут записаны все строки табличной части. Создание новых объектов Зачастую при разработке или модификации прикладных решений требуется выполнять некоторые действия, со- провождающие создание тех или иных новых объектов базы данных. Например, при создании новой приходной накладной может потребоваться автоматически запол- нять поле Склад, если известно, что все поступающие то- вары должны приходоваться только на один определен- ный склад. Также может потребоваться установка каких- либо других реквизитов документа по умолчанию.
При решении подобных задач следует иметь в виду, что логика системы разделяет такие понятия, как ввод нового объекта пользователем и создание нового объекта базы данных. Одним из следствий этого является отсутствие какого-либо события, вызываемого при создании нового объекта, которое может быть обработано в модуле объек- та. Система не предоставляет разработчику возможность анализа момента создания нового объекта. Дело в том, что создание нового объекта базы данных не всегда представляет собой ввод новой информации в сис- тему. Например, в процессе обмена данными может вы- полняться создание нового объекта базы данных узла. С точки зрения бизнес-логики прикладного решения при этом не происходит ввода новой информации в систему, поскольку эта информация уже присутствует в системе (только в другом узле). С другой стороны, ввод новой информации, как правило, выполняется при вводе новых объектов пользователем. И как раз в этих ситуациях требуется выполнять дейст- вия, например, по инициализации каких-либо реквизитов объекта. Учитывая приведенные выше соображения, рекоменду- ется обрабатывать создание новых объектов следующим образом. Если при вводе новой информации в систему и создании нового объекта требуется выполнять какие-ли- бо действия по инициализации реквизитов объекта, эти действия необходимо выделять отдельной экспортной процедурой в модуле объекта и вызывать эту процедуру в явном виде в тех ситуациях, когда это необходимо. Например, поскольку ввод информации пользователем осуществляется при помощи форм объектов, то в модуле формы объекта в процедуре ПередОткрытиемО можно ана- лизировать значение метода ЭтоНовыйО объекта и в явном виде вызывать созданную процедуру. Аналогичным обра- зом, если логика прикладного решения подразумевает, что при создании и записи нового объекта программно, без участия пользователя, должны быть проинициализи- рованы реквизиты объекта, то разработчик самостоятель- но должен обрабатывать такие ситуации и явно вызывать созданную процедуру модуля объекта. Блокировки При работе с объектными данными система обеспечивает два вида блокировок — пессимистическую и оптимисти- ческую, — которые позволяют выполнять целостные из- менения объектов при одновременной работе нескольких пользователей. Пессимистическая блокировка Механизм пессимистической блокировки запрещает из- менение данных объекта другими сессиями или данной сессией до тех пор, пока блокировка не будет снята этим объектом встроенного языка (рис. 4.16). Механизм пессимистической блокировки используется системой 1 С: Предприятие для блокировки объектов, ре- дактируемых в форме. В то же время разработчик также имеет возможность задействовать этот механизм, исполь- зуя средства встроенного языка. Если говорить о системе, то механизмом пессимистиче- ской блокировки управляют расширения форм приклад- ных объектов. В тот момент, когда пользователь начинает модификацию объекта в форме, расширение формы уста- навливает пессимистическую блокировку. Если после этого другой пользователь, например, попытается выпол- нить редактирование того же объекта, ему будет выдано сообщение о том, что не удалось заблокировать объект. Когда пользователь, редактировавший объект, закроет форму объекта, расширение формы снимет пессимисти- ческую блокировку. Рис. 4.16. Пессимистическая блокировка Разработчик, для того чтобы задействовать пессимисти- ческую блокировку, может использовать метод объекта Заблокировать). Этот метод позволяет установить песси- мистическую блокировку объекта и тем самым запретить изменение данных объекта базы данных другими сессия- ми 1 С: Предприятия и другими алгоритмами в текущей сессии, до тех пор пока блокировка не будет снята. Для снятия пессимистической блокировки разработчик мо- жет использовать метод объекта Разблокировать!). Также существует метод объекта Заблокирован!), который позволяет определить, заблокированы ли данные объекта базы данных этим объектом встроенного языка. При работе с пессимистической блокировкой из встроен- ного языка следует помнить о том, что блокировка уста- навливается при выполнении метода конкретного экзем- пляра объекта встроенного языка. Соответственно, снять блокировку можно, только выполнив соответствующий метод этого же экземпляра объекта. Если необходимо узнать, установлена ли блокировка на данные объекта или нет, нужно использовать метод Забло- кировать!). В случае если блокировка уже установлена ка- ким-либо объектом встроенного языка, будет вызвано ис- ключение (листинг 4.6). Листинг 4.6. Пример проверки пессимистической блокировки 0бъектЭкземлляр1 = Справочники.Номенклатура.НайтиПоКоду(1). ПолучитьОбъектО; 0бъектЭкзенпляр2 = Справочники.Номенклатура.НайтиПоКоду(1). ПолучитьОбъектО: 0бъектЭкземпляр1.Заблокировать(); Попытка 0бъектЭкземпляр2.Заблокировать(); Исключение Сообщить("Данные объекта уже заблокированы"); КонецПопытки; В приведенном примере создается два экземпляра одного и того же объекта — СправочникОбъект.Номенклатура, кото- рые содержат данные элемента справочника Номенклатура, имеющего код 1. После этого первый экземпляр объекта
устанавливает пессимистическую блокировку на данные объекта. Если в этой ситуации для второго экземпляра объекта выполнить метод Заблокировано, то он вернет зна- чение Ложь, так как блокировка была наложена первым эк- земпляром объекта. Однако если, в свою очередь, попы- таться выполнить метод Заблокировать О и для второго экземпляра объекта, то будет выдано сообщение о невоз- можности установить блокировку (так как данные объек- та уже заблокированы первым экземпляром объекта). Оптимистическая блокировка Оптимистическая блокировка запрещает запись объекта в базу данных, если после считывания объекта он был из- менен в базе данных (рис. 4.17). Рис. 4.17. Оптимистическая блокировка Строго говоря, оптимистическая блокировка представляет собой проверку, которая выполняется перед записью объ- екта в базу данных. Когда программный объект считыва- ет данные из базы данных, в числе прочего считывается и версия объекта, хранящегося в базе данных. Предполо- жим, что до начала редактирования данных (до установ- ки пессимистической блокировки) данные объекта в базе данных были изменены (например, другим пользовате- лем). В этом случае номер версии объекта, хранящийся в базе данных, также изменится. При попытке первого пользователя записать или заблокировать этот объект будет выполнена проверка соответствия версии объекта, находящегося в памяти, и версии объекта, хранящейся в базе данных. Так как версии отличаются, будет выдано сообщение об ошибке, то есть сработает оптимистическая блокировка. Оптимистическая блокировка гарантирует, что если поль- зователь изменяет объект, то его изменения не «затрут» изменения, сделанные другими сессиями или другими программными объектами в этой же сессии. Объектные блокировки и транзакции Важным моментом является то, что пессимистическая и оп- тимистическая блокировки обеспечиваются не средствами базы данных, а средствами собственного менеджера блоки- ровок, который работает «над уровнем» базы данных. По этой причине объектные блокировки абсолютно про- зрачны для транзакций. Единственная особенность за- ключается в том, что если пессимистическая блокировка была установлена в транзакции и в результате был вы- полнен откат этой транзакции (rollback), то блокировка будет автоматически снята. Подробнее о транзакциях можно прочитать в разделе «Транзакции», с. 70. Необъектные данные Модель хранения данных К необъектным данным в 1 С: Предприятии относятся данные следующих объектов конфигурации: ♦ регистр сведений; ♦ регистр накопления; ♦ регистр бухгалтерии; ♦ регистр расчета; ♦ перерасчет; ♦ последовательность; ♦ константа. Необъектные данные с точки зрения 1С:Предприятия представляют собой некоторый набор записей, которые хранятся в таблице. Каждая из этих записей полностью описывается значениями своих полей. Для системы эти записи не обладают какой-либо значимостью, кроме того, что в их полях содержатся некоторые значения. Запись можно удалить, а затем создать новую, с такими же значе- ниями полей. Состояние базы данных при этом не изме- нится (с точки зрения логики прикладного решения). Это принципиально отличает необъектные данные от объект- ных: объект нельзя создать дважды, он ценен сам по себе, самим фактом своего существования. Второе важное отличие заключается в том, что, изменив значения полей записи, мы получаем другую запись, в то время как изменение значений полей объекта не влечет за собой появление нового объекта. Объект всегда обладает некоторой «самостью», которая не зависит от значений его полей. Большинство необъектных сущностей конфигурации име- ют общий порядок работы с данными. Из всей совокупно- сти необъектных сущностей выделяются только констан- ты: для каждой константы в базе данных хранится одно значение. Поэтому в дальнейшем мы их рассматривать не будем; работа с ними не вызывает сложностей. Подчинение регистратору Важным свойством всех записей является их подчинение регистратору. Регистратор — это некоторый документ, с которым связаны записи необъектных данных. Не может существовать записей, не относящихся к какому-либо ре- гистратору. Исключение составляет лишь регистр сведе- ний, когда для него выбран независимый режим записи (без подчинения регистратору). Поэтому любая запись всегда содержит обязательное поле Регистратор (рис. 4.18). Записи, относящиеся к одному регистратору, называются движениями этого регистратора. Движения не являются частью владеющего ими документа, при записи и чтении документа они не записываются и не считываются. Одна- ко они тесно связаны с ним. Движения могут создаваться при проведении документа, могут удаляться при отмене проведения документа. Кро- ме этого, при удалении документа его движения всегда удаляются. Таким образом, время жизни записей опреде- ляется их регистратором: если регистратора нет, то и нет смысла в существовании его движений. Даже в том слу- чае, когда записи создаются без непосредственного уча- стия регистратора, они все равно обязательно должны
быть подчинены какому-либо документу; запись нельзя Наличие или отсутствие движений не связано с прове- денностью регистратора или с пометкой его на удаление: непроведенный документ может иметь движения, прове- денный документ может не иметь движений, помеченный на удаление документ также может иметь движения. Та- кой подход позволяет реализовывать в системе ЮПред- приятие различные способы регистрации изменений в учетных механизмах (регистрах). Например, движения документа могут редактироваться непосредственно в самом документе, и в этом случае по- нятие проведения документа просто не имеет смысла. Та- кой прием используется при автоматизации бухгалтер- ских задач, для ручного ввода проводок. Также дата движений документа не связана жестко с да- той регистратора. Например, один и тот же документ мо- жет иметь движения разными датами. Эта возможность используется, например, при автоматизации задач плани- рования, для ввода тех или иных планируемых в будущем значений. Наиболее простой моделью использования регистров яв- ляется создание движений в обработчике проведения ре- гистратора. В этом случае вся остальная логика работы будет поддерживаться системой автоматически. Другие варианты взаимодействия движений и регистратора сле- дует разрабатывать и описывать самостоятельно, в зави- симости от конкретной прикладной задачи. Уникальность записей Для каждого объекта метаданных в системе определен ключ записи. Данные объекта конфигурации не могут со- держать записи с одинаковыми значениями ключа записи. Ключ записи формируется, как правило, из значений не- скольких полей объекта конфигурации. Для разных объ- ектов конфигурации состав ключа записи отличается, кроме этого, он может быть различным для одного и того же объекта конфигурации, в зависимости от его свойств. Для всех необъектных сущностей, подчиненных регист- ратору, ключ записи включает ссылку на регистратор и номер строки. Номер строки собственно и используется для обеспечения уникальности записей, а также для упо- рядочивания записей в пределах регистратора. Кроме этого, в состав ключа записи могут входить и другие поля, например период, измерения регистра — для необъ- ектных сущностей, не подчиненных регистратору. Наличие уникального ключа требуется системе для реше- ния различных задач. Например, это позволяет позицио- нироваться в табличном поле на некоторую запись. Набор записей По аналогии с объектными данными, изменение которых возможно только при помвщи типов объектов, наборы за- писей используются для модификации необъектных дан- ных: они позволяют читать, модифицировать и удалять необъектные данные. По своей сути набор записей пред- ставляет собой коллекцию отдельных записей, принадле- жащих некоторому объекту конфигурации. В зависимости от объекта конфигурации набор записей может содержать только некоторые или же все записи, принадлежащие этому объекту конфигурации. Для ука- зания того, какие именно записи должны входить в набор записей, используется его свойство Отбор. Элементы от- бора в наборе записей для того или иного объекта конфи- гурации создаются платформой; разработчик не имеет возможности добавлять собственные элементы отбора, но может использовать существующие, устанавливая для них условия равенства нужному значению. В табл. 4.1 представлен состав отбора в наборе записей для различ- ных объектов конфигурации. Таблица 4.1. Поля, по которым устанавливается отбор Объект конфигурации Поля, по которым устанавливается отбор Регистр сведений (подчиненный регистратору) Регистратор Регистр сведений (непериодический, независимый) Набор измерений Регистр сведений ( периодический, независимый) Период и набор измерений Регистр накопления Регистратор Регистр бухгалтерии Регистратор Регистр расчета Регистратор и набор измерений Перерасчет Объект перерасчета (регистра- тор регистра расчета) и набор измерений перерасчета Последовательность Регистратор Существует следующая особенность работы системы с на- борами записей: если среди элементов отбора существует отбор по регистратору, то он должен обязательно быть ус- тановлен, иначе при записи такого набора будет выдано сообщение об ошибке. Отсюда следует, что для большин- ства объектов конфигурации, которые хранят необъектные данные, допускается модификация этих данных только час- тями, «гранулами» — наборами записей, относящихся к определенному регистратору (или более мелкими, если есть возможность установки других отборов). Наряду с этим для независимых регистров сведений допускается модификация сразу всех данных, хранящихся в регистре (если ни одно из условий отбора не задано).
Номенклатура Характеристика Комплектующая Количество Отбор: истика = DURON 1600 Компьютер AMD К7-2200 Клавиатуре 1 Характер Компьютер AMD К7-2200 Мышь 1 Компьютер AMD К7-2200 Системный блок 1 Компьютер AMD K7-2200 Монитор 1 >-► Отбор не установлен Компьютер DURON 1600 Монитор 2 Компьютер DURON 1600 Клавиатура 1 Компьютер DURON 1600 Модем 1 Компьютер DURON 1600 Мышь 1 Запись с замещением Компьютер DURON 1600 Системный блок 1 Компьютер DURON 1600 Монитор 1 Номенклатура Характерист Комплектующая Количество Компьютер AMD К7-2200 Клавиатура 1 Номенклатура Характеристика Комплектующая Количество Компьютер AMD К7-2200 Мышь 1 Компьютер AMD K7-2200 Клавиатура 1 Компьютер AMD K7-2200 Системный блок 1 Компьютер AMD K7-2200 Мышь 1 Компьютер AMD K7-2200 Монитор 1 Компьютер AMD K7-2200 Системный б лок 1 Компьютер DURON 1600 Клавиатура 1 Компьютер AMD K7-2200 Монитор 1 Компьютер DURON 1600 Мышь 1 Компьютер DURON 1600 Клавиатуре 1 - Отбор Компьютер DURON 1600 Системный блок 1 Компьютер DURON 1600 Мышь 1 Компьютер DURON 1600 Монитор 1 Компьютер DURON 1600 Системный блок 1 Компьютер DURON 1600 Монитор 1 Номенклатура Характерист . Комплектующая Количество Номенклатура Характеристика Комплектующая Количество Компьютер AMD K7-2200 Клавиатура 1 Компьютер AMD K7-2200 Клавиатура 1 Компьютер AMD K7-2200 Мышь 1 Компьютер AMD K7-2200 Мышь 1 Компьютер AMD K7-2200 Системный блок 1 Отбор Номенклатура = Компьютер Комплектующая = Мышь Компьютер AMD K7-2200 Системный блок 1 Компьютер AMD K7-2200 Монитор 1 Компьютер AMD K7-2200 Монитор 1 Компьютер DURON 1600 Клавиатура 1 Компьютер DURON 1600 Монитор 2 Компьютер DURON 1600 Мышь 1 Компьютер DURON 1600 Модем 1 Компьютер DURON 1600 Системный блок 1 добавлением Компьютер DURON 1600 Монитор 1 Рис. 4.21. Запись с Набор записей База данных до записи База данных после записи Рис. 4.19. Примеры наборов записей Регистратор Физическое лицо Организация Результат Отражение зарплаты 04-00001 от 31.01.2005 Алинов Станислав Иванович ЗАО Станкоимпорт 9840 Отражение зарплаты СИ-00001 от 31.01.2005 Васьков Ринат Леонтьевич ЗАО Станкоимпорт 1754,67 Отражение зарплаты СИ-00001 от 31.01.2005 Гостев Андриан Вячеславович ЗАО Станкоимпорт 6820 Отражение зарплаты ДС-00001 от 31.01.2005 Васьков Ринат Леонтьевич ООО Домстрой 2520 Сдельный наряд СИ-00001 ат 26.01.2005 Рулев Александр Алексеевич ЗнО Станкоимпорт #200 Сдельный наряд СИЧЮ001 от 26.01.2005 Матавии Михаил Якубович ЗАО Станкоимпорт 2800 дельный наряд 04-00001 от 6.01.2005 Петряков Искандер Якубович ЗАО Станкоимпорт 9® Сдельный наряд ДС-00002 от 26-01.2005 Ханафеев Виталий Зиновьевич ООО Домстрой 3400 Отбор Характеристика - DURON 1600 Компьютер DURON 1600 Модем 1 Компьютер DURON 1600 Сканер 1 Компьютер DURON 1600 Принтер 1 Запись с добавлением Набор записей Отбор: Регистратор = Сдельный наряд СИ-00001 от 26.01.2005 Рис. 4.20. Примеры наборов записей Номенклатура Характерист. Комплектующая Количество Компьютер AMD К7-2200 Клавиатура 1 Компьютер AMD К7-2200 Мышь 1 Компьютер AMD К7-2200 Системный блок 1 Компьютер AMD K7-2200 Монитор 1 Компьютер DURON 1600 Клавиатура 1 Компьютер DURON 1600 Мышь 1 Компьютер DURON 1600 Системный блок 1 Компьютер DURON 1600 Монитор 1 Б аза данных до записи Регистратор Сдельный нар СИ-00001 О1 Алексеевич Номенклатура Характерист Комплектующая Количество Компьютер AMD К7-2200 Клавиатура 1 Компьютер AMD К7-2200 Мышь 1 Компьютер AMD К7-2200 Системный блок 1 Компьютер AMD K7-2200 Монитор 1 Компьютер DURON 1600 Клавиатура 1 Компьютер DURON 1600 Мышь 1 Компьютер DURON 1600 Системный блок 1 Компьютер DURON 1600 Монитор 1 Компьютер DURDN 1600 Модем 1 Компьютер DURON 1600 Сканер 1 Компьютер DURON 1600 Принтер 1 База данных после записи Рис. 4.22. Запись с добавлением Например, для независимого регистра сведений Комплек- тующие номенклатуры набор записей может включать в се- бя как все записи регистра (если отбор не установлен), так и лишь некоторые его записи (рис. 4.19). В то же время для регистра расчета Основные начисления, у которого обязательно должен быть установлен отбор по регистратору, набор записей может включать в себя мак- симум все записи, принадлежащие одному регистратору, или некоторое их подмножество (рис. 4.20).
Отличительной особенностью наборов записей является то, что для них не существует понятия удаления. Набор записей можно только записать, причем запись может быть выполнена либо с замещением существующих запи- сей, удовлетворяющих отбору, либо с добавлением новых записей к существующим. При записи с добавлением новые записи будут добавле- ны к существующим (рис. 4.21). При записи с замещением существующие записи будут заменены новыми (рис. 4.22). Таким образом, для удаления записей необъектных дан- ных необходимо просто записать с замещением пустой набор записей (то есть набор записей, не содержащий ни одной записи). Набор записей представляет собой коллекцию объектов, имеющих тип записи. Перебрать все записи, входящие в набор записей, можно с помощью конструкции Для Каждо- го Из ... Цикл. Тип записи используется только в наборах записей. Отдельно от наборов записей этот тип не ис- пользуется. Основное назначение этого типа — предоста- вить доступ к значениям полей записи. Интерактивное редактирование наборов записей Для необъектных данных не существует механизма, ана- логичного объектным блокировкам (оптимистической и пессимистической). Поэтому при использовании набо- ра записей для интерактивного редактирования следует учитывать, что в период после считывания данных из базы данных и перед записью их обратно в базу данных они могут быть изменены в базе данных другой сессией или другим набором записей в этой же сессии. Таким образом, может возникнуть ситуация, когда изме- нения, внесенные одним пользователем, могут быть поте- ряны в результате того, что второй пользователь переза- пишет их старыми данными. Система типов Типы значений и типы данных Прикладное решение ЮПредприятия оперирует раз- личными величинами: числами, символами, объектами. Каждая величина имеет тип. Тип величины определяет возможные значения и набор определенных для них опе- раций. Существуют типы, определенные на уровне системы, и типы, создаваемые в конкретном прикладном решении. Например, на уровне системы определены примитивные типы, такие как Строка, Число, Булево и т. д. Также на уров- не системы определены и другие типы, которые могут быть использованы в прикладном решении, например универсальные коллекции значений (Массив, Структура, СписокЭначений), общие типы (ТекстовыйДокумент, Таблич- ныйДокунент, ПостроительОтчета, АнализДанных) и др. Полный перечень типов значений, которые может использовать система ЮПредприятие, приведен в описании встроен- ного языка и в синтакс-помощнике. Переменные встроенного языка ЮПредприятия не ти- пизированы. Это значит, что тип переменной определяет- ся типом того значения, которое хранится в переменной в данный момент. Таким образом, в произвольные моменты работы прикладного решения переменная может иметь различные типы значения. Подробнее о типах значений можно прочитать в разделе «Типы значений», с. 48. В то же время данные ЮПредприятия существуют не только в оперативной памяти компьютера, где они содер- жатся в объектах встроенного языка, но и в базе данных, где осуществляется долговременное хранение этих дан- ных. База данных представляет собой совокупность некоторо- го количества таблиц, создаваемых в соответствии со структурой метаданных прикладного решения. Таблицы базы данных состоят их полей, и для каждого поля обяза- тельно должен быть указан тип значений, которые могут храниться в этом поле. По этой причине все объекты ме- таданных, которые «отвечают» за создание тех или иных полей в базе данных, должны иметь совершенно опреде- ленный тип. Такими объектами являются, например, рек- визиты, измерения, ресурсы и т. д. Для того чтобы указать тип объекта метаданных, «отве- чающего» за создание того или иного поля базы данных, в системе 1 С: Предприятие используются не типы значе- ний, а более сложное понятие — тип данных. Такой подход позволяет, с одной стороны, изолировать разработчика от конкретного хранилища данных, а с дру- гой стороны — сделать работу с данными значительно бо- лее гибкой. Отличие типа данных от типа значения заключается в том, что тип данных является характеристикой, которая может содержать описание как одного, так и нескольких типов значений. В результате у разработчика появляются две важные возможности: ♦ уточнение некоторых примитивных типов значений. Например, можно указать, что реквизит Количество бу- дет содержать не просто числовые значения, а неотри- цательные числовые значения с количеством разрядов не более 15 и дробной частью из 3 разрядов; ♦ указание одновременно нескольких возможных типов значений. Например, можно указать, что реквизит Сдел- ка может содержать ссылку как на счет, выставленный покупателю, так и на счет, выставленный поставщику. В результате в реквизите Сделка смогут одновременно храниться как значения одного, так и другого типа. При этом тип данных этого реквизита будет всегда одним и тем же, но тип значения этого реквизита в каждый кон- кретный момент времени будет определяться типом значения, которое в нем хранится. Типы данных используются в системе ЮПредприятия не только в части, связанной с базой данных, но и в ин-
терфейсной части. Так, например, типы данных должны быть определены для всех реквизитов форм и для всех элементов управления, расположенных в форме. Кроме этого, некоторые объекты встроенного языка, в силу специфики своего использования, также могут потребо- вать указания типа данных, которые в них хранятся. На- пример, указание типа данных может использоваться для списка значений, для колонок таблицы значений и дерева значений. Подробнее о типах данных можно прочитать в разделе «Типы данных», с. 66. Типы значений Примитивные типы Число Числовой тип предназначен для представления десятич- ных чисел. Максимально допустимая разрядность числа, которое может быть сохранено в базе данных, составляет 32 знака, включая десятичную точку. Для числовых зна- чений, хранящихся в памяти (являющихся, например, значением некоторой переменной) разрядность не огра- ничена. Литерал значения типа Число Конкретные значения числового типа во встроенном язы- ке и языке запросов могут быть заданы литералом, кото- рый представляет собой набор цифр, написанных непо- средственно в тексте модуля. Этот набор цифр может начинаться с символов + («плюс») или - («минус»), обо- значающих знак числа. В качестве разделителя целой и дробной части числа используется символ . («точка») (табл. 4.2). Таблица 4.2. Примеры литералов типа Число Число Литерал 3874 3874 1475,25 1475.25 Значение типа Число по умолчанию Для числового типа значением по умолчанию является значение 0. По умолчанию, если не задан специальный формат, это значение будет представляться как 0. Однако некоторые элементы управления, используемые в интерфейсе системы, имеют другое представление ну- левого значения, что сделано для более удобного пред- ставления информации пользователю. Например, в ячейке табличного поля значение по умол- чанию числового типа отображается как пустое место (рис. 4.23). Такое поведение табличного поля позволяет создать спи- сок, который легко читается и не содержит лишней ин- формации. Однако если есть необходимость указывать для нулевых значений определенное представление, то это можно выполнить, используя свойство Формат соответ- ствующей колонки табличного поля (в приведенном при- мере — колонки Значение) (рис. 4.24). Рис. 4.23. Представление значения типа Число по умолчанию в табличном поле Рис. 4.24. Установка формата колонки табличного поля Для колонки табличного поля форматная строка поддер- живает параметр ЧН, который задает представление нуле- вого значения. В результате приведенная выше таблица будет выглядеть, например, следующим образом (рис. 4.25). Рис. 4.25. Представление нулевого значения в табличном поле Аналогичного результата можно добиться средствами встроенного языка (листинг 4.7). Листинг 4.7. Установка формата колонки табличного поля ЭлементыФормы.ТабличноеПоле1.Колонки. Значение.Формат - ”ЧН=’- - При задании представления нулевого значения для ко- лонки табличного поля следует иметь в виду, что таблич- ное поле обрежет концевые пробелы при выводе заданно- го представления нулевого значения. В поле ввода значение по умолчанию числового типа ото- бражается в зависимости от разрядности дробной части,
заданной при указании числового типа данных этого поля ввода (подробнее о числовых типах данных можно прочитать в разделе «Числовые типы данных», с. 66). Если количество разрядов дробной части равно нулю, то будет отображаться как 0, если количество разрядов дроб- ной части отлично от нуля, то будет отображено как 0,000 (количество нулей после запятой будет соответствовать количеству разрядов дробной части) (рис. 4.26). Рис. 4.26. Представление значения типа Число по умолчанию в поле ввода В отличие от колонки табличного поля, для поля ввода нельзя задать собственное представление нулевого значе- ния. Операции со значениями типа Число Для значений типа Число определены арифметические операции (табл. 4.3). Для значений типа Число определены логические опера- ции (табл. 4.4). Преобразование значений типа Число Неявное преобразование. Рассмотрим пример, когда пере- менная, указанная в качестве значения логического выра- жения в операторе цикла, по каким-либо причинам имеет тип Число (листинг 4.8). Листинг 4.8. Неявное преобразование значения типа Число Условие = 22; Если Условие Тогда КонецЕсли; В этом случае будет выполняться неявное преобразова- ние значения типа Число к нужному типу. Такое преобра- зование в ряде случаев может быть выполнено системой, если же такое преобразование невозможно — будет вы- звана ошибка исполнения. 1. Неявное преобразование к типу Строка. Любое значение типа Число может быть преобразовано к типу Строка. Это позволяет всегда иметь возможность получения пред- ставления такого значения (листинг 4.9). Листинг 4.9. Неявное преобразование значения типа Число к значению типа Строка Переменная = 156935.785; Сообщить(Переменная); Результатом выполнения этих операторов будет пред- ставление числа: 156 935,785. Преобразование будет вы- полняться в соответствии с текущими региональными настройками информационной базы, например, как в данном случае, группы разрядов будут отделены друг от друга символом пробела. Таблица 4.3. Арифметические операции для типа Число Операция Операнды Результат Сложение Число + Число Сумма операндов Вычитание Число - Число Разность операндов Умножение Число * Число Произведение операндов Деление Число / Число Частное операндов. Если второй операнд имеет значение 0 — будет вызвана ошибка исполнения Остаток от деления Число % Число Остаток от деления первого операнда на второй. Если второй операнд имеет значение 0 — будет вызвана ошибка исполнения Унарный минус - Число Изменение знака числа Таблица 4.4. Логические операции для типа Число Операция Операнды Результат Больше Число > Число Истина, если первый операнд больше второго. В противном случае Ложь Больше или равно Число >= Число Истина, если первый операнд больше либо равен второму. В противном случае Ложь Равно Число = Число Истина, если первый операнд равен второму. В противном случае Ложь Не равно Число <> Число Истина, если первый операнд не равен второму. В противном случае Ложь Меньше Число < Число Истина, если первый операнд меньше второго. В противном случае Ложь Меньше или равно Число <= Число Истина, если первый операнд меньше либо равен второму. В противном случае Ложь 2. Неявное преобразование к типу Булево. При выполне- нии булевых операций или при вычислении логических выражений любое ненулевое значение приводится к зна- чению Истина. Значение, равное нулю, приводится к зна- чению Ложь (листинг 4.10).
Листинг 4.10. Неявное преобразование значения типа Число к значению типа Булево Условие = 22; Если Условие Тогда Сообщить("Условие истинно."); иначе Сообщить("Условие ложно."): КонецЕсли: В приведенном примере будет получено сообщение об истинности условия, поскольку при вычислении логиче- ского выражения значение переменной Условие будет преобразовано к типу Булево, результатом чего будет зна- чение Истина. Также, например, при выполнении булевой операции НЕ в следующем примере значение переменной Условие бу- дет сначала преобразовано к типу Булево (значение Исти- на), а затем уже выполнена операция НЕ. В результате в окно сообщений будет выведено ложь (листинг 4.11). Листинг 4.11. Неявное преобразование значения типа Число к значению типа Булево Условие = 22: Сообщить(НЕ Условие): 3. Неявное преобразование в операциях сравнения. Поря- док неявного преобразования типов в операциях сравне- ния несколько отличается от описанного выше. Если в операции сравнения один из операндов имеет тип Число, а другой — Булево, то значение типа Булево будет приво- диться к типу Число, а затем будет выполнено сравнение. Например, в результате выполнения следующего кода (листинг 4.12) будет получено сообщение о ложности ус- ловия, поскольку булев операнд будет приведен к типу Число (значение 1), а затем уже будет выполнено сравне- ние. Листинг 4.12. Неявное преобразование в операции сравнения Условие = 22; Если Истина = Условие Тогда Сообщить ("Условие истинно.''): иначе Сообщить("Условие ложно."): КонецЕсли; Явное преобразование. Встроенный язык позволяет вы- полнить явное преобразование значения типа Число к ти- пам Булево и Строка. 1. Преобразование к типу Булево. Для этого используется встроенная функция БулевоО, в качестве параметра кото- рой передается преобразуемое число. Значение 0 преоб- разуется в Ложь, все остальные значения преобразуются в значение Истина. Например, в результате выполнения опе- ратора (листинг 4.13) будет получено сообщение истина. Листинг 4.13. Явное преобразование к типу Булево Сообщить(Булево(34.456)); А в результате выполнения следующего оператора (лис- тинг 4.14), будет выдано сообщение ложь. Листинг 4.14. Явное преобразование к типу Булево Сообщить(Булево(О)): 2. Преобразование к типу Строка. Любое числовое значе- ние может быть преобразовано к типу Строка при помощи встроенной функции СтрокаО. Результатом такого преоб- разования будет строковое представление числа, полу- ченное в соответствии с текущими региональными уста- новками информационной базы. Например, результатом выполнения оператора (лис- тинг 4.15) будет сообщение 26 475 834,456, в котором ис- пользуются, в данном случае, разделители групп разрядов (символ «пробел») и десятичный разделитель (символ «запятая»). Листинг 4.15. Явное преобразование к типу Строка Сообщить(Строка(26475834.456)); Строка Строковый тип предназначен для представления строк в формате Unicode произвольной длины. Литерал значения типа Строка Для того чтобы задать конкретные значения строкового типа, во встроенном языке и языке запросов использует- ся литералы строкового типа. Они представляют собой набор символов, заключенных в кавычки (табл. 4.5). Таблица 4.5. Примеры литералов типа Строка Строка Литерал книга "книга" проверка работы "проверка работы" Если в строке необходимо задать символ кавычка ("), то записываются две кавычки подряд (табл. 4.6). Таблица 4.6. Пример литерала типа Строка Строка Литерал фирма "Ваш сад” фирма Ваш сад Наряду с однострочными литералами во встроенном язы- ке могут быть использованы строковые литералы, состоя- щие из нескольких строк. Для обозначения таких литера- лов используется два различных способа записи. Во-первых, отдельные строки могут быть заключены в ка- вычки. В этом случае между ними не должно находиться никаких символов кроме пробелов, переводов строки и комментариев. Например, строка Внимание! В документе не могут присутствовать строки с нулевым количеством! может быть записана следующим образом (листинг 4.16). Листинг 4.16. Пример литерала типа Строка Сообщить("Внимание! " "В документе не могут присутствовать строки" "с нулевым количеством!"); Во-вторых, указание многострочных литералов осущест- вляется с использованием символа «|». В этом случае ка- вычки используются только в начале и конце литерала, а символ «|» размещается в начале каждой новой строки (листинг 4.17).
Листинг 4.17. Пример литерала типа Строка Сообщить (" Внимание! |В документе не могут присутствовать строки |с нулевым количеством!"); Результатом работы как первого, так и второго оператора будет следующее сообщение: Внимание! В документе не могут присутствовать строки с нулевым количеством! Значение типа Строка по умолчанию Для строкового типа значением по умолчанию является пустая строка (литерал Это значение не имеет пред- ставления, иначе говоря, оно не отображается. В некото- рых случаях, например при вычислении значений в от- ладчике, для наглядности в качестве представления этого значения может использоваться его литерал Операции со значениями типа Строка Для значений типа Строка определена операция конкате- нации (табл. 4.7). Для значений типа Строка определены логические опера- ции (табл. 4.8). Таблица 4.7. Операция конкатенации Операция Операнды Результат Конкатенация Строка + Строка Строка, являющаяся соединением первой и второй строки. Длина результирующей строки равна сумме длин соединяемых строк При выполнении логических операций больше, больше или равно, меньше, меньше или равно существует особен- ность, связанная с тем, что система 1С:Предприятие по- зволяет создавать прикладные решения на различных языках. Для того чтобы прикладное решение максимально соот- ветствовало национальным особенностям, принятым в конкретной стране, есть возможность установить регио- нальные установки информационной базы, соответст- вующие некоторому языку и стране. Региональные уста- новки позволяют задать формат представления чисел, дат, времени, логических значений и, что важно в данном случае, определяют порядок сортировки строковых зна- чений, принятый в конкретном регионе. Внутри платформы 1С:Предприятие 8.0 работа строками ведется только в UNICODE и строковые данные в базах данных также сохраняются в UNICODE. Стандартом оп- ределен некоторый генеральный порядок сортировки для UNICODE. Но он подходит не для всех языков. Поэтому для некоторых языков в этот генеральный порядок внесе- ны минимальные изменения для обеспечения соответст- вия конкретному языку. В результате этого, например, для русских и латыш- ских региональных установок будет различный порядок следования строк при сортировке их по возрастанию (табл. 4.9). Таблица 4.8. Логические операции Операция Операнды Результат Больше Строка > Строка Истина, если первая строка больше второй. В противном случае Ложь Больше или равно Строка >= Строка Истина, если первая строка больше либо равна второй. В противном случае Ложь Меньше Строка < Строка Истина, если первая строка меньше второй. В противном случае Ложь Меньше или равно Строка <= Строка Истина, если первая строка меньше либо равна второй. В противном случае Ложь Равно Строка = Строка Истина, если первая строка равна второй. В противном случае Ложь Не равно Строка <> Строка Истина, если первая строка не равна второй. В противном случае Ложь Таблица 4.9. Порядок следования строк для различных региональных установок Русский (Россия) Латышский (Латвия) Аса АсЬ АсЬ Аса Такой порядок соответствует принятому в России и Лат- вии алфавиту. Поскольку сортировка строковых значений выполняется на основе сравнения их друг с другом, то один и тот же оператор (листинг 4.18) при русских региональных уста- новках будет давать результат Истина, а при латышских — nepareizs, что значит «ложь». Листинг 4.18. Сравнение строк Результат = "асЬ" > "аса"; Таким образом, результат выполнения логических опера- ций над строковыми значениями будет зависеть не толь- ко от самих операндов, участвующих в выражении, но и от региональных установок информационной базы, в ко- торой выполняется эта операция. Преобразование значений типа Строка Неявное преобразование. При выполнении различных опе- раторов кода могут возникать ситуации, когда значения типа Строка не подходят для выполнения данных опера- ций. Например, если при выполнении следующего опера- тора, переменная Строка будет иметь значение 25 (лис- тинг 4.19). Листинг 4.19. Неявное преобразование значения типа Строка Строка = "25"; Результат = 35 + Строка; Сообщить(Результат);
В этом случае будет выполняться неявное преобразова- ние значения типа Строка к нужному типу. Такое преобразование в ряде случаев может быть выпол- нено системой, если же такое преобразование невозмож- но — будет вызвана ошибка исполнения. 1. Неявное преобразование к типу Число. Если выполнить приведенный выше пример, то строка 25 будет преобразо- вана к типу Число и в окно сообщений будет выведено 60. Однако следует заметить, что преобразование значения типа Строка к типу Число будет выполняться только тогда, когда подобное преобразование осмысленно. Например, если значение переменной Строка будет равно а25, то в этом случае преобразование уже выполнено не будет и будет вызвано исключение. 2. Неявное преобразование к типу Булево. Данное преоб- разование также выполняется лишь тогда, когда такое преобразование имеет смысл. Прежде всего, к типу Булево всегда будут преобразованы русскоязычные и англоязычные представления булевых значений: истина и ложь, true и false. Например, рассмотрим выполнение следующего фраг- мента кода (листинг 4.20). Листинг 4.20. Неявное преобразование к типу Булево Если "истина" тогда Сообщить("Истина"): Иначе СообщитьС'Ложь"); КонецЕсли: Если "false" тогда Сообщить("Истина”); Иначе СообщитьС'Ложь"); КонецЕсли; В результате в окно сообщений будет выведен текст: Истина Ложь Однако, кроме этого, к булевым значениям будут преоб- разовываться также строковые значения, соответствую- щие представлению булевых значений для языка, вы- бранного в региональных установках информационной базы. Например, если в региональных установках инфор- мационной базы выбрать Язык (Страна) равным Чешский (Чехия), то тогда следующий код (листинг 4.21) будет вы- полнен без ошибок и в окно состояния будет выведено: Ложь. Листинг 4.21. Неявное преобразование к типу Булево Если " пергаvda" тогда СообщитьС'Истина"); Иначе СообщитьС'Ложь"): КонецЕсли; Если этот же код попытаться выполнить с региональ- ными установками Грузинский (Грузия), то будет вызва- но исключение, в результате того, что значение nepravda не может быть преобразовано к типу Булево. Если же в этой ситуации строку nepravda заменить на Ogqjatno, что значит «ложь» по-грузински, то пример (листинг 4.22) отработает без ошибок и в окно сообщений будет выве- дено: Ложь. Листинг 4.22. Неявное преобразование к типу Булево Если тогда Сообщить("Истина"); Иначе СообщитьС'Ложь"): КонецЕсли; Явное преобразование. Строковое значение может быть преобразовано к типам Число или Дата. 1. Преобразование к типу Число. Встроенный язык позво- ляет выполнить данное преобразование с помощью встро- енной функции ЧислоО. При этом будут преобразованы только те строки, которые представляют собой правиль- ное строковое представление литерала численного типа. Например, может быть выполнено преобразование стро- ки 1125.78 к числу 1125.78 (листинг 4.23). Листинг 4.23. Явное преобразование к типу Число Сообщить(Число("1125.78")); Следует заметить, что если в строке в качестве разделите- ля целой и дробной части будет использоваться не точка, а запятая, преобразование также будет выполнено (лис- тинг 4.24). Листинг 4.24. Явное преобразование к типу Число Сообщить(Число("1125,78")): 2. Преобразование к типу Дата. Для этого используется встроенная функция Дата(). Она позволяет преобразовать строку, которая представляет собой части даты, записан- ные в определенном порядке: год, месяц, день, час, мину- та и секунда. Например, для того чтобы получить дату 15 апреля 2003 года 17 часов 45 минут 34 секунды, преобразуемая строка должна иметь вид 20030415174534 (листинг 4.25). Листинг 4.25. Преобразование к типу Дата Сообщить(Дата("20030415174534")); В результате выполнения приведенного кода будет полу- чена нужная дата: 15.04.2003 17:45:34. Дата Тип Дата предназначен для представления значения даты и времени с точностью до секунды. Минимальным значе- нием типа Дата является дата 01 января 0001 года 00 часов 00 минут 00 секунд. Литерал значения типа Дата Конкретные значения типа Дата могут быть заданы лите- ралом, который представляет собой последовательность цифр, заключенных в одинарные кавычки. Последова- тельность цифр представляет собой части даты в следую- щем порядке: год, месяц, день, час, минута и секунда. Час- ти даты могут быть отделены друг от друга различными разделителями; час, минута и секунда могут быть не ука- заны — в этом случае предполагается, что они равны нулю (табл. 4.10). В языке запросов для указания литералов типа Дата ис- пользуется ключевое слово ДАТАВРЕМЯ, после которого в скобках последовательно указываются год, месяц, день, час, минута и секунда. Последние три указывать не обяза- тельно (табл. 4.11).
Таблица 4.10. Примеры литералов типа Дата Дата Литерал 15.04.2003 22:45:33 '20030415224533' 15.04.2003 0:00:00 '20030415' 15.04.2003 22:45:33 '2003-04-15 22:45:33' 15.04.2003 22:45:33 '2003/04/15-22/45/33' Таблица 4.11. Примеры литералов типа Дата Дата Литерал 15.04.2003 22:45:33 ДАТАВРЕМЯ(2003, 04,15,22,45, 33) 15.04.2003 0:00:00 ДАТАВРЕМЯ(2003, 04,15) Значение типа Дата по умолчанию Для типа Дата значением по умолчанию является 01 янва- ря 0001 года 00 часов 00 минут 00 секунд. При выводе значения даты по умолчанию она отобра- жается в соответствии с используемыми региональными установками (например, для русского языка это будет 01.01.0001 0:00:00). Однако при выводе значения даты по умолчанию неко- торые элементы управления она будет представляться иначе, что обусловлено удобством ввода или отображения. Например, значение даты по умолчанию в поле ввода бу- дет отображено в виде символов-разделителей даты, ис- пользуемых при данных региональных установках. Со- став разделителей будет определяться составом даты (Дата и время, Дата, Время), указанным при описании типа данных, с которыми работает данное поле ввода (рис. 4.27). Подробнее о типах данных, описывающих значения типа Дата, можно прочитать в разделе «Типы данных, описы- вающие значения типа Дата», с. 67. Рис. 4.27. Пустая дата в поле ввода Если существует необходимость задания собственного представления даты по умолчанию, то это можно выпол- нить, используя свойство Формат поля ввода (рис. 4.28). В поле ввода форматная строка поддерживает параметр ДП, который задает представление значения даты по умол- чанию. В результате приведенный выше пример будет выглядеть следующим образом (рис. 4.29). Аналогичного результата можно добиться, используя средства встроенного языка (листинг 4.26). При выводе значения даты по умолчанию в табличное поле она будет отображаться как пустое место, вне зави- симости от того, какой состав даты установлен при описа- нии типа данных (рис. 4.30). Рис. 4.28. Установка формата в поле ввода Рис. 4.29. Отображение пустой даты в поле ввода Рис. 4.30. Пустая дата в табличном поле Листинг 4.26. Установка формата в поле ввода ЭлементыФормы.ПолеВводаДатаИВремя. Формат = "ДП='01.01.2003 00:00:00"'; ЭлементыФормы.ПолеВводаДата.Формат = ”ДП='01.01.2003'": ЭлементыФормы. ПолеВводаВремя. Формат = "ДП='ОО:ОО:ОО"'; Если есть необходимость указывать для значений даты по умолчанию определенное представление, то это можно выполнить, используя свойство Формат колонки таблично- го поля (в приведенном примере — колонки Значение) (рис. 4.31). Для колонки табличного поля форматная строка поддер- живает параметр ДП, который задает представление пус- той даты. В результате приведенная выше таблица будет выглядеть, например, следующим образом (рис. 4.32). Аналогичного результата можно добиться средствами встроенного языка (листинг 4.27). Листинг 4.27. Установка формата колонки табличного поля ЭлементыФормы.ТабличноеПоле1.Колонки.Значение.Формат = "ДП='01.01.2003 00:00:00'";
Рис. 4.31. Установка формата для колонки табличного поля _ □ X Действия* X1 Значение Н 05.04 2004 5:50:42 определенное значение 01 01 2003 00 СЮ:ОО ".чачение по умолчанию 05 04 2004 00000 опреде пенное значение Выполнить Закрыть Рис. 4.32. Представление пустой даты в табличном поле Операции со значениями типа Дата Для значений типа Дата определены арифметические опе- рации (табл. 4.12). Для значений типа Дата определены логические операции (табл. 4.13). Таблица 4.12. Арифметические операции Операция Операнды Результат Сложение Дата + Число Дата, увеличенная на количество секунд Вычитание Дата - Дата Число, соответствующее разнице между двумя датами, измеренной в секундах Вычитание Дата - Число Дата, уменьшенная на количество секунд Преобразование значений типа Дата Неявное преобразование. При выполнении различных опе- раторов кода могут возникнуть ситуации, когда значения типа Дата не подходят для выполнения данных операций. Например, при выводе значений типа Дата может быть выполнено преобразование к строке (листинг 4.28). Листинг 4.28. Неявное преобразование значения типа Дата ПерененнаяДата = '20030514234512'; Сообщить(ПерененнаяДата); Таблица 4.13. Логические операции Операция Операнды Результат Больше Дата > Дата Истина, если первый операнд больше второго. В противном случае Ложь Больше или равно Дата >= Дата Истина, если первый операнд больше либо равен второму. В противном случае Ложь Равно Дата = Дата Истина, если первый операнд равен второму. В противном случае Ложь Не равно Дата <> Дата Истина, если первый операнд не равен второму. В противном случае Ложь Меньше Дата < Дата Истина, если первый операнд меньше второго. В противном случае Ложь Меньше или равно Дата <= Дата Истина, если первый операнд меньше либо равен второму. В противном случае Ложь Явное преобразование. Явным образом значение типа дата может быть преобразовано только к строке. Для этого ис- пользуется встроенная функция СтрокаО, в качестве пара- метра которой передается преобразуемая дата. Результатом такого преобразования будет строковое представление даты, полученное в соответствии с текущими региональ- ными установками информационной базы. Например, результатом выполнения оператора (лис- тинг 4.29) будет сообщение 27.04.2003 12:36:58. Листинг 4.29. Явное преобразование типа Дата Сообщить(Строка('20030427123658')); Для информационной базы, например, с греческими ре- гиональными установками, результатом выполнения это- го же оператора будет сообщение 27/4/2003 12:36:58 цц. Булево Тип Булево предназначен для представления логических величин. Он имеет только два значения: Истина и Ложь. Литерал значения типа Булево Конкретные значения типа Булево во встроенном языке и языке запросов задаются литералами (табл. 4.14). Таблица 4.14. Литералы типа Булево Значение Литерал истина Истина или True ложь Ложь или False Значение типа Булево по умолчанию Значением типа Булево по умолчанию является значение Ложь.
Операции со значениями типа Булево Для значений типа Булево определены операции сравне- ния. При сравнении булевых значений считается, что зна- чение Истина больше, чем значение Ложь (табл. 4.15). Таблица 4.15. Операции сравнения Операция Операнды Больше Булево > Булево Больше или равно Булево >= Булево Равно Булево = Булево Не равно Булево <> Булево Меньше Булево < Булево Меньше или равно Булево <= Булево Для значений типа Булево определены булевы операции (табл. 4.16). Таблица 4.16. Булевы операции Операция Операнды Результат И Булево И Булево Истина, если оба операнда имеют значение Истина. В остальных случаях Ложь ИЛИ Булево ИЛИ Булево Ложь, если оба операнда имеют значение Ложь. В остальных случаях Истина НЕ НЕ Булево Истина, если значение операнда Ложь. В противном случае Ложь Преобразование значений типа Булево Неявное преобразование. При выполнении различных опе- раторов кода могут возникать ситуации, когда значения типа Булево не подходят для выполнения данных опера- ций (листинг 4.30). Листинг 4.30. Неявное преобразование значений типа Булево Число = 10; Булево = Истина; Сообщить(Число + Булево); В этом случае может быть выполнено неявное преобразо- вание значения типа Булево к нужному типу. Если такое преобразование не может быть выполнено — будет вызва- на ошибка исполнения. 1. Неявное преобразование к типу Число. Если логика ис- полнения требует преобразования значения типа Булево к типу Число, то это преобразование выполняется по сле- дующим правилам: значение Истина преобразуется к зна- чению 1, а значение Ложь — к значению 0. Таким образом, результатом выполнения предыдущего примера (лис- тинг 4.30) будет строка 11. 2. Неявное преобразование к типу Строка. Данный тип преобразования проиллюстрируем следующим примером (листинг 4.31). Листинг 4.31. Неявное преобразование к типу Строка Булево = Истина; Сообщить(Булево); В результате будет получено представление значения в соответствии с текущими региональными установками информационной базы. Например, для русских регио- нальных установок это будет значение истина, а для поль- ских — prawda. Явное преобразование. Встроенный язык позволяет вы- полнить явное преобразование значения типа Булево. 1. Преобразование к типу Число. Для этого используется встроенная функция ЧислоО, которой в качестве парамет- ра передается булево значение. При этом значение Истина преобразуется в 1, а значение Ложь — в 0 (листинг 4.32). Листинг 4.32. Преобразование к типу Число Результат = Число(Истина); Сообщить(Результат); 2. Преобразование к типу Строка. Встроенный язык позво- ляет также преобразовывать значение типа Булево к типу Строка. Для этого используется встроенная функция Стро- ка, которая возвращает представление булева значения в соответствии с текущими региональными установками информационной базы (листинг 4.33). Листинг 4.33. Преобразование к типу Строка Результат = Строка(Истина); Сообщить(Результат); В результате выполнения этого кода, в окно сообщений бу- дет выведено истина (для русских региональных установок). Неопределено Значение типа Неопределено применяется тогда, когда не- обходимо использовать «пустое значение», не принадле- жащее ни к одному другому типу данных, определенных в прикладном решении. Тип Неопределено имеет одно един- ственное значение — Неопределено. Это значение использу- ется, например, как значение составного типа по умолча- нию. По этой причине составной тип всегда содержит тип Неопределено. О составном типе данных подробнее можно прочитать в разделе «Составной тип данных», с. 68. Представлением значения Неопределено является пустая строка. Литерал значения типа Неопределено Значение типа Неопределено во встроенном языке и языке запросов задается литералом Неопределено. Операции со значением Неопределено Для значения Неопределено определены операции сравнения на равенство и неравенство со значениями других типов. Таким образом, для любой переменной всегда может быть выполнено сравнение на равенство (или неравенство) ее значения значению Неопределено (листинг 4.34). Листинг 4.34. Сравнение со значением Неопределено Если РеквизитФорныСоставной = Неопределено Тогда СообщитьС'Истина"); Иначе СообщитьС'Ложь"); КонецЕсли;
Преобразование значений типа Неопределено Значение Неопределено может быть преобразовано только в значение типа Строка. Такое преобразование может вы- полняться системой неявно (например, при выводе зна- чения Неопределено) или явно, с использованием встроенной функции СтрокаО. Результатом преобразования является пустая строка. Null Тип Nul 1, так же как и тип Неопределено, имеет единствен- ное значение — Null. Это значение используется системой для обозначения отсутствующего значения при работе с базой данных. Такая ситуация может возникнуть, например, при соеди- нении нескольких таблиц в запросах, когда для одной из соединяемых таблиц нет записей в другой таблице, удов- летворяющих указанным условиям. Кроме приведенного примера, значение Nul 1 может быть получено и в других случаях. Например, когда выполня- ется обращение к реквизитам объекта, которые не ис- пользуются. Допустим, у иерархического справочника Номенклатура существует реквизит Артикул, для которо- го свойство Использование установлено в значение ДляЭле- нента. В этом случае поле Артикул будет доступно для ре- дактирования только у элементов справочника. У групп справочника это поле не будет содержать никакой инфор- мации. Поэтому при обращении к реквизиту Артикул у группы справочника Номенклатура система будет возвращать зна- чение Null (листинг 4.35). Листинг 4.35. Значение типа Null Выборка = Справочники.Номенклатура.ВыбратьО; Пока Выборка.Следующий() Цикл Если Выборка.ЭтоГруппа Тогда Префикс = "Группа: "; Иначе Префикс = "Элемент: КонецЕсли; Сообщить(Префикс + СокрЛГЦВыборка.Наименование) + ", тип артикула: " + ТипЗнч(Выборка.Артикул)); КонецЦикла: В приведенном примере выбираются все элементы спра- вочника Номенклатура, и затем выводится информация о типе значения реквизита Артикул для каждого элемента выборки. Литерал значения типа Null Значение Nul 1 во встроенном языке и языке запросов за- дается литералом Null, а представлением значения Null является пустая строка. Операции со значениями типа Null Для значения Nul 1 определены операции сравнения на ра- венство и неравенство со значениями других типов. В ре- зультате этого для любой переменной всегда может быть выполнено сравнение на равенство (или неравенство) ее значения значению Nul 1 (листинг 4.36). В приведенном примере выбираются все элементы спра- вочника Номенклатура. Затем для каждого элемента про- веряется равенство его артикула значению Nul 1, и в зави- симости от этого формируется строка для вывода сооб- щения. Листинг 4.36. Сравнение со значением типа Null Выборка = Справочники.Номенклатура.Выбрать(); Пока Выборка.СледующийО Цикл Суффикс = ?(Выборка.Артикул = Null, "не используется". Выборка.Артикул); Сообщить(СокрЛГЦВыборка.Наименование) + ", артикул: " + Суффикс); КонецЦикла: Преобразование значений типа Null Значение Nul 1 может быть преобразовано только в значе- ние типа Строка. Такое преобразование может выполнять- ся системой неявно (например, при выводе значения Null) или явно, с использованием встроенной функции СтрокаО. Результатом преобразования является пустая строка. Тип Значения типа Тип используются для идентификации различных типов значений и их сравнения. Значения этого типа возвращаются двумя системными функциями: Тип() и ТипЗнчО. Также значения этого типа могут быть получены из объекта ОписаниеТипов в виде мас- сива значений (метод ТипыО). Функция Тип() позволяет получить значение этого типа, соответствующее переданному в качестве параметра име- ни некоторого типа (листинг 4.37). Листинг 4.37. Использование функции Тип() ТипСтрока = ТипССтрока"); ТипЧисло = Тип("Число"): ТипСсылкаНаСправочникНоменклатура = Тип("СправочникСсылка.Номенклатура"): Функция ТипЗнчО также позволяет получить значение типа Тип, однако в качестве параметра ей передается не имя типа, а само значение какого-либо типа (листинг 4.38). Листинг 4.38. Использование функции ТипЗнчО ТипСтрока = ТипЗнч("произвольная строка"); ТипЧисло = Тип3нч(387.67); ТипСсылкаНаСправочникНоменклатура = ТипЗнч(Справочники.Номенклатура.НайтиПоКоду("00001")); Операции со значениями типа Тип Для значений типа Тип определены операции сравнения на равенство и неравенство. Это позволяет выполнять проверку принадлежности произвольного значения неко- торому типу (листинг 4.39). Листинг 4.39. Проверка принадлежности значения типу Если ТипЗнч(ПроверяемаяПеременная) = ТипССтрока") Тогда СообщитьСТип проверяемой переменой - строка"); КонецЕсли; Преобразование значений типа Тип Значения этого типа могут быть преобразованы только к значениям типа Строка. Такое преобразование может быть выполнено системой неявно (при выводе значения,
например) или явно, с использованием встроенной функ- ции СтрокаО. Результатом такого преобразования будет представление описываемого типа, полученное в соответ- ствии с используемым языком интерфейса платформы (табл. 4.17). Таблица 4.17. Преобразование к типу Строка Значение Язык интерфейса платформы Представление Тип(«Строка») Русский Строка Тип(«Строка») Украинский Рядок Тип(«Строка») Латышский Rinda Тип(«Справочник Ссылка. Номенклатура») Русский Справочник ссылка: Номенклатура Тип(« Справочник Ссылка. Номенклатура») Казахский Аныктама алтеме: Номенклатура Тип(«Справочник Ссылка. Номенклатура») Грузинский 0б<п&5бю ЗобоЗбд&д: Номенклатура Типы, образуемые в прикладном решении В отличие от примитивных типов, которые определены на уровне технологической платформы и поддерживаются в любом прикладном решении, прикладные типы создаются в конкретных прикладных решениях в результате добавления в конфитурацию какого-либо объекта метаданных. Приклад- ные типы создаются платформой автоматически и позволя- ют работать с данными, хранящимися в тех структурах, кото- рые описываются данным объектом конфигурации. В зависимости от объекта конфигурации будут добав- ляться различные типы данных. Например, при добавле- нии справочника Номенклатура будут созданы такие типы данных, как: СправочникМенеджер.Номенклатура; СправочникСсылка.Номенклатура; СправочникОбъект.Номенклатура; СправочникВыборка.Номенклатура; СправочникСписок.Номенклатура. Если же в конфитурацию добавить, например, регистр све- дений КурсыВалют, то станут доступны следующие типы: РегистрСведенийМенеджер.КурсыВалют; РегистрСведенийВыборка.КурсыВалют; PerистрСведенийСписок.КурсыВалют; Таблица 4.18. Основные типы для работы с данными объектов конфигурации Объект конфигурации Менеджер Список Выборка Ссылка Объект Набор записей Запись Ключ записи Константа + Критерий отбора + + Журнал документов + + + Перечисление + + + Справочник + + + + + Документ + + + + + План видов характеристик + + + + + План счетов + + + + + План видов расчета + + + + + Бизнес-процесс + + + + + Задача + + + + + План обмена + + + + Отчет + + Обработка + + Последовательность + + + Перерасчет + + + Регистр сведений + + + + + + Регистр накопления + + + + + + Регистр бухгалтерии + + + + + + Регистр расчета + + + + + +
РегистрСведенийМенеджерЗаписи.КурсыВалют; РегистрСведенийНаборЗаписей.КурсыВалют; РегистрСведенийЗапись.КурсыВалют; PerистрСведенийКлючЗаписи.КурсыВалют. Как можно заметить из названий, некоторые типы «похо- жи» (например, СправочникСписок.Номенклатура и Регистр- СведенийСписок.КурсыВалют), а некоторые нет (например, СправочникОбъект.Номенклатура и РегистрСведенийНаборЗапи- сей.КурсыВалют). Это действительно так: типы, создавае- мые для различных объектов конфигурации и принадле- жащие к одной группе прикладных типов (например, <вид обьекта>Список.<имя>), имеют схожую функциональность, схожее поведение и одинаковые приемы работы с ними. Такая организация системы прикладных типов сущест- венно облегчает разработку прикладных решений, по- скольку если разработчик освоил работу со списком справочника, то он уже без труда, по аналогии, сможет ра- ботать и со списком регистра сведений и, например, со списком бизнес-процесса (табл. 4.18). Для некоторых объектов конфигурации создаются до- полнительные типы, реализующие специальную функ- циональность, присущую только данным объектам кон- фигурации (табл. 4.19). Таблица 4.19. Дополнительные типы для работы с данными объектов конфигурации Объект конфнпрацни Типы Константа КонстантаМенеджерЗначения.<имя> КонстантыНабор План счетов ПланСчетовВидыСубконто.<имя> ПланСчетовВидыСубконтоСтрока.<имя> План видов расчета ВедущиеВидыРасчета.<имя> ВедущиеВидыРасчетаСтрока.<имя> ВытесняющиеВидыРасчета.<имя> ВытесняющиеВидыРасчетаСтрока.<имя> БазовыеВидыРасчета.<имя> БазовыеВидыРасчетаСтрока.<имя> Регистр сведений РегистрСведенийМенеджерЗаписи.<имя> Регистр бухгалтерии РегистрБухгалетрииСубконто.<имя> Менеджер объектов Для каждого вида объектов конфигурации (справочники, документы и т. д.) в системе определен тип менеджера этих объектов (СправочникиМенеджер, ДокументыМенеджер и т. д.). Эти типы существуют всегда, вне зависимости от того, есть ли в конкретном прикладном решении хоть один та- кой объект или нет. Каждый из этих типов имеет единственное значение в кон- кретном прикладном решении. Это можно проиллюстри- ровать на следующем примере (листинг 4.40). Менеджеры объектов доступны через соответствующие свойства глобального контекста (например, Справочники или Документы). Листинг 4.40. Сравнение экземпляров объектов менеджеров МенеджерСправочников! = Справочники; МенеджерСправочников2 = Справочники; Если МенеджерСправочников! = МенеджерСправочников2 Тогда Сообщить("Объекты равны"); КонецЕсли; Главная задача этого типа — предоставить доступ к ме- неджерам конкретных объектов метаданных (Справочник- Менеджер.<иня>, ДокументМенеджер.<иня> и т. д.) (рис. 4.33). Рис. 4.33. Структура типов Кроме этого, менеджер объектов позволяет проверить, является ли тип какого-либо значения типом ссылки на объект этого типа (листинг 4.41). Листинг 4.41. Использование менеджера для проверки принадлежности к типам ссылок СсылкиНаВсеСправочники = Справочники.ТипВсеСсылкиО; Если СсылкиНаВсеСправочники. СодержитТип(ТипЗнч(АнализируеноеЭначение)) Тогда Сообщить("Это ссылка на справочник"); Иначе Сообщить("Значение не является ссылкой на справочник"); КонецЕсли; В приведенном примере используется метод ТипВсеСсыл- киО менеджера справочников для того, чтобы в перемен- ной СсылкиНаВсеСправочники получить объект ОписаниеТипов, содержащий типы ссылок на все справочники приклад- ного решения. Затем, используя его метод СодержитТипО, проверяется, входит ли тип анализируемого значения в состав этого описания типов или нет. Менеджеры конкретных объектов метаданных доступны двумя путями. Во-первых, они доступны как свойства ме- неджера объектов (листинг 4.42). Листинг 4.42. Обращение к менеджеру объекта конфигурации МенеджерСправочников = Справочники: МенеджерСправочникаКонтрагенты = МенеджерСправочников. Контрагенты; Кроме этого, менеджеры объектов можно получить пере- бором коллекции значений, которой является менеджер объектов. Элементами этой коллекции как раз и являют- ся менеджеры отдельных объектов (листинг 4.43).
Листинг 4.43. Обход коллекции менеджеров объектов МенеджерСправочников = Справочники; Для Каждого МенеджерСправочника Из МенеджерСправочников Цикл Сообщить(ТипЗнч(МенеджерСправочника)); КонецЦикла; Менеджер Менеджер прикладного объекта можно назвать «точкой входа» в конкретный объект метаданных в объектной мо- дели встроенного языка. Объекты этого типа предостав- ляют доступ к общим действиям, относящимся к кон- кретному объекту метаданных (например, к справочнику Контрагенты или к документу Авансовый отчет). В основ- ном это: ♦ получение форм и макетов; ♦ получение выборок из данных этого объекта конфигу- рации; ♦ создание и поиск элементов данных; ♦ доступ к предопределенным элементам данных; ♦ выполнение общих действий, поддерживаемых данным объектом конфигурации. В конкретном прикладном решении всегда существует только один экземпляр каждого менеджера, в чем можно убедиться на следующем примере (листинг 4.44). Листинг 4.44. Сравнение экземпляров объектов менеджеров объекта конфигурации МенеджерСправочникаКонтрагенты1 = Справочники.Контрагенты; МенеджерСправочникаКонтрагенты2 = Справочники.Контрагенты; Если МенеджерСправочникаКонтрагенты! = МенеджерСправочникаКонтрагенты2 Тогда Сообщить("Объекты равны”); КонецЕсли; Объект Тип объекта так же как и ссылка, создается не для всех объектов конфигурации, а только для тех, которых хра- нят в базе данных объектные данные (справочники, доку- менты, планы счетов и пр.). Только с помощью объекта может быть выполнена моди- фикация данных, хранящихся в базе данных. Другие типы объектных данных позволяют выполнять только чтение данных из базы данных. Более подробно о данных объектного типа можно прочи- тать в разделе «Объект», с. 39. Ссылка Тип ссылки создается не для всех объектов конфигура- ции, а только для тех, которые хранят данные объектного типа (справочники, документы, планы счетов и пр.). Тип ссылки служит, прежде всего, для однозначной иден- тификации объекта данных (как совокупности логически связанных данных) в базе данных. Значением ссылки яв- ляется, фактически, уникальный внутренний идентифи- катор, который хранится в поле Ссылка таблиц, создавае- мых системой для объекта конфигурации. Ссылка позволяет обращаться к свойствам объекта базы данных, а также получать сам объект. Более подробно об этом можно прочитать в разделе «Ссылка», с. 37. Набор записей Тип набора записей, в отличие от ссылок и объектов, предназначен для работы с необъектными данными, та- кими как, например, наборы записей различных регистров. Так же как и объект для объектных данных, набор запи- сей является единственным объектом, с помощью кото- рого, в конечном счете, выполняется модификация не- объектных данных. Более подробно о необъектных данных можно прочитать в разделе «Необъектные данные», с. 44. Список Список предназначен для динамического просмотра дан- ных объекта конфигурации в элементе управления таб- личное поле. Объекты списков, как правило, создаются системой автоматически, в процессе визуального конст- руирования; можно назначить этот тип табличному полю или просто произвольному реквизиту формы. Список осуществляет считывание данных из базы дан- ных порциями, в процессе навигации пользователя по списку. По этой причине такие объекты называют еще списками динамического просмотра или динамическими списками. Каждая очередная порция считанных данных отражает актуальное состояние списка. Список позволяет настроить состав полей, которые будут считаны из базы данных (свойство Колонки), а также уста- новить отбор и порядок. Колонки списка Колонки списка представляют собой объект КолонкиСпи- ска, являющийся коллекцией отдельных колонок (Колон- каСписка). Можно добавлять, удалять колонки из коллек- ции, перебирать колонки списка или обращаться к ним по индексу. Поскольку список предназначен для отображения дан- ных табличным полем, то после того, как табличное поле будет связано со списком, список будет содержать неко- торый набор колонок, которые необходимы для функцио- нирования табличного поля. Эти колонки будут присут- ствовать в списке даже в том случае, если табличное поле, отображающее этот список, не будет содержать ни одной колонки. Состав таких колонок различается для разных объектов метаданных, и в сводном виде он представлен в табл. 4.20 и 4.21: Для справочника некоторые колонки будут присутство- вать в зависимости от вида справочника: Родитель — если справочник иерархический с иерархией элементов, Родитель, ЭтоГруппа — если справочник иерархический с иерархией групп и элементов, Владелец — если справочник подчиненный. Для плана видов характеристик колонки Родитель и Это- Группа будут присутствовать, только если план видов ха- рактеристик иерархический. Для регистра сведений некоторые колонки будут присут- ствовать в зависимости от вида регистра: Период — если регистр сведений периодический, Активность, Регистратор — если регистр сведений подчинен регистратору.
Таблица 4.20. Состав полей списков объектов конфигурации, работающих с объектными данными Ссылка Пометка- Удаления Предопреде- ленный Родитель ЭтоГруппа Дата Проведен Владелец Код Наименование Вид Забалансовый Ведущая- Задача Завершен Стартован Выполнена Справочник + + + * * * План видов характеристик + + + * * План счетов + + + + + + + + План видов расчета + + + План обмена + + Бизнес-процесс + + + + + + Задача + + + + Документ + + + + Журнал документов + + + + Таблица 4.21. Состав полей списков объектов конфигурации, работающих с необъектными данными Активность Регистратор ВидДвижения Период Сторно Регистр сведений * * * Регистр накопления + + * Регистр бухгалтерии + + * Регистр расчета + + Для регистра накопления колонка ВидДвижения будет присутствовать, только если это регистр накопления ос- татков. Для регистра бухгалтерии колонка ВидДвижения будет присутствовать, только если этот регистр не поддержива- ет корреспонденцию. Как правило, колонками списка управляет табличное поле, отображающее данные этого списка. Такой меха- низм работы позволяет минимизировать обращения к базе данных, так как выполняется чтение только тех по- лей, которые отображаются в табличном поле, а также тех, которые необходимы для обеспечения работы таб- личного поля. По этой причине, при отключении видимо- сти или удалении колонки в табличном поле, она будет удалена и в связанном с этим табличном полем списке. Однако существуют ситуации, когда необходимо, чтобы источник данных (список) содержал колонки, которые не отображаются в табличном поле. Для этого можно ис- пользовать свойство колонки списка АвтоУдаление. При ус- тановке этого свойства в значение Ложь соответствующая колонка уже не будет удаляться из списка при отключе- нии видимости или удалении ее из табличного поля. Отбор Свойство Отбор позволяет ограничивать состав считывае- мых данных различными условиями, которые накладыва- ются на считываемые поля. В отбор по умолчанию вклю- чаются все поля источника данных, за исключением полей типа ХранилищеЗначения, так как по этим полям отбор невоз- можен. Например, если в форме расположено табличное поле, свя- занное со списком справочника Номенклатура, то отбор спи- ска может быть настроен следующим образом (листинг 4.45). Листинг 4.45. Настройка отбора списка ОтборСписка = СписокСправочника.Отбор; ОтборСписка.Наименование.ВидСравнения = ВидСравнения.Содержит; ОтборСписка.Наименование.Значение = "жен"; ОтборСписка.Наименование.Использование = Истина; ОтборСписка.ЭтоГруппа.Установить(Ложь, Истина); В данном примере показаны два способа управления от- бором. Во-первых, разработчик имеет возможность для каждого элемента отбора задать нужный вид сравнения и значе- ние. При помощи этого способа устанавливается условие на наименование считываемых элементов справочника — будут считаны только те элементы, в наименовании кото- рых содержится строка «жен». Во-вторых, в большинстве случаев достаточно исполь- зовать более короткий способ установки отбора, с ис- пользованием метода УстановитьО элемента отбора. Та- ким способом задается условие считывания только тех
элементов справочника, которые не являются группой. Единственное ограничение в данном случае — это то, что вид сравнения, устанавливаемый таким образом — Равно. Если необходимо использовать другой вид сравнения — нужно описывать его отдельно, как в первом случае. Порядок Свойство Порядок позволяет указывать, в каком порядке будут отсортированы записи источника данных. При выборе полей для упорядочивания следует учиты- вать, что упорядочивание возможно не по всем полям. Так, например, для любых прикладных объектов невоз- можно упорядочивание по полям: ♦ типа Строка неограниченной длины; ♦ типа ХранилищеЗначения; ♦ по полям составного типа (если в состав типов входит более одного типа); ♦ по полям, являющимся наборами типов. Настройки порядка имеют важное значение для работы механизма динамического просмотра данных. Дело в том, что при работе этого механизма система использует ин- дексы тех таблиц, содержимое которых отображается. Если не один из индексов таблицы не соответствует за- данному пользователем упорядочиванию, механизм ди- намического просмотра задействован не будет, и из базы данных будут считываться сразу все данные, которые должны быть отображены в списке. Это может приводить к «задержкам» при работе пользователя. При установке порядка следует учитывать индексирова- ние, которое система осуществляет по умолчанию, а так- же индексирование, задаваемое разработчиком (за счет использования свойств Индексировать и Индексировать с доп. упорядочиванием). Это позволит использовать динами- ческие списки максимально эффективным образом. По умолчанию система упорядочивает данные по полям, которые представлены в таблицах 4.22 и 4.23. Также сис- тема выполняет и дополнительное упорядочивание в тех случаях, когда требуется исключить неоднозначность в упорядочивании данных. Например, если справочник упорядочен по полю Наименование, то система выполнит дополнительное упорядочивание по полю Ссылка, чтобы для элементов, имеющих одинаковое наименование, так- же можно было определить порядок. Таким образом, например, для списка неиерархического справочника оптимальным будет упорядочивание по полю Код или по полю Наименование, а для списка регист- ра накопления — упорядочивание по полю Период. Таблица 4.22. Упорядочивание в списках объектных данных Прикладной объект Упорядочивание по умолчанию Дополнительное упорядочивание Справочник (иерархический, «группы сверху») ЭтоГруппа + Код или ЭтоГруппа + Наименование (в зависимости от основного представления справочника) Ссылка Справочник (без иерархии или «группы сверху» не установлено) Код или Наименование (в зависимости от основного представления) План видов характеристик План счетов План видов расчета План обмена Бизнес-процесс Дата Задача Документ Журнал документов Таблица 4.23. Упорядочивание в списках необъектных данных Прикладной объект Упорядочивание по умолчанию Дополнительное упорядочивание Регистр сведений (периодический) Период Список измерений в той последователь- ности, как они заданы в конфигураторе Регистр сведений (непериодический) Список измерений в той последователь- ности, как они заданы в конфигураторе Регистр накопления Период Регистратор + НомерСтроки Регистр бухгалтерии Регистр расчета ПериодРегистрации
Таблица 4.24. Варианты упорядочивания для списков объектных данных по умолчанию и при использовании варианта Индексировать Прикладной объект Поля, упорядочивание по которым является оптимальным Поля, упорядочивание по которым также является оптимальным, при условии, что для Реквизит (Графа) установлено «Индексировать» Справочник (иерархический, «группы сверху») ЭтоГруппа + Код ЭтоГруппа + Наименование ЭтоГруппа + Реквизит Справочник (без иерархии или «группы сверху» не установлено) Код Наименование Реквизит План видов характеристик План счетов План видов расчета План обмена Бизнес-процесс Дата Номер Завершен Стартован Задача Дата Наименование Номер Выполнена Документ Дата Номер Журнал документов Дата Графа Таблица 4.25. Варианты упорядочивания для списков объектных данных по умолчанию и при использовании варианта Индексировать с доп. упорядочиванием Прикладной объект Поля, упорядочивание по которым является оптимальным Поля, упорядочивание по которым также является оптимальным, при условии, что для Реквизит (Графа) установлено «Индексировать с доп. упорядочиванием» Справочник (иерархический, «группы сверху») ЭтоГруппа + Код ЭтоГруппа + Наименование ЭтоГруппа + Реквизит + Код ЭтоГруппа + Реквизит + Наименование Справочник (без иерархии или «группы свер- ху» не установлено) Код Наименование Реквизит + Код Реквизит + Наименование План видов характеристик План счетов План видов расчета План обмена Бизнес-процесс Дата Номер Завершен Стартован Реквизит + Дата Задача Дата Наименование Номер Выполнена Документ Дата Номер Журнал документов Дата Г рафа + Дата
Наряду с тем, что система индексирует по умолчанию структуры данных, разработчик дополнительно может указать необходимость индексирования по соответствую- щему реквизиту, используя его свойство Индексировать. При этом он может использовать один из двух вариантов построения индекса: Индексировать или Индексировать с до- полнительный упорядочиванием. В варианте Индексировать индекс строится непосредствен- но по самому реквизиту. Использование такого варианта позволяет эффективно упорядочивать динамические спи- ски не только по тем полям, которые индексируются сис- темой по умолчанию, но также и по данному реквизиту. В варианте Индексировать с дополнительным упорядочиванием индекс будет строиться по указанному реквизиту плюс по некоторому полю, которое обычно используется систе- мой для упорядочивания по умолчанию. Например, для неиерархического справочника индекс будет строиться по данному реквизиту плюс код или по данному реквизи- ту плюс наименование. Такой вариант позволяет эффек- тивно отбирать динамические списки по сочетанию поля реквизита и поля, используемого для упорядочивания по умолчанию. В сводном виде различные оптимальные варианты упо- рядочивания представлены в табл. 4.24-4.26. Следует также учитывать, что неправильный выбор по- лей для упорядочивания может привести не только к не- эффективной работе механизма динамического просмот- ра списков, но даже к невозможности его использования вообще. Это может происходить, например, если в составе полей, по которым производится упорядочивание, присутствует поле, которое не является полем примитивного типа. На- пример, если упорядочить регистр накопления по полю, имеющему тип СправочникСсылка.Контрагенты, то в этом слу- чае упорядочивание будет выполняться по полю основного представления справочника Контрагенты, кото- рое находится не в таблице регистра сведений, а в табли- це справочника Контрагенты. Также динамический просмотр списка не будет работать, если для полей, по которым выполняется упорядочива- ние, задано различное направление сортировки. Более подробно об индексировании таблиц базы данных можно прочитать в разделе «Индексы таблиц базы дан- ных», с. 788. Выборка Выборка предназначена для динамического обхода эле- ментов данных, хранимых в структуре объекта конфигу- рации. Выборка не считывает данные целиком в память, а получает их блоками, по мере обхода выборки методом Следующий О (листинг 4.46). Листинг 4.46. Пример обхода выборки ВыборкаВалют = Справочники. Валюты. ВыбратьО; Пока ВыборкаВалют.Следующий() Цикл Сообщить(ВыборкаВалют.Наименование); КонецЦикла; Благодаря тому, что считывание данных осуществляется порциями, выборку можно использовать для обработки очень больших объемов информации. Каждый блок считываемых данных содержит 25 записей. Для объектных таблиц каждая такая запись содержит все данные объекта, включая все его поля и табличные части. Поэтому, например, при обращении к реквизитам выбор- ки или при получении объекта из выборки не происходит повторного обращения к базе данных. Таблица 4.26. Варианты упорядочивания для списков необъектных данных по умолчанию и при использовании варианта Индексировать Прикладной объект Поля, упорядочивание по которым является оптимальным Поля, упорядочивание по которым также является оптимальным, при условии, что для Поле установлено «Индексировать» Регистр сведений (периодический) Период Период + <список измерений> <список всех измерений> + Период Поле + Период Поле + Период + <список измерений> Регистр сведений (непериодический) Список измерений в той последовательности, как они заданы в конфигураторе Поле + <список измерений> Регистр накопления Регистр бухгалтерии Период Поле + Период Регистр расчета ПериодРегистрации ПериодДействия ПериодРегистрации + <список всех базовых измерений> ПериодДействия + <список всех базовых измерений> <список всех базовых измерений> + ПериодДействия <список всех базовых измерений> + ПериодРегистрации ПериодРегистрации + Поле Поле + ПериодРегистрации
Выборка осуществляет считывание данных в определен- ном порядке. Этот порядок может задаваться, например, путем указания параметров Отбор и Порядок метода Вы- братьО. Отбор может быть выполнен только по одному полю, причем это может быть только то поле, для которого по- строен индекс. Кроме полей, которые индексируются системой по умолчанию, это может быть также поле, для которого в конфигураторе установлен признак индек- сирования в значение Индексировать или Индексировать с дополнительным упорядочиванием. Отбор по таким полям позволяет выполнять выборку быстро и эффективно. На- пример, приведенный ниже пример (листинг 4.47) позво- ляет выбрать из справочника Номенклатура только те эле- менты, для которых не задан артикул. Листинг 4.47. Пример использования отбора СтруктураОтбора = Новый Структура; СтруктураОтбора.Вставить("Артикул", ""); ВыборкаНоменклатуры = Справочники.Номенклатура. Выбрать( , , СтруктураОтбора); Пока ВыборкаНоменклатуры.СледующийО Цикл Сообщить(ВыборкаНоменклатуры.Наименование); КонецЦикла; Отбор задается структурой, содержащей единственный элемент, у которого ключ соответствует имени поля, а значение — значению отбора. Порядок отбираемых записей также может быть задан с использованием полей, которые либо индексируются по умолчанию, либо эти поля имеют примитивный тип и для них построение индекса указано в явном виде в кон- фигураторе. Например, следующий пример (листинг 4.48) позволяет выбрать элементы справочника Договоры контр- агентов в порядке убывания даты договора. Листинг 4.48. Пример использования порядка ВыборкаДоговоров = Справочники.ДоговорыКонтрагентов. Выбрать( , , , "Дата Убыв”); Пока ВыборкаДоговоров.Следующий() Цикл Сообщить(ВыборкаДоговоров); КонецЦикла; Для иерархических данных (например, справочников, пла- нов видов характеристик, планов счетов) существует также иерархическая выборка, получаемая методом ВыбратьИерар- хическиО. Такая выборка отличается от обычной тем, что выдает данные путем обхода записей в соответствии с их иерархией. То есть после выдачи элемента, выдается подчи- ненный ему элемент, если такой существует. Если подчи- ненных не существует, то выдается следующий элемент. Причем каждое считывание подчиненных элементов реали- зовано как считывание отдельного блока данных. Кроме отбора и порядка, выборка позволяет задать также родителя и владельца считываемых данных. При указа- нии конкретного родителя выборка, получаемая методом ВыбратьО, будет содержать те элементы, родитель кото- рых равен указанному (рис. 4.34). В то же время выборка, получаемая методом ВыбратьИерар- хическиО, будет содержать все элементы, находящиеся в иерархии указанного родителя, то есть в первом, втором и последующих уровнях иерархии (рис. 4.35). Если в методе Выбрать () в качестве родителя указать пус- тую ссылку, то будут выбраны все элементы первого уровня (рис. 4.36). При указании в параметрах выборки конкретного вла- дельца будут отбираться записи подчиненного справоч- ника, владелец которых равен указанному. Например, в следующем примере (листинг 4.49) будут выбраны все договоры контрагента с кодом Ю0004. Листинг 4.49. Выборка подчиненных элементов Владелец = Справочники.Контрагенты.НайтиПоКоду("Ю0004"); ВыборкаДоговоров = Справочники.ДоговорыКонтрагентов. ВыбратьИерархически( .Владелец); Пока ВыборкаДоговоров.СледующийО Цикл Сообщить(ВыборкаДоговоров); КонецЦикла; Особенности использования выборки Как было показано выше, выборка считывает данные в определенной последовательности сортировки. При об- ходе выборки методом СледующийО выполняется получе- ние очередных блоков данных в соответствии с порядком сортировки и в соответствии с выдачей записей ранее считанного блока. Другими словами, очередной блок счи- тывается как множество записей, которые следуют в ука- занном порядке после последней полученной записи пре- дыдущего блока (рис. 4.37). Особенностью такой схемы работы механизма выборки является то, что разработчик не имеет контроля над акту-
альностью получаемой информации, даже если выборка инициирована в транзакции. При получении очередной записи нет возможности определить, считывается ли эта запись из уже полученного ранее блока или же она была только что считана в составе нового блока записей. Рис. 4.37. Считывание данных блоками Эта особенность работы механизма выборки может при- водить к тому, что в выборку могут попасть данные уда- ленного объекта, некоторые записи могут попасть дваж- ды или не попасть в выборку вообще. Получение данных удаленного объекта. Например, после получения записей очередного блока одна из записей, от- носящихся к этому блоку, была удалена из базы данных. В этом случае к моменту окончания обхода выборки фи- зически эта запись будет отсутствовать в базе данных, хотя в то же время она будет присутствовать в получен- Множественное попадание записи в выборку. Например, в процессе получения выборки справочника в порядке наименования, элемент справочника Женские сапоги был переименован в Сапоги женские. В этом случае порядок следования данной записи изменится, и может возник- нуть ситуация, когда переименованный элемент справоч- ника в порядке следования окажется среди записей еще не считанного блока. В этом случае при получении дан- ного блока эта запись будет считана повторно (рис. 4.39). Непопадание записи в выборку. Ситуация, когда запись может вообще не попасть в выборку, прямо противопо- ложна предыдущей. Например, в процессе выборки спра- вочника в порядке наименования элемент справочника Сапоги женские, находящийся в порядке следования среди записей еще не считанного блока, был переименован в Женские сапоги и в соответствии с порядком следова- ния оказался среди записей уже считанного ранее блока (рис. 4.40). Рис. 4.39. Множественное попадание записи в выборку Рис. 4.40. Непопадание записи в выборку Грабли Компьютер Удаление иерархических данных. Особенность использова- ния выборки для обхода и удаления иерархических дан- ных связана с тем, что при удалении элемента (родителя) удаляются и все его подчиненные элементы (рис. 4.41). Таким образом, при использовании обычной выборки мо- жет возникнуть ситуация, когда в результате удаления элемента могут быть удалены также и элементы, уже счи- танные в текущем блоке (рис. 4.42). Рис. 4.42. Удаление родителя в процессе выборки В этом случае при попытке выполнения каких-либо дей- ствий с полученным из выборки объектом (на рисунке — Подчиненный!) будет выдаваться ошибка, так как в базе данных этот объект уже не существует.
По этой причине, для удаления иерархических данных следует использовать иерархическую выборку. В этом случае все подчиненные элементы будут располагаться в порядке следования в одном или нескольких блоках за родительским элементом, и после удаления родителя (и соответственно его подчиненных элементов) просто будет выполнено чтение следующего за ними по порядку блока записей (рис. 4.43). Удаленный элемент Удаленный подчиненный элемент Удаленный подчиненный элемент Удаленный подчиненный элемент Рис. 4.43. Удаление родителя в процессе иерархической выборки Обобщая все перечисленные особенности использования выборок, можно сказать, что следует внимательно отно- ситься к изменению объектов в процессе обхода динами- ческой выборки, так как это может повлиять на порядок их включения в выборку. Наряду с этим рекомендуется использовать динамические выборки либо для задач, не требующих ответственного чтения данных, либо для рег- ламентных задач, которые могут выполняться в моно- польном режиме. Также использование динамических выборок можно рекомендовать в тех случаях, когда объем данных, выбираемых из базы данных, очень велик, и по- лучение выборки такого объема другими способами (на- пример, запросом) неэффективно. Типы данных Тип данных в системе 1 (^Предприятие представляет со- бой перечень возможных типов значений, которые могут быть использованы тем или иным элементом системы. Типы данных используются при описании таких элемен- тов системы, как: ♦ объекты метаданных (реквизиты, измерения, ресурсы и др.); ♦ реквизиты формы; ♦ элементы управления, расположенные в форме и в таб- личном документе; ♦ некоторые объекты встроенного языка (список зна- чений, колонки таблицы значений и дерева значений и др-). Тип данных позволяет перечислить типы значений, кото- рые используются, а также для некоторых примитивных типов значений позволяет задать квалификаторы, описы- вающие допустимые значения примитивных типов. При визуальном конструировании тип данных может быть описан с помощью палитры свойств или в специаль- ном диалоге редактирования типа данных. Во встроенном языке для описания типа данных используется объект встроенного языка ОписаниеТипов. Числовые типы данных При описании допустимых значений типа Число сущест- вует возможность указать: ♦ допустимый знак числа (он может быть любым или не- отрицательным); ♦ общую разрядность числа; ♦ разрядность дробной части. Эта возможность часто используется при организации интерфейса системы. При редактировании объектов конфигурации (например, при указании типа данных реквизита формы) числовой тип данных описывается средствами визуального конст- руирования (рис. 4.44). Рис. 4.44. Редактирование типа данных Число Кроме этого, числовой тип данных может быть указан и средствами встроенного языка (например, при созда- нии таблицы значений, которая в дальнейшем будет ис- пользована для ввода данных) (листинг 4.50). Для этого используется объект КвалификаторыЧисла. Листинг 4.50. Использование квалификаторов числа КвалификаторЧисла = Новый КвалификаторыЧисла(5, 2, ДопустиныйЗнак.Неотрицательный); ОписаниеТипа = Новый ОписаниеТиповСЧисло", КвалификаторЧисла); ТаблицаСкидок.Колонки.Добавить("Товар", Новый ОписаниеТипов("СправочникСсылка.Номенклатура”)); ТаблицаСкидок.Колонки.Добавить("Скидка", ОписаниеТипа); ЭлементыФормы.ТабличноеПолеСкидки.Создат ьКолонки(); В этом примере сначала создается новый объект Квалифика- торыЧисла, устанавливающий общее количество разрядов равным пяти, количество разрядов дробной части равным двум и допустимый знак числа — неотрицательный. Затем, на основании этого объекта создается новый объект Описа- ниеТипов, содержащий описание типа Число с указанными ограничениями. Далее, при добавлении колонки Скидка в таблицу значений ТаблицаСкидок этот объект указывается в качестве описания типа данной колонки. Таким образом, в колонке Скидка таблицы значений ТаблицаСкидок сможет находиться неотрицательное число, содержащее пять раз- рядов, из которых два отведены под дробную часть числа. Строковые типы данных При описании допустимых значений типа Строка сущест- вует возможность указать: ♦ какой вариант ограничения длины будет использовать- ся для строкового значения (фиксированная длина или переменная длина);
♦ длину строкового значения (в случае фиксированной длины). В зависимости от длины строки различают строки огра- ниченной и неограниченной длины. Если длина строки равна нулю, то такая строка имеет неограниченную длину. В противном случае строка будет иметь ограниченную длину. Отличие строк ограниченной и неограниченной длины можно проиллюстрировать следующим примером. Пусть есть два реквизита: строка длиной 10 (СтрокаОгра- ниченнаяЮ) и строка неограниченной длины (СтрокаНе- ограниченная). Тогда при присвоении этим реквизитам строкового значения, имеющего длину 14 символов, в первом случае оно будет обрезаться до 10 символов, а во втором случае — нет (листинг 4.51): Листинг 4.51. Использование строк ограниченной и неограниченной длины СтрокаОграниченнаяЮ = "новое значение": Сообщить("Строка ограниченной длины (10): " + . + СтрокаПерененнаяЮ + .); СтрокаНеограниченная = "новое значение"; Сообщить("Строка неограниченной длины: " + .. + СтрокаНеограниченная + .); Результатом выполнения приведенного примера будут следующие сообщения: Строка ограниченной длины (10): "новое знач" Строка неограниченной длины: "новое значение" Строки ограниченной длины могут быть двух видов: фиксированной и переменной длины. Их отличие также лучше всего продемонстрировать на примере. Пусть есть два реквизита: строка фиксированной длины 10 символов (СтрокаФиксированнаяЮ) и строка перемен- ной длины 10 символов (СтрокаПеременнаяЮ). Тогда, при присвоении этим реквизитам строкового значения, имею- щего длину 5 символов, в первом случае оно будет допол- няться пробелами справа до указанной длины, а во вто- ром случае — нет (листинг 4.52). Листинг 4.52. Использование строк фиксированной и переменной длины СтрокаФиксированнаяЮ = "новое”: Сообщить!"Строка фиксированной длины (10): “ + . + СтрокаФиксированнаяЮ + .); СтрокаПерененнаяЮ = "новое"; Сообщить("Строка переменной длины (10): " + . + СтрокаПеременнаяЮ + Результатом выполнения приведенного примера будут следующие сообщения: Строка фиксированной длины (10): "новое" Строка переменной длины (10): "новое" При редактировании объектов конфигурации (например, при указании типа данных реквизита формы) строковый тип данных описывается средствами визуального конст- руирования (рис. 4.45). Кроме этого, строковый тип данных может быть указан и средствами встроенного языка. Например, при созда- нии таблицы значений, которая в дальнейшем будет ис- пользована для ввода данных (листинг 4.53). Для этого используется объект КвалификаторыСтроки. Рис. 4.45. Редактирование типа данных Строка Листинг 4.53. Использование квалификаторов строки КвалификаторСтроки = Новый КвалификаторыСтроки(5, ДопустинаяДлина.Переменная); ОписаниеТипа = Новый ОписаниеТипов("Строка", КвалификаторСтроки); ТаблицаСкидок.Колонки.Добавить("Товар", Новый ОписаниеТиповССправочникСсылка.Номенклатура")); ТаблицаСкидок.Колонки.ДобавитьСАртикул", ОписаниеТипа); Элем ентыФормы.ТабличноеПолеСкидки. Соз датьКолонкиО; В этом примере сначала создается новый объект Квалифи- каторыСтроки, устанавливающий переменную длину строки в пять символов, затем на основании этого объекта созда- ется новый объект ОписаниеТипов, содержащий описание типа Строка с указанными ограничениями. Далее, при до- бавлении колонки Артикул в таблицу значений Таблица- Скидок этот объект указывается в качестве описания типа данной колонки. Таким образом, в колонке Артикул таб- лицы значений ТаблицаСкидок сможет находиться строка переменной длины, содержащая максимум пять разрядов. Типы данных, описывающие значения типа Дата При описании допустимых значений типа Дата существу- ет возможность указать части даты, которые будут ис- пользованы: ♦ дата и время; ♦ дата; ♦ время. При редактировании объектов конфигурации (например, при указании типа данных реквизита формы) использу- ются средства визуального конструирования (рис. 4.46). Редактирование типа данных [^Составной тип данных; Произвольный -ДО Число Строга Булево___________________________________д Состав доты (дата и время т ОК 11 Отмена | Рис. 4.46. Редактирование типа данных Дата Кроме этого, тип данных, описывающий значения типа Дата, может быть указан и средствами встроенного языка. Например, при создании таблицы значений, которая в дальнейшем будет использована для ввода данных (лис- тинг 4.54). Для этого используется объект Квалифика- торыДаты.
Листинг 4.54. Использование квалификаторов даты КвалификаторДаты = Новый КвалификаторыДаты(ЧастиДаты.Дата): ОписаниеТипаДата = Новый ОписаниеТиповС'Дата”, КвалификаторДаты); КвалификаторЧисла = Новый КвалификаторыЧисла(15, 2); ОписаниеТипаЧисло = Новый ОписаниеТиповС'Число". КвалификаторЧисла); ТаблицаКурсВалют.Колонки.Добавить("Дата". ОписаниеТипаДата); ТаблицаКурсВалют.Колонки.Добавить("Курс", ОписаниеТипаЧисло); ЭленентыФорны.ТабличноеПолеКурсВалют.СоздатьКолонки(); В этом примере сначала создается новый объект Квалифи- каторыДаты, который устанавливает использование части даты — Дата. Затем, на основании этого объекта создается новый объект ОписаниеТипов, содержащий описание типа Дата с указанными ограничениями. Далее, при добавле- нии колонки Дата в таблицу значений ТаблицаКурсВалют этот объект указывается в качестве описания типа созда- ваемой колонки. Таким образом, в колонке Дата смогут находиться значения типа Дата, для которых возможно изменение только непосредственно самой даты. Время у этих значений всегда будет равно 00 часов 00 минут 00 се- кунд. Составной тип данных До сих пор мы рассматривали типы данных, содержащие описание только одного типа значений. Однако в общем случае тип данных может содержать перечень нескольких типов значений. Такой тип данных называется состав- ным. Благодаря наличию составного типа в базе данных могут храниться реквизиты, значения которых имеют разный тип в разные моменты времени, однако в один момент времени может храниться значение только одного из пе- речисленных типов. Например, документ Внутренний заказ может иметь рекви- зит Заказчик, имеющий составной тип данных: Справочник- Сашка. Подразделения, СправочникСсылка.Склады (рис. 4.47). Рис. 4.47. Реквизит составного типа Это значит, что в этом реквизите могут храниться как значения ссылок на справочник Подразделения, так и зна- чения ссылок на справочник Склады. Тип значения такого реквизита в каждый момент време- ни может быть различным и определяется значением, ко- торое в данный момент хранится в реквизите. Другими словами, если реквизиту присвоить значение ссылки на справочник Подразделения, то тип значения реквизита бу- дет СправочникСсылка.Подразделения, если присвоить ссылку на справочник Склады, то тип значения будет — Справоч- никСсылка. Склады. Описание значений составного типа Описание составного типа данных может быть выпол- нено как средствами визуального конструирования, так и средствами встроенного языка. В процессе визуального описания объектов конфигура- ции для этого используется окно редактирования типа данных (рис. 4.48). Рис. 4.48. Окно редактирования типа данных Разработчик может перечислить типы значений и наборы типов, которые должны входить в составной тип данных, а также, при необходимости, задать квалификаторы для числовых, строковых значений и значений типа Дата. Описывать составной тип данных можно также средства- ми встроенного языка. Например, если в форме располо- жено поле ввода ПолеВводаСоставногоТипа, не связанное с данными, то задать его составной тип данных можно сле- дующим образом (листинг 4.55). Листинг 4.55. Описание составного типа МассивТипов = Новый Массив; МассивТипов.Добавить(Тип("Строка")); МассивТипов.Добавить(Тип("Число")): МассивТипов.Добавить(ТипС'СправочникСсылка.Номенклатура")); ОписаниеСоставногоТипа = Новый ОписаниеТипов(МассивТипов); ЭленентыФорны.ПолеВводаСоставногоТипа.ТипЗначения = ОписаниеСоставногоТипа: В этом примере сначала создается массив, содержащий все нужные типы значений, а затем на его основании соз- дается новый объект ОписаниеТипов, который присваивает- ся свойству ТипЗначения нужного поля ввода. Это свойство как раз и определяет тип данных, которые будут редакти- роваться в поле ввода.
Значение реквизита составного типа по умолчанию Для реквизита составного типа значением по умолчанию является значение Неопределено (подробнее о значении Не- определено можно прочитать в разделе «Неопределено», с. 55). По этой причине тип Неопределено всегда входит со- ставной тип данных, наряду с прочими типами. Представ- лением значения Неопределено является пустая строка. Если значение реквизита составного типа данных по умол- чанию отображается в поле ввода, то в этом случае поле ввода будет содержать дополнительную информацию, указывающую на то, что этот элемент управления под- держивает выбор из нескольких типов значений: вместо многоточия, кнопка выбора будет содержать символ «Т» (рис. 4.49). Рис. 4.49. Отображение значения по умолчанию реквизита составного типа При нажатии па кнопку выбора система предложит вы- брать один из возможных типов значений, а после этого можно будет ввести конкретное значение выбранного типа. Преобразование значений, хранящихся в реквизитах составного типа Неявное преобразование При присвоении значений реквизитам, имеющим состав- ной тип данных, могут возникнуть ситуации, когда при- сваемое значение не соответствует текущему типу значе- ния реквизита. В этом случае система будет выполнять неявное преобразование типа присваемого значения к од- ному из доступных типов значений. Если составной тип данных содержит тип присваемого значения, то реквизиту будет установлен новый тип зна- чения и новое значение. Например, пусть для реквизита СоставнойРеквизит задан составной тип данных (рис. 4.50) и текущее значение рек- визита равно Истина. Рис. 4.50. Состав типов После выполнения оператора, приведенного в листин- ге 4.56, значение реквизита станет равным «новая строка». Листинг 4.56. Присвоение нового значения реквизиту составного типа СоставнойРеквизит = "новая строка": Если тип присваемого значения не соответствует ни од- ному из типов, входящих в составной тип данных, тогда система попытается привести тип присваемого значения к одному из типов составного типа данных. Например, после выполнения оператора (листинг 4.57) значение реквизита СоставнойРеквизит станет равным строке 10, то есть система приведет значение типа Число к значению типа Строка, который входит в составной тип данных. Листинг 4.57. Присвоение значения реквизиту составного типа СоставнойРеквизит = 10: В случае если система не сможет выполнить приведение присваемого значение ни к одному типу, входящему в со- ставной тип данных, реквизиту будет присвоено значение по умолчанию — Неопределено. Явное преобразование Явное преобразование к значению реквизита составного типа данных может быть выполнено с использованием объекта встроенного языка ОписаниеТипов. Этот объект имеет метод ПривестиЗначениеО, который позволяет при- вести значение произвольного типа к значению, соответ- ствующему составному типу данных (листинг 4.58). Листинг 4.58. Приведение значения МассивТипов = Новый Массив; МассивТипов.Добавить(Тип ("Строка")); МассивТипов.Добавить(Тип("Число")): МассивТипов.Добавить(Тип(”СправочникСсылка.Номенклатура")); ОписанмеСоставногоТипа = Новый ОписаниеТипов(МассивТипов); ПриводимоеЗначение = Справочники.Номенклатура. НайтиПоКодуС"00001"): Результат = ОписаниеСоставногоТипа. ПривестиЗначение(ПриводимоеЗначение); СообщитьС" + ТипЭнч(Результат) + " + Результат); В результате выполнения этого кода будет выведено сле- дующее сообщение: Справочник ссылка: Номенклатура: Сигареты Если несколько видоизменить код и в качестве приводи- мого значения получить не ссылку на справочник но- менклатура, а объект справочника, то результат будет уже другим: Строка: Сигареты Так происходит потому, что тип СправочникОбъект.Номенк- латура не входит в составной тип данных, и система при- водит его к одному из типов, входящих в составной тип, в данном случае к типу Строка. Наборы типов При выборе типа данных реквизита система, помимо вы- бора типов, определенных в конкретном прикладном ре- шении, предоставляет разработчику возможность выби- рать наборы типов. Наборами типов, например, являются ЛюбаяСсылка, СправочникСсылка, Характеристика.<имя> и др. Наборы типов, так же как и составной тип данных, содер- жат некий перечень типов, определенных в данном при-
кладном решении, однако, в отличие от составного типа, этот перечень формируется системой автоматически, в результате анализа метаданных. Проведем сравнение на примере ссылок на справочники. Допустим, в прикладном решении имеются справочники Номенклатура и Контрагенты. Тогда мы можем определить реквизит составного типа данных, в который входят типы СправочникСсылка.Номенклатура и СправочникСсылка.Контраген- ты. Наряду с этим мы можем определить реквизит, содер- жащий набор типов СправочникСсылка. И в том и в другом случае мы будем иметь возможность хранить в реквизите ссылки как на справочник Номенклатура, так и на справоч- ник Контрагенты. Теперь добавим в конфигурацию новый справочник Це- ны. В реквизите составного типа мы по-прежнему сможем хранить только ссылки на справочники Номенклатура и Контрагенты, а в реквизите, описанном как набор типов, мы сможем хранить ссылку на любой из справочников, доступных в данной конфигурации, в том числе и на справочник Цены. При запуске прикладного решения набор типов преобра- зуется системой, как правило, в составной тип, содержа- щий все типы, которые должны входить в этот набор. По- этому во втором случае в набор типов попадет и новый справочник Цены. Однако набор типов не всегда преобразуется системой в составной тип данных. Если оказывается, что в набор типов входит единственный тип значений, то набор типов будет преобразован в этот самый тип значений. Такая си- туация возможна, например, когда план видов характери- стик (назовем его Свойства) имеет единственный тип зна- чений в свойстве ТипЗначенияХарактеристик. Тогда набор типов Характеристика.Свойства будет преобразован систе- мой не в составной тип данных, содержащий один тип значений, а в тот единственный тип значений, который указан для плана видов характеристик. Эта особенность может быть важна, когда, например, вы- полняется проверка реквизита, тип которого описан как Характеристика.Свойства, на заполненность. В случае когда Характеристика.Свойства преобразуется системой в состав- ной тип данных, проверять нужно на значение Неопределе- но, а если Характеристика.Свойства преобразуется в опреде- ленный тип значения, то проверять нужно на значение по умолчанию данного типа. Транзакции Независимо о выбранного варианта работы (файловый или клиент-серверный), система 1 С: Предприятие обеспе- чивает работу с информацией, хранящейся в базе данных с использованием механизма транзакций. Транзакция — это неделимая, с точки зрения воздействия на базу данных, последовательность операций манипули- рования данными, выполняющаяся по принципу «все или ничего», и переводящая базу данных из одного цело- стного состояния в другое целостное состояние. Если по каким-либо причинам одно из действий транзакции не- выполнимо или произошло какое-либо нарушение рабо- ты системы, база данных возвращается в то состояние, ко- торое было до начала транзакции (происходит откат транзакции). Одним из главных свойств транзакции является ее ато- марность, то есть неделимость. Рассмотрим простой при- мер: интерактивная пометка на удаление группы справоч- ника. Фактически это означает, что нужно выполнить целую последовательность операций: ♦ для группы справочника установить значение поля По- меткаУдаления; ♦ записать группу справочника; ♦ выбрать все элементы справочника, находящиеся в иерар- хии помечаемой группы; ♦ для каждого из них установить значение поля Пометка- Удаления; ♦ выполнить запись каждого из выбранных элементов. В общем случае нет гарантии, что каждая из перечислен- ных операций будет успешно выполнена. Например, один из подчиненных элементов справочника может редакти- роваться другим пользователем, и система в этом случае не сможет изменить данные этого элемента справочника. В результате часть элементов справочника окажется по- меченными на удаление, а часть — нет. С точки зрения системы такая ситуация недопустима и нарушает целост- ность базы данных, так как результатом интерактивной пометки на удаление должна быть установка пометки на удаление самого элемента и всех его подчиненных эле- ментов. То есть должны быть выполнены либо все пере- численные операции, либо ни одна из них. Для того чтобы обеспечить именно такое поведение, уста- новка пометки на удаление выполняется системой в транзакции. Если в процессе выполнения этой последо- вательности операций произойдет ошибка (например, один из подчиненных элементов будет заблокирован дру- гим пользователем), будет выполнен откат транзакции, и изменения, которые к этому моменту произошли в базе данных, будут отменены (рис. 4.51). транзакция ошибка Рис. 4.51. Отказ от изменений, выполненных в транзакции Таким образом, перечисленная последовательность опе- раций становится неделимой с точки зрения базы данных: изменения будут зафиксированы в базе данных только в том случае, если транзакция успешно завершена, то есть выполнены все перечисленные операции (рис. 4.52). Транзакции могут использоваться как самой системой, так и разработчиком при написании модулей.
Рис. 4.52. Принятие изменений, выполненных в транзакции Начать Отменить транзакцию транзакцию Рис. 4.53. Отмена изменений Система осуществляет неявный вызов транзакций при выполнении любых действий, связанных с модификаци- ей информации, хранящейся в базе данных. Например, все обработчики событий, расположенные в модулях объ- ектов и наборов записей, связанные с модификацией дан- ных базы данных, вызываются в транзакции. Наряду с этим разработчик может использовать работу с транзакциями в явном виде. Для этого используются процедуры глобального контекста НачатьТранзакциюО, За- фиксироватьТранзакциюО и ОтменитьТранзакциюО- База данных Начать Зафиксировать транзакцию транзакцию Рис. 4.54. Принятие изменений Использование явного вызова транзакций Процедура НачатьТранзакциюО позволяет открыть тран- закцию. После этого все изменения информации базы данных, выполняемые последующими операторами, мо- гут быть либо целиком приняты, либо целиком отверг- нуты. Для принятия всех выполненных изменений использует- ся процедура ЗафиксироватьТранзакциюО. Для того чтобы отменить все изменения, выполнявшиеся в открытой транзакции, используется процедура Отме- нитьТранзакциюО. Например, может использоваться следующая схема рабо- ты с транзакцией (листинг 4.59). Листинг 4.59. Пример использования транзакции НачатьТранзакциюО; // Последовательность выполняемых операторов // Проверка возможности выполнения операции Если НЕ <условие> Тогда ОтненитьТранзакциюО; КонецЕсли; // Последовательность выполняемых операторов ЗафиксироватьТранзакциюО; Суть этой схемы заключается в том, что в процессе вы- полнения связанной последовательности изменений дан- ных базы данных проверяется возможность выполнения некоторых операций. Если операцию выполнить невоз- можно, осуществляется откат всех произведенных изме- нений к состоянию, которое существовало перед выпол- нением оператора НачатьТранзакциюО (рис. 4.53). Если все операции выполнены успешно, то после выпол- нения оператора ЗафиксироватьТранзакциюО все произве- денные изменения будут зафиксированы в базе данных (рис. 4.54). Обработка ошибок базы данных в транзакции Далеко не во всех случаях разработчик заранее может предусмотреть все возможные проверки. По большому счету это и не нужно. Встроенный язык предоставляет разработчику возможность перехватывать и обрабаты- вать ошибочные ситуации, возникающие в процессе вы- полнения модуля с помощью конструкции Попытка ... Ис- ключение ... КонецПопытки. В конструкцию Попытка ... КонецПопытки заключаются операторы, при выполнении которых может произойти исключительная ситуация, а после оператора Исключение описывается последователь- ность действий, которая должна выполняться в случае, если возникает исключительная ситуация (ошибка). Таким образом, схема работы с транзакцией в более об- щем виде может выглядеть следующим образом (лис- тинг 4.60). Листинг 4.60. Обработка исключительных ситуаций НачатьТранзакциюО; // Последовательность операторов Попытка // Последовательность выполняемых операторов Исключение ОтменитьТранзакциюО КонецПопытки; // Последовательность выполняемых операторов ЗафиксироватьТранзакциюО; При использовании такой схемы следует помнить о том, что не все ошибки, возникающие при работе с базой дан- ных, обрабатываются системой одинаково. В общем случае, все ошибки базы данных можно разде- лить на две категории: ♦ невосстановимые; ♦ восстановимые.
Невосстановимые ошибки — это ошибки, при возникнове- нии которых нормальное функционирование ЮПред- приятия может быть нарушено, например, могут быть ис- порчены данные. При возникновении невосстановимой ошибки выполнение ЮПредприятия прекращается в лю- бом случае. Если невосстановимая ошибка произошла в процессе вы- полнения транзакции, то все изменения, сделанные в рам- ках этой транзакции, отменяются системой (рис. 4.55). База данных невосстановимая ошибка Рис. 4.55. Невосстановимая ошибка Восстановимые ошибки — это ошибки, не вызывающие серьезных нарушений в работе ЮПредприятия. В случае возникновения восстановимой ошибки дальнейшая рабо- та системы может быть продолжена. При этом, естествен- но, сама операция, вызвавшая ошибку, прекращается, и вызывается исключение, которое может быть перехва- чено и обработано конструкцией Попытка ... Исключе- ние ... КонецПопытки. Если восстановимая ошибка произошла в процессе вы- полнения транзакции, то система автоматически не вы- полняет отмену транзакции, предоставляя разработчику возможность самостоятельно обработать сложившуюся ситуацию (рис. 4.56). База данных транзакция восстановимая ошибка Рис. 4.56. Восстановимая ошибка В зависимости от характера произошедшей ошибки воз- можны различные сценарии обработки этой ситуации. Если произошедшая ошибка не связана с базой данных, то возможно продолжение транзакции и дальнейшей ра- боты модуля. Если разработчик считает это необходи- мым, он может отменить транзакцию или наоборот, про- должить выполнение транзакции, если произошедшая ошибка не нарушает атомарность транзакции. Если же исключительная ситуация была вызвана ошиб- кой базы данных, то система фиксирует факт возникнове- ния ошибки в этой транзакции и дальнейшее продолжение транзакции или ее фиксация становятся невозможны. Единственная операция с базой данных, которую разра- ботчик может произвести в данной ситуации, — это отме- на транзакции. После этого он может осуществить попыт- ку выполнения этой транзакции еще раз. Например, фрагмент кода, реализующий этот подход при записи некоторых данных в базу данных, может выгля- деть следующим образом (листинг 4.61). Листинг 4.61. Обработка исключительных ситуаций // Признак окончания попыток выполнения записи Записано = Ложь; // Попытки записи выполняются в цикле Пока Не Записано Цикл Попытка НачатьТранзакциюО; Данные.Записать(); ЗафиксироватьТранзакциюО; // В случае фиксации транзакциии // прекратить попытки записи Записано = Истина; Исключение // В случае неудачи отменить текущую транзакцию // и следующую попытку начать с новой транзакции ОтменитьТранзакциюО; КонецПопытки; КонецЦикла; Вложенный вызов транзакций В рамках уже выполняемой транзакции можно обращать- ся к процедурам НачатьТранзакциюО, ЗафиксироватьТранзак- циюО и ОтменитьТранзакциюО. Например, может использо- ваться следующая схема вызовов (листинг 4.62). Листинг 4.62. Вложенный вызов транзакций НачатьТранзакциюО; // Вложенный вызов транзакции НачатьТранзакциюС); ЗафиксироватьТранзакциюО; // Вложенный вызов транзакции НачатьТранзакциюО; ЗафиксироватьТранзакциюО; ЗафиксироватьТранзакциюО; Однако подобное обращение не означает начала новой транзакции в рамках уже выполняющейся. 1 (^Предпри- ятие не поддерживает вложенных транзакций. Это озна- чает, что всегда действует только транзакция самого верхнего уровня. Все транзакции, вызванные внутри уже открытой транзакции, фактически относятся к той же транзакции, а не образуют вложенную транзакцию. Та- ким образом, отмена изменений, выполняемая во «вло- женной» транзакции, будет приводить, в конечном счете, не к отмене изменений самой «вложенной» транзакции (рис. 4.57), а к отмене всех изменений транзакции верхне- го уровня (рис. 4.58). Рассмотрим подробнее механику вложенных вызовов транзакций, реализуемую 1 С:Предприятием. Когда в рамках выполняемой транзакции происходит вызов процедуры НачатьТранзакциюО, фактически выполняется все- го лишь увеличение на единицу внутреннего счетчика тран- закций. Процедура НачатьТранзакциюО действительно начи- нает новую транзакцию только в случае, если значение внутреннего счетчика транзакций равно нулю (рис. 4.59).
Начать транзакцию Зафиксировать транзакцию Рис. 4.57. Механика вложенных транзакций Начать транзакцию Зафиксировать транзакцию Начать Начать транзакцию транзакцию „ в Зафргофоеатъ Отменить транзакцию транзакцию Рис. 4.58. Обработка вложенных вызовов транзакций в 1С:Предприятии База данных Рис. 4.59. Работа метода НачатьТранзакциюО Счетчик транзакций Рис. 4.60. Работа метода ЗафиксироватьТранзакциюО Обращение к методу ЗафиксироватьТранзакциюО приводит к фиксации результата транзакции только в том случае, если значение внутреннего счетчика транзакций равно единице (рис. 4.60). Обращение к методу ОтменитьТранзакциюО при значении счетчика транзакций больше единицы приведет не толь- ко к уменьшению значения счетчика, но и к установке признака, не позволяющего зафиксировать результа- ты выполнения всей транзакции в целом. Последующее обращение к процедуре ЗафиксироватьТранзакциюО при зна- чении счетчика равном единице приведет, фактически, к отмене всей транзакции верхнего уровня (рис. 4.61). Рис. 4.61. Работа метода ОтменитьТранзакциюО Таким образом, не всегда можно быть уверенным, что об- ращение к методу НачатьТранзакциюО действительно начи- нает новую транзакцию, а обращение к методам Зафикси- роватьТранзакциюО и ОтметинитьТранзакциюО действительно завершает транзакцию.
По этой причине во многих случаях, при возникновении ошибки при выполнении транзакции, разумнее выдать сообщение и предоставить пользователю решать: повто- рить попытку выполнения операции еще раз или перед повторением попытки предпринять какие-то действия по устранению ситуации, приведшей к ошибке. Влияние транзакций на работу программных объектов Как уже отмечалось выше, механизм транзакций обеспечи- вает атомарность и согласованность изменений, выполняе- мых в базе данных. Работа с данными базы данных осущест- вляется в системе 1С:Предприятие посредством различных программных объектов, которые используются системой не- посредственно, а также доступны во встроенном языке. Результат такого опосредованного взаимодействия не все- гда является очевидным и иногда может вызвать непони- мание. В общем случае программные объекты, используемые системой 1С:Предприятие, абсолютно «прозрачны» для транзакций базы данных. Иначе говоря, транзакции базы данных могут вызываться при выполнении различных методов программных объектов, однако, например, дейст- вия, выполняемые базой данных при откате транзакции, в общем случае никак не влияют на соответствующие программные объекты. В качестве примера рассмотрим изменение наименова- ния элемента справочника, выполняемое в транзакции, которая затем отменяется. При выполнении метода ПолучитьОбъектО данные объекта будут считаны из базы данных в свойства экземпляра программного объекта СправочникОбъект. Номенклатура (лис- тинг 4.63). Листинг 4.63. Получение объекта справочника Товар = Справочники.Номенклатура.НайтиПоКодуС1). ПолучитьОбъектО: Таким образом, и в базе данных, и в свойстве программ- ного объекта будет находиться одно и то же значение на- именования — Старое наименование (рис. 4.62). После этого вызывается транзакция и изменяется значе- ние свойства Наименование программного объекта на Новое наименование (листинг 4.64). Рис. 4.62. Получение объекта справочника Листинг 4.64. Изменение наименования элемента справочника в транзакции Товар = Справочники.Номенклатура.НайтиПоКодуС1). ПолучитьОбъектО: НачатьТранзакциюО; Товар.Наименование = "Новое наименование": Теперь наименование в базе данных и в свойстве про- граммного объекта отличаются (рис. 4.63). Рис. 4.63. Изменение наименования элемента справочника в транзакции После этого выполняется запись программного объекта (листинг 4.65). Листинг 4.65. Запись объекта справочника Товар = Справочники.Номенклатура.НайтиПоКоду(1). ПолучитьОбъектО; НачатьТранзакциюО; Товар.Наименование = "Новое наименование"; Товар. Записать О: После успешной записи данных программного объекта в базу данных наименование элемента справочника и в памяти, и в базе данных будет одинаковым: Новое наиме- нование (рис. 4.64). Рис. 4.64. Успешная запись объекта справочника Затем выполняется отмена транзакции (листинг 4.66). Листинг 4.66. Отмена транзакции Товар = Справочники.Номенклатура.НайтиПоКодуС!). ПолучитьОбъектО; НачатьТранзакциюО: Товар.Наименование = "Новое наименование": Товар.Записать!); ОтненитьТранзакциюО;
Рис. 4.65. Отмена транзакции В результате того, что изменения, выполненные в базе данных в транзакции, не принимаются, состояние базы данных возвращается в исходное, то есть то, которое было до начала транзакции. Это значит, что наименование эле- мента справочника снова принимает значение Старое на- именование. Однако эти изменения никоим образом не касаются про- граммного объекта: значение свойства наименование ос- тается равным Новое наименование (рис. 4.65). Для того чтобы сравнить наименования в базе данных и программном объекте, можно выполнить запрос к базе данных (листинг 4.67). Листинг 4.67. Сравнение наименования элемента справочника в базе данных и программном объекте Товар = Справочники.Номенклатура.НайтиПоКодуО. ПолучитьОбъектО: НачатьТранзакциюО; Товар.Наименование = "Новое наименование": Товар.ЗаписатьО: ОтменитьТранзакциюО; Запрос = Новый Запросе" | ВЫБРАТЬ Справочник.Номенклатура.Наименование | ГДЕ Справочник.Номенклатура.Код = 1"); Выборка = Запрос. Выполнить О. Выбрать О; Выборка.Следующий(); НаименованиеВБазе = Выборка.Наименование; НаименованиеВПамяти = Товар.Наименование; Сообщить(НаименованиеВПамяти); Сообщить(НаименованиеВБазе): Если теперь заново прочитать данные объекта из базы данных в программный объект, то значение наименова- ния в программном объекта станет таким же, как и в базе данных (листинг 4.68). Из приведенного примера следует важный вывод: при от- мене транзакций базы данных разработчик (если в этом есть необходимость) должен самостоятельно обеспечи- вать адекватное изменение данных соответствующих программных объектов. Это можно выполнять путем пе- речитывания всех данных объекта или путем изменения некоторых реквизитов программного объекта (если, на- пример, это необходимо для отображения в интерфейсе). Однако, как в любом правиле, здесь тоже есть исключе- ния. В силу значительной прикладной специфики про- граммных объектов 1 С:Предприятия в некоторых случа- ях откат изменений, выполненных в базе данных, все же может влиять на значения свойств соответствующих про- граммных объектов. Листинг 4.68. Перечитывание данных объекта Товар = Справочники. Номенклатура. НайтиПоКодуО .ПолучитьОбъектО; НачатьТранзакциюО ; Товар.Наименование = "Новое наименование": Товар. Записать О: ОтменитьТранзакциюО; Запрос = Новый Запросе | ВЫБРАТЬ Справочник.Номенклатура.Наименование | ГДЕ Справочник.Номенклатура.Код = 1"): Выборка = Запрос.ВыполнитьО.ВыбратьО; Выборка.Следующий(); НаименованиеВБазе =Выборка.Наименование: НаименованиеВПамяти = Товар.Наименование; Сообщить(НаименованиеВПамяти); Сообщить(НаименованиеВБазе); Товар.ПрочитатьО; СообщитьСТовар.Наименование); Восстановление признака проведенности документа При отмене транзакции признак проведенности документа восстанавливает значение, которое было до начала транз- акции (листинг 4.69). Листинг 4.69. Восстановление признака проведенности документа НачатьТранзакциюО; Накладная = Документы. ПриходнаяНакладная.СоздатьДокументО; Накладная. Дата = ТекущаяДатаО: Накладная.Записать(РежимЗаписиДокумента.Проведение); Проведен = Накладная.Проведен: ОтменитьТранзакциюО: Сообщить (Накладная. Проведен); //ложь Сообщить(Проведен); //истина Очистка ссылки Если объект был создан в транзакции, то при ее откате очищается значение ссылки (листинг 4.70). Листинг 4.70. Очистка ссылки НачатьТранзакциюО; Товар = Справочники.Номенклатура.СоздатьЭлементО; Товар.ЗаписатьО: Ссылка = Товар.Ссылка; ОтменитьТранзакциюО; Сообщить(Товар.Ссылка = Справочники.Номенклатура. ПустаяСсылкаО); //истина Сообщить(Ссылка); // «Объект не найден> // (1:9e4b00055d4c7bcfUd934028f79e857)
Очистка кода/номера объекта Если объект создавался вне транзакции и при записи его в транзакции использовался код/номер, сгенерирован- ный автоматически, то при отмене транзакции код/номер очищается (листинг 4.71). Листинг 4.71. Очистка кода Товар = Справочники.Номенклатура.СоздатьЭлементО; НачатьТранзакциюО; Товар.ЗаписатьО; Код = Товар.Код; ОтменитьТранзакциюО; Сообщить(Товар.Код): // О Сообщить(Код); // В Уровни изоляции транзакций В идеальном случае транзакции должны обеспечивать изоляцию выполняемых изменений. Иными словами, не- сколько транзакций, выполняющих изменение данных, не должны мешать друг другу. Самым простым способом решения этой проблемы явля- ется последовательное выполнение транзакций. Следую- щая транзакция выполняется после того, как закончилась предыдущая. Однако в реальной ситуации, при многопользователь- ской работе, такой подход приводит к резкому снижению производительности базы данных. Поэтому на практике используются механизмы, позволяющие выполнять не- сколько транзакций одновременно. Для того чтобы одновременное выполнение транзакций стало возможным, используется несколько уровней изо- ляции транзакций. На самом низшем уровне изоляции транзакции могут сильно мешать друг другу. На самом высшем уровне они полностью изолированы. Таким образом, за большую изоляцию транзакций прихо- дится платить большими накладными расходами и замед- лением работы системы. Возможность изоляции одних транзакций от других реа- лизуется благодаря блокировкам, накладываемым на используемые ими данные. В зависимости от уровня изо- ляции накладываются различные типы блокировок на различные объекты базы данных на различное время. С точки зрения базы данных все операции с данными (в том числе и чтение) выполняются с использованием транзакций. С точки зрения ЮПредприятия работа с данными может выполняться в одном из двух режимов: ♦ в транзакции; ♦ вне транзакции. Режим работы с данными вне транзакции допускает только операции чтения данных. Этот режим введен для того, чтобы обеспечить максимальную скорость и параллель- ность чтения данных. Поэтому любая операция чтения данных, выполняемая вне транзакции, считается безот- ветственной. Это означает, что такая операция чтения мо- жет вернуть устаревшие данные или даже незафиксиро- ванные изменения, произведенные другой транзакцией, то есть чтение выполняется «не глядя» на блокировки данных, расставленные другими транзакциями. Режим работы с данными в транзакции допускает любые операции чтения и модификации данных, при этом долж- ны соблюдаться следующие правила: ♦ чтение данных должно быть воспроизводимым, то есть любая последующая операция чтения данных с тем же условием выборки должна возвращать такой же резуль- тат; ♦ результат чтения должен содержать наиболее актуаль- ные данные, что означает, что никакая другая транзак- ция не может изменить данные, считанные в данной транзакции, до тех пор, пока данная транзакция не бу- дет завершена; ♦ результат чтения не должен содержать незафиксиро- ванные изменения данных базы данных. Независимо от того, в транзакции или нет выполняется обращение к данным в ЮПредприятии, на уровне SQL Server это обращение к данным (в том числе и чтение данных) выполняется в транзакции, явной или неявной. Таким образом, при любых операциях с данными плат- форма ЮПредприятия будет указывать SQL Server уро- вень изоляции транзакций, который необходимо исполь- зовать для выполнения данной операции, даже если с точки зрения 1 С:Предприятия эта операция выполняется вне транзакции. В силу технологических особенностей реализации базы данных, в файловом и клиент-серверном вариантах рабо- ты используются различные уровни изоляции транзакций. В файловом варианте работы используются блокировки на уровне таблиц базы данных, одинаковые как для объ- ектных, так и для необъектных данных. В клиент-серверном варианте работы используются бло- кировки на уровне записей таблиц, причем для объектных и необъектных данных используются различные уровни изоляции транзакций. Это позволяет обеспечить боль- шую параллельность (пропускную способность) в конку- рентных режимах работы. Файловый вариант Нетранзакционное чтение Чтение, выполняемое вне транзакции, не вызывает никаких блокировок. В файловом варианте платформа ЮПред- приятия поддерживает версионирование при нетранзак- ционном чтении. Поэтому при чтении используется со- стояние данных таблиц, которое имело место на начало выполнения запроса (рис. 4.66). Рис. 4.66. Нетранзакционное чтение в файловом варианте работы
Таким образом, чтение данных одним запросом в файло- вом варианте всегда позволяет получать целостные дан- ные. Чтение в транзакции Чтение данных в транзакции является ответственным, то есть данные, считанные в транзакции, гарантированно не могут быть изменены до тех пор, пока транзакция не закончится. В файловом варианте работы для этого используется раз- деляемая блокировка (Shared Lock), накладываемая на всю таблицу, данные которой считываются. Таким обра- зом, данные этой таблицы могут быть прочитаны други- ми транзакциями, однако изменить их они не смогут, так как для изменения данных они будут пытаться уста- новить исключительную блокировку (Exclusive Lock), ко- торая несовместима с разделяемой блокировкой, уста- новленной другой транзакцией. Если чтение данных выполняется запросом с использова- нием конструкции ДЛЯ ИЗМЕНЕНИЯ, то в этом случае накла- дывается исключительная блокировка (Exclusive Lock) на всю таблицу. Другие транзакции не смогут выполнить чтение данных из этой таблицы до тех пор, пока исключи- тельная блокировка не будет снята, так как для этого им потребуется установить разделяемую (Shared Lock) или исключительную (Exclusive Lock, если они также выпол- няют чтение с использованием ДЛЯ ИЗМЕНЕНИЯ) блокировки, которые несовместимы с эксклюзивной блокировкой, ус- тановленной другой транзакцией. Модификация При модификации данных в файловом варианте рабо- ты используется исключительная блокировка (Exclusive Lock), накладываемая на всю таблицу, которая содержит модифицируемые данные. Таким образом, другие тран- закции будут ожидать снятия исключительной блокиров- ки с этой таблицы, если им нужны данные, содержащиеся в ней. Клиент-серверный вариант В клиент-серверном варианте работы используются раз- личные уровни изоляции транзакций, поддерживаемые SQL Server. Нетранзакционное чтение Чтение, выполняемое вне транзакции, использует уро- вень изоляции READ UNCOMMITED. Этот уровень изоляции используется потому, что SQL Server не поддерживает версионирование для считываемых данных. В то же вре- мя должна быть обеспечена предсказуемая скорость при выполнении чтения, то есть нельзя «спотыкаться» о бло- кировки, расставленные другими транзакциями. Уровень изоляции READ UNCOMMITED является самым низ- шим и, таким образом, обеспечивает максимальную па- раллельность выполнения нескольких транзакций. Обо- ротной стороной является то, что этот уровень изоляции допускает чтение незафиксированных изменений, выпол- ненных другими транзакциями (рис. 4.67). Таким образом, в клиент-серверном варианте работы при чтении вне транзакции можно получить несогласованные данные. Рис. 4.67. Нетранзакционное чтение в клиент-серверном варианте работы Наглядное проявление этого эффекта можно наблюдать, например, в списке справочника при массированном соз- дании новых элементов этого справочника. Динамиче- ские списки осуществляют чтение данных вне транзак- ции. Поэтому, если в одном сеансе работы запустить обработку, которая в транзакции создает большое коли- чество элементов справочника, а в другом сеансе работы открыть и периодически обновлять список этого справоч- ника, можно увидеть, что, несмотря на то, что транзакция, открытая обработкой, еще не зафиксирована, в списке справочника уже появляются все новые и новые эле- менты. Чтение в транзакции, модификация Для чтения и модификации данных в транзакции в кли- ент-серверном варианте работы используются одни и те же уровни изоляции, однако эти уровни различные для объектных и необъектных данных. Объектные данные Особенность объектных данных заключается в том, что они обладают довольно большой гранулярностью и мало «завязаны» друг на друга. Поэтому при работе с объект- ными данными используется уровень изоляции REPEATABLE READ. Этот уровень изоляции осуществляет блокировку отдельных записей таблицы. Таким образом, другие тран- закции могут читать и записывать данные других записей этой же таблицы. Например, при записи элемента справочника Номенклатура будет заблокирована только одна запись основной табли- цы справочника Номенклатура, которая содержит данные записываемого элемента. Любые соседние записи этой таблицы могут быть изменены другими транзакциями, то есть могут быть одновременно записаны любые другие элементы этого справочника. Необъектные данные Необъектные данные характеризуются более сложными взаимными связями, по сравнению с объектными данны- ми. Поэтому при работе с необъектными данными ис- пользуется самый высокий уровень изоляции — SERIALIZA- BLE. При работе с этим уровнем изоляции SQL Sever на- кладывает дополнительные блокировки на диапазон зна- чений индекса. При этом накладывается блокировка как на саму запись индекса, так и на диапазон значений от те- кущего значения ключа до ближайшего следующего. На данном уровне изоляции не допускается не только мо- дификация другими транзакциями прочитанных данных,
но и добавление новых записей в диапазон данных, огра- ниченный условиями выполняемого запроса. Это обеспе- чивает высокую степень целостности и непротиворечиво- сти обрабатываемых в рамках транзакции данных. Например, если существуют записи с идентификаторами 3 и 5 и делается попытка изменить запись с идентифика- тором 4, то, в общем случае, будут дополнительно забло- кированы записи с идентификаторами 3 и 5. Записи с идентификаторами меньше 3 и больше 5 могут быть мо- дифицированы. Однако при определенных условиях блокировки уста- навливаемые для этого уровня изоляции, могут приво- дить к снижению пропускной способности системы. При- чиной этого являются эксклюзивные блокировки таблиц базы данных, устанавливаемые SQL Server, для обеспече- ния целостности и непротиворечивости обрабатываемых в рамках транзакции данных. Переход от блокировок на уровне записи таблицы базы данных к табличным блокировкам (эскалация блокиро- вок) чаще всего обуславливается отсутствием записей в некоторых таблицах базы данных, используемых в рам- ках транзакции. При использовании уровня изоляции SERIALIZABLE SQL Server блокирует весь диапазон прочи- танных данных, не допуская добавления, удаления и мо- дификации данных в рамках этого диапазона. Ввиду от- сутствия записей в таблице, она блокируется целиком на все время выполнения транзакции, что приводит к дегра- дации пропускной способности системы. Использование конструкции ДЛЯ ИЗМЕНЕНИЯ Если транзакционное чтение данных в клиент-серверном варианте выполняется запросом с использованием конст- рукции ДЛЯ ИЗМЕНЕНИЯ, то в этом случае накладывается бло- кировка обновления (Update Lock) на считываемые записи (для объектных данных) или на диапазон записей (для необъектных данных) таблицы. Другие транзакции не смогут прочитать эти данные, если они также выполняют чтение с использованием конструкции ДЛЯ ИЗМЕНЕНИЯ, так как блокировки обновления несовместимы между собой. Однако другие транзакции, выполняющие чтение без ис- пользования конструкции ДЛЯ ИЗМЕНЕНИЯ, смогут читать эти данные (блокировка обновления (Update Lock) совмес- тима с разделяемой блокировкой (Shared Lock), наклады- ваемой при «обычном» чтении), но не смогут изменить их, так как для этого потребуется установить исключи- тельную блокировку (Exclusive Lock), которая несовмес- тима с блокировкой обновления (Update Lock), установ- ленной другой транзакцией. Подробнее об использовании конструкции ДЛЯ ИЗМЕНЕНИЯ можно прочитать в разделе «Использование в запросах оператора ДЛЯ ИЗМЕНЕНИЯ», с. 726. Получение согласованных данных при чтении Как было показано выше, при нетранзакционном чтении данных в клиент-серверном варианте работы можно по- лучить нецелостные данные. При работе в файловом варианте изменения незавершен- ных транзакций не читаются, однако все равно есть воз- можность получить несогласованные данные при неодно- кратном обращении к базе данных. Такая ситуация может возникнуть, если между выполне- нием одного и другого запроса состояние считываемых данных было изменено другой транзакцией. Поэтому если требуется считать заведомо целостное со- стояние данных, то чтение данных (например, запросы) следует выполнять в рамках транзакции. В этом случае гарантируется целостность и неизменность считанных данных. ВНИМАНИЕ Если считываемые данные служат основой для каких-либо расчетов, на основании которых будут производиться из- менения данных (например, при проведении документов), то такие операции чтения обязательно должны выполнять- ся в рамках транзакции. Вместе с этим следует взвешенно подходить к использо- ванию транзакций и применять их там, где это действи- тельно необходимо. Например, стремясь к получению целостных данных, не следует огульно включать в тран- закции целые отчеты; но если требуется получение согла- сованной выборки данных, следует проанализировать не- обходимость использования транзакции при получении такой выборки.
Глава 5. Клиент-серверный вариант работы Общие сведения о клиент-серверном варианте работы Клиент-серверный вариант работы системы ЮПредпри- ятие предполагает использование 3-уровневой архитек- туры: клиент — сервер 1С:Предприятия — сервер баз дан- ных. В этом варианте работы клиентское приложение взаимодействует с сервером баз данных посредством специ- ального приложения — сервера 1С:Предприятия (рис. 5.1). Рис. 5.1. Схема работы в клиент-серверном варианте Трехуровневая архитектура 1С:Предприятия разработа- на таким образом, что пользователю не требуется доступ ни к каким файловым ресурсам, связанным с 1 (^Пред- приятием. Пользователю клиентского приложения 1 (^Пред- приятия также не требуется доступ к базе данных сервера баз данных. В качестве клиентского приложения могут выступать 4 вида различных приложений: ♦ консоль сервера 1С:Предприятия; ♦ 1С:Предприятие; ♦ 1 С: Предприятие в режиме конфигуратора; ♦ внешнее соединение 1С:Предприятия. Консоль сервера 1С:Предприятия предоставляет визуаль- ный интерфейс, который позволяет выполнять админист- рирование сервера: просмотр списка активных соедине- ний, принудительное завершение соединений, создание, изменение и удаление информационных баз и другие ад- министративные действия. Каждый экземпляр приложения 1С:Предприятие и каж- дый экземпляр внешнего соединения являются для сер- вера 1С:Предприятия отдельным клиентом. Их соедине- ние с сервером всегда ассоциируется с определенной информационной базой. Для этого сервер 1 С: Предприятия хранит список зареги- стрированных информационных баз и выполняет аутен- тификацию пользователей, подключающихся к информа- ционным базам. В общем случае сервер 1С:Предприятия обеспечивает од- новременную работу нескольких пользователей с несколь- кими информационными базами, которые могут управ- ляться различными серверами баз данных (рис. 5.2). Рис. 5.2. Работа нескольких пользователей с несколькими информационными базами При запуске 1С:Предприятия соединение создается по- сле выбора клиент-серверной информационной базы и режима запуска (1С:Предприятие\Конфигуратор) в диа- логе Запуск 1 С: Предприятия и разрывается при завершении приложения. Модуль внешнего соединения соединяется с сервером в процессе исполнения метода Connect и получения ука- зателя на созданный этим методом СОМ-объект внешнего соединения. Соединение будет разорвано при уничтоже- нии COM-объекта внешнего соединения. Это происходит либо при выполнении метода Release интерфейса IUnknown на языке С\С++, либо при потере указателя на этот объ- ект (например, при присвоении COM-объекту значения Nul 1 или Неопределено, при уничтожении локальной среды процедуры или функции и т. п.), либо после освобожде- ния объекта «внешнее соединение» сборщиком мусора (Java, .NET) (листинг 5.1).
Листинг 5.1. Уничтожение СОМ-объекта внешнего соединения // Соединений нет МодульВнешнихСоединений = Новый С0М0бъект("У8.С0МСоппес1ог"); Соединение! = МодульВнешнихСоединений. Connect!"Srvr=ServerName:Ref=InfoBaseName“); // Одно соединение Соединение2 = МодульВнешнихСоединений. Connect!"Srvr=ServerName:Ref=InfoBaseName"); // Два соединения Соединение! = Неопределено; // Одно соединение Соединение2 = Неопределено: // Соединений нет Выполнение общих функций Основная задача сервера ЮПредприятия — обеспечение интерфейса клиентского приложения с базой данных. Он преобразует запросы, поступающие от клиентского прило- жения, в запросы на языке Transact SQL, передает их SQL Server, получает от него результат выполнения запроса, пре- образует его и передает обратно клиентскому приложению. Кроме этого, на сервере 1 С: Предприятия сосредоточено выполнение различных общих функций платформы: ♦ чтение и сохранение конфигураций и настроек пользо- вателя; ♦ операции над базой данных, включая ограничения дос- тупа к данным; ♦ хранение значений параметров сеанса; ♦ ведение журнала регистрации; ♦ поддержка оперативной отметки времени; ♦ другие функции (управление объектными блокировка- ми, идентификаторы и т. п.). Управление сервером ЮПредприятия Сервер 1 С:Предприятия является СОМ+ приложением и не имеет собственного интерфейса. Управление сервером 1 С: Предприятия возможно тремя способами: ♦ средствами операционной системы; ♦ с помощью консоли сервера ЮПредприятия; ♦ программно. Средствами операционной системы могут быть выполнены простейшие действия: запуск и установка сервера. Посколь- ку сервер ЮПредпритятия является СОМ+ приложением, то эти действия можно выполнить, например, с помощью утилиты Component Services операционной системы. Консоль сервера 1С .Предприятия позволяет управлять специфическими функциями сервера ЮПредприятия, и ее использование подробно описано в документации. Программное управление сервером может быть осуществ- лено как средствами встроенного языка, так и средствами других программных систем, поддерживающих техноло- гию СОМ (например, из программ на Visual Basic). Во встроенном языке сервер ЮПредприятия доступен через COM-объект V8.C0MConnector. Этот объект поддержи- вает метод ConnectServerO, который позволяет подклю- читься к серверу ЮПредприятия по имени компьютера, на котором он запущен. В результате устанавливается со- единение с сервером, которое не отображается в списке активных соединений сервера и не привязано к какой-ли- бо конкретной информационной базе. Это соединение не влияет на блокировки информационных баз и баз дан- ных. В результате становится возможным выполнение следующих административных действий: ♦ получение списка информационных баз, зарегистриро- ванных на сервере (GetlnfoBasesO). Для выполнения этой операции аутентификация не требуется; ♦ получение списка администраторов сервера (GetSrvr- UsersO). Если существует хотя бы один администратор сервера, то создание и изменение информационных баз, зарегистрированных на сервере, может выполняться толь- ко администраторами сервера ЮПредприятия. Если не существует ни одного администратора сервера, то создание информационных баз может выполняться любым пользователем, а для выполнения каких-либо административных действий над информационной ба- зой, необходимо аутентифицироваться с правами адми- нистратора этой информационной базы; ♦ создание объекта описания администратора сервера (CreateSrvrUserlnfoO); ♦ создание или модификация администратора сервера (CreateSrvrllser!)). Если существует хотя бы один адми- нистратор сервера, то для выполнения этой операции требуется аутентификация администратора сервера; ♦ удаление администратора сервера (DropSrvrllser!)). Для выполнения этой операции требуется аутентификация администратора сервера; ♦ аутентификация в одной или нескольких информаци- онных базах (AddAuthenticationO). Для того чтобы вы- полнить какие-либо административные действия над информационной базой, необходимо аутентифициро- ваться с правами администратора этой информацион- ной базы; ♦ получение списка соединений клиентских приложений с конкретной информационной базой (GetIBConnectionsO). Выполнение этой операции доступно при наличии ад- министративных прав в данной информационной базе; ♦ создание объекта описания информационной базы (CreatelnfoBaselnfo!)); ♦ создание новой информационной базы (CreatelnfoBaseO). Если существует хотя бы один администратор сервера, то для выполнения этой операции требуется аутенти- фикация администратора сервера; ♦ удаление информационной базы (DropInfoBaseO). Если существует хотя бы один администратор сервера, то для выполнения этой операции требуется аутентифи- кация администратора сервера; ♦ разрыв клиентского соединения (Disconnect!)); ♦ подключение к конкретной информационной базе (Connect!));
Программное управление сервером ЮПредприятия может быть использовано, например, для принудительного за- вершения работы пользователей информационной базы. При этом нужно учитывать, что после разрыва соедине- ния соответствующее клиентское приложение завершит- ся аварийно (листинг 5.2). Листинг 5.2. Завершение работы пользователей информационной базы Коннектор = Новый С0М0бъект("У8.С0МСоппес1ог"); Сервер = Коннектор.ConnectServer("TestServer"); // Аутентифицироваться с административными правами // в нужной базе Сервер.AddAuthenticationC"Администратор" // Создать объект нужной информационной базы ИнформационнаяБаза = Сервер. CreatelnfoBaselnfoO; ИнформационнаяБаза.Мате = "TestBase"; // Получить соединения базы СоединенияБазы = Сервер.6еб1ВСоплесб1оп5(ИнформационнаяБаза); // Разорвать соединения клиентских приложений Для Каждого Соединение Из СоединенияБазы Цикл Сервер.Disconnect(Соединение); КонецЦикла; Более подробно использование программного управле- ния сервером ЮПредприятия можно посмотреть в обра- ботке Консоль сервера ЮПредприятия, которая находится в информационно-технологическом сопровождении (ИТС). Для соединения с сервером ЮгПредприятия из других программных систем также необходимо получить СОМ- объект V8.C0MConnector. Например, аналогичная процедура удаления всех соеди- нений информационной базы VBScript может выглядеть следующим образом (листинг 5.3). Листинг 5.3. Завершение работы пользователей информационной базы Dim connector Set connector = Create0bject(”v8.C0MConnector") Dim server Set server = connector.ConnectServerC"TestServer") server.AddAuthentication "UserName", "UserPassword" Dim ibDesc Set ibDesc = server.CreatelnfoBaselnfoO ibDesc.Name = "TestDB" Dim connections connections = server.GetIBConnectionsCibDesc) Dim i Dim connection For i = LBound(connections) To UBound(connections) set connection = connections(i) server.Disconnect connection Next Работа встроенного языка на сервере Одной из важных функций сервера ЮПредприятия яв- ляется возможность выполнения на нем прикладного кода 1 С: Предприятия. Для этого используются общие модули конфигурации, с помощью которых можно пере- носить выполнение кода с клиентского приложения на сервер. Техника передачи выполнения прикладного кода на сер- вер и обратно подробно рассмотрена в разделе «Органи- зация выполнения кода на сервере или на клиенте», с. 86. Здесь мы остановимся на общих рекомендациях, касаю- щихся выполнения прикладного кода на сервере Ю:Пред- приятия. Существует две основные причины, по которым имеет смысл переносить некоторые действия на сервер 1С:Пред- приятия: ♦ повышение производительности прикладного решения; ♦ выполнение действий, связанных с управлением досту- пом к данным. С целью повышения производительности системы имеет смысл выносить на сервер обработки больших объемов данных, не требующие сложных вычислений. Такие обра- ботки на сервере будут выполняться быстрее из-за того, что отсутствует звено передачи данных между клиент- ским приложением и сервером ЮПредприятия. Кроме того, сервер ЮПредприятия осуществляет более быст- рый доступ к серверу баз данных. Не следует переносить на сервер абсолютно все такие об- работки. Дело в том, что перенос выполнения кода на сер- вер не всегда дает 100% гарантию существенного роста производительности. В реальной работе загруженность сервера 1 (^Предприятия может быть достаточно значи- тельной, и выполнение большого количества кода на сер- вере может привести даже к замедлению работы. При разработке прикладного решения не всегда существует возможность воспроизвести реальную нагрузку на систе- му, а одиночные тесты производительности, в отсутствие реальной рабочей нагрузки, дадут, скорее всего, неверные результаты. Поэтому прежде чем переносить исполнение того или иного фрагмента кода на сервер, следует проана- лизировать возможные последствия этого действия. Однозначно не рекомендуется переносить на сервер дли- тельные обработки данных. Это может привести к значи- тельному неудобству администрирования системы, так как выполнение кода на сервере прервать нельзя. Поэто- му подобные длительные обработки желательно разби- вать на фрагменты, длительность которых ограничена и не зависит от объема хранимых в информационной базе данных. В этом случае за одно обращение к серверу мож- но обрабатывать один такой фрагмент. Безопасная зона Одной из важных функций сервера ЮПредприятия, по- мимо собственно обеспечения интерфейса между клиент- ским приложением и сервером базы данных, является создание так называемой безопасной зоны — логической области системы, в которой данные находятся в безопас- ности. В общем случае, различные пользователи системы тем или иным образом подключаются к базе данных и ис- пользуют те или иные данные. Очевидно, что разные пользователи обладают разными правами на разные виды данных. В этой ситуации сервер ЮПредприятия является
своего рода «барьером», дальше которого информация базы данных может распространяться только с учетом всех разрешений, назначенных тому или иному пользова- телю. Внутри безопасной зоны возможны любые дейст- вия с данными без учета ограничений, накладываемых правами пользователей (рис. 5.3). Рис. 5.3. Безопасная зона Создание безопасной зоны становится возможным благо- даря тому, что сервер 1С:Предприятия выполняет кон- троль ограничений доступа к данным при выполнении операций с базой данных. Это касается как «обычных» прав, относящихся к отдельным объектам конфигурации, так и ограничений доступа к данным, задаваемых на уровне записей и полей таблиц базы данных. Ограниче- ния доступа к данным накладываются сервером 1 С: Пред- приятия в момент обращения к базе данных. При моди- фикации данных, перед тем как обратиться к серверу баз данных, сервер 1 С: Предприятия анализирует запраши- ваемое действие в соответствии с имеющимися правами и только после этого выполняет (или не выполняет) обра- щение к серверу баз данных. Таким образом, система га- рантирует, что данные, доступ к которым не санкцио- нирован клиентскому приложению, могут существовать только в безопасной зоне. Однако следует понимать, что вопрос безопасности дан- ных не может на 100% быть решен самой системой. Суще- ствует два момента, в которых нельзя исключить влияние «человеческого фактора». Если этим моментам не уде- лить должного внимания, существование безопасной зоны может быть нарушено. Первый момент связан с исполь- зованием привилегированных модулей, а второй — собст- венно с администрированием прикладного решения. Контроль прав в привилегированных модулях Привилегированные модули представляют собой общие модули, которые выполняются в безопасной зоне без кон- троля прав. Другими словами, привилегированные модули компилируются только на стороне сервера и, соответст- венно, могут быть выполнены только на сервере 1С:Пред- приятия. При выполнении кода, содержащегося в приви- легированных модулях, контроль прав не осуществляется. Наличие привилегированных модулей позволяет решать целый ряд задач, которые невозможно решить с помощью прав на объекты конфигурации или с помощью ограниче- ний доступа к данным на уровне записей и полей. Напри- мер, задачу, требующую предоставить пользователю воз- можность выполнить какое-либо одно административное действие, в то время как все остальные административ- ные действия должны быть для него недоступны. Более подробно использование привилегированных модулей рассмотрено в разделе «Выполнение кода на сервере без проверки прав», с. 89. В силу того, что при выполнении привилегированного модуля контроль прав не осуществляется, такой модуль может стать «лазейкой», через которую клиент сможет получить данные, на которые у него нет прав. Чтобы этого избежать, при разработке привилегирован- ных модулей следует исходить из того, что в общем слу- чае не известно, откуда выполнение прикладного кода было передано в этот модуль. Скорее всего, оно будет пе- редано именно из того места конфигурации, которое име- ет в виду разработчик. Однако не исключена ситуация, что выполнение может быть передано и из другого места (например, из внешней обработки, если известно имя вы- зываемой процедуры привилегированного модуля). Поэтому, прежде чем выполнять какие-либо действия с данными в привилегированном модуле, следует убе- диться, что ситуация соответствует той, на которую рас- считана работа этого модуля. Приведем пример. Допустим, в филиале нужно обеспе- чить возможность ввода новых пользователей системы. В то же время нельзя назначить административные права кому-либо из пользователей, так как информация, хра- нящаяся в базе данных, довольно конфиденциальная. В этом случае может быть принято решение, что ввод но- вых пользователей в систему будет осуществлять, напри- мер, только главный менеджер филиала Борисов. В этом случае создается специальная обработка, которая пользователю Борисов позволяет задать все параметры, требуемые для ввода нового пользователя. При выполне- нии этой обработки управление передается в привилеги- рованный модуль, в котором собственно и выполняется создание нового пользователя без проверки прав. При этом, несмотря на то, что этой обработкой никто кроме Борисова пользоваться не может, в привилегированном модуле следует обязательно выполнить проверку того, что текущим пользователем является Борисов. И только после этого создавать нового пользователя системы. Если этого не сделать, то потенциально любой пользова- тель системы, «подсмотревший» имя вызываемой проце- дуры, может написать внешнюю обработку, с помощью которой также обращаться к этой процедуре и создавать новых пользователей. Администрирование клиент- серверного варианта работы Второй момент, который может ослабить безопасную зону, используемую в клиент-серверном варианте работы, — это неграмотное администрирование аппаратных средств, на которых работает прикладное решение. Информационная база 1 С:Предприятия представляет собой совокупность данных, доступ к которым должен
осуществляться исключительно средствами ЮПредпри- ятия. Поэтому необходимо обеспечить такой порядок ра- боты прикладного решения, при котором невозможно использовать данные информационной базы напрямую механизмами, отличными от ЮПредприятия. Следующие рекомендации помогут правильно сконфигу- рировать аппаратные и программные средства, исполь- зуемые в клиент-серверном варианте работы: Компьютер сервера баз данных 1. Доступ к компьютеру, на котором установлен SQL Server, должен быть запрещен для всех, кроме админист- раторов системы. Доступ должен быть запрещен как фи- зически (организационными мерами), так и программно, при этом особое внимание следует уделить списку поль- зователей Windows, имеющих право интерактивного вхо- да в серверный компьютер. 2. Доступ к файлам баз данных SQL Server должен быть запрещен всем пользователям Windows, кроме пользова- теля, от имени которого работает SQL Server. Пользова- теля, от имени которого работает SQL Server, можно по- смотреть или изменить при помощи SQL Server Enterprise Manager в диалоге свойств SQL Server на закладке Security в рамке Startup service account. Желательно, чтобы этот пользователь был предназначен только для SQL Server и не мог входить ни интерактивно, ни удаленно. При необ- ходимости доступ к этим файлам может быть разрешен лишь наиболее квалифицированным администраторам. База данных SQL Server размещается в специальном файле, например C:\Program Files\Microsoft SQL Server\MSSQL\ Data\InfoBase.mdf. Наряду с этим файлом SQL Server мо- жет создавать и другие файлы, в частности файл журнала транзакций, например C:\Program Files\Microsoft SQL Server\ MSSQL\Data\ib_tmp_log.LDF. 3. Рекомендуется полностью запретить удаленный доступ через сеть к файлам компьютера, на котором установлен SQL Server и хранятся базы данных. 4. В SQL Server должна быть включена аутентификация SQL Server and Windows при помощи SQL Server Enterprise Manager в диалоге свойств SQL Server на закладке Security. 5. Следует создать в SQL Server пользователя, имеющего полные права на базу данных, хранящую информацион- ную базу, с паролем и указать имя этого пользователя и его пароль в диалоге создания информационной базы. Необходимо ограничить или запретить доступ к этой базе данных со стороны других пользователей SQL Server. Также необходимо установить пароль пользователю sa, который должны знать только администраторы. Компьютер сервера ЮПредприятия 1. Доступ к компьютеру, на котором установлен сервер 1С:Предприятия должен быть запрещен для всех, кроме администраторов системы. Доступ должен быть запре- щен как физически (организационными мерами), так и программно, при этом особое внимание следует уделить списку пользователей Windows, имеющих право инте- рактивного входа в серверный компьютер. 2. Следует запретить доступ к файлам каталога данных сервера ЮПредприятия (обычно C:\Documents and Settings\ All Users\Application Data\lC\lCv8) всем пользователям Win- dows, кроме того, от имени которого работает сервер 1 С:Предприятия (обычно USER1CV8SERVER). Наиболее важным файлом данных сервера ЮПредприятия явля- ется файл srvrib.lst, который обычно находится в каталоге C:\Documents and Settings\All Users\Application Data\lC\lCv8. Доступ к этому файлу должно иметь только приложение, являющееся сервером ЮПредприятия. 3. Рекомендуется для компьютера, на котором установ- лен сервер ЮПредприятия, полностью запретить уда- ленный доступ к файлам через сеть. Взаимодействие компьютеров 1. Следует выбрать необходимый уровень защиты прото- кола связи сервера 1 С:Предприятия и SQL Server. Здесь важно, что для повышения защищенности протокола на том компьютере, на котором установлен SQL Server, в диалоге SQL Server Network Utility можно установить флаг Force Protocol Encryption, что обеспечит шифрование дан- ных перед их передачей по сети. При этом аналогичный флаг необходимо установить на компьютере — сервере 1 С:Предприятия в диалоге SQL Server Client Network Utility. Нужно учитывать, что установка этого флага приведет к некоторому снижению производительности. 2. Следует выбрать необходимый уровень защиты прото- кола связи клиента 1 С: Предприятия с сервером ^Пред- приятия. Соединение с сервером реализуется механизма- ми COM\DCOM. Защита протокола передачи данных между клиентом и сервером возложена на встроенную в СОМ+ систему безопасности. Поэтому настройку защи- ты можно сделать на компьютере — сервере ЮПредпри- ятия при помощи утилиты Component Services. На закладке Security свойств СОМ+ приложения 1CV8 нужно выбрать необходимое значение Authentication level for calls. Наи- большую защиту обеспечивает режим Packet Privacy, под- разумевающий кодирование данных перед тем, как пере- давать их по сети. Следует учитывать, что использование этого режима может привести к заметному снижению производительности. Администрирование ЮПредприятия Административные права следует назначать только тем пользователям ЮПредприятия, которые являются ад- министраторами. Пользователь с административными правами имеет, в частности, возможность выполнить вы- грузку/загрузку информационной базы, а также выпол- нять любые изменения прав, тем самым получая доступ к любым данным информационной базы. Варианты использования При использовании клиент-серверного варианта работы допускаются различные варианты взаимного расположе- ния сервера баз данных, сервера 1 С: Предприятия и кли- ентского приложения на компьютерах. Наиболее желательным является размещение всех трех приложений на разных компьютерах (рис. 5.4). В этом случае как сервер баз данных, так и сервер ЮПредприятия смогут полноценно использовать аппа- ратные ресурсы и работать максимально производитель- но. Также этот вариант использования предоставляет лучшие возможности для масштабирования системы, по- скольку модификацию аппаратных средств можно произ-
водить независимо, исходя из реальной загрузки того или иного сервера. Рис. 5.4. Размещение приложений на разных компьютерах При умеренной нагрузке на прикладное решение и при небольших объемах вычислений, производимых на серве- ре 1С:Предприятия, возможно размещение сервера баз данных и сервера 1С:Предприятия на одном компьютере (рис. 5.5). Рис. 5.5. Размещение сервера баз данных и сервера 1С:Предприятия на одном компьютере Такой вариант является более дешевым, однако менее эффективным с точки зрения производительности. Рабо- та обоих серверов на одном компьютере предъявляет, в частности, повышенные требования к объему оператив- ной памяти, которая активно используется как одним, так и другим приложением. Также возможны и другие варианты взаимного размеще- ния приложений, например на одном и том же компьюте- ре (рис. 5.6). Рис. 5.6. Размещение сервера баз данных и сервера 1С:Предприятия на рабочей станции Этот вариант вряд ли имеет смысл использовать для ре- альной многопользовательской работы, однако он может часто применяться, например, при разработке приклад- ных решений одним разработчиком. Особенности использования При использовании клиент-серверного варианта работы следует учитывать некоторые особенности его функцио- нирования. Запуск и остановка сервера При установке первого соединения с информацион- ной базой сервер 1С:Предприятия выполняет чтение наи- более важных и часто используемых данных из информа- ционной базы. Эти данные в дальнейшем могут совмест- но использоваться несколькими соединениями. Поэтому установка первого соединения может выполняться не- сколько дольше, чем второго и последующих. Кроме того, если соединение является первым для всего сервера 1С:Предприятия после долгого бездействия, то к этому моменту сервер может быть остановлен механизмом СОМ+ и выгружен из памяти. Поэтому потребуется загрузка всех его компонентов, что тоже может занять некоторое время. Разрыв последнего соединения с данной информацион- ной базой приводит к выгрузке из памяти всех данных этой информационной базы, а разрыв последнего соеди- нения с данным сервером 1 С: Предприятия — выгрузке большинства входящих в его состав компонент. При этом если используются установки СОМ+ по умолчанию, то через 3 минуты после разрыва последнего соединения с сервером 1С:Предприятия он будет остановлен и выгру- жен из памяти.
Соединения с сервером Каждое соединение с информационной базой требует не- значительных ресурсов, однако в следующих случаях лиш- ние соединения могут мешать нормальной работе: ♦ соединение с Конфигуратором не позволяет подсоеди- ниться к информационной базе другим Конфигурато- ром; ♦ обновление конфигурации базы данных и некоторые другие операции, требующие монопольного доступа к информационной базе, не могут быть выполнены, если соединений с данной информационной базой больше одного; ♦ если в процессе работы 1 С:Предприятия была начата транзакция, то эта транзакция ассоциируется с соеди- нением сервера 1 С:Предприятия с данным клиентским приложением 1 С: Предприятия. Нештатное завершение клиентского приложения 1 С:Предприятия в этот мо- мент может привести к тому, что транзакция останется незавершенной вместе с неразорванным соединением. Незавершенная транзакция может быть препятствием для нормальной работы других клиентских приложе- ний ЮПредприятия; ♦ при начале редактирования объекта или при выполне- нии метода <объект>.3аблокировать() на данные объекта устанавливается пессимистическая блокировка. Все блокировки объектов также ассоциируются с соедине- нием и сохраняются либо до момента снятия блокиров- ки (окончание редактирования или выполнение метода <объект>. Разблокировать О) или до разрыва соединения. Неснятые блокировки объектов также могут быть помехой для работы других клиентских приложений 1 (/Предприятия. В перечисленных случаях нежелательные соединения не- обходимо разорвать, для чего обычно достаточно завер- шить установившие их приложения. Если это затрудни- тельно, то соединения можно разрывать при помощи консоли сервера ЮПредприятия или программно. При этом установившие их приложения завершатся аварийно и все их несохраненные данные будут потеряны. Отдельный случай представляют соединения, за которы- ми уже не стоят никакие приложения. Такие соединения могут остаться от приложений, завершившихся не штат- но. Механизм СОМ+ следит за активностью прило- жения, установившего соединение с СОМ+ сервером, в большинстве случаев распознает соединения, оставшие- ся без клиентских приложений, и через 6-8 минут авто- матически разрывает такие соединения. Если это соеди- нение мешает продолжению работы то, не дожидаясь автоматического разрыва соединения механизмами СОМ+, можно разорвать соединение при помощи консоли серве- ра ЮПредприятия или программно. Выполнение кода на сервере Выполнение кода на встроенном языке, исполняемого на сервере, невозможно прервать. Это значит, что: ♦ процедура ОбработкаПрерыванияПользователя на сервере недоступна; ♦ разрыв соединения утилитой администрирования ин- формационных баз невозможен, если управление нахо- дится на сервере. Для прерывания исполнения кода, зациклившегося на сервере, необходимо перезагружать серверное приложе- ние, что приводит к перерыву в работе всех клиентов это- го сервера. Поэтому код, исполняемый на сервере, дол- жен отлаживаться наиболее тщательно. Следует избегать выполнения на сервере очень долгих действий (занимаю- щих десятки минут и часы), а также действий, время ис- полнения которых может неограниченно расти, с ростом объема информационной базы. Отладка кода на сервере Встроенный в ЮПредприятие отладчик не позволяет от- лаживать код, исполняемый на сервере. Для отладки ис- полняемого на сервере кода можно применять различные методы: ♦ исполнение серверного кода перенести на клиента (ус- тановив соответствующие флаги в свойствах модулей). Исполнение модуля на клиенте логически ничем не от- личается от исполнения его на сервере. Однако так нельзя проверить работу привилегированных модулей; ♦ воспользоваться файловым вариантом информацион- ной базы. В этом случае все модули, в том числе и при- вилегированные, выполняются на клиенте и доступны отладчику 1 С: Предприятия. Использование аппаратных ресурсов сервером Серверу 1 С:Предприятия доступно не более 2 (или 3) ги- габайт виртуального адресного пространства. Это адрес- ное пространство делится между всеми пользователями. Поэтому учитывать ограничения на максимальные раз- меры коллекций, выборок из базы данных и текстов за- просов к базе данных в клиент-серверном варианте более важно, особенно для кода, исполняемого на сервере. Кроме того, клиент-серверный вариант ЮПредприятия накладывает ограничения на использование нескольких ин- формационных баз на одном сервере 1 С: Предприятия. Не следует через один сервер 1 С: Предприятия работать со многими информационными базами. Подсоединение к ин- формационной базе хотя бы одного клиента приводит к за- грузке ее конфигурации в память сервера (для конфигура- ции Управление Производственным Предприятием — около 90 мегабайт виртуального адресного пространства). Под- соединение последующих клиентов к этой же информаци- онной базе дополнительных больших объемов памяти не потребует. Однако подсоединение клиента к другой инфор- мационной базе на этом же сервере приведет к загрузке и ее конфигурации тоже. Таким образом, факт одновременного подсоединения клиентов хотя бы к 11 различным информа- ционным базам с конфигурациями, сравнимыми с Управ- ление Производственным Предприятием, может привести сервер ЮПредприятия в неработоспособное состояние. Совместная работа с сервером Нежелательно использовать для разработки и тестирова- ния конфигураций тот сервер ЮПредприятия, на кото- ром работает большое количество пользователей. Это обу- словлено тем, что сохранение конфигурации и обновление конфигурации базы данных требует значительного объема свободного виртуального адресного пространства, которо- го в нагруженном сервере 1 С: Предприятия может не быть.
Использование виртуальной памяти Размер файла подкачки страниц компьютера, на котором установлен сервер 1 С: Предприятия, должен быть не менее 2 гигабайт (если используется режим 3Gb, то 3 гигабайт). Размещение сервера SQL-сервер целесообразно размещать на отдельном от сервера 1С:Предприятия компьютере, если: ♦ объем оперативной памяти компьютера с сервером ЮПредприятия меньше 4 гигабайт; ♦ на сервер 1С:Предприятия вынесена обработка данных; ♦ возможна установка Microsoft SQL Server на 64-разряд- ной системе. Если конфигурация выполняет какие-нибудь вычисле- ния на сервере, то необходимо учитывать возможность одновременного выполнения таких вычислений по ини- циативе нескольких пользователей. Если количество пользователей, которые могут выполнять данное вычис- ление одновременно, достаточно большое, то серверный компьютер может быть перегружен, что приведет к сни- жению производительности системы. Длительная работа сервера Длительная работа сервера 1 С:Предприятия приводит к эффекту фрагментации виртуального адресного про- странства серверного приложения, что может стать при- чиной некоторого снижения производительности сервера ЮПредприятия. Для борьбы с этим эффектом рекомен- дуется периодическая перезагрузка серверного приложе- ния 1С:Предприятия. Организация выполнения кода на сервере или на клиенте Используя возможность управления компиляцией модулей можно передавать исполнение кода с клиента на сервер; по- сле выполнения вызванной процедуры или функции, систе- ма продолжит исполнение кода на клиенте. Это позволяет, например, сложные алгоритмы расчета выполнять не на клиентской машине, а на более мощном сервере, что увели- чивает общую производительность прикладного решения. Передача выполнения с клиента на сервер может быть выполнена только путем вызова процедуры общего модуля. После запуска прикладного решения выполнение кода всегда осуществляется на клиенте. В процессе работы ис- полнение кода, может быть передано на сервер следую- щим образом: при вызове процедуры или функции, ее по- иск сначала осуществляется на стороне клиента. Если скомпилированный контекст клиента не содержит вызы- ваемой процедуры, ее поиск будет осуществлен на сторо- не сервера. Если вызываемая процедура будет найдена, то выполнение кода будет передано на сервер. После того как вызываемая процедура завершит свою работу, выпол- нение будет передано обратно на клиента. Простейшим примером передачи выполнения кода на сер- вер может служить вызов экспортируемой процедуры об- щего модуля, у которого установлено только свойство Сер- вер. Экземпляр этого модуля будет скомпилирован только на стороне сервера. При вызове в модуле отчета этой экс- портной процедуры она не будет найдена на стороне кли- ента, и выполнение будет передано на сервер (рис. 5.7). Рис. 5.7. Передача выполнения кода на сервер Аналогичным образом выполнение может быть передано на сервер при помощи инструкций препроцессору. На- пример, общий модуль, который компилируется как на стороне сервера, так и на стороне клиента, содержит сле- дующий текст (листинг 5.4). Листинг 5.4. Передача исполнения кода на сервер с использованием инструкций препроцессора Процедура ТекущийДолгО Экспорт КонецПроцедуры #Если Сервер Тогда Процедура ПересчитатьО Экспорт КонецПроцедуры ^КонецЕсли Процедура Проверить О Экспорт КонецПроцедуры Тогда экземпляр этого модуля, скомпилированный на стороне сервера, будет содержать описание процедуры Пересчитать, в то время как в экземпляре, скомпилирован- ном на стороне клиента, это описание будет отсутство- вать. Тогда, при вызове этой процедуры, например, в мо- дуле отчета, она не будет найдена на стороне клиента, и выполнение перейдет на сервер (рис. 5.8). После того, как выполнение передано на сервер, все ос- тальные вызовы процедур и функций будут выполняться также на стороне сервера (рис. 5.9). Важно отметить, что разработчик не может «управлять» передачей выполнения с сервера обратно на клиента. Вы- полнение будет передано только после завершения вы- полнения вызванной процедуры или функции. Другими словами, если выполнение осуществляется на сервере и вызываемая процедура не найдена в скомпилированном на стороне сервера коде, то будет выдано сообщение об ошибке даже в том случае, если вызываемая процедура присутствует в экземпляре, скомпилированном на сторо- не клиента (рис. 5.10).
Рис. 5.8. Передача выполнения кода на сервер Рис. 5.9. Исполнение вызовов процедур на сервере Рис. 5.10. Исполнение вызовов процедур на сервере
Изменение поведения объектов в зависимости от контекста выполнения Инструкции препроцессору могут быть использованы для того, чтобы изменять поведение объекта в зависимо- сти от того, создан он на клиенте или на сервере. Например, пусть после проведения документа Накладная требуется выводить на экран печатную форму документа с использованием табличного документа. В этом случае вызов функции, осуществляющей вывод этой формы Вы- вестиФормуНакладной в процедуре обработки проведения документа, можно заключить в инструкции препроцессо- ру, и этот вызов будет присутствовать только в экземпля- ре модуля объекта документа Накладная, скомпилирован- ном на стороне клиента (листинг 5.5). Листинг 5.5. Условная компиляция модуля объекта Процедура ОбработкаПроведения(Отказ, Режим) #Если Клиент Тогда ВывестиФорнуНакладной(); ^КонецЕсли КонецПроцедуры Таким образом, если в будущем возникнет необходи- мость, например, создания обработки для проведения группы накладных на сервере (ПровестиНакладные), такая обработка будет работать корректно, поскольку вызов функции ВывестиФормуНакладной будет отсутствовать в экземпляре модуля, скомпилированном на стороне серве- ра; в противном случае попытка использования объекта ТабличныйДокумент на сервере (для вывода печатной фор- мы) привела бы к ошибке (рис. 5.11). Рис. 5.11. Проведение накладной на сервере и клиенте Рис. 5.12. Использование функции модуля приложения
Особенности использования экспортируемых переменных, функций и процедур модуля приложения (модуля внешнего соединения) При написании текстов модулей объектов не рекоменду- ется использовать экспортируемые переменные, функ- ции и процедуры модуля приложения или модуля внеш- него соединения. Это связано с тем, что модуль объекта может компилироваться как на стороне сервера, так и на стороне клиента, в то время как модуль приложения и модуль внешнего соединения компилируются только на стороне клиента. В результате может возникнуть ситуа- ция, когда объект будет обрабатываться некоторой сер- верной обработкой и не сможет обратиться к экспорти- руемым процедурам/функциям модуля приложения или модуля внешнего соединения. Например, если при проведении документа Накладная с помощью экспортируемой функции модуля прило- жения проверяется правильность заполнения рекви- зитов документа, то при групповом проведении доку- ментов на сервере будет выдана ошибка исполнения (рис. 5.12). Передача параметров на сервер и возврат значений При передаче выполнения кода на сервер, как правило, выполняется передача некоторых параметров вызывае- мой процедуры или функции. Также, в случае вызова функции, будет выполняться передача результата работы функции с сервера на клиента. Важно учитывать, что не все типы значений и объекты, работа с которыми возможна на сервере, могут быть пере- даны с клиента на сервер и обратно. В общем, можно ска- зать, что на сервер могут быть переданы немутабельные объекты (то есть объекты, значения которых не могут из- меняться) и мутабельные объекты некоторых определен- ных типов. Немутабельными, например, являются примитивные типы, ссылки, значения системных перечислений, хранилище значения. Что касается системных перечислений, то, не- смотря на то, что в принципе все они могли бы участво- вать в обмене с сервером, допускается передача только тех, которые не имеют отношения к интерфейсным объ- ектам (так как интерфейсные объекты не могут использо- ваться на сервере). Также могут передаваться некоторые универсальные коллекции значений: Структура, Соответ- ствие, ТаблицаЗначений, Массив и др. Важно, что элементы этих коллекций не должны содержать мутабельных зна- чений. Точная информация о возможности использования ти- пов значений и объектов на сервере, и передаче их между клиентом и сервером, находится в документации, в опи- сании конкретных объектов. Выполнение кода на сервере без проверки прав Выполнение кода на сервере, помимо решения задач про- изводительности прикладного решения, может также использоваться для выполнения действий, которые за- прещены текущими правами пользователя. Для этого ис- пользуются общие модули, у которых установлено свой- ство Привилегированный. Такие модули могут исполняться только на сервере, и при их выполнении сервер не осуще- ствляет проверку прав. Необходимость в использовании привилегированных мо- дулей может возникнуть, например, когда стандартных возможностей системы прав доступа не хватает для того, чтобы описать специфику работы пользователя. Например, есть филиал компании, в котором ни один из сотрудников не имеет административных прав. Инфор- мационная база обслуживается специалистами централь- ного офиса, которые периодически приезжают в филиал. Однако для текущей работы филиала необходимо обес- печить возможность добавления в информационную базу новых пользователей самими сотрудниками филиала. Сложность этой задачи заключается в том, что для того, чтобы пользователь информационной базы имел возмож- ность модифицировать список пользователей, он должен обладать административными правами. Однако админи- стративные права, помимо модификации пользователей, позволяют выполнять и целый ряд других операций с ба- зой данных, например редактирование основной конфи- гурации, загрузку/выгрузку информационной базы и пр. В такой ситуации выполнение кода без проверки прав на сервере позволяет разрешить добавление пользователей в информационную базу, в то время как все администра- тивные функции для данного пользователя запрещены. Реализовать это можно с помощью обработки, которая создает новый объект ПользовательИнформационнойБазы и пре- доставляет возможность заполнить все его реквизиты: имя, пароль, набор прав и пр. Затем выполнение переда- ется в процедуру привилегированного модуля, в которую, в качестве параметра, также передается и сам объект Поль - зовательИнформационнойБазы. Для записи этого объекта тре- буется наличие административных прав у текущего поль- зователя, но так как в привилегированном модуле код выполняется без проверки прав, то новый пользователь успешно добавляется в список пользователей, после чего управление передается обратно на клиента. В приведенной выше последовательности действий есть один важный момент, на который всегда следуют обра- щать пристальное внимание при написании текстов при- вилегированных модулей. При разработке прикладного решения подразумевается, что «рядовой» пользователь не обладает административ- ными правами и не имеет доступа к тексту конфигу- рации. Однако пользователю может быть разрешено ис- пользование внешних обработок, а значит, он может попытаться обратиться к функции привилегированного модуля из своей собственной обработки и выполнить те действия, на которые, возможно, у него не должно быть прав. Для исключения такой ситуации, перед тем, как в приви- легированном модуле выполнять какие-либо действия,
следует удостовериться, что эта процедура вызвана именно тем пользователем, который имеет на это право (рис. 5.13). Рис. 5.13. Схема проверки прав в привилегированном модуле Например, добавление новых пользователей в информа- ционную базу может быть разрешено только менеджеру филиала, причем даже менеджер не должен иметь воз- можности добавлять пользователей с административ- ными правами. В то же время нужно предусмотреть, что администратор системы должен иметь возможность с по- мощью той же обработки добавить пользователя с любы- ми (в том числе и административными) правами. В этом случае текст привилегированного модуля может выгля- деть следующим образом (листинг 5.6). Листинг 5.6. Процедура привилегированного модуля Процедура ЗаписатьПользователя(ПользовательИБ) Зкспорт // Проверить наличие роли Администратор //у добавляемого пользователя. РольАдминистратор = Метаданные.Роли.Администратор: Если ПользовательИБ.Роли.Содержит(РольАдминистратор) Тогда // Проверить у текущего пользователя // наличие адиинистративных прав. Если РольДоступна(РольАдминистратор) Тогда // Выполнить запись нового пользователя. ПользовательИБ.ЗаписатьО; Иначе Сообщить!"Отсутствуют административные права. (Добавление нового пользователя не выполнено."); КонецЕсли; Иначе // у добавляемого пользователя // нет роли Администратор // Проверить, что текущий пользователь обладает // правами Менеджера или Администратора Если РольДоступна(РольАдминистратор) ИЛИ РольДоступнаСМетаданные.Роли.Менеджер) Тогда // Выполнить запись нового пользователя. ПользовательИБ.ЗаписатьО; Иначе Сообщить("Недостаточно прав доступа | для добавления пользователя.”); КонецЕсли: КонецЕсли: КонецПроцедуры Сначала проверяется, назначены ли административные права добавляемому пользователю. Если добавляется пользователь с административными правами, то проверя- ется, является ли текущий пользователь администрато- ром. Если же добавляется пользователь без администра- тивных прав, то проверяется, является ли текущий пользователь менеджером или администратором. Запись нового пользователя выполняется только при соблюде- нии перечисленных условий. В противном случае выда- ется сообщение об отсутствии прав, и выполнение воз- вращается на клиента.
Глава 6. Хранение информации Задачи хранения информации При создании любых решений в области автоматизации практически всегда приходится решать задачи хранения информации. При этом поднимаются вопросы собствен- но предназначения хранимой информации и многочис- ленные технологические вопросы. К технологическим вопросам можно отнести те, которые приходится решать для достижения оптимального соот- ношения показателей: ♦ объем; ♦ надежность; ♦ функциональность; ♦ быстродействие Причем на всех этапах жизненного цикла информации: ♦ запись информации; ♦ хранение информации; ♦ получение информации; ♦ удаление информации. При создании бизнес-приложений сложность решений этих задач обусловлена наличием противоречий между: ♦ необходимостью обеспечения удобства представления логики взаимодействия сущностей в информационной модели; ♦ необходимостью хранения больших объемов информа- ции; ♦ повышенными требования к широкой функционально- сти и высокой производительности доступа к этим дан- ным. Например, чем больше объем — тем, в общем случае, сложнее обеспечение скорости доступа к информации (рис. 6.1). Рис. 6.1. Схема противоречий между требованиями к хранимой информации И в результате «очевидные» прямые решения одних во- просов ухудшают возможности решения других. Например, хранение информации о происходящих в жиз- ни автоматизируемого предприятия событиях в виде на- бора неструктурированных текстов — идеальное решение с точки зрения простоты и скорости регистрации. Однако последующая обработка этой информации для составле- ния каких бы то ни было аналитических отчетов в таком случае будет сопряжена с колоссальными временными затратами. Потому что, как для решения задачи поиска информации обо всех продажах предприятия, так и для поиска информации о продажах одному покупателю, не- обходимо будет пересмотреть данные всех текстов. И чем больше функциональных возможностей потребу- ется на этапе получения информации, тем дольше будут работать соответствующие обработки, зачастую по не- скольку раз «просматривая» одну и ту же информацию, но уже с разными целями. Объектно-реляционная парадигма системы 1С:Предпри- ятие позволяет в принципе решить проблему соотноше- ния удобства представления и манипулирования объек- тами, отражающими прикладные сущности, с должной надежностью и эффективностью обработки больших объ- емов информации этих объектов в базе данных. Объекты и процессы прикладной области отражаются в решении посредством объектов конфигурации. Таким образом объекты конфигурации обеспечивают удобство манипулирования данными, характеризующими приклад- ные объекты и процессы. Но сами данные объектов хранятся в реляционной базе данных (в виде таблиц, полей, индексов), при этом обес- печиваются вопросы оптимального быстродействия при больших объемах информации (рис. 6.2). Рис. 6.2. Схема представления и манипулирования данными в 1С:Предприятии В системе 1С:Предприятие все возможные к применению в решениях прикладные объекты прототипированы. Каж- дый прототип отвечает за отражение в прикладном реше- нии определенной совокупности объектов или процессов прикладной области, имеющих схожие поведенческие ха-
рактеристики и схожую роль в общей картине решения. Примерами прототипов являются справочники, докумен- ты, регистры различных видов и так далее. В рамках средств платформы для каждого прототипа уже предопределены: ♦ оптимальная, для большинства задач, структура хране- ния информации в реляционной базе данных; ♦ набор средств встроенного языка для манипулирова- ния этой информацией; ♦ методы, свойства, события и типовые, для решаемых задач, операции; ♦ способы отображения и редактирования; ♦ средства регулирования прав доступа и т. д. Рис. 6.3. Пример представления и манипулирования данными Таким образом облегчается работа разработчика конкрет- ного прикладного решения. С точки зрения эффективно- го хранения информации, вместо решения задач «низко- го» уровня он занят решением вопросов: ♦ выбора среди прототипов нужных; ♦ создания в рамках прототипов объектов с наиболее подхо- дящим составом для отражения прикладных сущностей; ♦ обеспечения обмена информацией и взаимодействия между созданными объектами. Обеспечение же всей остальной необходимой функцио- нальности берет на себя система. Но и в этих вопросах у разработчиков достаточно широкие возможности, при необходимости «подправления» поведения программы. В частности, при решении задач, связанных с вводом и получением информации для последующего ана- лиза. Например, при отображении динамических списков сис- тема считывает из базы данных содержимое только види- мых полей и полей, необходимых «для технологических нужд». Если же разработчику необходимо сделать так, чтобы данные некого поля, не отображаясь, тем не менее, считывались из базы данных вместе с остальными, он мо- жет этого добиться. Подробно это описано в разделе «Ко- лонки списка», с. 59. Итак, вернемся к общим вопросам, связанным с обеспече- нием эффективного хранения информации. Прежде все- го, они не являются самоцелью. К выбору прототипов объектов для использования в рам- ках решения необходимо подходить с точки зрения обес- печения целей автоматизации и областей применимости прототипов. А вот уже если одинаковая функциональность может быть достигнута различными, альтернативными, с точки зрения организации хранения информации, путя- ми, то выбор оптимального варианта построения конфи- гурации как раз и будет определяться оптимальностью решения вопросов хранения информации. Причем разработчику необходимо решать эти вопросы в комплексе. Потому что все объекты будут тесно связа- ны между собой логическими, информационными, интер- фейсными и прочими связями в интересах преследова- ния общих целей автоматизации. В общем виде взаимосвязь и предназначение объектов, относящихся к соответствующим прототипам, могут быть описаны следующим образом (рис. 6.4). Рис. 6.4. Взаимосвязь различных групп объектов Если требуется хранить в базе данных информацию, из- меняющуюся достаточно редко, работа с которой строит- ся по принципу «ввели один раз, но используется много раз», наиболее удобны для хранения такой информации объекты из блока условно-постоянная информация. То есть справочники, перечисления, константы, планы видов ха- рактеристик — при решении практически любых задач. Планы счетов, планы видов расчетов и т. п. — при реше- ниях специфичных задач, сопряженных с использовани- ем принципа «двойной записи», использованием меха- низмов сложных периодических расчетов и т. д. Если требуется хранить информацию о происходящих в жизни автоматизируемого предприятия действиях (со- бытиях и выполняемых операциях), то есть — информа- цию, для которой важна привязка ко времени, то наибо- лее удобно использовать документы. На схеме к этой же группе относятся и другие объекты, которые используют- ся для решения вопросов дополнительной функциональ- ности системы при обслуживании этой информации:
♦ журналы — средства визуального группирования ин- формации разных документов; ♦ последовательности — средства логического группиро- вания информации разных документов; ♦ нумераторы — средства группирования разных доку- ментов для ведения единой нумерации. Если требуется хранить информацию о состоянии пока- зателей, учитываемых в системе, то более удобны для ре- шения этих задач объекты из группы регистры. Причем показатели могут иметь привязку ко времени или не иметь ее, быть наиболее общими или достаточно специ- фичными, предназначенными к использованию в специ- альных моделях учета (те же: «двойная запись», «слож- ные периодические расчеты» и т. д.). Чаще всего модель обмена информацией между объекта- ми вышеописанных прототипов обслуживает следующую модель автоматизации бизнес-решений: ♦ требуемые аналитические и информационные материа- лы о различных аспектах состояния дел на автоматизи- руемом предприятии получаются пользователями по- средством отчетов и обработок (объектов, специально предназначенных для обеспечения вывода информации в удобном для пользователя виде); ♦ для обеспечения максимального быстродействия фор- мирования отчетной информации о состоянии учиты- ваемых в системе показателей, алгоритмы представле- ния этой информации берут ее в уже готовом (или почти готовом виде, с последующей «дообработкой») из регистров; ♦ изменение состояния учитываемых показателей в реги- страх производится не произвольным образом, а при наличии «документального подтверждения». То есть информация регистров вторична, она заполняется на основании данных документов. Ведь именно докумен- ты служат для обеспечения регистрации происходящих в жизни автоматизируемого предприятия событий; ♦ однозначность толкования вводимой в документы ин- формации обеспечивается организацией заполнения до- кументов посредством выбора элементов объектов хра- нения условно-постоянной информации, отражающих объекты прикладной области. Однако, как уже было замечено выше, разработчик не обязан слепо следовать предлагаемой логике. В ситуаци- ях, когда это окажется оправданным, можно применять приемы, «упрощающие» или даже полностью «отвергаю- щие» ее. Например, в платформе системы 1С:Предприятие есть возможности и средства прямого интерактивного ввода информации в регистры, формирования отчетов на осно- вании данных первичных документов, заполнения спра- вочников посредством обработок и так далее. Более того, рассмотрение и оценка возможных вариантов выбора прототипов и объектов будет производиться фак- тически каждый раз заново, для данной конкретной си- туации данного конкретного решения. Потому что даже в рамках преследования одинаковых целей автоматизации, но для разных условий функционирования эффективная композиция структуры объектов в рамках решения мо- жет оказаться разной. Например, ситуации для предприятия, заключающего в течение года сто сделок по десять миллионов рублей, и для предприятия, заключающего в год десять миллио- нов сделок по сто рублей, — с точки зрения оптимизации хранения информации различаются. Поэтому цель данного раздела не навязать «единственно верную» структурную технологию решения задач хране- ния информации (тем более что такой не существует), а показать возможности решения вопросов хранения ин- формации. И зачастую, — в сравнении плюсов и мину- сов альтернативных вариантов использования для этих решений различных видов объектов системы 1С:Пред- приятие. Варианты подходов к решению задач хранения информации Хранение информации, общей для информационной базы При решении вопросов хранения общей информации есть возможности организовать решения в рамках работы с конфигурацией или с базой данных. Использование общих картинок Например, картинки с логотипами юридических лиц ком- пании могут храниться в составе общих картинок конфи- гурации, а могут в составе реквизитов справочника (на- пример, справочника Организации) (рис. 6.5). С точки зрения надежности хранения информации успеш- ность обращения к картинке в первом случае «гарантиру- ется» неизменностью конфигурации, во втором — мерами разграничения прав доступа пользователей к объектам базы данных (то есть при неудачном стечении обстоя- тельств при обращении к картинке может выясниться, что она удалена или модифицирована пользователем). Использование макетов Если предпочтение отдается хранению информации на уровне конфигурации, то, кроме картинок, возможно ис- пользование макетов — общих макетов и макетов объек- тов конфигурации. При этом могут быть использованы следующие виды ма- кетов: ♦ макет текстового документа; ♦ макет табличного документа; ♦ макет двоичных данных; ♦ макет ActiveDocument; ♦ макет HTML-документа; ♦ макет географической схемы.
Конфигурация * ? X Рис. 6.5. Пример хранения картинок в составе конфигурации Чаще всего макеты используются для хранения данных шаблонов нужных типов. Например, когда в конфигурации нужно хранить «краси- вый» шаблон приглашения, разработанный в Word, с це- лью его автоматического заполнения при выполнении со- ответствующей задачи работы пользователя (рис. 6.6). $ Конфигурация Примеры: Приглашение - ~ X Рис. 6.6. Пример хранения макета ActiveDocument При этом можно макеты загружать из файлов, а можно создавать «пустые» макеты нужного вида (рис. 6.7). Конструктор макета Синоним: Комментарий: Загрузить из Ф< X - Выберите тип » О Табличный. О Текстовый. О Двоичные л @ Active docur О HTML докут О ГеограФиче | Готово ] | Отмена 11 Справка | Рис. 6.7. Создание макета Имя: Но, кроме того, макеты могут, например, использоваться в ситуациях, когда необходимо организовать для отчетов «запоминание» данных для их построения. Так, в ряде типовых решений фирмы «1С» используются технологии «универсальных отчетов», основанные на хра- нении в макете отчета информации, согласно которой от- чет впоследствии строится, и использовании возможно- стей «гибкой донастройки» этой информации непосред- ственно в макете (рис. 6.8). Рис. 6.8. Хранение настроек отчета в макете табличного документа Хранения единичных значений условно-постоянной информации Зачастую при решении задач необходимо реализовывать хранение данных неких единичных значений, которые меняются крайне редко. Использование констант Константы — классические объекты для хранения таких данных. Добавлять новые константы или удалять старые можно только в режиме конфигурирования, но вот запол-
нение и модификация значений обычно производится пользователями (если не ограничен доступ). При решении прикладных задач посредством констант обычно запоминаются общие для всей информационной базы значения. Можно привести примеры таких констант, как ОсновнаяБазоваяВалюта или ОсновнаяОрганизация. Также в константах могут храниться значения по умолча- нию для поддержания работы критичных к пустым значе- ниям алгоритмов. Такими константами являются, напри- мер, константы НачалоРабочегоДня, ОкончаниеРабочегоДня. Кроме этого, благодаря тому, что значения, хранящиеся в константе, общие для всех, с помощью констант можно организовать информирование пользовательских сеансов работы с программой. Например, пользователь с административными правами имеет право устанавливать для булевой константы Заверше- ниеРаботы значение Истина. А соответствующая обработка ожидания проверяет значение этой константы и в случае необходимости завершает пользовательский сеанс. Пример данного механизма реализован в составе демонстрационной конфигурации «Хранение информации и учет движения средств», которая находится на прилагаемом компакт-диске. Необходимая функциональность реализуется в рамках модуля приложения (листинг 6.1). Листинг 6.1. Фрагмент модуля приложения Перем ЗавершитьРаботу: Процедура ПриНачалеРаботыСистены() КонтрольРежимаЗавершенияРаботыПопьзователей(); ПодключитьОбработчикОжидания( "КонтрольРежинаЗавершенияРаботыПользователей". 180); КонецПроцедуры Процедура КонтрольРежимаЗавершенияРаботыПользователей() Экспорт: // Определить текущее значение константы Завершение = Константы.ЗавершениеРаботыПользователей. Получить!); Если Завершение Тогда Если ЗавершитьРаботу Тогда // Завершить работу окончательно ЗавершитьРаботуСистемыО; Иначе // Предупредить пользователя и приготовиться // завершить работу в следующий раз ТекстПредупреждения = "Работа системы будет |автоматически завершена через 3 минуты!"; Предупреждение(ТекстПредупреждения, 30. "Завершение работы"); ЗавершитьРаботу = Истина; КонецЕсли; КонецЕсли; КонецПроцедуры //-............... // Выполнить начальную инициацию флага завершения работы ЗавершитьРаботу = Ложь; Использование регистров сведений В случае когда необходимо хранить информацию, общую для базы данных, но используемую для отдельных на- правлений учета или отдельных подсистем конфигура- ции, может оказаться оправданным хранение единичных условно-постоянных значений не посредством констант, а посредством ресурсов регистра сведений. Рассмотрим, например, непериодический независимый регистр сведений УчетнаяПолитика (рис. 6.9). йЛ УчетнаяПолитика i-JL Измерения ф- Ресурсы ..| ВестиПартионныйУчетПоСклацам — f СписыватьПартииПриПроведенииДокументов — f СпособО ценкиМПЗ ..I ПараметрАВСКлассиФикацииПокупателей --1 ПараметрРаспределенияПокупателейПоСтадиям — f СтратегияСписанияПартийТоваровПоСтатусам | Иелмъ зомгьС*л«кW1 оКоличествуТ овара | ИстжхшхввгьСкмвм^ЛоСуммеДокумента — g Итзмжв«гкС*мв«»/1о8иад0плать! ..(I ВедениеУчетаПоПроектам — I НеВключатьНДСВСтоимостьЛаргий 2 Реквизиты Рис. 6.9. Структура регистра УчетнаяПолитика Возможности пользователей по модификации значений бу- дут определяться средствами разграничении прав доступа. Обратите внимание: в данном регистре не подразумева- лось использование измерений, а значит, разрезов учета значений ресурсов. То есть данные регистра могут ис- пользоваться как общие для всей базы данных. Подробнее о регистрах сведений можно прочитать в раз- деле «Хранение информации в регистрах сведений», с. 107. Использование перечислений Для решения задач, когда необходимо хранить уже не единичные значения, а некие конечные наборы значений и при этом не подразумевается их модификация пользо- вателями, возможно применение перечислений. Все операции по добавлению, изменению, удалению зна- чений измерений производятся только в режиме работы Конфигуратор. Само же хранение информации перечислений реализует- ся в соответствующих таблицах базы данных (по одной для каждого перечисления) (рис. 6.10). I. J fI-- "• ЧастноеЛицо \ I !Организация ' {”2 Макеты &{..} Виды Договоров Е3{. ) РазмещениеЗаказовПокупэтелей Й { ) ВиаыОпераций Таблица перечисления "ВидыКонтрагентов" в базе данных Порядок Ссылка 0 ЧастноеЛицо 1 Организация Рис. 6.10. Хранение значений перечислений Обращение для чтения этой информации возможно как средствами табличной модели (запросы), так и объектны- ми методами.
Если, например, в ходе обработки необходимо использо- вать заранее известное значение перечисления, то его можно получить с помощью обращения к глобальному контексту (листинг 6.2). Листинг 6.2. Пример получения значения перечисления ЗаполняемоеЗначениеВидаКонтрагента = Перечисления.ВидыКонтрагентов.ЧастноеЛицо; Еще раз подчеркнем: при использовании такого кода раз- работчик уверен, что данное значение перечисления не может быть удалено или изменено пользователем, по- скольку модификация этих данных возможна только в ре- жиме Конфигуратор. Кроме того, многие «типовые операции», связанные с ис- пользованием перечислений, уже реализованы средства- ми платформы. Например, в ходе некой обработки надо предложить поль- зователю выбрать значение перечисления Виды Контраген- тов. Задача может быть решена так (листинг 6.3). Листинг 6.3. Пример организации интерактивного выбора значения перечисления СписокЗначенийПеречисления = Новый СписокЗначений; // Прочитать значения перечисления из базы данных Запрос = Новый Запрос; Запрос.Текст = " |ВЫБРАТЬ ВидыКонтрагентов.Ссылка КАК Значение, ПРЕДСТАВЛЕНИЕ(ВидыКонтрагентов.Ссылка) КАК ПредставлениеЗначения | ИЗ | Перечисление.ВидыКонтрагентов КАК ВидыКонтрагентов"; Результат = Запрос. ВыполнитьО; Выборка = Результат.ВыбратьО; Пока Выборка.Следующий() Цикл // Заполнить значения списка СписокЗначенийПеречисления.Добавить(Выборка.Значение, Выборка.ПредставлениеЗначения); КонецЦикла; // Предложить пользователю выбрать значение ВыбранноеЗначение = СписокЗначенийПеречисления. ВыбратьЗлемент("Выберите вид контрагента"): Краткий комментарий: запросом из таблицы перечисле- ния ВидыКонтрагентов считываются значения и представ- ления для каждой записи. В цикле выборки из результата запроса заполняются значения и представления списка значений СписокЗначенийПеречисления. В конце пользова- телю предлагается выбрать значение из списка СписокЗна- ченийПеречисления. Однако если бы выбор значения перечисления нужен был для заполнения поля, имеющего визуальное пред- ставление в форме обработки, то данный код писать не пришлось бы вообще. Достаточно было бы установить со- ответствующий тип значения поля ввода (Перечисление- Ссылка.ВидыКонтрагентов) (рис. 6.11). Дальнейшая функциональность была бы реализована сис- темой автоматически (рис. 6.12). Рис. 6.12. Выбор значения перечисления в поле ввода Использование предопределенных лементов В ситуациях, когда требуется сочетать «гарантии нали- чия» информации с гибкими возможностями модифика- ции этой информации, интересные возможности предо- ставляет использование предопределенных элементов спра- вочников, планов видов характеристик, планов счетов и т. п. Благодаря тому что добавление и удаление предопреде- ленных элементов возможно только в режиме работы Конфигуратор, разработчик может быть уверен в их «со- хранности» при любых действиях пользователей. Кроме этого, каждый предопределенный элемент обладает уни- кальным именем, что позволяет создавать алгоритмы, использующие, например, предопределенные виды кон- тактной информации, предопределенные вычеты НДФЛ, предопределенные счета налогового учета и так далее. Таким образом, предопределенные элементы не «обезли- чены» для конфигурации, и конфигурация имеет воз- можность отличить один предопределенный элемент от другого (рис. 6.13). Режим "Конфигуратор* Метаданные Й 3 Справочники ЕЙ ЭидыСобытий ----------s j r-J Реквизиты iffi Т абличные части I | И Формы = I Макеты 1д__:____ Э •> Справочник Виды событий _ П X Режим ЧС.Предприятие' Ess____ 5 Выставка 1С Предприятие X 6 Заключение договора Удаление |ццци^чпг элемента справочника запрещено Добавит __________,1g Столяре Т(ЛеФонныйр ------------«Ц. Измени П| езентация 3 Ci минар Рис. 6.11. Тип значения поля ввода Установить пометку удаления В Закончить редактирование Del Shft+F2 Рис. 6.13. Пример предопределенного элемента справочника Обращение к предопределенным элементам возможно посредством обращения к содержимому глобального кон- текста.
Например, если при создании документа Событие необ ходимо заполнить значение реквизита ВидСобытия (тип значения: СправочникСсылка.ВидыСобытий) предопределенным элементом справочника, это может выглядеть так, как по- казано в листинге 6.4. Листинг 6.4. Пример использования предопределенного элемента справочника // Создать новый документ НовоеСобытме = Документы.Событие.СоздатьДокунентО; // Заполнить поля НовоеСобытие.Дата = РабочаяДата; И Заполнить значением предопределенного элемента НовоеСобытие.ВидСобытия = Справочники.ВидыСобытий.Семинар; // .. // Записать документ НовоеСобытие.Записать(); При работе с объектами встроенного языка предопределен- ные элементы отличаются от «обычных» лишь значением свойства Предопределенный (у обычных — Ложь, у предопре- деленных — Истина). Работа пользователя с предопреде- ленными элементами, по сравнению с обычными, ограни чивается лишь невозможностью удалить их. Все остальные способы модификации предопределенных элементов сле- дует ограничивать правами доступа или с помощью при кладных алгоритмов. Это означает, что пользователь при необходимости мо- жет изменить наименование предопределенного элемен- та, код, пометить на удаление и т. д. При этом для сис- темы этот предопределенный элемент остается тем же самым предопределенным элементом, так как его внут- ренний идентификатор не меняется. Хранение информации объектных и необъектных сущностей При выборе прототипов объектов для хранения инфор- мации одним из типичных вопросов, возникающих при неочевидных случаях, является выбор между объектны- ми и необъектными данными. Например, между регист- ром сведений и справочником. Подробно о функциональных отличиях данных объект- ных и необъектных можно прочитать в разделе «Работа с данными», с. 36. В рамках текущей темы ограничимся лишь вопросами выбора. Для принятия решения рекомендуется обращать внима- ние на природу данных предметной области. Если они об ладают некой «самостью», несмотря на смену значений отдельных свойств этого объекта, то предпочтение следу- ет отдавать к определению этих данных, как объектных. Например, сотрудник может сменить фамилию, имя, пас- порт, цвет глаз и т. д., однако при этом он останется все тем же сотрудником. Таким образом, мы рассмотрели ти- пичный пример идентификации сотрудников предпри- ятия как данных объектных и подлежащих учету посред- ством справочника. Однако следует учитывать что выбор вида объекта кон- фигурации не должен производиться для каждой сущ- ности отдельно. Необходимо анализировать наличие и остальных сущностей в комплексе всей прикладной зада- чи. Причем желательно не только на текущий момент, но и с учетом развития задачи в будущем. Например, состав сотрудников предприятия целесооб- разно хранить посредством объекта конфигурации Спра- вочник (рис. 6.14). Справочник "Сотрудники" Ссылка Код Наименование Рис. 6.14. Таблица справочника Сотрудники Однако, если взглянуть на проблему шире, может ока- заться, что на самом деле тут смешиваются две сущности: ♦ «Физические лица», как отражение реальных людей, с которыми предстоит иметь дело в рамках решения; ♦ «Сотрудники подразделений предприятия», причем один и тот же человек может быть сотрудником нескольких подразделений предприятия, выполняя в них различ- ные «роли» (должности, круг обязанностей и проч.). Причем вторая сущность как объект нигде не фигуриру ет, просто нужно помнить «кто есть кто». Тогда хранение данных сотрудников подразделений может быть реализо- вано посредством регистра сведений (рис. 6.15). Рис. 6.15. Связь таблицы справочника и таблицы регистра сведений Если аналогичным образом рассматривать хранение дан- ных о сотрудниках и их трудовых договорах, то можно также выделить две сущности. ♦ «Физическое лицо»; ♦ «Сотрудник — трудовой договор», как отражение юри- дических отношений данного лица с организацией, имею- щее при этом объектную природу, поскольку впослед- ствии ссылка на трудовой договор будет фигурировать во многих документах и регламентированных отчетах. В этом случае для хранения данных следует использовать два справочника (рис. 6.16). Таким образом, выбор каждого из вариантов хранения информации определяется тем, какую сущность предмет- ной области будет отражать тот или иной объект. При этом разработчикам рекомендуется также и имя объекта определять так, чтобы оно максимально отражало описы-
ваемую сущность. Это позволит впоследствии обеспечить правильное восприятие и использование объекта. Справочник “ФизическиеЛица" Ссылка Код Наименование Справочник "Г рудовыеДогио><ъэ(. е рудников" Ссылка Код Наименование ФизЛицо * Рис. 6.16. Связь таблиц справочников Хранение информации в самих объектах или в других объектах Необходимо помнить, что любой объект — это единая сущность с точки зрения манипулирования данными. То есть при любых операциях с объектом (чтение, запись, модификация) происходит обращение к информации базы данных, касающейся всего объекта. Например, справочник Договоры Контрагентов имеет под- чиненные объекты: два реквизита (ДатаПоставки и ВидДо- говора) и табличную часть Спецификация. В свою очередь, в состав табличной части тоже входит ряд реквизитов (рис. 6.17). Дог лесе* / j” par емтов □ | Реквизиты j-— ДатаПоставки ВиоДоговора Табличные части Б-ciaj Спецификация ...— Номенклатура — Количество — Цена — Сумма Рис. 6.17. Структура справочника ДоговорыКонтрагентов Хранение этой информации в базе данных будет реализо- вано системой следующим образом: ♦ в основной таблице справочника будет храниться ин- формация в следующих полях: • Ссылка; • Код; Наименование; Пометка удаления; Предопределенный; Родитель; Владелец; ЭтоГруппа; ДатаПоставки; • ВидДоговора; ♦ информация табличной части Спецификация — в от- дельной таблице, содержащей следующие поля: • Ссылка (значение этого поля равно значению поля Ссылка основной таблицы справочника); • НомерСтроки; • Номенклатура; • Количество; Цена; Сумма. Любое обращение к объекту документа приведет к тому, что из базы данных будет считана информация, соответ- ствующая данному объекту, из обеих таблиц. При этом не важно, как именно выполнялось обращение. Посредством метода «ПолучитьОбъектО» из ссылки (листинг 6.5) или при открытии формы, основным рекви- зитом которой является объект договора (рис. 6.18). Листинг 6.5. Пример получения объекта справочника из ссылки ОбъектДоговора = СсылкаНаДоговор.ПолучитьОбъектО: Рис. 6.18. Открытие формы объекта, отображающей табличную часть В последнем случае, кстати, не важно, будут отображать- ся на форме данные табличной части элемента или нет (рис. 6.19). Рис. 6.19. Открытие формы объекта, в которой табличная часть не отображается Объект в любом случае считывается целиком, поскольку при открытии формы система также создает объект спра- вочника, обеспечивая тем самым целостность изменений, вносимых в данные объекта как интерактивно, так и про- граммно, в модуле формы. Данную особенность нужно иметь в виду для сущностей, при работе с которыми часто необходим доступ именно
к объектам, а не ссылкам (например, объекты, которые часто модифицируются пользователями). При чтении объекта или его модификации данные будут считываться и записываться по объекту целиком. Таким образом, чем меньше этих данных будет, тем быстрее будут выпол- няться операции, меньше будет продолжительность бло- кировок и т. д. Из этого можно сделать вывод, что информацию, кото- рую предполагается хранить в объектах, следует анализи- ровать на предмет разделения на «активно используемую» и «не активно используемую». Активно используемую информацию можно хранить в реквизитах самого объек- та или его табличных частей. Неактивно используемую информацию об объекте можно хранить не в самом объ- екте, а посредством других информационных структур. Однако при этом придется «самостоятельно» заботиться о поддержании целостности изменений при модифика- ции данных объекта. Для вышеприведенного примера, если информацию спе- цификаций можно считать «не активно используемой», то ее хранение можно организовать посредством, напри- мер, регистра сведений СпецификацииДоговоров или под- чиненного справочника СпецификацииДоговоров. И в том и в другом случае, при считывании объекта дого- вора обращения к информации спецификации выпол- няться не будет (рис. 6.20). Рис. 6.20. Открытие формы объекта Однако при необходимости выполнить такое обращение, это будет легко сделать, например с помощью запроса (листинг 6.6). Листинг 6.6. Пример получения данных подчиненного справочника запросом Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ СпецификацииДоговоров.Код. СпецификацииДоговоров.Наименование. СпецификацииДоговоров.Номенклатура, СпецификацииДоговоров.Количество, СпецификацииДоговоров.Цена, СпецификацииДоговоров.Сунна ИЗ Справочник.СпецификацииДоговоров КАК СпецификацииДоговоров ГДЕ СпецификацииДоговоров.Владелец = &Владелец"; Запрос.УстановитьПараметр("Владелец", Договор); Результат = Запрос.ВыполнитьО; Выборка = Результат.ВыбратьО; Пока Выборка.СледующийО Цикл // Выполнить действия со информацией строки спецификации //... КонецЦикла; В этом случае из базы данных будет считана лишь нуж- ная информация спецификаций. Обратиться к данным подчиненного справочника можно и с помощью объектной модели работы с данными (лис- тинг 6.7). Листинг 6.7. Получение данных подчиненного справочника с помощью объектной модели работы с данными Выборка = Справочники.СпецификацииДоговоров.Выбрать( ,СсылкаНа8ладельца); Пока Выборка.Следующий() Цикл // Выполнить действия со строкой спецификации //... КонецЦикла; В этом случае, в отличие от табличной модели работы с данными, будут считаны целиком объекты элементов подчиненного справочника. При выборе того или иного варианта хранения, кроме разницы между «хранением необъектных данных» и «хра- нением объектных данных» (рассмотренной в разделе «Хранение информации объектных и необъектных сущ- ностей», с. 97), можно еще учесть требования к уникаль- ности информации, накладываемые используемыми объ- ектами системы ЮПредприятие. Если необходимо обеспечить жесткую уникальность по- нятия «Номенклатурная позиция спецификации догово- ра» (то есть одна и та же номенклатурная позиция не мо- жет быть указана более одного раза в спецификации одного договора), тогда предпочтительнее вариант с ис- пользованием регистра сведений. Он как раз позволяет хранить информацию только уникальную с точки зрения ключевых полей (в данном случае — измерений Договор и Номенклатура). Для подчиненного же справочника таких ограничений по уникальности нет. Если необходимо хранить информа- цию в виде простой таблицы, то этот вариант будет пред- почтительнее. Аналогична цепочка рассуждений, если в ходе решения некой прикладной задачи на этапе конфигурирования для объекта необходимо ввести много признаков или осо- бых свойств. Одно дело, если эти свойства и признаки касаются всех элементов данной сущности и активно используются при работе с объектами, им соответствующими. Тогда инфор- мацию данных свойств уместно хранить в виде реквизи- тов объекта. Например, реквизит Услуга булевою типа для справочника Номенклатура. Очень многие прикладные механизмы, ра- ботающие с элементами справочника Номенклатура, долж- ны быстро различать ситуации работы с услугами или материальными номенклатурными позициями. Другое дело, если этот признак касается лишь некоторых элементов и используется лишь в отдельных механизмах. Тогда для хранения этой информации нерационально ис-
пользовать реквизиты, а можно использовать другие объ- екты. Например, информацию о том, какие из физических лиц являются пользователями, уместнее хранить в отдельном справочнике (с реквизитом ФизЛицо) или в соответствую- щем регистре сведений. Кроме того, возможна ситуация, когда необходимо, чтобы новые признаки и характеристики могли вводиться не только на этапе конфигурирования (разработчиками), но и в режиме работы ЮПредприятие — пользователями. Для реализации этой возможности удобна организация хранения информации с использованием объекта План ви- дов характеристик. Более подробно этой теме посвящен раздел «Хранение дополнительных характеристик произ- вольного типа. Использование плана видов характери- стик», с. 131. В ситуации, когда требуется с помощью специальных свойств выделить только один элемент, использование реквизитов объектов вообще является неверным. Напри- мер, введение булевого реквизита БазоваяВалюта в состав справочника Валюты нерационально как с точки зрения хранения информации (поле будет существовать для всех элементов, хотя значение Истина, с прикладной точки зре- ния, уместно только у одного элемента), так и с точки зрения быстродействия. Для корректного разрешения по- добных ситуаций уместно считать элементы, обладающие такими специальными свойствами, данными, общими для всей базы данных. И организовывать хранение информа- ции об этом посредством констант или регистров сведе- ний. Так же осторожно нужно подходить к использованию строковых реквизитов неограниченной длины. Крайне не рекомендуется использовать их для хранения информа- ции, объем которой может быть достаточно большим или непрогнозируемым. Примером такого некорректного ис- пользования реквизита может служить сохранение в рек- визите значения, получаемого функцией ЗначениеВСтро- куВнутрО (например, для таблицы значений, содержащей большое количество строк). Не рекомендуется хранить в реквизитах активно исполь- зуемых объектов картинки и образы файлов (использова- ние полей типа ХранилищеЗначений), если заранее известно, что размер их будет велик. Для сохранения подобной ин- формации следует использовать альтернативные методы. Хранение иерархической информации Иерархическими принято считать структуры, у которых четко прослеживаются отношения «один ко многим». На- пример, «один руководитель — много подчиненных» (рис. 6.21). Рис. 6.21. Пример одноуровневой иерархии Кроме того, уровней иерархии может быть больше одно- го: «один руководитель, в подчинении которого находят- ся руководители подразделений, в подчинении которых находятся подчиненные» — пример трехуровневой иерар- хической структуры (рис. 6.22). Ну а в общем случае — уровней может быть значительно больше. Рис. 6.22. Пример многоуровневой иерархии Необходимо отметить, что в прикладных задачах в любом случае используется не бесконечное количество уровней иерархии. Например, хотя и говорят, что бюрократия бес- конечна — составляя организационно-штатную структу- ру любой организации, всегда приходим к конечному ко- личеству уровней подчинения, ответственности и т. д. В данном разделе мы не будем обсуждать достоинства и недостатки использования иерархических структур в области их применения. Сосредоточимся на возможно- стях организации хранения иерархической информации средствами системы 1 С: Предприятия. Для «экономного» хранения информации об иерархично- сти хранимых данных достаточно, если каждый из ниже стоящих элементов будет «помнить» ссылку на непосред- ственно стоящий над ним элемент. Таким образом, информацию об иерархии можно хранить не только в виде схем, но и в виде таблиц. Например, ин- формация о вышеприведенной схеме может храниться так, как показано в табл. 6.1. Таблица 6.1. Пример хранения иерархической информации Сотрудник Руководитель Директор Руководитель отдела закупок Директор Менеджер по закупкам Руководитель отдела закупок Товаровед Руководитель отдела закупок Руководитель отдела продаж Директор Менеджер по продажам Руководитель отдела продаж Продавец Руководитель отдела продаж Секретарь Директор Каждая строка таблицы содержит информацию по одной персоне. Для каждой строки таблицы упоминание некой персоны в поле Руководитель означает, что данный со- трудник непосредственно подчинен именно этому руко- водителю (а в информации по этому руководителю будет
указано, кому он в свою очередь подчинен). В строке, от- ражающей информацию по директору поле Руководитель пусто. Это значит, что в данной схеме у директора нет ру- ководителей. Еще говорят «директор находится на корне- вом уровне иерархии». Данный прием применяется при хранении иерархиче- ской информации объектов прикладной области на уров- не объектов базы данных системы 1С:Предприятие. То есть «нижестоящие» элементы должны помнить ссылку на «вышестоящие» элементы иерархии. Однако это не значит, что разработчик в каждом отдельно взятом случае должен выполнение этого приема «дово- дить» до уровня таблиц базы данных. В типовых ситуаци- ях эту работу берет на себя сама система. Разберем, что же это за ситуации. При разработке бизнес-решений разработчику чаще всего приходится иметь дело с иерархическими структурами при организации хранения условно-постоянной инфор- мации (справочники, планы видов характеристик), реже — при работе с регистрацией событий. В отношении хранения условно-постоянной информации учтены следующие ситуации: ♦ иерархия объектных данных одной сущности (рассмат- ривается в разделе «Хранение иерархии данных одной сущности»); ♦ иерархия объектных данных разных сущностей (рас- сматривается в разделе «Хранение иерархии данных разных сущностей», с. 105); ♦ хранение иерархии необъектных данных внутри объек- та (рассматривается в разделе «Хранение подчиненных данных в составе объекта», с. 103); ♦ хранение иерархии необъектных данных вне объекта (рассматривается в разделе «Хранение подчиненных данных вне объекта», с. 105). В остальных же случаях или для реализации ситуаций иерархии событий разработчик всегда может реализовать свою иерархическую схему посредством добавления рек- визита к «подчиненным» объектам, значением которого должна являться ссылка на объект-владелец. Например, в рамках некоторого договора был оформлен документ ЗаказПокупателя. На основании документа Заказ- Покупателя был введен документ РеализацияТоваров. На основании документа РеализацииТоваров были введены документы СчетФактура и ПриходныйКассовыйОрдер. Впо- следствии часть товара была возвращена, то есть на осно- вании документа РеализацииТоваров был введен документ ВозвратТоваровОтПокупателя. Аналогичная цепочка доку- ментов может быть оформлена в отношении другого до- кумента ЗаказПокупателя (рис. 6.23). Необходимо хранить информацию о том, что все эти до- кументы находятся в иерархии конкретного договора с покупателем. Решается данная задача включением в состав всех объек- тов, которые могут «подчиняться» договору, реквизита, ссылающегося на данный договор. Этот пример более широко (в отношении вопросов ввода на основании, отображения иерархии подчинения дого- вору) рассмотрен в разделе «Ввод на основании», с. 160 и приведен в составе демонстрационной конфигурации «Хранение информации и учет движения средств», кото- рая находится на прилагаемом компакт-диске. Рис. 6.23. Структура документов, введенных на основании Хранение иерархии данных одной сущности Выше обсуждалась схема организационно-штатной струк- туры компании (рис. 6.24). Рис. 6.24. Организационно-штатная структура компании Допустим, при проектировании принято решение, что персоналии, отраженные в схеме, относятся к одной сущ- ности прикладной области — пользователи программы, и являются примерами данных объектного типа. Как ин- формация об этой иерархии может быть отражена средст- вами платформы ЮПредприятия? Для этого при разработке следует произвести настройку свойств объекта конфигурации — справочника Пользова- тели, — касающихся иерархии справочника. А именно: справочник — иерархический, вид иерархии — иерархия элементов (то есть нижестоящие элементы справочника иерархически подчиняются вышестоящим именно эле- ментам справочника), количество уровней иерархии ог- раничено, только три (рис. 6.25). Дальнейшую работу возьмет на себя система. В состав ос- новной таблицы справочника Пользователи будет добав- лено поле Родитель для хранения в записях иерархически подчиненных элементов ссылок на элементы, которым они непосредственно иерархически подчиняются. Обра- щение к этому предопределенному полю будет возмож- но посредством соответствующих объектов встроенного языка для манипулирования данными справочника или посредством запросов.
Рис. 6.25. Настройка иерархии справочника Пользователи Кроме того, при записи и модификации данных в справоч- нике Пользователи система будет отслеживать ограничение по количеству уровней иерархии, не позволяя реализовать попытки их превышения, выдавая соответствующие пре- дупреждения. Кроме того, в расширения соответствующих форм и эле- ментов форм будут включены средства, облегчающие реше- ние задач отображения информации справочника в иерар- хическом виде. Например, отображение родителей верхних уровней в табличном поле списка справочника (рис. 6.26). Рис. 6.26. Список справочника Пользователи Пример реализации подобной схемы приведен в демонст- рационной конфигурации «Хранение информации и учет движения средств» (справочник Пользователи), которая находится на прилагаемом компакт-диске. Рассмотренный выше пример касался случая иерархии элементов. Однако могут встречаться задачи, когда иерархия ис- пользуется лишь для логического упорядочивания хране- ния и отображения данных объектных сущностей. Например, данные справочника Номенклатура удобнее пред- ставлять в виде упорядочивания по товарным группам (рис. 6.27). Обратите внимание: каждый конечный элемент обладает конкретной закупочной ценой. Однако говорить о значе- нии закупочной цены родителя этих элементов — нон- сенс с прикладной точки зрения. Таким образом, свойст- ва элементов и свойства их родителей отличаются друг от друга. Для реализации решений подобных задач исполь- зуется вид иерархии Иерархия групп и элементов. С точки зрения хранения данных в базе данных для двух видов иерархии большой разницы нет, но для приклад- ной и интерфейсной функциональности — возможности отличаются сильно. Каждый реквизит объекта справочника или плана вида характеристик, если используется иерархия групп и эле- ментов, может иметь следующие значения свойства Ис- пользование: ♦ Для элемента; ♦ Для группы; ♦ Для группы и элемента. Это позволяет легче решать задачи, для которых необ- ходимо выделять свойства, присущие нужным уровням иерархии. Например, значение реквизита ОтветственныйМенеджер присуще только группам справочника Контрагенты. Счи- тается, что все элементы нижестоящих уровней данной группы закреплены за этим менеджером (рис. 6.28). В этом случае для реквизита ОтветственныйМенеджер зна- чение свойства Использование указывается — Для группы. Выгоды использования такого решения проявятся, на- пример, при решении задачи «перезакрепления» контр- агентов за другим менеджером. Чтобы «перезакрепить» все элементы, входящие в группу, не обязательно будет указывать каждому контрагенту его нового ответственно- го менеджера, достаточно лишь указать другое значение реквизита ОтветственныйМенеджер для этой группы. С другой стороны, реквизит ОтветственныйМенеджер мож- но сделать используемым и группами и элементами. То- гда предложенная схема закрепления сможет учитывать ситуации, когда контрагент находится в группе, закреп- ленной за одним менеджером, но сам закреплен за другим менеджером. ** Справочник Номенклатура Действия S-JM Мониторы “ В - Номенклатура КлавидтурЬ-у Закупочная ц. ЬбР2в4мыикД1$-720 Mouse А4. 9 D0029 00027 32 1 00060 Мышь 3D-Sensoi_________ Мышь GENIUS "EASY”(. Мышь Ice Mouse MUS-2 Мышь LOGITECH M-S48 .. Сам родитель - лишь средство ( упорядочивания элементов (реквизитами не обладает) Полное 2,35 1,10 мышь м Мышь GENIUS Т Д 1,15 MUS2P/1Q0-PS М . 0,80 Х15 Мышь LOSITECIj^ МышыаеттйМо al Рис. 6.27. Список справочника Номенклатура
Рис. 6.28. Группы и элементы справочника Контрагенты Для интерфейсных задач, при использовании данного вида иерархии, система опять же берет на себя реше- ния большинства вопросов различного поведения групп и элементов: ♦ «разделение» форм на основную форму элемента и ос- новную формы группы для операций заполнения и про- смотра данных объектов; ♦ «разделение» на форму выбора и форму выбора группы для реализации операций выбора; ♦ определение того, в каких ситуациях правомерен выбор групп, а в каких нет (по умолчанию, например, реквизиты документов интерактивно могут заполняться только значениями элементов); ♦ использование специальных свойств табличных полей, позволяющих просматривать (в зависимости от необ- ходимости) только элементы, только группы или эле- менты и группы и т. д. Хранение подчиненных данных в составе объекта Практически все объекты системы ЮПредприятие, пред- назначенные для хранения данных объектных сущностей (справочники, документы, планы видов характеристик, планы видов расчета и т. д.), имеют возможность хранить свою информацию не только в виде значений реквизитов, но и в составе подчиненных табличных частей. Подобным образом также может решаться задача хране- ния информации «один ко многим», рассмотренная ранее в разделе «Хранение иерархической информации», с. 100. В качестве примера возьмем все ту же организационно- штатную структуру компании (см. рис. 6.24). Допустим, на ее основе необходимо реализовать хранение информации об объектной сущности «Руководители». Решение может быть реализовано в виде справочника Руководители так, чтобы руководители были элементами справочника, а рядовые сотрудники указывались в стро- ках табличной части ПодчиненныеРядовыеСотрудники, как ссылки на элементы справочника ФизическиеЛица, (рис. 6.29). Рис. 6.29. Схема хранения данных справочника Руководители В результате в системе будет реализовано хранение ин- формации об объектных сущностях — «Руководителях», с указанием подчиненных, в качестве их описания. Однако необходимо иметь в виду, что информация строк подчиненной табличной части не имеет своей объектной сущности. То есть при данном способе хранения инфор- мации нельзя будет сослаться ни на одного «рядового подчиненного некого руководителя». В составе докумен- тов можно будет создавать реквизиты с типом значения СправочникСсылка.Руководители, но нельзя будет создать ре- квизиты, ссылающиеся на строки табличной части Подчи- ненныеРядовыеСотрудники. Для задач, когда ссылка на такие сведения смысла не имеет, хранение множества подчиненных данных, харак- теризующих данный объект, внутри самого объекта мо- жет быть весьма удобным. Классическим примером являются документы с такими табличными частями, как ПоступлениеТоваров, Состав, Со- бытие, СторонниеЛица и т. д. Схемы, когда подчиненная информация сама имеет иерар- хический вид, также могут быть реализованы внутри объ- екта, если это покажется удобным. Например, при оформлении заказа покупателя необходи- мо дать возможность пользователю вводить не только ин- формацию о том, какие номенклатурные позиции, в каком количестве и по какой цене желает приобрести покупа- тель, но и еще произвольное количество дополнительных пожеланий по любой номенклатурной позиции в свобод- ной форме, с возможностью отметки, насколько эти по- желания действительно важны. Представление информации в этом случае может быть отображено следующей таблицей (табл. 6.2). Поскольку речь идет о регистрации события «заказ поку- пателя», то для хранения информации логично использо- вать объект — документ ЗаказПокупателя. Таким образом, получаем три уровня иерархии: ♦ документ; ♦ указание номенклатурных позиций документа с коли- чественно-суммовыми характеристиками; ♦ указание дополнительных пожеланий к номенклатур- ным позициям.
Таблица 6.2. Схема представления информации Заказ Номенклатура Количество Цена Сумма Пожелания Заказ № 32 от 12.02.05 Лазерный принтер Canon LBP-810 2 200 400 Белого цвета Дополнительно упаковать в гофро-тару Телефон LG W7200 10 30 300 Без гарнитуры Доставку приурочить к 8 марта Цвет любой, только не черный Реализация хранения этой информации может быть орга- низована следующим образом. Для хранения информа- ции о заказанных товарах с количественно-суммовыми характеристиками можно использовать табличную часть Состав. Но дополнительные пожелания хранить в рамках этой табличной части будет неудобно. Как показано в таблице выше, к одной номенклатурной позиции может предъявляться более одного требования и форма инфор- мации этих требований более «свободная», нежели указа- ние цены, количества и суммы. В этом случае для хранения информации о дополнитель- ных пожеланиях покупателя, если эту информацию надо хранить внутри объекта, можно использовать еще одну табличную часть ДополнительныеТребования. Реквизитами табличной части ДополнительныеТребования будут Требо- вание, Важность и Номенклатура (рис. 6.30). Соответствие с информацией табличной части Состав будет организо- ванно именно по номенклатурным позициям. □да] ЗаказПокупателя Е1 Я Реквизиты |—— Контрагент |.— Договор — Размещение Й Т абличные части i Б Е:Е| Состав | !--« Номенклатура ; : 1.— Количество i i-Цена : | — Сумма В-1:11 ДополнительныеТребования I™ — Номенклатура :.— Требование — Важно Рис. 6.30. Структура документа ЗаказПокупателя Дополнительный сервис для пользователя может касать- ся вопроса подбора номенклатурных позиций в таблич- ную часть ДополнительныеТребования только из перечис- ленных в табличной части Состав. В демонстрационной конфигурации «Хранение инфор- мации и учет движения средств», которая находится на прилагаемом компакт-диске, в форме документа ЗаказПо- купателя приведен один из вариантов решения этой за- дачи. В форме документа расположена панель с двумя заклад- ками Состав и Дополнительные требования (рис. 6.31). Поскольку для выполнения операций заполнения допол- нительных требований пользователь сначала должен бу- дет открыть соответствующую закладку, — обработчик события смены закладки реализован в виде следующей процедуры (листинг 6.8). Рис. 6.31. форма документа ЗаказПокупателя Листинг 6.8. Обработчик события ПриСменеСтраницы Процедура Панель1ПриСменеСтраницы(Элемент, ТекущаяСтраница) И Проверить, активизирована ли И закладка "Дополнительные требования" Если ТекущаяСтраница = 1 Тогда И Заполнить список номенклатурных позиций. И использованных в табличной части "Состав" мНоменклатураСостава.ЗагрузитьЗначения( Состав.ВыгрузитьКолонку("Номенклатура")); КонецЕсли; КонецПроцедуры В процедуре обработки события При смене страницы (индекс страницы ДополнительныеТребования равен 1) происходит заполнение промежуточного списка значений мНоменкла- тураСостава номенклатурными позициями из табличной части Состав. Для того, чтобы возможности выбора номенклатурных позиций на странице ДополнительныеТребования ограни- чивались лишь значениями, выгруженными в список зна- чений мНоменклатураСостава, — свойства поля ввода Но- менклатура установлены следующим образом (рис. 6.32). Обработчик события НачалоВыбораИзСписка реализован следующим образом (листинг 6.9). Листинг 6.9. Обработчик события НачалоВыбораИзСписка Процедура ДополнительныеТребованияНоменклатураНачалоВыбораИзСпискаС Элемент, СтандартнаяОбработка) И Назначить список выбора полю ввода номенклатуры Элемент.СписокВыбора = мНоменклатураСостава; КонецПроцедуры
3 ак <1 з пик чнатр ля Важно верование п [аЫ| <Поле ввода> аЯ Попе ввода [] Номер Контрагент 1 Договор. | Размещение: | Состав ] Дополнительныетребования |_________ Рис. 6.32. Свойства поля ввода Номенклатура Необходимо заметить, что в данном примере иерархиче- ских данных не реализована связь «один ко многим» в чистом виде. Ведь информация «номенклатурная пози- ция заказа покупателя» не относится к объектным дан- ным. В общем случае, одна и та же номенклатурная пози- ция может быть указана сколько угодно раз в табличном поле Состав. И значит, невозможно установить, к какой именно строке состава (с этой номенклатурной позици- ей) относятся пожелания покупателя, описанные в таб- личной части ДополнительныеТребования. Однако в поста- новке задачи это и не требовалось. То есть либо такие ситуации не критичны для логики работы разрабатывае- мого решения, либо пользователь сам может описать, что имелось в виду, — в строковом реквизите «требование». В ситуациях же, когда поддержание однозначности свя- зей «один ко многим» критично, разработчику необхо- димо будет решать этот вопрос. Для этого следует либо дополнительно обеспечивать уникальность значений рек- визитов, или комбинаций значений реквизитов в самом объекте, либо «вынося» хранение этой информации в другие объекты, специально предназначенные для обес- печения уникальности комбинаций значений сущно- стей — регистры сведений. Хранение иерархии данных разных сущностей Допустим, необходимо организовать хранение информа- ции по предыдущей трудовой деятельности каждого со- трудника компании. Сами сотрудники признаны сущно- стями объектного типа и для хранения их информации в рамках решения создан справочник Сотрудники. Как решить задачу? С одной стороны, данная информа- ция непосредственно связана с сотрудником и могла бы быть реализована посредством включения табличной части ТрудоваяДеятельность в состав объектов справочника Со- трудники. Но к выбору такого варианта надо подходить осторожно. Как обсуждалось в разделе «Хранение подчиненных дан- ных в составе объекта», с. 103, — подчиненные табличные части предназначены для учета только необъектных сущ- ностей. То есть при таком решении в других объектах системы невозможно будет использовать поля или рекви- зиты, соответствующие понятию «место предыдущей ра- боты конкретного сотрудника». Если же необходимость в такой объектной сущности есть или может появиться, то решение видится в использо- вании подчиненного справочника ТрудоваяДеятельность. В его элементах можно хранить информацию о должно- сти, месте работы, дате начала деятельности, дате оконча- ния деятельности по каждому «эпизоду» предыдущей ра- боты сотрудника. Впоследствии эта сущность может быть использована, например, для организации структуры регистра накопле- ния СтажРаботы, или для заполнения реквизитов соответ- ствующих документов. Хранение подчиненных данных вне объекта Для хранения необъектных данных, соответствующих оп- ределенным комбинациям значений измерений, предна- значены регистры сведений. Более подробно устройство и функциональность регистров сведений рассмотрены в разделе «Хранение информации в регистрах сведений», с. 107. Сейчас же лишь рассмотрим лишь один пример. В торговой компании покупатели закреплены за ме- неджерами, их обслуживающими. Сами менеджеры ком- пании, в свою очередь, относятся к тому или иному де- партаменту. Необходимо иметь представление, кто за кем закреплен на каждый момент времени. В данном случае вариант хранения информации в регист- ре сведений предпочтителен тем, что автоматически бу- дет обеспечена уникальность значений измерений. То есть в регистре ЗакреплениеПокупателей невозможно будет создать две записи с одним и тем же покупателем (соот- ветственно, невозможно одного покупателя закрепить за несколькими менеджерами). Аналогично — в отношении регистра ЗакреплениеМенеджеров. Кроме того, регистры сведений позволяют хранить не только статические варианты иерархических структур, но и изменяющиеся во времени. Если указанные регистры сведений сделать периодическими, то впоследствии мож- но будет легко хранить динамику картины отношений. То есть отражать в системе все изменения, касающиеся за- креплений (например, менеджер со всей своей клиент- ской базой передан другому департаменту). И так же легко получать информацию о состоянии модели закреплений на любой момент времени. Также для ситуаций, когда в готовое (и эксплуатируемое) решение приходится вводить новые сущности, добавле- ние новых измерений к регистру сведений позволяет лег- ко решать задачи усложнения «взаимоотношений» дан- ных. Например, начиная с какого-то момента закрепление по- купателей за менеджерами продолжает оставаться одно- значным, но только в рамках конкретных проектов. То есть в основном проекте Торговля за обслуживание некого покупателя по-прежнему отвечает тот же менеджер, но в проекте Информационное сопровождение — совсем другой (да еще и из другого департамента).
С точки зрения классификации ситуации хранения дан- ных такое изменение «революционно», отдельные его час- ти можно даже рассматривать как переход от схемы «один ко многим», к схеме «многие ко многим». Однако сама реализация подобного «поворота событий» очень проста. В состав регистра ЗакреплениеПокупателей достаточно до- бавить измерение Проект. И поскольку система обеспечи- вает в регистре сведений уникальность комбинаций зна- чений измерений, задача уже фактически решена. Остается лишь согласовать с пользователями, будет ли в регистре сведений ЗакреплениеПокупателей пустая ссылка на проект (для старых данных) с прикладной точки зре- ния восприниматься проектом основной деятельности предприятия — Торговля, — либо необходимо произвести соответствующую обработку для заполнения этих данных. Так же легко в состав регистра сведений может быть вве- дена дополнительная информация, характеризующая кон- кретные комбинации значений измерений. Это реализу- ется посредством добавления ресурсов. Например, для регистра ЗакреплениеПокупателей могут быть введены такие ресурсы, как Лояльность, ЧастотаКонтактов, СуммаКвотыПродаж и так далее. Для регистра Закрепление- Менеджеров могут быть введены такие ресурсы, как Базо- выйОклад, ПроцентПремии, Эффективность и тому подобное. Хранение информации, имеющей привязку ко времени Практически все объекты, поддерживающие возможность добавления новых полей (значений, реквизитов), могут работать с данными типа Дата. Но зачастую предметом хранения является не информация о датах, а «другая» ин- формация, которая просто должна храниться в привязке ко времени. Например, необходимо помнить, начиная с какого момента времени, для таких-то номенклатурных позиций действуют такие-то цены. Информацию, хранящуюся в привязке ко времени, чаще всего разделяют на содержащую: ♦ объектные данные; ♦ необъектные данные. Использование документов В задачах хранения объектных данных, привязанных ко времени, речь обычно идет о регистрации неких событий и всего, что с ними связано, например, в хозяйственной жизни предприятия. Чаще всего для хранения такой ин- формации выбираются объекты Документ. В нашем примере (с хранением информации о ценах), если необходимо в привязке ко времени фиксировать, как (и вследствие какого события) произошло изменение цен, то для хранения этой информации можно использо- вать документ ИзменениеЦенКомпании (рис. 6.33). В пользу такого решения говорит функциональность объ- ектов документов, поддерживаемая на уровне платформы 1 С:Предприятия: ♦ заполнение; ♦ запись; ♦ проведение; ♦ формирование движений по регистрам; ♦ расположение на оси времени; ♦ пометка на удаление; ♦ удаление. Рис. 6.33. Документ ИзменениеЦенКомпании Кроме этого, положительным моментом является «ре- шенность» (средствами платформы) вопросов отображе- ния списков документов, возможности группирования разных видов документов в единой хронологии для обще- го отображения или для общей обработки и так далее. Подробно эти вопросы освещены в главе 7 «Документы и последовательности», с. 136. Использование периодических регистров сведений Как рассуждали выше, в разделе «Задачи хранения ин- формации», с. 91, для решения учетных и аналитических задач кроме учета событий важно, чтобы система в опре- деленных ситуациях учитывала показатели, которые из- меняются или при обработке вышеуказанных событий, или вследствие других действий пользователя. Возможно, в нашем примере будет необходимо быстро получить ответ, для какого товара в такой-то момент вре- мени действует такая-то цена. Получение этой информации из документов может оказаться неудобным или длитель- ным по времени, потому что данные разных документов могут противоречить друг другу, и для определения «ис- тины» разработчику придется прописать некие алгоритмы. Использование периодических регистров сведений по- зволяет в данной ситуации (и подобных ей) достаточно быстро создать решение, большую часть функционально- сти которого поддерживает сама платформа (рис. 6.34). В-.Ц ЦеныНоменклатуры В Д— Измерения i I i-Ц Номенклатура I— ТипЦены i Й " & Ресурсы I =.f Цена Й-S Реквизиты Ответственный Рис. 6.34. Структура регистра накопления ЦеныНоменклатуры Например, получение информации об актуальных значе- ниях цен на некоторый момент времени (рис. 6.35).
среза ['‘КонецП ери ода"] Рис. 6.35. Схема получения актуальных цен Подробно вопросы состава и функциональности регист- ров сведений рассмотрены ниже, в разделе «Хранение ин- формации в регистрах сведений». При этом хотелось бы заметить, что в рассмотренном нами примере оба варианта хранения данных, имеющих привязку ко времени, не противоречат друг другу. Они могут «мирно уживаться» в одном решении и обеспечи- вать каждый свою функциональность. И даже более того, «помогают» друг другу. Данный пример полностью при- веден в составе демонстрационной конфигурации «Хра- нение информации и учет движения средств», которая находится на прилагаемом компакт-диске. Использование объекта ХранилищеЗначения При решении вопросов хранения информации желатель- но различать информацию, обеспечивающую основную бизнес-логику решения, и другую, вспомогательную ин- формацию. Данные основной бизнес-логики активно используются в учетных и аналитических механизмах. Для них важны такие вопросы, как индексирование, упорядочивание в запросах и выборках, суммирование, поиск и т. п. Вопро- сам обеспечения хранения этих данных, по сути, посвя- щена большая часть данной главы. Данные же вспомогательной информации нужно просто хранить. Все возможное манипулирование этой инфор- мацией сводится к операциям записи и чтения. Вопросам организации хранения такой информации посвящен только текущий раздел. Итак, платформа системы 1С:Предприятие предоставляет возможность хранения некоторой вспомогательной ин- формации в базе данных посредством полей типа Хранили- щеЗначений. Особенностью использования таких полей яв- ляется то, что база данных «не обязана ничего знать» о природе хранимой там информации. Это могут быть картинки, файлы, таблицы, данные примитивных типов, — да что угодно. База данных отвечает лишь за хранение этой информации, не обеспечивая больше никакой функ- циональности. При этом еще говорят, что тип значения ХранилищеЗначения позволяет хранить значения различных типов в сериализованном виде, то есть в виде, который позволяет записывать данные и восстанавливать их. ПРИМЕЧАНИЕ Для всех объектов, чьи данные сериализуются, в описании встроенного языка данная возможность указывается отмет- кой «Сериализуется». Важной особенностью хранилища значений является воз- можность хранения данных в сжатом виде. Это позволяет существенно сократить размеры базы данных при необ- ходимости хранения больших объемов информации. С прикладной точки зрения, в полях типа ХранилищеЗначения можно хранить, например, значения каких-то вспомога- тельных настроек пользователей, фотографии, изображе- ния, образы файлов и так далее. Например, фотографии сотрудников или файлы с аудиозаписью важных перего- воров (то есть данные типа Картинка или ДвоичныеДанные). При этом, хотя в системе не существует явного ограни- чения на размер данных, хранящихся в полях типа Храни- лищеЗначения, следует все-таки осмотрительно подходить к решению, что именно требуется хранить в базе данных. Большой объем хранимой вспомогательной информации может привести к тому, что административные операции (например, создание резервной копии базы данных) вы- полняются медленно из-за большого объема базы дан- ных. А большой объем обусловлен не требованиями обес- печения основной бизнес-логики, а тем, что кто-то из сотрудников решил хранить в базе данных любимые фильмы. Особенно аккуратно надо относиться к возможности ис- пользования полей типа ХранилищеЗначений в составе объ- ектов (например, справочников, документов), активно использующихся при реализации основной бизнес-логи- ки. Ведь данные объектов считываются целиком при об- ращении к ним. Поэтому, например, вопрос хранения тех же фотографий лучше решать не в составе справочника Сотрудники, а в отдельном подчиненном справочнике или регистре сведений. Тогда будет сохранена возможность идентификации соответствия изображений сотрудникам, к которым они относятся. И в то же время при использо- вании объектов справочника Сотрудники для решения других задач выполняемые операции не будут замедлять- ся из-за необходимости считывания из базы данных боль- ших объемов информации. Хранение информации в регистрах сведений Удобным средством для реализации задач хранения ин- формации необъектных данных, развернутой в некоторых разрезах, является использование регистров сведений. Для решения таких задач регистры сведений обладают функциональностью, которая включает в себя: ♦ уникальность записей в разрезах ключей записей; ♦ периодичность; ♦ подчинение записей регистратору. Разберем использование этой функциональности на при- мерах.
Уникальность записей регистра сведений Одним из основных «показаний» для использования имен- но регистров сведений для хранения данных является то, что регистры сведений обеспечивают уникальность хра- нимой информации для конкретных комбинаций значе- ний разрезов ее хранения. То есть набор значений разрезов является уникальным ключом каждой записи регистра. Сама информация в регистре хранится в виде значений ресурсов. А разрезы хранения информации реализуются посредством измерений регистра. Рассмотрим следующий пример. Для хранения значения метода списания себестоимости, действующего на авто- матизируемом предприятии, может использоваться непе- риодический регистр сведений УчетнаяПолитикаПредприятия. В случае отсутствия измерений (разрезов хранения ин- формации) состав регистра будет выглядеть следующим образом (рис. 6.36). Й 'Jf УчетааяПогитикаПредтри! тмя b -jL* Измерения ф” 4 Ресурсы *•• | МетодСписамияСебестоимостам Отсутствие измерений означает отсутствие Хранение информации реализуется на ресурсах регистра сведений Рис. 6.36. Структура регистра УчетнаяПолитикаПредприятия В таком регистре можно хранить только одно значение метода списания себестоимости (табл. 6.3). Таблица 6.3. Значение, хранимое в регистре МетодСписанияСебестоимости FIFO Запись другого значения в данный регистр обязательно должна сопровождаться замещением предыдущего (табл. 6.4). Два значения одновременно храниться не могут. Таблица 6.4. Значение, хранимое в регистре МетодСписанияСебестоимости Средневзвешенный Это соответствует требованиям прикладной области. Ведь действительно, если для решения ряда учетных задач по- требуется получать значение используемого на предпри- ятии метода списания себестоимости, то важно, что бы он был одним и тем же. Если же автоматизируемое предприятие, например, пред- ставляет собой ряд самостоятельных юридических лиц (организаций), то для хранения информации об учетной политике каждой организации в рассмотренный регистр сведений можно ввести измерение Организация (рис. 6.37). В результате данные в регистре смогут храниться в разре- зе организаций. Й УчетнаяПотатикзПредприятия JL. Измерения ь- I—Организация^-------' ф- £ Ресурсы ..I Мето дСписанияСебестои моста Рис. 6.37. Структура регистра УчетнаяПолитикаОрганизации По каждой конкретной организации в регистре сможет присутствовать только одна запись. Значение метода спи- сания себестоимости в этой записи будет «персональ- ным» для этой организации. И ключом этой записи будет значение организации (табл. 6.5). Таблица 6.5. Пример хранения данных в регистре УчетнаяПолитикаОрганизации Организация МетодСписания- Себестоимости ООО «АвтоматикаСвязьПроект» FIFO ООО «Информационные системы» Средневзвешенный ООО «Мультимедиа Плюс» Средневзвешенный Таким образом, важно понимать, что регистр сведений не является простой таблицей для хранения произвольной информации. Требование уникальности записей по клю- чевым полям обязательно. И оно отслеживается систе- мой автоматически, при любых попытках модификации данных или модификации состава регистра сведений. Если в вышеприведенном примере после заполнения дан- ных регистра информацией об организациях попытаться удалить измерение Организация из регистра, как объекта конфигурации, то система не позволит внести эти изме- нения в конфигурацию базы данных (рис. 6.38). Рис. 6.38. Сообщения при реорганизации базы данных Количество используемых в составе регистра сведений измерений и ресурсов определяется задачами, которые решаются посредством этого регистра. Например, если стоит задача хранения информации о «персональных» для покупателей ценах на товары, она может быть решена посредством регистра сведений со следующим составом (рис. 6.39). Й-ф Щ х. -и-- ванныйПрайс Й JL. Измерения t— Покупатель ?--t* Но мен кгв тура ЙРесурсы ..| Цена Рис. 6.39. Структура регистра накопления
Однако впоследствии любые «расширения» этой задачи не приводят к необходимости серьезной структурной пе- рестройки в вопросах организации хранения информа- ции и достаточно легко реализуются. Например, если впоследствии необходимо будет ввести понятие «Договор», когда по одному договору с покупа- телем на товары одни цены, а по другому могут быть со- всем другие. Или если по каждой поставляемой номенк- латурной позиции понадобится хранить не просто инфор- мацию о ценах продажи, но и учет сезонной скидки, усло- вия доставки, процент предоплаты, срок отсрочки плате- жа и т. д. Все эти требования могут быть реализованы в рамках все того же регистра, за счет добавления соот- ветствующих ресурсов и измерений (рис. 6.40). f' Регистр сведений УчетнаяПодитикаПредприятия _ □ X. возможных *П ериодичность* значениями. бизнес-зад ач Рис. 6.41. Периодичность регистра сведений ГЦ>х»*«М1*<»овакныйПрайс Измерения 1-- L. Покупатель 1--Ц Номенклатура t— Договор В & Ресурсы | I...| Цена | | УчетСе зонной Скидки |..| Сло со бДо ставки f Пропен тПредопгиты *•- | СрокОтсрочки Платежа Рис. 6.40. Структура регистра сведений Важно лишь то, что в данном случае «ключом уникально- сти» записей регистра будет уже номенклатурная пози- ция конкретного договора с покупателем. ВНИМАНИЕ Хотелось бы обратить внимание, что возможность расши- рения функциональности регистра за счет добавления но- вых ресурсов не является обязательной к использованию. В некоторых случаях уместнее добавление новых регист- ров сведений. Подробно этот вопрос рассматривается в разделе «Проектирование структуры регистров сведений», с. 128. Периодические регистры сведений Одной из возможностей регистра сведений является хра- нение данных не только в разрезе указанных измерений, но и в хронологическом разрезе. Разработчик может создавать периодические регистры сведений, указывая минимальную периодичность хране- ния данных. Например, для случая реализации хранения информации в регистре сведений УчетнаяПолитикаПредприятия не толь- ко в разрезе организаций, но и в разрезе лет (в действи- тельности учетная политика предприятия принимается сроком на год), в состав объекта конфигурации можно внести следующее изменение, — указать периодичность хранения информации регистра В пределах года (рис. 6.41). В результате в структуру хранения данных регистра бу- дет добавлено поле «Период». Причем оно будет включе- но в состав ключа записей регистра. То есть, по сути, яв- ляется еще одним разрезом хранения информации. Теперь в регистре УчетнаяПолитикаПредприятия (см. рис. 6.37) смогут храниться, например, такие данные (табл. 6.6). Таблица 6.6. Пример хранения данных в регистре УчетнаяПолитикаОрганизации Период Организация МетодСписания- Себестоимости 2005 г. ООО «АвтоматикаСвязь Проект» FIFO 2005 г. ООО «Информационные системы» Средневзвешенный 2005 г. ООО «Мультимедиа Плюс» Средневзвешенный 2006 г. ООО «АвтоматикаСвязь Проект» Средневзвешенный 2006 г. ООО «Мультимедиа Плюс» LIFO Таким образом, в регистре сведений можно хранить не просто статические данные, но и историю изменений этих данных. При такой организации хранения информации появля- ются возможности: ♦ получения информации, актуальной на тот или иной временной момент; ♦ получения информации о значениях данных, «вступаю- щих в силу» после некого временного момента; ♦ получения картины «динамики» изменения данных за некоторый период; ♦ решения других прикладных задач, связанных с хране- нием информации в привязке ко времени. Например, периодический регистр сведений Персонифици- рованныйПрайс сможет не только хранить информацию о том, какова цена на определенную номенклатуру сейчас (или была в прошлом), но и о том, как она будет изменяться в будущем (если эти изменения будут заранее планировать- ся). Более подробно вопросы получения информации из периодического регистра рассмотрены в разделе «Получе- ние данных из периодических регистров сведений», с. 123. Подчинение записей регистратору В ряде прикладных задач возникает необходимость обес- печения «обоснования» хранимой в регистрах сведений информации наличием документов, зарегистрировавших изменения этой информации.
Ключевые поля Период F* Список Цен^Нзменклатуры Действия- ij- ИЯ ||я5] И вменение цен компании 1 от 03 01 2165 |Ном. Акт Изменение цен ко Изменение иен компании 1 от 03.01 2005 ЕЗ Изменение цен ко Алании 1 от 03.01 2005 . Изменение цен ко Алании 1 от 03 01 2005 .. Изменение цен ко знании 2 от 17 06 2005,, Изменение цен ко Алании 2 от 17.06 2005.. Изменение цен ко лпании 2 от 17 06.2005. Из* ^ot_1ZD6J?005~ Поле “НомерСтроки” содержит порядковый номер записи в наборе J записей, подчиненных / регистратору 7 щкщ _ П х . Номенклатура ГС Набор записс й, 0Г £И Цена 15 ' ___17 20 10 . gLj ___17 19 22 W ан Ж подчиненны i регистратор j 1706.200512:00:00 Пульт РХ 17 06.2005 12:00:00 Пульт РХ 17 06 200512:00:00 Пульт РХ 17 06 200512:00:00 Пульт УН Тип цены Оптовая Мелкоопт . Розничная Оптовая Мелкоопт Оптовая Мелкоопт . Розничная Мелкоопт . 2 3 Рис. 6.42. Хранение данных в регистре сведений, подчиненном регистратору Рис. 6.43. Свойства регистра сведений Цены Номенклатуры Например, изменение отпускных цен компании может производиться только определенным кругом лиц, и каж- дое такое изменение должно сопровождаться оформлени- ем соответствующего документа. То есть данные регистра сведений должны четко «пом- нить», в связи с каким именно документом они там оказа- лась (рис. 6.42). Чаще всего при этом необходимо обеспечивать грануляр- ность записи или модификации данных регистра сведе- ний. В качестве такой «гранулы» используется набор за- писей, подчиненных документу-регистратору. Например, при проведении документа-регистратора его набор запи- сей целиком перезаписывается. Для того чтобы разработчику не пришлось решать массу вопросов обеспечения данной функциональности «собст- венными руками», он может воспользоваться штатными возможностями платформы. Для этого достаточно установить значение Подчинение ре- гистратору свойству Режим записи регистра сведений, как объекта конфигурации (рис. 6.43). С точки зрения хранения данных в регистре установка значения Подчинение регистратору свойства Режим записи приводит к включению в состав регистра полей Регистра- тор, НомерСтроки и Активность. Далее требуется указать, какие именно документы могут быть регистраторами записей регистра (рис. 6.44). Это можно сделать как при редактировании самого реги- стра как объекта конфигурации, так и при редактирова- нии документа-регистратора как объекта конфигурации. Благодаря этому облегчается труд разработчика, которому необходимо сформировать или модифицировать набор (на- боры) записей регистра (регистров), подчиненных некому документу. Подробно этот вопрос освещен в разделе «Созда- ние, изменение, удаление записей регистра сведений», с. ИЗ. Платформа во многих механизмах будет сама использовать обращение к данным свойствам объектов конфигурации. Например, при удалении документа система будет для каж- дого регистра, в котором он может быть регистратором, проверять наличие наборов записей, подчиненных этому документу (движений документа), с целью их удаления или удалять все движения документа при отмене проведения или при перепроведении, если свойство Удаление движений документа имеет значение Удалять движения автоматически. ( Регистр сведений ЦеныНоменклатуры _ П х Основные Данные [►Регистраторы Формы Макеты Подсистемы Права Интерфейсы Обмен данные Прочее Регистраторы: Г~| РучнаяОперация О ЗаписьДвижений О ЗаказПокупателя О £! Событие ИзменениеЦенКомпании Р г-менениеЦенй ймпаним & Документ-регистратор [ Действия у] £ Рис. 6.44. Регистраторы регистра сведений Хотелось бы обратить внимание, что поле Регистратор обеспечивает привязку к документу, но не всегда входит в разряд ключевых полей. Для того чтобы поле Регистратор стало ключевым, необхо- димо для такого регистра сведений (с режимом записи Подчинение регистратору) установить значение По позиции регистратора свойству Периодичность. С прикладной точки зрения это означает возможность хранения в регистре сведений данных с привязкой к вре- менной оси с «дробностью» до момента времени. То есть фактически каждый регистратор может делать движения по любым комбинациям измерений (при этом не будет
конфликтовать по поводу уникальности с другими доку- ментами). А значения ресурсов можно получать не толь- ко на определенный период, но и на момент времени до- кумента (рис. 6.45). Рис. 6.45. Получение значений ресурсов на момент времени документа Однако необходимо понимать, что с точки зрения реше- ния реальных бизнес-задач точность записи хронологии изменений информации, большая чем «до секунды», вряд ли требуется. Таким образом, исходя из области применения, если тре- буется разместить действия двух событий в определен- ном хронологическом порядке, то их нужно «помещать» в разные периоды. То есть если записи движений форми- руются так, что поле Период заполняется значением Дата документа, то надо менять дату документа (рис. 6.46). Рис. 6.46. Запись движений документов с точностью до даты Хронология записей регистра сведений с периодично- стью По позиции регистратора внутри секунды однозначна с точки зрения чтения информации, но не управляема раз- работчиком с точки зрения записи информации. Например, при отображении движений регистра внутри секунды они упорядочиваются системой по ссылкам на регистраторы, то есть по внутренним идентификаторам документов. И такой порядок неизменен при любом обра- щении на чтение информации, однако нет возможности произвольно изменить его (внутри секунды). Структура регистра сведений В состав регистра сведений, как объекта конфигурации, включаются: ♦ измерения; ♦ ресурсы; ♦ реквизиты. Как уже было рассмотрено выше, в разделе «Уникаль- ность записей регистра сведений», с. 108: ♦ ресурсы хранят данные регистра, то есть ту информа- цию, ради хранения которой регистр, собственно, созда- вался и с которой работает функциональность регистра; ♦ измерения используются для обеспечения разрезов хра- нения этой информации. Кроме того, для ситуаций, когда необходимо кроме дан- ных хранить дополнительную информацию о собственно записях регистра, возможно использование реквизитов. Хотелось бы особо отметить, что деление информации регистра на реквизиты и ресурсы — элемент общего под- хода. И хотя технологически хранение информации ре- сурсов и реквизитов регистра сведений существенно не различается, правильное «отнесение» разработчиком дан- ных к ресурсам или реквизитам позволяет впоследствии быстро отличить, что является «функцией» регистра, а что просто комментирует запись. Строго говоря, это один из ключевых моментов организа- ции разработки в 1 С:Предприятии — деление структуры метаданных по ролям, исполняемым конкретными объек- тами в прикладном решении, а не только по их техноло- гическому устройству. Например, регистр сведений ЦеныНоменклатуры хранит информацию о ценах в разрезах номенклатурных пози- ций и типов цен. Эта информация впоследствии исполь- зуется для работы механизмов ценообразования. Но кро- ме того, для вопросов контроля над изменением цен в составе регистра есть реквизит Ответственный, в котором для каждой записи регистра указывается ссылка на поль- зователя, ответственного за ввод данной записи (рис. 6.47). хранения Рис. 6.47. Структура регистра сведений ЦеныНоменклатуры Далее, как было рассмотрено выше, регистры сведений могут иметь режим записи Подчинение регистратору, вслед- ствие чего в состав таблиц регистра добавляется поле Реги- стратор. И регистр сведений может быть периодическим — вследствие чего в состав его таблиц добавляется поле Пе- риод (рис. 6.48). Данные каждого регистра сведений хранятся в отдельной таблице базы данных. Каждая такая таблица имеет сле- дующий состав колонок: ♦ Период — дата записи. Определяет положение данной записи на временной оси. Это поле существует только для периодических регистров;
Рис. 6.48. Основные свойства регистра сведений ЦеныНоменклатуры ♦ Регистратор — содержит ссылку на документ, которому подчинена данная запись. Это поле существует только для регистров с режимом записи Подчинение регистра- тору; ♦ НомерСтроки — уникальный номер данной записи в на- боре записей регистра, подчиненных документу, ука- занному в поле Регистратор. Это поле существует только для регистров с режимом записи Подчинение регистра- тору; ♦ Активность — имеет тип Булево. Содержит признак влия- ния записи на получение информации из регистра. За- писи, для которых значение данного свойства установ- лено в Ложь, не будут учитываться при получении «первых» или «последних» записей регистра, а также при получении сведений на определенный момент вре- мени. Это поле существует только для регистров с ре- жимом записи Подчинение регистратору; ♦ <Измерение> — содержит значение измерения. Количе- ство таких полей равно количеству измерений, опреде- ленных для регистра как объекта конфигурации; ♦ <Ресурс> — значение ресурса. Количество таких полей равно количеству измерений, определенных для реги- стра как объекта конфигурации; ♦ <Реквизит> — значение реквизита. Количество таких по- лей равно количеству реквизитов, определенных для регистра как объекта конфигурации. Таким образом, для регистра ЦеныНоменклатуры с режи- мом записи «Подчинение регистратору» и периодичностью «По позиции регистратора» пример заполнения таблицы базы данных будет следующим (темным фоном выделе- ны ключевые поля записей) (табл. 6.7). Теперь рассмотрим непериодический регистр сведений Сотрудники с независимым режимом записи (рис. 6.49). □ 11 Сотрудники Б- JL Измерения | I--t— Физическое Лицо U Подразделение Ресурсы = L_g Должность Рис. 6.49. Структура регистра Сотрудники Таблица регистра Сотрудники, хранящая информацию в базе данных, может быть заполнена следующим обра- зом (темным фоном выделены ключевые поля записей) (табл. 6.8). Конечно же, функциональность регистра сведений с неза- висимым режимом записи и регистра сведений с режи- мом записи Подчинение регистратору различается. Так же различается функциональность использования периоди- ческих и непериодических регистров сведений. Таблица 6.7. Пример заполнения регистра сведений ЦеныНоменклатуры Период Регистратор Номер- Строки Актив- ность Номен- клатура ТипЦены Цена Ответст- венный 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 00:00:00 1 Истина Пульт РХ Оптовая 150,00 Семенов 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 00:00:00 2 Истина Пульт РХ Мелкооптовая 170,00 Семенов 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 00:00:00 3 Истина Пульт РХ Розничная 200,00 Семенов 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 00:00:00 4 Истина Пульт VH Оптовая 100,00 Семенов 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 00:00:00 5 Истина Пульт VH Мелкооптовая 90,00 Семенов 17.06.2005 12:00:00 Изменение цен компании 2 от 17.06.2005 12:00:00 1 Истина Пульт РХ Оптовая 170,00 Иванов 17.06.2005 12:00:00 Изменение цен компании 2 от 17.06.2005 12:00:00 2 Истина Пульт РХ Мелкооптовая 190,00 Иванов 17.06.2005 12:00:00 Изменение цен компании 2 от 17.06.2005 12:00:00 3 Истина Пульт РХ Розничная 220,00 Иванов 17.06.2005 12:00:00 Изменение цен компании 2 от 17.06.2005 12:00:00 4 Истина Пульт VH Мелкооптовая 100,00 Иванов
Таблица 6.8. Пример заполнения регистра сведений Сотрудники Физическое лицо Подразделение Должность Иванов Иван Сергеевич Отдел продаж Руководитель Семенов Сергей Петрович Отдел продаж Менеджер Семенов Сергей Петрович Отдел закупок Руководитель Петровский Семен Иванович Руководство компании Руководитель Петровская Ирина Ивановна Бухгалтерия Бухгалтер Поэтому для поддержания должного быстродействия при обращении к данным информационной базы для таблиц регистров сведений, в зависимости от вида регистра, соз- даются, например, следующие индексы: ♦ для регистра сведений с периодичностью «По позиции регистратора»: Период + Регистратор + НомерСтроки; Регистратор + НомерСтроки; * Измерение! + [Измерение? +...] + Период + Регистратор — если для данного регистра есть хоть одно измерение. В дан- ный индекс включаются все измерения в том порядке, в котором они заданы в составе регистра как объекта конфигурации, поле «Период» и поле «Регистратор»; ♦ для непериодического регистра сведений: * Измерение! + [Измерение? +...] — если для данного ре- гистра есть хоть одно измерение. В данный индекс включаются все измерения в том порядке, в котором они заданы в составе регистра как объекта конфигу- рации. Использование индексов позволяет сократить время вы- полнения операций с данными регистра. Вышеприведенное описание структуры индексов позво- ляет утверждать, что в общем случае порядок расстанов- ки измерений регистра сведений имеет важное значение. Измерения, к значениям которых необходим быстрый доступ (например, при реализации отборов), следует рас- полагать первыми, далее — в порядке убывания «попу- лярности в отборах». Таким образом будет обеспечивать- ся возможность эффективного применения индексов при реализации задач чтения информации из таблицы регистра. Также необходимо иметь в виду, что, например, SQL Server накладывает определенное ограничение — не более 16 полей в индексе. Поэтому работа с регистрами, имею- щими очень большое количество измерений, может быть неэффективна по скорости из-за невозможности исполь- зования индексов. Более подробно об индексировании физических таблиц регистра сведений можно прочитать в разделе «Индексы таблиц базы данных», с. 788. Создание, изменение, удаление записей регистра сведений В общем случае, в таблицу регистра сведений записи мо- гут вводиться пользователем вручную, генерироваться в процессе выполнения обработок либо при поведении до- кументов. Таблица 6.9. Пример заполнения регистра сведений ЦеныНоменклатуры Период Регистратор Номер- Строки Актив- ность Номен- клатура ТипЦены Цена Ответст- венный 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 00:00:00 1 Истина Пульт РХ Оптовая 150,00 Семенов 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 00:00:00 2 Истина Пульт РХ Мелкооптовая 170,00 Семенов 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 00:00:00 3 Истина Пульт РХ Розничная 200,00 Семенов 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 00:00:00 4 Истина Пульт VH Оптовая 100,00 Семенов 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 00:00:00 5 Истина Пульт VH Мелкооптовая 90,00 Семенов 17.06.2005 12:00:00 Изменение цен компании 2 от 17.06.2005 12:00:00 1 Истина Пульт РХ Оптовая 170,00 Иванов 17.06.2005 12:00:00 Изменение цен компании 2 от 17.06.2005 12:00:00 2 Истина Пульт РХ Мелкооптовая 190,00 Иванов 17.06.2005 12:00:00 Изменение цен компании 2 от 17.06.2005 12:00:00 3 Истина Пульт РХ Розничная 220,00 Иванов 17.06.2005 12:00:00 Изменение цен компании 2 от 17.06.2005 12:00:00 4 Истина Пульт VH Мелкооптовая 100,00 Иванов
Для понимания работы механизмов формирования или модификации записей в таблице регистра сведений необ- ходимо, прежде всего, исходить из следующих положений: ♦ все записи в регистрах уникальны с точки зрения ком- бинации значений в ключевых полях; ♦ добавление, изменение, удаление информации в реги- страх производится «гранулами», представляющими собой наборы записей. Поясним эти положения на примерах. Для регистра све- дений ЦеныНоменклатуры с режимом записи Подчинение ре- гистратору ключевыми полями являются Период, Регистра- тор, Номенклатура, ТипЦены. Гранулой обмена информации с базой данных является набор записей, подчиненных од- ному регистратору (табл. 6.9). Разным фоном в таблице выделены наборы записей. Со- гласно постулату об уникальности записей по значениям ключевых полей невозможно, например, записать одно- временно две записи с одинаковыми значениями полей Товар, ТипЦены, Период, Регистратор (табл. 6.10). При подобной попытке система выдаст соответствующее предупреждение и не выполнит запись. Это обосновыва- ется требованиями прикладной области. Поскольку не- возможно одновременно установить для одного и того же товара две разных оптовых цены. В то же время положение о «гранулярности» модифи- кации информации регистра облегчает реализацию опе- раций удаления или модификации данных. Потому что с прикладной точки зрения: ♦ удаление документа Изменение цен компании №1 должно повлечь за собой удаление всех записей регистра, под- чиненных данному документу; ♦ изменение в данных документа при его перепроведении должно повлечь создание нового набора записей (дви- жений документа), который должен полностью замес- тить старые записи регистра, подчиненные этому доку- менту. Приемы добавления, удаления и модификации движений регистров с режимом записи Подчинение регистратору — универсальны. То есть они одинаковы, что для подчинен- ных регистров сведений, что для других видов регистров (накопления, бухгалтерии, расчетов). ПРИМЕЧАНИЕ Надо лишь помнить о различии ключей записей регистров накопления и регистров сведений. В регистре накопления номер строки входит в ключ записи, поэтому одним документом можно писать одинаковые значения в разные записи. В регистре сведений номер за- писи не входит в ключ, поэтому одинаковые значения из- мерений и даты одним документом писать нельзя! Очень подробно примеры подобных действий описаны в разделе «Свойство Движения объекта документа» и раз- деле «Запись набора записей регистра без использования свойства Движения» главы 8 «Реализация задач учета дви- жения средств». В отношении регистров сведений с независимым режи- мом записи «гранулами обмена с базой данных» будут на- боры записей с установленными отборами по значениям ключевых полей регистра. Кроме того, для некоторых прикладных задач может по- надобиться реализация обмена информацией независи- мых регистров сведений в рамках распределенных баз данных. В таких ситуациях в «гранулы обмена между ба- зами данных» будут включаться комбинации значений измерений с установленным свойством Основной отбор. Также в основной отбор может включаться поле Период для периодических регистров (рис. 6.50). Е Ведущее Запрет незаполненных значений 0 Рис. 6.50. Свойство Основной отбор Например, в состав демонстрационной конфигурации «Хранение информации и учет движения средств», кото- рая находится на прилагаемом компакт-диске, входит ПерсонифицированныйПрайс — регистр сведений с незави- симым режимом записи и периодичностью В пределах дня (рис. 6.51). С прикладной точки зрения посредством этого регистра руководство компании может указывать информацию об Таблица 6.10. Пример записей с одинаковыми значениями ключевых полей Период Регистратор Номер- Строки Актив- ность Номен- клатура ТипЦены Цена Ответст- венный 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 0:00:00 1 Истина Пульт РХ Оптовая 150,00 Семенов 03.01.2005 00:00:00 Изменение цен компании 1 от 03.01.2005 0:00:00 2 Истина Пульт РХ Оптовая 155,00 Петров
исключительных условиях ценообразования для отдель- ных покупателей. Причем режим редактирования позво- ляет заполнять данные этого регистра и «вручную», и «программно» (например, посредством обработки Рас- поряжениеНаУстановкуЦенПокупателя). ЁНП Пг^>***й«х>мванныйГ^айс ф'^- Измерения Ь t-* Покупатель L-t— Номенкгвтура ф Ресурсы I L • g Цена Рис. 6.51. Структура регистра сведений ПерсонифицированныйПрайс Ключевыми полями для этого регистра будут Период, Покупатель, Номенклатура. Поэтому «гранулой модифика- ции» может считаться любая комбинация значений этих полей. Например, если для решения некой задачи нам необходи- мо устанавливать или менять на определенный период для определенного покупателя цены на все номенклатур- ные позиции сразу. Тогда «гранулами модификации» бу- дут наборы записей, соответствующие комбинациям зна- чений полей Период, Покупатель. Таким образом, данные, хранимые в регистре, можно представить следующим об- разом (табл. 6.11). В результате такого гранулирования данные каждой гра- нулы, то есть наборы записей, соответствующие каждой грануле, можно удалять или замещать целиком. Именно это и реализуется посредством обработки Распо- ряжениеНаУстановкуЦеныПокупателя, входящей в состав де- монстрационной конфигурации «Хранение информации и учет движения средств», которая находится на прила- гаемом компакт-диске. В форме обработки посредством полей ввода пользова- тель заполняет реквизиты формы ВыбранныйПокупатель и ДатаУстановки. А посредством табличного поля можно ввести в таблицу Товары информацию о том, какие цены для каких номенклатурных позиций нужно назначить выбранному покупателю на дату установки (рис. 6.52). Текст процедуры, вызываемой обработчиком нажатия на кнопку Выполнить, представлен в листинге 6.10. Обработка Распоряжение на установку цен п Действия- (?)ВыбранныйПокупатель Несткт*,стее*ыь-запись | Посредством Формы набора записей Для покупателя: [Компания “Риона” «— |*-‘|х| “ Сдаты [06.102005 « ffi-- . Рис. 6.52. Форма обработки РаспоряжениеНаУстановкуЦен Листинг 6.10. Обработчик события нажатия на кнопку Выполнить Процедура НепосредственнаяЗаписьВРегистрС) // Создать набор записей, соответствующий грануле "Период - Покупатель” НаборЗаписей = РегистрыСведений.ПерсонифицированныйПрайс. СоздатьНаборЗаписей(); НаборЗаписей.Отбор.Период.Установить(ДатаУстановки); НаборЗаписей.Отбор.Покупатель.Установить(ВыбранныйПокупатель); // Добавить записи в созданный набор записей Для Каждого СтрокаТовара Из Товары Цикл НоваяЗапись = НаборЗаписей.ДобавитьО; НоваяЗапись.Период = ДатаУстановки; НоваяЗапись.Покупатель = ВыбранныйПокупатель; НоваяЗапись.Ноненклатура = СтрокаТовара.Ноненклатура; НоваяЗапись.Цена = СтрокаТовара.Цена; КонецЦикла; // Записать набор записей с занещениен старого, // соответствующего той же грануле НаборЗаписей.Записать(); КонецПроцедуры Таблица 6.11. Пример заполнения данными регистра сведений ПерсонифицированныйПрайс Период Покупатель Номенклатура Цена Гранула «31.01.2005 — Компания «Риона»» 31.01.2005 Компания «Риона» Монитор 17' Philips 107S20 300,00 Гранула «27.08.2005 — ЦветМетМаш» 27.08.2005 ЦветМетМаш Пульт VH 120,00 Гранула «06.10.2005 — Компания «Риона»» 06.10.2005 Компания «Риона» Монитор 17' Philips 107S20 290,00 06.10.2005 Компания «Риона» Монитор 19' Hitachi СМ715ЕТ 290,00 06.10.2005 Компания «Риона» Монитор LCD 22' M8537ZM/A 350,00 Гранула «31.01.2006 — Ялта-Лтд» 31.01.2006 Ялта-Лтд Мышь 3D-Sensor 4,00 Примечание. Серым фоном в таблице выделены ключевые поля.
Таблица 6.12. Данные регистра сведений Период Покупатель Номенклатура Цена Гранула «31.01.2005 — Компания «Риона»» 31.01.2005 Компания «Риона» Монитор 17' Philips 107S20 300,00 Гранула «27.08.2005 — ЦветМетМаш» 27.08.2005 ЦветМетМаш Пульт VH 120,00 Гранула «06.10.2005 —Компания «Риона»» 06.10.2005 Компания «Риона» Монитор 17' Philips 107S20 295,00 06.10.2005 Компания «Риона» Монитор 15' LG Studioworks 575N 300,00 Гранула «31.01.2006 - Ялта-Лтд» 31.01.2006 Ялта-Лтд Мышь 3D-Sensor 4,00 В процедуре сначала создается набор записей с установ- кой значений отбора по ключевым полям. То есть по полю Период и по измерению Покупатель. Далее в цикле перебора строк таблицы Товары происхо- дит заполнение записей в созданном наборе записей. После чего, сформированный набор записей записывает- ся с замещением старого набора записей регистра, соот- ветствующего той же грануле (у параметра Замещать мето- да набора записей Записать О значение по умолчанию — Истина). В результате выполнения обработки (исходные данные см. рис. 6.52) таблица регистра будет содержать следую- щие данные (табл. 6.12). Как видите, информация, соответствующая грануле «06.10.2005 — Компания «Риона»» заместилась согласно данным таблицы «Товары» обработки. Необходимо иметь ввиду, что для независимого регистра сведений подобное «гранулирование» — умозрительное, виртуальное. То есть посредством его можем получить совершенно любой набор записей (главное, чтобы отбор устанавливался по ключевым полям или ни по одному из них и только на равенство). Но не всегда можно будет за- писать любой набор, так как если в отбор включены не все ключевые поля и выполняется добавление, то можно пересечься с существующими значениями ключевых полей. Конечно, выполнение записи набора записей с замещени- ем просто очистит старые записи, с которыми «пересека- емся». Но иногда на практике возникают задачи, когда необходимо запретить такое замещение. В рассмотрен- ном нами примере, допустим, обработка Распоряжение- НаУстановкуЦеныПокупателя не должна позволять устанав- ливать новые цены для покупателя на определенный период по тем номенклатурным позициям, по которым цены уже были установлены ранее. Такое требование легко реализуемо. Достаточно лишь в той же процедуре установить значение Ложь параметру Замещать метода Записать О набора записей регистра (лис- тинг 6.11). Листинг 6.11. Фрагмент кода // Записать набор записей с замещением старого, // соответствующего той же грануле НаборЗаписей.Записать(Ложь): При попытке выполнения обработки для условий, ото- браженных выше (см. рис. 6.52), система выдаст преду- преждение о том, что запись с такими ключевыми полями уже существует (табл. 6.13) и запись нового набора запи- сей не состоится. Таблица 6.13. Запись с дублирующими значениями ключевых полей Период Покупатель Номенклатура 06.10.2005 Компания «Риона» Монитор 17’ Philips 107S20 Для ситуаций, когда необходимо замещать все записи не- зависимого регистра сведений новым набором записей, гранулой можно считать весь регистр. Для этого доста- точно вообще не устанавливать отбор. То есть если в обработке, подобной вышеприведенной, не нужно указывать установки отборов (листинг 6.12). Листинг 6.12. Пример записи набора записей без установки отбора Процедура КнопкаВыполнитьНажатие(Кнопка) // Создать набор записей НаборЗаписей = РегистрыСведений.ПерсонифицированныйПрайс. СоздатьНаборЗаписей(); // Добавить записи в созданный набор записей Для Каждого СтрокаТовара Из Товары Цикл НоваяЗапись = НаборЗаписей.Добавить!); НоваяЗапись.Период = ДатаУстановки; НоваяЗапись.Покупатель = ВыбранныйПокупатель; НоваяЗапись.Номенклатура = СтрокаТовара.Номенклатура; НоваяЗапись.Цена = СтрокаТовара.Цена; КонецЦикла; // Записать набор записей с замещением старого, // соответствующего той же грануле НаборЗаписей.Записать(); КонецПроцедуры Тогда при записи нового набора записей с замещением будут замещены все записи регистра. Для некоторых задач необходимо, чтобы таблица незави- симого регистра сведений просто полностью очищалась.
Такого результата легко добиться следующим образом (листинг 6.13). Листинг 6.13. Пример очистки регистра сведений НаборЗаписей » РегистрыСведений.ПерсонифицированныйПрайс. СоздатьНаборЗаписей!): НаборЗаписей .ЗаписатьО; В некоторых задачах бывает необходимо модифициро- вать записи, соответствующие неким сложным условиям, причем модификации будут подвергаться и значения клю чевых полей. Например, в регистре ПерсонифицированныйПрайс нужно повысить на 20% цены на все номенклатурные позиции, входящие в группы, в названиях которых упоминаются слово «принтеры», если они стоят меньше 300, и «переоп- ределить» их на некого выделенного покупателя. То есть для остальных покупателей таких цен больше быть не должно. Пример реализации такой задачи с использованием объекта МенеджерЗаписи регистра сведений приведен в обработке ДействияСДаннымиРегистраСведений демонст- рационной конфигурации «Хранение информации и учет движения средств», которая находится на прила- гаемом компакт-диске (листинг 6.14). Краткий комментарий: сначала готовится объект манипу- лирования данными одной записи регистра сведений — менеджер записи. Далее посредством запроса из основной таблицы регист- ра получаются записи, соответствующие условиям. Обра- тите внимание: условие по наименованию позволяет по- лучить значения, в которых в любом месте наименования встречается сочетание символов «принтер». В цикле перебора выборки результата запроса устанавли- ваются значения ключевых полей менеджера записи, и производится чтение записи из базы данных. Далее изме- няется значение покупателя в записи, а цена в нее уста- навливается, как увеличенное на 20% значение цены из выборки. После этого методом ЗаписатьО менеджера записи произ- водится непосредственная запись в таблицу базы данных с замещением. Хотелось бы отметить, что в данном примере было рас смотрено использование менеджера записи для программ- ной работы, но объект РегистрСведенийМенеджерЗаписи.<иня> предназначен еще и для обеспечения интерактивной ра- боты с записью регистра сведений. Обязательное усло- вие — регистру сведений в конфигурации установлен ре- жим записи Независимый (рис. 6.53). Обратите внимание: на схеме отображено, что непосред- ственные операции обмена информацией с базой данных менеджер записи реализует посредством все тех же объ- ектов манипулирования данными — наборов записей ре- гистра. Их два. Один набор записей — пустой. Он исполь- зуется для удаления записи со старыми ключевыми значениями. Л второй набор записей содержит одну за- пись, ту, которую нужно записать в регистр. Использование интерактивных возможностей формы за- писи регистра повышает удобство обеспечения работы пользователя с минимальными затратами труда разра- ботчика (рис. 6.54). Листинг 6.14. Процедура ПовыситьЦеныНажатие Процедура ПереопределитьЦеныНажатие(Элемент) // Подготовить менеджер записи Запись - РегистрыСведений.ПерсонифицированныйПрайс. СоздатьМенеджерЗаписи!); // Получить данные записей, соответствующих условиям Запрос = Новый Запрос; Запрос.Текст = " ВЫБРАТЬ ПерсонифицированныйПрайс.Период, ПерсонифицированныйПрайс.Покупатель. ПерсонифицированныйПрайс.Номенклатура, ПерсонифицированныйПрайс.Цена ИЗ РегистрСведений.ПерсонифицированныйПрайс КАК ПерсонифицированныйПрайс ГДЕ ПерсонифицированныйПрайс.Номенклатура.Наименование ПОДОБНО ""^принтерГ"' И ПерсонифицированныйПрайс.Цена < 300"; Результат = Запрос.ВыполнитьО, Выборка = Результат. ВыбратьО, Пока Выборка.СледующийО Цикл // Установить ключевые поля менеджера записи Запись.Период = Выборка.Период; Запись.Покупатель = Выборка.Покупатель; Запись.Номенклатура = Выборка.Номенклатура; // Прочитать запись из базы данных Запись.Прочитать!); И Убедиться, что запись все еще есть в базе данных Если Запись.Выбран!) Тогда И Переопределить покупателя Запись.Покупатель = ВыделенныйПокупатель; И Установить новую цену Запись.Цена = Выборка.Цена * 1.2; // Записать модифицированную запись в базу данных Запись.Записать!); КонецЕсли; КонецЦикла; КонецПроцедуры Рис. 6.53. Схема использования менеджера записи регистра сведений
(' Регистр сведений ПерсонифицированныйПрайс Основные Данные Регистраторы ► Формы Макеты Подсистемы Права щий из одной «старой» записи), потом уже записывает «новый» (состоящий из «новой» записи) (рис. 6.56). _ П х -Редактирован! Указание в „ свойствах объекта О В списке конфигурации этих ©диалоге способа» редактирования боими способами форн ft ? пнслх lepco шфмкирпшмиый чра*1 0410.2005 15.11 2005 ea|i6.Q2.2tre Приводит к возможности выполнения интерактивных модификаций записей посредством формы записей в режиме ”1С Предприятие" А все вопросы основной Функциональности формы записи “берет на себя" система. Рис. 6.54. Использование формы записи регистра сведений При необходимости у разработчика есть возможность «вмешиваться» в процесс модификации данных регистра посредством использования обработчиков событий. В случае записи новой записи (то есть записи с такими ключевыми полями еще не было) из формы записи реги- стра сведений последовательность задействования обра- ботчиков событий следующая (рис. 6.55). Рис. 6.56. Последовательность событий, вызываемая при записи из формы существующей записи регистра сведений Рис. 6.55. Последовательность событий, вызываемая при записи из формы новой записи регистра сведений Как видно на схеме, удаление «старого» набора записей производится посредством записи пустого набора запи- сей. При этом получается, что обработчики событий мо- дуля набора записей будут вызываться дважды. Итак, подробно рассмотрены возможности работы по- средством менеджера записи. Однако надо заметить, что и с набором записей также возможна работа в интерак- тивном режиме (рис. 6.57). Обратите внимание: ряд событий выполняются в одной транзакции. Вследствие этого, если в рамках любого из обработчиков этих событий установить параметру Отказ значение Истина, то транзакция будет отменена. То есть новая запись не запишется, да и любые другие изменения в базе данных не выполнятся (ведь в рамках этих обра- ботчиков событий разработчик мог пытаться менять что- то еще). Это важно с точки зрения обеспечения непроти- воречивости изменений в информации объектов, связан- ных единой прикладной задачей. В случае модификации уже существующей записи реги- стра посредством менеджера записи могут быть измене- ны значения ключевых полей. А значит, запись набора с новыми ключевыми полями сама по себе не заместит «старый» набор. Поэтому здесь система работает в два этапа: сначала удаляет «старый» набор записей (состоя- Рис. 6.57. Схема использования набора записей регистра сведений Пример организации интерактивного ввода приведен в обработке РаспоряжениеНаУстановкуЦеныПокупателя, на закладке Посредством формы набора записей. Эта обработка входит в состав демонстрационной конфигурации «Хра- нение информации и учет движения средств», которая находится на прилагаемом компакт-диске.
Пользователь заполняет посредством соответствующих полей ввода реквизиты формы ВыбранныйПокупатель и Да- таУстановки. Далее, по нажатию кнопки Открыть форму на- бора записей, управление передается процедуре, которая представлена в листинге 6.15. Листинг 6.15. Процедура ОткрытьФормуНабораЗаписей Процедура ОткрытьФормуНабораЗаписей() // Создать набор записей, соответствующий // грануле "Период - Покупатель” НаборЗаписей - РегистрыСведений.ПерсонифицированныйПрайс. СоздатьНаборЗаписей(): НаборЗаписей.Отбор.Период.Установить(ДатаУстановки); НаборЗаписей.Отбор.Покупатель.Установить( ВыбранныйПокупатель): // Прочитать его из базы данных НаборЗаписей.Прочитать(): // Открыть форму набора записей ФормаНабораЗаписей = НаборЗаписей. ПолучитьФормуС"ФормаНабораЗаписей”, Строка(ВыбранныйПокупатель) + Строка(ДатаУстановки)); ФормаНабораЗаписей.Открыть!); КонецПроцедуры Краткий комментарий: сначала создается набор записей регистра сведений, соответствующий основному отбору по периоду и покупателю. Затем в него считываются дан- ные из базы данных. Потом создается форма данного набора записей с ключом уникальности, определяемым как строка, составленная из выбранного покупателя и даты установки. Указание та- кого ключа уникальности важно для ситуации, когда пользователь, не закрыв форму одного набора записей, захочет редактировать информацию в форме другого на- бора записей. Таким образом, если форма набора записей, соответствующих ключу «покупатель — период», уже бу- дет на момент выполнения процедуры открыта, она про- сто активизируется. Если нет (а, например, будет открыта форма другого набора записей), то система откроет новую форму для редактирования именно этого набора записей. Обработка Распоряжение на установку цен п... _ О X Действия* (?) Для покупателя: [Компания *Риона" .... { ВыбранныйПокупатель Непосредственная запись | Посредством Формы набор^зы-»—. —- Рис. 6.58. Использование формы обработки Распоряжение На Установку Цен Покупателя Обработку дальнейших действий пользователя можно доверить самой системе. Поскольку расширения формы набора записей реализуют всю основную функциональ- ность, которая может потребоваться при модификации данных регистра (рис. 6.58). Если разработчику необходимо изменить эту функцио- нальность, то это возможно сделать за счет использова- ния соответствующих обработчиков событий (рис. 6.59). Рис. 6.59. Последовательность событий при записи в форме набора записей регистра сведений При работе с формой набора записей регистра сведений порядок задействования обработчиков событий не разли- чается для ситуаций записи нового набора записей и для ситуации записи уже существовавшего, но модифициро- ванного набора записей. Дополнительная функциональность при создании и удалении записей регистра сведений Кроме рассмотренных выше основных вопросов органи- зации заполнения и модификации информации регист- ров сведений хотелось бы еще разобрать ряд вспомога- тельных, но не менее важных для организации решения некоторых прикладных задач вопросов. Так для ряда задач важно не допустить записи данных с «пустыми» значениями разрезов учета. В рассмотренном выше примере регистра сведений Пер- сопифицпроваппыйПрайс с прикладной точки зрения уди- вительна, например, следующая запись (табл. 6.14). Трак- товать ее данные не предоставляется возможным. Таблица 6.14. Пример записи в регистре сведений ПерсонифицированныйПрайс Период Покупатель Номенкла- тура Цена 31.01.2005 Компания «Риона» 300,00
Для того чтобы не допустить записи подобной информа- ции в регистр, можно, конечно выполнять соответствую- щую проверку в обработчике события ПередЗаписью. Однако, поскольку подобная задача в практике может встречаться не раз, данная проверка добавлена к функциональности платформы. Для ее автоматического задействования достаточно лишь установить свойство Запрет незаполненных значений у изме- рения Номенклатура (рис. 6.60). 1 С: Предприятие X ©Запись не верна] Значение поля Номенклатура не может быть пустым! Компания "Риона” 31 01 2005 0:00:00 (Регистр сведений: П«гш«ццхе|1ьГ прайс) Таблица 6.15. Пример ссылки на отсутствующий объект базы данных Период Покупатель Номенкла- тура Цена 31.01.2005 Компания «Риона» < Объект не найден> 300,00 В результате при выполнении непосредственного удале- ния элементов справочника система будет производить запись в регистр сведений пустого набора записей с отбо- ром по ссылке на удаленный объект. Кроме того, свойство Ведущее используется еще систе- мой, например, при заполнении подменю Перейти команд- ных панелей в формах списков и объектов (рис. 6.62). Данная функциональность, опять же, облегчает быструю разработку прикладных решений. 00021 Монитор Монитор 19'1 00023 00024 Рис. 6.62. Автоматическое формирование пункта меню Перейти Рис. 6.60. Свойства измерения Номенклатура Хотелось бы обратить внимание, что данная проверка вы- полняется именно в момент попытки записи данных в ре- гистр. Если, например, сначала свойство установлено не было и регистр уже заполнился данными записей (среди которых встречаются и записи с пустыми значениями но- менклатуры), а потом в конфигурации данное свойство установили, то при реструктуризации базы данных это действие никак не отрабатывается. Запрет касается имен- но момента и только момента записи данных в регистр. В отношении поля Период для периодических регистров сведений и в отношении поля Регистратор регистра сведе- ний с подчиненным режимом записи подобная проверка выполняется всегда (рис. 6.61). Рис. 6.61. Сообщение об ошибке при попытке записи «пустого значения» поля Период Другая особенность связана с удалением информации из базы данных. Платформа 1 С: Предприятия допускает не- посредственное удаление объектов без контроля ссылоч- ной целостности. Если в результате такой операции будут удалены, например, элементы справочника Номенклатура, ссылки на которые использованы в записях регистра све- дений, то информация регистра сведений с прикладной точки зрения может стать некорректной (табл. 6.15). Если разработчик хочет, чтобы подобные ситуации кор- ректно отрабатывались средствами самой платформы, то достаточно для измерения Номенклатура при конфигури- ровании установить свойство Ведущее. Получение данных из регистров сведений Только хранение информации, как таковое, вряд ли тре- буется при решении прикладных задач. Конечно же, все- гда подразумевается возможность получения хранимой информации при необходимости. Можно выделить два больших круга задач, касающихся получения информации из регистров сведений: ♦ получение информации о записях регистра для техно- логических целей (обычно касающихся именно хране- ния этой информации); ♦ получение информации «функции» регистра (обычно для решения вопросов, ради которых регистр создавали). Таким образом, например, из рассмотренного выше реги- стра ПерсонифицированныйПрайс, хранящего цены прода- жи в разрезах покупателей и номенклатурных позиций, может понадобиться получить информацию для проведе- ния операций манипулирования с этими ценами. Напри- мер, повысить на отдельные товары цены на определенный процент. А может понадобиться проведение сравнитель- ного анализа: насколько персональные цены в среднем ниже общефирменных и как это влияет на вал продаж по отдельным номенклатурным позициям. Получение данных из непериодических регистров сведений В случае работы с регистрами сведений, у которых отсут- ствует привязка данных ко времени (непериодические регистры), решение задач обоих типов выполняется непо-
средственным обращением к записям таблицы базы дан- ных, отвечающей за хранение информации регистра. В зависимости от сложности условий отборов, применяе- мых при этом, в зависимости от необходимости соединения информации регистра с информацией других источников, в зависимости от необходимости использования механизма динамического чтения данных используют или объектную модель представления информации (чтение посредством методов объектов, отвечающих за манипулирование дан- ных регистров), или табличную модель представления информации (обращение к данным посредством запро- сов, написанных на языке запросов 1С:Предприятия). И тот и другой способ обращения выполняется впослед- ствии за счет одних и тех же запросов СУБД к таблице регистра сведений. Однако, исходя из функциональных возможностей, мож- но различить ситуации, когда уместнее применять работу с той или иной моделью. Объектная модель обычно применяется: ♦ для случаев чтения данных с простейшими отборами (обязательно только на равенство значению, более того, применяя метод Выбрать О, отбор можно строить только по одному полю); ♦ в случае необходимости применения механизма дина- мического чтения данных. Посредством этого механиз- ма чтение данных осуществляется по блокам, а не цели- ком сразу всех. Данная функциональность подробно описана в разделе «Список», с. 59. Табличная модель применима: ♦ во всех случаях, когда не требуется использование ме- ханизма динамического чтения данных. Таким образом, посредством запросов можно выбирать данные с отборами какой угодно сложности (как по изме- рениям, так и по любым другим полям или по подчинен- ным полям полей записей регистра). Кроме того, при не- обходимости в том же запросе информацию регистра можно тут же соединять с информацией других источни- ков и/или выполнять дополнительную обработку полу- ченных данных. Рассмотрим несколько примеров, приведенных в обработ- ке ДействияСДаннымиРегистраСведений в демонстрационной конфигурации «Хранение информации и учет движения средств», которая находится на прилагаемом компакт-диске. Для непериодического независимого регистра сведений Сотрудники, все поля которого — ссылки на элементы со- ответствующих справочников (рис. 6.63), задача перебора всех записей регистра может быть решена так, как показа- но в листинге 6.16. Сотрааники Измерения |“'t— Физическое Лицо 1— Подразделение ф- (и Ресурсы L.-g Должность Рис. 6.63. Структура регистра Сотрудники Листинг 6.16. Пример перебора всех записей регистра ВыборкаЗаписей = РегистрыСведений.Сотрудники.ВыбратьО; Пока ВыборкаЗаписей.Следующий() Цикл И Выполнить действие с очередной записью //... КонецЦикла; Хотелось бы отметить, что по умолчанию дополнитель- ное упорядочивание записей при работе с выборкой не производится (табл. 6.16). Таблица 6.16. Пример результата работы с выборкой Физическое лицо Подразделение Должность Иванов Иван Сергеевич Отдел продаж Руководитель Семенов Сергей Петрович Отдел продаж Менеджер Семенов Сергей Петрович Отдел закупок Руководитель Петровский Семен Иванович Руководство компании Руководитель Петровская Ирина Ивановна Бухгалтерия Бухгалтер В таблице выше видно, что ссылка по Семенову на отдел продаж оказалась «раньше» ссылки на отдел закупок. Хотя порядок мог быть и каким-то другим. Теперь рассмотрим задачу получения должности опреде- ленного физического лица в определенном подразделе- нии. Это пример задачи на «функцию» регистра сведений. В качестве «параметров» передаем значения физического лица и подразделения, в качестве «результата функции» ожидаем значение должности (листинг 6.17). Листинг 6.17. Пример получения должности физического лица И Подготовить структуру отбора по измерениям СтруктураОтбора = Новый Структура: СтруктураОтбора.Вставить("ФизическоеЛицо", ПроверяемоеЛицо); СтруктураОтбора.ВставитьС"Подразделение", ВыбранноеПодразделение); И Получить структуру с данными ресурсов записи СтруктураРесурсов = РегистрыСведений. Сотрудники. Получить(СтруктураОтбора): И Сообщить занимаемую должность Должность = СтруктураРесурсов.Должность: Если Должность.Пустая() Тогда Сообщить("В этом подразделении не работает"); Иначе Сообщить(Должность); КонецЕсли: Обратите внимание: для метода ПолучитьО обязательна передача параметра, содержащего структуру отбора зна- чений по всем измерениям непериодического регистра. Результатом применения метода является структура, в которой для каждого элемента ключом будет название ресурса регистра, а значением — значение ресурса из най- денной записи регистра. Следующая задача — проверить, работает ли в компании определенное физическое лицо. И если работает — вы- полнить некоторые действия с записью по этому сотруд- нику. Допустим, ссылка на проверяемое физическое лицо будет в переменной ПроверяемоеЛицо. Тогда решение можно реализовать следующим образом (листинг 6.18).
Листинг 6.18. Пример проверки наличия записи по физическому лицу в регистре сведений И Подготовить структуру отбора по измерению "ФизическоеЛицо" СтруктураОтбора = Новый Структура( "ФизическоеЛицо”, ПроверяемоеЛицо); И Получить выборку с отбором ВыборкаЗаписей = РегистрыСведений.Сотрудники.ВыбратьС СтруктураОтбора); И Выполнить действия Пока ВыборкаЗаписей.СледующийО Цикл И Выполнить действия с записью //... КонецЦикла; В данном примере применялся отбор по значению изме- рения регистра. Вообще в качестве полей для отбора мо- гут использоваться измерения или реквизиты регистра, для которых в конфигураторе установлен признак индек- сирования в значение Индексировать или установлен при- знак Ведущее. Но необходимо помнить, что отбор при этом возможен только по одному полю. Рассмотренные задачи также могли быть решены и по- средством соответствующих запросов. Рассмотрим ряд задач, когда применение запросов более уместно, нежели применение объектной модели. Доступ к информации таблицы регистра в базе данных осуществляется посредством основной таблицы регистра сведений. Состав ее полей соответствует составу полей таблицы регистра сведений в базе данных (можно по- смотреть в разделе «Структура регистра сведений», с. 111). Допустим, требуется сообщить наименования физиче- ских лиц, упомянутых в записях регистра сведений «Со- трудники». Условие — в наименовании должностей этих лиц должно быть слово «Руководитель». Эта задача мо- жет быть решена следующим образом (листинг 6.19). Листинг 6.19. Пример получения физических лиц, в наименовании должностей которых присутствует слово Руководитель Процедура СообщитьСписокРуководителейПредприятияНажатиеС Элемент) И Получить перечень нужных физических лиц Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ | Сотрудники.ФизическоеЛицо.Наименование КАК ФизЛицо |ИЗ | РегистрСведений.Сотрудники КАК Сотрудники I ГДЕ Сотрудники.Должность.Наименование ПОДОБНО ""^Руководитель^...............................: I // Перебрать и сообщить полученный список Результат = Запрос.Выполнить О; Выборка = Результат.ВыбратьО: Пока Выборка.СледующийО Цикл Сообщить(Выборка.ФизЛицо); КонецЦикла; КонецПроцедуры Краткий комментарий; в запросе выбираем неповторяю- щиеся наименования всех физических лиц из таблицы регистра, если наименования должностей в этих записях содержат набор символов «Руководитель» (в любом месте наименования). Далее выборка результата запроса пере- бирается, и в цикле сообщается полученная информация. Попытка решения этой задачи посредством выборки была бы грубой методической ошибкой: ♦ во-первых, выборка не может строиться с отбором по значениям ресурсов. То есть перебирать пришлось бы все записи регистра; ♦ во-втпорых, условие отбора устанавливается не по зна- чению поля Должность, а по наличию в наименовании этой должности сочетания символов «Руководитель». То есть такая проверка в цикле перебора записей реги- стра привела бы к необходимости применения запроса СУБД к таблице данных справочника Должности. И это на каждом шаге цикла! ♦ в-третьих, сообщать нужно наименования физических лиц. То есть при выполнения условия проверки для каждой «подходящей» записи регистра, системе при- шлось бы еще обращаться посредством запроса СУБД к таблице справочника ФизическиеЛица для считыва- ния наименования элемента, соответствующего нуж- ной ссылке. Таким образом, решение посредством объектной модели привело бы к многочисленным обращениям к таблицам базы данных (на каждом шаге цикла перебора всех запи- сей регистра). Решение же посредством запроса будет реализовано сис- темой за счет левых соединений таблиц регистра и двух справочников, но за одно обращение к базе данных. Не говоря уже о том, что выборка результата запроса будет меньше выборки всех записей регистра. Следующая задача — сообщить, сколько подразделений компании задействовано в регистре «Сотрудники». Эта задача может быть решена посредством следующего за- проса (листинг 6.20). Листинг 6.20. Пример получения количества задействованных подразделений Процедура СообщитьСколькоПодразделенийВКомпанииНажатиеС Элемент) И Установить исходно, что подразделений нет КоличествоПодразделений = 0; И Посчитать количество "непустых" подразделений И в записях регистра Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ КОЛИЧЕСТВОСРАЗЛИЧНЫЕ Сотрудники.Подразделение) КАК КоличествоПодразделений ИЗ РегистрСведений.Сотрудники КАК Сотрудники ГДЕ Сотрудники.Подразделение <> &ПустоеПодразделение"; Запрос.УстановитьПараметр("ПустоеПодразделение". Справочники.Подразделения.ПустаяСсылка()); Результат = Запрос.ВыполнитьО; Выборка = Результат.ВыбратьО; Если Выборка.СледующийО Тогда КоличествоПодразделений = Выборка.КоличествоПодразделений; КонецЕсли; И Сообщить полученные результаты Сообщить(КоличествоПодразделений); КонецПроцедуры
В данном случае применен запрос, вычисляющий количе- ство упоминаний различных подразделений в соответст- вующем поле записей регистра. При этом записи с неза- полненным полем Подразделение не учитываются. Если выборка запроса будет непустой (есть записи), то исходное нулевое количество подразделений заменяется на определенное в запросе. В данном случае продемонстрирована возможность при- менения агрегатных функций при чтении информации регистра запросом. Следующая задача — получить список «внутренних со- вместителей» с предоставлением информации: в каких отделах, на каких должностях они работают. Внутренни- ми совместителями называются физические лица, зани- мающие несколько должностей или в одном, или в раз- личных подразделениях предприятия. Данная задача может быть решена посредством примене- ния запроса со следующим текстом (листинг 6.21). Листинг 6.21. Пример получения списка внутренних совместителей ВЫБРАТЬ Сотрудники.ФизическоеЛицо КАК ФизическоеЛицо, Сотрудники.Подразделение КАК Подразделение, Сотрудники.Должность КАК Должность ИЗ РегистрСведений.Сотрудники КАК Сотрудники ГДЕ Сотрудники.ФизическоеЛицо В (ВЫБРАТЬ Сотрудники.ФизическоеЛицо КАК ФизическоеЛицо ИЗ РегистрСведений.Сотрудники КАК Сотрудники СГРУППИРОВАТЬ ПО Сотрудники.ФизическоеЛицо ИМЕЮЩИЕ КОЛИЧЕСТВО(Сотрудники.ФизическоеЛицо) > 1) В запросе выбирается информация по всем записям реги- стра, где упоминаются физические лица, соответствую- щие условию. Условие проверяет вхождения физических лиц в перечень, полученный вложенным запросом. Во вложенном запросе применяется группирование с приме- нением агрегатной функции КОЛИЧЕСТВОО по полю Физиче- скоеЛицо, при этом условием будут отсечены те физлица, которые упоминались только один раз. Получение данных из периодических регистров сведений Для периодических регистров сведений задачи получе- ния информации для технологических вопросов решают- ся так же, как и было рассмотрено выше для непериоди- ческих регистров. Поэтому все примеры, рассмотренные в разделе «Получение данных из непериодических реги- стров сведений», с. 120, будут уместны и в этом случае. Единственное отличие в том, что к перечню ключевых полей добавляется поле Период, которое можно использо- вать в отборах. Так, метод ВыбратьО для случая периоди- ческого регистра позволяет работать не только с отбором по значению измерения, но и с отбором по временному интервалу, в который могут попадать значения поля Пе- риод. Рассмотрим примеры получения информации из перио- дического (периодичность — В пределах дня) независимого регистра сведений ПерсонифицированныйПрайс (рис. 6.64). В Пер<1»«^мфованныйПрайС В JL- Измерения i : 1— Покупатель 1— Номенкгвтура Й- Ресурсы I Цена Рис. 6.64. Структура регистра ПерсонифицированныйПрайс Для получения выборки всех записей регистра в интерва- ле дат между значениями, содержащимися в переменных НачалоИнтервала и КонецИнтервала, с отбором по номенк- латурной позиции (содержится в переменной Выбранный- Товар) можно сделать следующий фрагмент кода (лис- тинг 6.22). Листинг 6.22. Пример получения записей регистра И Подготовить структуру отбора по измерению "Номенклатура" СтруктураОтбора = Новый СтруктураС"Номенклатура", ВыбранныйТовар); И Получить выборку записей ВыборкаЗаписей = РегистрыСведений.ПерсонифицированныйПрайс. Выбрать(НачалоИнтервала, КонецИнтервала. СтруктураОтбора); Пока ВыборкаЗаписей.Следующий() Цикл // Выполнить действие с очередной записью //... КонецЦикла; Необходимо помнить, что отбор при этом возможен толь- ко по одному полю, и в качестве полей для отбора могут использоваться измерения или реквизиты регистра, для которых в конфигураторе установлен признак индекси- рования в значение Индексировать или установлен признак Ведущее. Кроме того, для реализации различных задач, в плане не- обходимости включения/выключения записей «гранич- ных периодов», нужно иметь в виду следующее: ♦ в параметр НачалоИнтервала передается начало интерва- ла, в котором будут выбираться записи периодического регистра. Он может задаваться значениями типа Дата, МонентВренени, Граница. Если значение данного параметра не указано, то будут выбираться записи с самой ранней включительно; ♦ в параметр КонецИнтервала передается конец интервала, в котором будут выбираться записи периодического ре- гистра. Он также может задаваться значениями типа Дата, МонентВренени, Граница. Если значение данного пара- метра не указано, то будут выбираться записи по самую последнюю включительно. В результате, при передаче значений типа Дата или Монент- Вренени в выборку, получим записи включая значения На- чалоИнтервала и КонецИнтервала (рис. 6.65). Если же требуется получить записи, исключая гра- ничные, то необходимо использовать объект Граница. На- пример, получение выборки в интервале дат, исключая границы, может быть выполнено следующим образом (листинг 6.23).
значения поля "Период" записей КонецИнтервала Временная ось Интервал выборки Рис. 6.65. Получение записей включая граничные значения Листинг 6.23. Пример получения записей регистра сведений // Установить значения границ ГраницаНачалаИнтервала = Новый Граница(НачалоИнтервала, ВидГ раницы.Исключая); ГраницаКонцаИнтервала = Новый Граница(КонецИнтервала, ВидГ раницы.Исключая); И Подготовить структуру отбора по измерению "Номенклатура" СтруктураОтбора = Новый Структура("Номенклатура", ВыбранныйТовар); И Получить выборку записей ВыборкаЗаписей = РегистрыСведений.ПерсонифицированныйПрайс.Выбрать( Г раницаНачалаИнтервала, Г раницаКонцаИнтервала, СтруктураОтбора); Пока ВыборкаЗаписей.СледующийО Цикл И Выполнить действие с очередной записью //... КонецЦикла; Получение данных в этом случае можно проиллюстриро- вать следующей схемой (рис. 6.66). Н ачалоИнтервала КонецИнтервала 11 Временная ось поля "Период" записей Интервал выборки Рис. 6.66. Получение записей исключая граничные значения Кроме того, если периодичность регистра меньше чем день (В пределах секунды или По позиции регистратора), то не- обходимо помнить, что дата в системе 1С:Предприятие включает в себя и время. Даже если время не указано явно, оно принимает значе- ние 00:00:00. То есть если в качестве параметра НачалоИн- тервала передать значение «1 декабря 2005 года» (данное значение может быть получено так: ’20051201'), а в каче- стве параметра КонецИнтервала передать «31 декабря 2005 года» (’20051231'), то в результате выборки будут построены с даты «01.12.2005 00:00:00» по дату «31.12.2005 00:00:00». То есть в результат, по сути, не войдут данные 31 декабря (рис. 6.67). Для предотвращения возможных недоразумений по это- му поводу удобно использовать функцию КонецДняО. Эта функция возвращает значение последней секунды дня указанной в качестве параметра даты (листинг 6.24). В результате будут получены записи с даты «01.12.2005 00:00:00» по дату «31.12.2005 23:59:59» включительно. При использовании запроса можно реализовывать не только перечисленные выше, но и гораздо более сложные условия, в том числе и по полю Период. Рис. 6.67. Пример получения данных регистра сведений, когда интервал задан без явного указания времени Листинг 6.24. Пример использования функции КонецДняО И Определить конец дня "правой" границы КонецДняИнтервала = КонецДня(КонецИнтервала): И Получить выборку записей ВыборкаЗаписей = РегистрыСведений.ЦеныНоменклатуры.Выбрать( НачалоИнтервала. КонецДняИнтервала); Пока ВыборкаЗаписей.Следующий() Цикл И Выполнить действие с очередной записью //... КонецЦикла: Например, задача получения выборки данных всех записей регистра ПерсонифицированныйПрайс, которые датированы выходными днями (субботами и воскресениями), может быть решена посредством следующего запроса (листинг 6.25). Листинг 6.25. Пример запроса ВЫБРАТЬ ПерсонифицированныйПрайс.Период, ПерсонифицированныйПрайс.Покупатель, ПерсонифицированныйПрайс.Номенклатура, ПерсонифицированныйПрайс.Цена ИЗ РегистрСведений.ПерсонифицированныйПрайс КАК ПерсонифицированныйПрайс ГДЕ ДЕНЬНЕДЕЛИ(ПерсонифицированныйПрайс.Период) > 5 В запросе было применено условие с использованием функции работы с датами языка запросов — ДЕНЬНЕДЕЛИО. Данная функция возвращает порядковые номера дней не- дели по переданному параметру. Рассмотрим примеры задач получения информации из периодического регистра сведений не в технологических целях, а для обслуживания задач учетных или аналитиче- ских механизмов. Если необходимо получить информацию значений ресур- сов одной записи регистра, соответствующей указанным в параметрах значениям всех измерений и периода, объ- ектная модель получения информации также позволяет использовать метод Получить(). Например, нужно сообщить, какую цену установили для покупателя Покупатель по номенклатурной позиции То- вар, начиная с ДатаУстановки (листинг 6.26). Часто встречаются задачи, в которых каждая запись пе- риодического регистра сведений используется не как средство для хранения данных, а как средство для хране- ния информации истории изменения данных.
Листинг 6.26. Пример получения цен по номенклатурной позиции И Подготовить структуру отбора по измерениям СтруктураОтбора = Новый Структура; СтруктураОтбора.Вставить("Покупатель", Покупатель); СтруктураОтбора.Вставить("Номенклатура", Товар); И Получить структуру с данныии ресурсов записи СтруктураРесурсов = РегистрыСведений.ПерсонифицированныйПрайс.Получить( ДатаУстановки, СтруктураОтбора); И Сообщить цену Сообщить(СтруктураРесурсов.Цена); Ведь в рассмотренном выше примере, если цена на товар для этого покупателя была установлена не именно на эту дату, а на какую-то другую, то метод Получить О вернет структуру с пустыми значениями (рис. 6.68). В итоге получим желаемый результат (рис. 6.69). Записи периодического регистра (периодичность - “В пределах дня*'] Рис. 6.69. Пример использования метода ПолучитьПоследнееО Записи периодического регистра (периодичность - “В пределах дня**] Рис. 6.68. Пример использования метода ПолучитьО для периодического регистра сведений С прикладной точки зрения, в ситуации, отображенной на схеме, при обращении к данным регистра, пользова- тель мог хотеть получить «актуальное» для 12.10.2005 значение цены, а не установленное 12.10.2005. То есть в логике пользователя, как само собой разумею- щееся, может лежать правило: «пока цена не сменилась — действует прежняя». И при обращении к данным регист- ра пользователь желает получить цену, установленную на некую дату, а если не установлена, то «прежнюю», в об- щем случае — «последнюю установленную». Для реализации подобной логики в функциональности периодического регистра сведений существует метод По- лучитьПоследнееО. Для тех же переменных получение по- следних актуальных данных может быть таким (лис- тинг 6.27). Листинг 6.27. Пример использования метода ПолучитьПоследнее() // Подготовить структуру отбора по измерениям СтруктураОтбора = Новый Структура; СтруктураОтбора.Встав ить("Покупатель", Покупатель); СтруктураОтбора.ВставитьС'Номенклатура", Товар); // Получить структуру с данными актуальных значений ресурсов СтруктураРесурсов = РегистрыСведений. ПерсонифицированныйПрайс. ПолучитьПоследнееСДатаУстановки. СтруктураОтбора); // Сообщить "последнюю" цену Сообщить(СтруктураРесурсов.Цена); Может встретиться задача, когда пользователь заранее не знает, для каких комбинаций значений измерений ему требуется получить данные «последних актуальных» (на дату КонецПериода) значений ресурсов регистра. То есть хочет получить все значения для всех комбинаций изме- рений (или для некоторых, соответствующих условиям отбора) (рис. 6.70). Рис. 6.70. Задача получения последних значений по комбинации значений измерений Для решения подобных задач можно использовать метод СрезПоследнихО, возвращающий таблицу значений, запол- ненную данными записей, наиболее поздних ближайших к дате среза (КонецПериода) (табл. 6.17). Таблица 6.17. Результат получения среза последних Покупатель Номенклатура Цена ООО Сигма Пульт VX 120,00 ООО Сигма Пульт PW 218,00 Ялта-ЛТД Пульт VX 135,00 В ходе выполнения метода СрезПоследнихО, платформа ЮПредприятия фактически выполняет запрос к базе данных. Данный запрос реализует следующий алгоритм: ♦ выбрать записи таблицы регистра, соответствующие условиям отбора по значениям измерений, у которых значение поля Период меньше или равно значению па- раметра КонецПериода;
♦ по выбранным записям получить максимальные значе- ния поля Период для каждой комбинации значений по- лей измерений. Это будут данные вложенного запроса. Получается, что в нем известны ключи «последних акту- альных» записей, то есть наиболее близких к дате среза; ♦ соединить таблицу вложенного запроса с основной таб- лицей регистра по равенству значений полей измере- ний и поля Период; ♦ из полученной таблицы получить интересующие дан- ные «последних актуальных» записей. Подобную функциональность можно реализовать запро- сом по основной таблице периодического регистра сведе- ний (листинг 6.28). Листинг 6.28. Пример получения среза последних запросом ВЫБРАТЬ ПерсонифицированныйПрайс.Покупатель, ПерсонифицированныйПрайс.Номенклатура, ПерсонифицированныйПрайс.Цена ИЗ (ВЫБРАТЬ ПерсонифицированныйПрайс.Покупатель КАК Покупатель. ПерсонифицированныйПрайс.Номенклатура КАК Номенклатура, МАКСИМУМ(ПерсонифицированныйПрайс.Период) КАК Период ИЗ РегистрСведений.ПерсонифицированныйПрайс КАК ПерсонифицированныйПрайс ГДЕ ПерсонифицированныйПрайс.Период <= &КонецПериода И Указать другие условия отбора при необходимости СГРУППИРОВАТЬ ПО ПерсонифицированныйПрайс.Покупатель. ПерсонифицированныйПрайс.Номенклатура) КАК ВложенныйЗапрос ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПерсонифицированныйПрайс КАК ПерсонифицированныйПрайс ПО ВложенныйЗапрос.Покупатель = ПерсонифицированныйПрайс.Покупатель И ВложенныйЗапрос.Номенклатура = ПерсонифицированныйПрайс.Номенклатура И ВложенныйЗапрос.Период = ПерсонифицированныйПрайс.Период Поскольку задачи получения среза последних встречают- ся достаточно часто, система 1С;Предприятие позволяет использовать виртуальную таблицу получения среза по- следних, которая реализует описанный выше алгоритм. То есть вместо использования запроса по основной таб- лице регистра разработчик для получения среза может воспользоваться запросом, например, следующего вида (листинг 6.29). Как видите, текст запроса значительно проще. Листинг 6.29. Пример использования виртуальной таблицы Срез последних ВЫБРАТЬ СрезЦен.Покупатель, СрезЦен.Номенклатура, СрезЦен.Цена ИЗ Per истрСведений.ПерсонифицированныйПрайс. СрезПоследнихС&КонецПериода, ) КАК СрезЦен Таким образом, за счет использования виртуальных таб- лиц разработчик работает сразу с «производными» дан- ными, необходимыми для решения прикладных задач. А тонкости организации оптимального получения этих данных обеспечиваются системой. Что же за данные можно получить посредством виртуаль- ной таблицы среза последних? Практически все, которые касаются записей. Виртуальная таблица среза последних содержит следующие поля: ♦ Период — это поле имеет тип Дата. Содержит период, к которому относится запись регистра; ♦ Регистратор — это поле имеет тип ДокументСсылка.<имя>. Существует только в случаях, если периодичность ре- гистра По позиции регистратора. Данное поле содержит ссылку на документ-регистратор, к которому относится запись регистра; ♦ НомерСтроки — это поле имеет тип Число. Существует только в случаях, если периодичность регистра По пози- ции регистратора. Содержит значение поля НомерСтроки записи движения регистра; ♦ Активность — это поле имеет тип Булево. Существует только в случаях, если периодичность регистра По пози- ции регистратора. Содержит признак активности записи, то есть влияния на получение среза последних (или среза первых); ♦ <Измерение> — тип значения этого поля определяется типом измерения. Каждое из таких полей содержит значение измерения регистра. Имена полей совпадают с именами измерений, заданными для объекта конфи- гурации; ♦ <Ресурс> — тип значения этого поля определяется ти- пом ресурса. Каждое из таких полей содержит значение ресурса регистра. Имена полей совпадают с именами ресурсов, заданными для объекта конфигурации; ♦ <Реквизит> — тип значения этого поля определяется ти- пом реквизита Каждое из таких полей содержит значение реквизита регистра. Имена полей совпадают с именами реквизитов, заданными для объекта конфигурации. Виртуальная таблица среза последних не хранится в базе данных, а строится в момент обращения к ней. Поэтому при использовании ее в запросах поддерживается весьма гибкая функциональность за счет использования пара- метров: ♦ <Дата> — имеет тип Дата, МонентВренени или Граница. Если параметр не задан, будут выбираться наиболее поздние записи, то есть без ограничения по времени; ♦ <Условие> — содержит конструкцию языка запросов — условие. Строится по любым полям регистра накопле- ния (или подчиненных им полям). Используется для ограничения состава исходных записей, по которым при построении виртуальной таблицы будут выпол- няться срез. Если параметр не указан — будет использо- ваться все активные записи регистра. Например, соответствующее применение условий в за- просах с использованием виртуальных таблиц позволяет легко решать задачи отбора информации так, как это по- требуется. Рассмотрим несколько примеров для периодического ре- гистра сведений ЦеныНоменклатуры (рис. 6.71). Рассмотрим следующую задачу: требуется получить ин- формацию о том, по каким товарам на текущий момент есть цены меньше 100, кто за это «ответственен» и когда
он установил такую цену. Задача может быть решена сле- дующим образом (листинг 6.30). 5 ЦеныНоменклатуры Измерения = - t—Номенклатура 1-ТипЦены □ & Ресурсы I Цена |j Я Реквизиты i =-•— Ответственный Рис. 6.71. Структура регистра ЦеныНоменклатуры Листинг 6.30. Пример получения данных из регистра сведений ВЫБРАТЬ ЦеныНоненклатурыСрезПоследних.Период, ЦеныНоненклатурыСрезПоследних.Номенклатура, ЦеныНоненклатурыСрезПоследних.ТипЦены, ЦеныНоменклатурыСрезПоследних.Цена. ЦеныНоменклатурыСрезПоследних.Ответственный ИЗ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних ГДЕ ЦеныНоменклатурыСрезПоследних.Цена < 100 Обратите внимание, в постановке задачи акцент ставился на текущие цены. Поэтому в запросе сначала выполняет- ся срез последних, а потом в таблице среза определяются записи, в которых цена меньше 100. То есть если когда-то на какой-то товар была низкая цена, но на текущий мо- мент положение исправлено (установлена цена больше 100), то «никого за это наказывать не будем». Рассмотрим другую задачу: требуется получить инфор- мацию, по каким товарам вообще когда-нибудь устанав- ливались цены меньше 100, кто «ответственен» за послед- ние назначения таких цен и когда они выполнялись. Возможное следующее решение (листинг 6.31). Листинг 6.31. Пример получения данных из регистра сведений ВЫБРАТЬ ЦеныНоменклатурыСрезПоследних.Период, ЦеныНоменклатурыСрезПоследних.Номенклатура. ЦеныНоменклатурыСрезПоследних.ТипЦены, ЦеныНоменклатурыСрезПоследних.Цена, ЦеныНоменклатурыСрезПоследних.Ответственный ИЗ РегистрСведений.ЦеныНоменклатуры.СрезПоследних( Цена < 100) КАК ЦеныНоменклатурыСрезПоследних В данном случае акцент сделан на записях регистра, в ко- торых цена меньше 100. А вот уже для записей, соответст- вующих этому условию, будет произведен срез послед- них. То есть в данном случае «отвечать» будет последний, кто устанавливал низкие цены, даже если на текущий мо- мент цена на этот товар уже совсем другая. Рассмотренная выше функциональность получения среза последних для периодического регистра, но только уже «с другим знаком» легко получается за счет применения методов ПолучитьПервоеО, СрезПервыхО и виртуальной таб- лицы среза первых. Для таких задач важны данные запи- сей, соответствующих точке среза или первых следующих после нее в истории изменения информации регистра. Например, для ситуации, когда нужны данные по кон- кретной комбинации значений измерений (рис. 6.72). Записи периодического регистра (периодичность - "В пределах дня**] Рис. 6.72. Получение первых данных по комбинации значений измерений Также возможна ситуация, когда нужны данные среза всех «первых следующих» (рис. 6.73). Комбинации значений измерений ООО Сигма - Пульт VX ООО Сигма - Пульт FW 120 Срез первых следующих 215 218 устанавливаемые значения цен Ялга-Лтд - Пульт VX временная ось Дата получения среза Рис. 6.73. Получение среза первых По аналогии с работой в отношении получения «послед- них актуальных», приемы получения «первых следую- щих» абсолютно те же, только меняются названия мето- дов и виртуальной таблицы. Функциональность получения этих данных связана с по- лучением записей, у которых минимальный период, из равных или больших временному моменту получения среза. Соответственно, если «параметр среза» (НачалоПе- риода или Дата) не указан, срез будет производиться по значению даты по умолчанию, то есть «01.01.01 00:00:00». А значит, в срез попадут самые первые по хронологии за- писи таблицы регистра. Особенности получения данных из регистров сведений с режимом записи Подчинение регистратору Установка режима записи Подчинение регистратору означа- ет добавление к физической таблице регистра сведений в базе данных ряда предопределенных полей: ♦ Регистратор; ♦ НомерСтроки; ♦ Активность. Кроме того, как было рассмотрено выше, для таких реги- стров невозможно наличие записей без ссылки на доку- мент-регистратор. Данные особенности играют свою роль при получении информации из регистра.
Для быстрого получения информации наборов записей, подчиненных некому регистратору, имеются возможно- сти использования объектной модели представления дан- ных — метод ВыбратьПоРегистраторуО. Например, если ссылка на нужный документ хранится в переменной ДокументРегистратор, то получить записи ре- гистра можно с помощью следующего кода (листинг 6.32). Листинг 6.32. Пример получения данных из регистра сведений, подчиненного регистратору ВыборкаДвиженийДокумента = РегистрыСведений.ЦеныНоменклатуры. ВыбратьПоРегистратору( ДокументРегистратор); Пока ВыборкаДвиженийДокумента.Следующий() Цикл И Выполнить действие с очередной записью движения //... КонецЦикла; Аналогичного результата можно добиться, используя со- ответствующий отбор в запросе (листинг 6.33). Листинг 6.33. Пример получения данных регистра сведений запросом Запрос = Новый Запрос; Запрос.Текст = " |ВЫБРАТЬ |ГДЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры ЦеныНоменклатуры.Регистратор = &РегистраторОтбора": Запрос.УстановитьПараметрС'РегистраторОтбора", ДокументРегистратор); Результат = Запрос. ВыполнитьО: Выборка = Результат.ВыбратьО: Пока Выборка.Следующий() Цикл И Выполнить действие с очередной записью движения //... КонецЦикла; В ряде задач может оказаться полезным использование полей Активность и НомерСтроки. Например, рассмотрим задачу получения перечня «длинных» документов (кото- рым, например, подчинено более 100 записей в движениях по регистру). Данная задача может быть решена посредст- вом применения следующего запроса (листинг 6.34). Листинг 6.34. Пример получения данных из регистра сведений ВЫБРАТЬ РАЗЛИЧНЫЕ ЦеныНоменклатуры.Регистратор ИЗ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры ГДЕ ЦеныНоменклатуры.НомерСтроки > 100 Рассмотрим другую задачу: требуется получить перечень документов с неактивными записями. Эта задача мо- жет быть решена посредством следующего запроса (лис- тинг 6.35). Важно помнить, что для получения «срезов первых» и «срезов последних» система использует только те запи- си, в поле Активность которых стоит Истина. Снять или установить активность можно только для всех записей набора записей, подчиненных некому регистратору. Таким образом, реализуется прикладная задача: при необходи- мости можно сделать документ «неиграющим» без удале- ния его движений. Но поскольку документ с прикладной точки зрения это регистрация события, то отключение влияния события может выполняться только полностью для всех записей, принадлежащих данному документу. Листинг 6.35. Пример получения данных регистра сведений ВЫБРАТЬ РАЗЛИЧНЫЕ ЦеныНоменклатуры.Регистратор ИЗ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры ГДЕ (НЕ ЦеныНоменклатуры.Активность) В остальном примеры и возможности получения данных из регистра сведений, описанные в разделах «Получение данных из непериодических регистров сведений», с. 120 и «Получение данных из периодических регистров сведе- ний», с. 123, вполне применимы и для регистров сведе- ний, подчиненных регистратору. Проектирование структуры регистров сведений Как было рассмотрено ранее, регистр сведений может со- держать несколько измерений, ресурсов и реквизитов. Зачастую у разработчиков при проектировании приклад- ных решений возникает вопрос: «Что лучше? Создать не- сколько регистров с большим количеством ресурсов, или наоборот, создать много регистров, но с меньшим количе- ством ресурсов?» В общем случае, единого ответа на этот вопрос нет. Для того чтобы облегчить принятие решения в каждой конкретной ситуации, приведем несколько моментов, на которые следует обращать внимание при проектировании регистров сведений. Структурный подход. Каждая запись в регистре сведений содержит информацию о том, что для данной комбина- ции ключевых полей установлены некоторые значения ресурсов. В том числе и в периодическом регистре сведе- ний. То есть, если запись добавляется или модифициру- ется, это выполняется для всех значений ресурсов. Нель- зя отметить, что, начиная с такого-то момента, значение такого-то ресурса не меняется, а меняются только значе- ния других ресурсов. Восприятие пользователем. При проектировании регистра важно проанализировать, как реально меняются значения данных, которые будут храниться в регистре, и вырабо- тать определенную модель отражения этих изменений в базе данных. Важно, чтобы отражение предметной облас- ти в регистре правильно воспринималось пользователем. Например, при хранении информации о курсах валют приходится иметь дело с информацией о курсе и кратно- сти каждой валюты (24 рубля за 100 японских йен — курс 24, кратность 100). Курс Центробанка меняется еже- дневно, кратность... ну, наверное, один раз в несколько де- сятков лет.
То есть если исходить из «накладных затрат» на выпол- нение операций с этой информацией в регистре, то напра- шивается решение о разделении ее на два регистра: Кур- сыВалют и КратностиВалют. Однако с точки зрения восприятия информации пользо- вателем, данные о курсе отдельно от данных о кратно- сти — это нонсенс. Ну а поскольку работать с курсом и кратностью всегда придется «одновременно», то проще реализовать задачу одним регистром с двумя ресурсами. Учет потенциальных модификаций состава регистра. Как обсуждалось выше, состав существующего регистра све- дений всегда можно «расширить». Одним из направле- ния расширения является ввод новых разрезов информа- ции, то есть, измерений. Например, для регистра ПерсонифицированныйПрайс (рис. 6.74), принимая решение по добавлению ресурса ПредпочитаемыйЦвет, в котором будет содержаться инфор- мация о том, какого цвета товары предпочитает покупа- тель, желательно заранее уточнить, а не потребуется ли впоследствии добавить к такому регистру измерение До- говор для более детального учета обещанных покупателю отпускных цен. Если потребуется, то лучше будет все же информацию разделить между несколькими регистрами. В одном будет храниться информация о каких-то качественных пожела- ниях покупателей, в другом — информация о ценах с дру- гим уровнем детализации. B-W gmwuu ванныйПрайс Измереемп | Ц. Покупатель L, Номенкгапра Е- { Ресурсы 1..| Цена Рис. 6.74. Структура регистра ПерсонифицированныйПрайс Время получения данных, необходимых для работы меха- низмов решения. Например, при работе некоторого меха- низма важно получать данные объекта и данные, связан- ные с данным объектом. Очевидно, что получение этих «связанных» данных из нескольких ресурсов одного ре- гистра (одной таблицы) будет происходить, в общем слу- чае быстрее, нежели получение этих данных из несколь- ких регистров (нескольких таблиц). Время записи информации в базу данных. Запись в не- сколько регистров сведений, в общем случае, будет вы- полняться медленнее, нежели запись одной записи с не- сколькими ресурсами. «Слабое звено». Если данные одного из ресурсов надо мо- дифицировать очень часто, то объем базы будет расти су- щественнее, если в составе регистра много ресурсов. Осо- бенно если какой-нибудь из ресурсов будет являться хранилищем значений, в котором будет храниться кар- тинка или бинарные данные. Такие данные вообще целе- сообразнее выделять в отдельный регистр. Хранение дополнительных характеристик Один из часто встречающихся вопросов хранения инфор- мации — это вопрос организации хранения значений характеристик, набор которых заранее неизвестен. Таким образом, при разработке прикладного решения нет воз- можности создать заранее набор реквизитов объекта. Кроме этого, велика вероятность, что конкретные харак- теристики будут использоваться не для всех объектов, а только для некоторого ограниченного их количества. Например, для некоторых элементов справочника Номенк- латура может потребоваться хранить информацию об их цвете, мощности, габаритах (для бытовой техники), для других же — о размере, росте, материале и, опять же, о цвете (одежда), для третьих подобная информация во- обще не имеет смысла (услуги). При этом не исключена вероятность, что автоматизируемая компания станет «по- путно» торговать еще мобильными телефонами, что по- требует наличия ряда специфичных характеристик но- менклатуры, таких как поддерживаемые стандарты обме- на информацией, наличие цифровой камеры, тип батареи и т. д. Классическая реляционная модель предполагает, что для хранения какой-либо информации в базе данных в табли- це заводится колонка (поле) с определенным типом и именем. То есть введение реквизитов является естествен- ным способом решения подобной задачи. Однако в рассматриваемом случае подобное решение яв- ляется неэффективным и, зачастую, неприемлемым с точки зрения требований, предъявляемых заказчиком. Неэффективность решения «в лоб» заключается в том, что подавляющее большинство характеристик использу- ется лишь для небольшого, ограниченного количества элементов справочника Номенклатура. Это означает, что вводя для каждой характеристики отдельный реквизит, мы тем самым необоснованно увеличиваем объем храни- мой информации. В самом деле, создав реквизит Размер (тип Число), мы добавили в физическую таблицу справоч- ника Номенклатура, новую колонку. Но эта колонка будет хранить «содержательные» данные только для элементов справочника из группы Одежда (которых, например, 100- 150 штук). Если при этом общее количество элементов в справочнике Номенклатура будет равняться 10-15 тыся- чам, значит, практически для всех элементов справочни- ка в этой колонке будет содержаться значение 0, так как данная характеристика для них не имеет смысла. С практической точки зрения создание реквизитов для хранения значений характеристик в большинстве случаев может быть неприемлемо потому, что добавление нового реквизита возможно только в режиме работы Конфигура- тор. В реальной ситуации, как правило, необходимо соз- давать новые характеристики непосредственно в процес- се работы, в режиме 1С:Предприятие. Таким образом, путь ввода новых реквизитов может ока- заться слишком «затратным» во всех смыслах. В данном разделе мы рассмотрим возможные варианты решения задач динамического дополнения состава ин- формации, характеризующей объекты.
Хранение дополнительных характеристик определенного типа Рассмотрение задачи хранения дополнительных характе- ристик начнем с простого примера, когда все дополни- тельные характеристики, вводимые пользователем, име- ют один и тот же тип значения. Допустим, необходимо организовать хранение дополнительной информации о контрагентах: ♦ кто из них относится к «нерезидентам» (зарубежные контрагенты); ♦ с кем из них можно торговать в кредит; ♦ кто относится к категории постоянных покупателей и т. д. Другими словами, необходимо обеспечить возможность ввода и хранения следующих характеристик контраген- тов: ♦ Резидент (тип Булево — Истина, Ложь); ♦ ПостоянныйПокупатель (тип Булево — Истина, Ложь); ♦ <новая характеристика» (тип Булево — Истина, Ложь). Как было рассмотрено выше, вариант с булевыми рекви- зитами Резидент, ПостоянныйПокупатель и т. п. — слишком «затратен» и неудобен. Один из вариантов решения этой задачи приведен в де- монстрационной конфигурации «Хранение информации и учет движения средств», которая находится на прила- гаемом компакт-диске. Это использование справочника Категории для хранения видов характеристик и регистра сведений КатегорииКонтрагентов для хранения соответст- вия конкретной характеристики конкретному контраген- ту (рис. 6.75). Рис. 6.75. Структура регистра КатегорииКонтрагентов Тип значения измерения Контрагент — СправочникСсыл- ка.Контрагенты. Тип значения измерения Категория — Спра- вочникСсылка .Категории. Использование справочника Категории как объекта для хранения классификатора категорий, позволяет предо- ставить пользователям возможности динамической мо- дификации этой информации. То есть ввод новой харак- теристики (категории) не требует помощи разработчика. Далее, обратите внимание в составе регистра нет ресур- сов. Хотя, как описано в разделе «Хранение информации в регистрах сведений», с. 107, именно посредством ресур- сов организуется хранение информации в регистрах све- дений. Дело в том, что комбинации значений измерений обеспе- чивают уникальность каждой записи регистра, а наличие самой записи по сути и является информацией. Ведь по каждой комбинации «Контрагент — Категория» необхо- димо обеспечить хранение информации булевого типа. Если Истина, значит, контрагент относится к этой катего- рии. Это в нашем случае реализовано просто наличием записи. Ну а значение Ложь в нашем случае будет реализо- вано отсутствием записи. Итак, общую схему хранения дополнительных характе- ристик контрагентов можно представить следующим об- разом (рис. 6.76). Рис. 6.76. Общая схема хранения дополнительных характеристик Дальнейшее использование этой информации в учетных или аналитических механизмах прикладного решения можно будет реализовывать посредством, например, со- единений с информацией регистра. Так в составе демонстрационной конфигурации «Хранение информации и учет движения средств», которая находит- ся на прилагаемом компакт-диске, есть отчет ПродажиСОт- боромПоКатегориямКонтрагентов, в котором пользователь может применять отборы по категориям покупателей (рис. 6.77). Рис. 6.77. Отчет продажи с отбором по категориям контрагентов Сам отчет формируется за счет использования построи- теля отчета, которому передается следующий текст за- проса (листинг 6.36). Краткий комментарий: условие отбора контрагентов по категориям реализуется во вложенном запросе по регист- ру сведений за счет использования языка запросов
построителя отчета (инструкции, заключенные в {...}). Благодаря этому вопрос организации отбора категории «берет на себя» построитель отчета (подробнее об ис- пользовании построителя отчета можно прочитать в раз- деле «Построитель отчета», с. 415). То есть пользователь сможет при необходимости обойтись вообще без отбора, организовать отбор по одной категории, по списку кате- горий, по всем категориям, кроме выбранных и так далее. Реализация этой функциональности не требует усилий разработчика. Листинг 6.36. Пример запроса, используемого при формировании отчета ВЫБРАТЬ ПродажиОбороты.Номенклатура КАК Номенклатура, ПродажиОбороты.Контрагент КАК Контрагент, ПродажиОбороты.КоличествоОборот КАК КоличествоОборот. ПродажиОбороты.СуммаОборот КАК СуммаОборот ИЗ (ВЫБРАТЬ РАЗЛИЧНЫЕ КатегорииКонтрагентов.Контрагент КАК Контрагент ИЗ РегистрСведений.КатегорииКонтрагентов КАК КатегорииКонтрагентов {ГДЕ КатегорииКонтрагентов.Категория.*}) КАК ВложенныйЗапрос ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.0бороты(8НачалоПериода, &КонецПериода. . ) КАК ПродажиОбороты ПО ВложенныйЗапрос.Контрагент = ПродажиОбороты.Контрагент ИТОГИ СУММА(КоличествоОборот), СУММА(СуммаОборот) ПО Номенклатура. Контрагент Далее таблица неповторяющихся контрагентов, получен- ных во вложенном запросе, соединяется с таблицей обо- ротов регистра Продажи и подводятся промежуточные итоги по номенклатуре и контрагентам. Затем, уже поль- зуясь средствами построителя отчета, пользователь может «распорядиться» этими итогами так, как ему требуется. Здесь мы рассмотрели вариант использования категори- рования контрагентов в отчете. От разработчика требова- лось по крайней мере сформировать текст запроса. Контрагенты Ганза ДсЙ€ПМЯ ’ 14 © Gfe fe* Меню "Перейти" j системой Код. |00004 Наименование Ганза Родитель По ста адм км । Открытие формы списка регистре с отбором по 1 текушемд Контрагенту так же реализуется системой I оптовый адрес: ЕЕ ЕЕ —I f Список Категорм* контрагентов _ С X j? Рис. 6.78. Использование команды Перейти Но ряд функциональных вопросов в таком решении сис- тема может взять на себя полностью. Так, если устано- вить для измерений регистра КатегорииКонтрагентов свой- ство Ведущее, то пользователь при необходимости сможет быстро получать форму списка регистра с отбором по соот- ветствующим значениям из форм справочников (рис. 6.78). Кроме того, при удалении объектов, с которыми связаны записи регистра, система будет автоматически удалять такие записи. Это описано в разделе «Дополнительная функциональность при создании и удалении записей ре- гистра сведений», с. 119. Хранение дополнительных характеристик произвольного типа. Использование плана видов характеристик Рассмотрим подробно вариант решения задачи о хране- нии дополнительных характеристик номенклатурных по- зиций. Допустим, для ряда товаров необходимо организовать хранение информации о весе, для некоторых товаров — о цвете, для некоторых — об области применения и так далее. Пример решения данной задачи с использованием реги- стра сведений — имеет право на жизнь. Однако в отличие от рассмотренной в предыдущем разделе («Хранение до- полнительных динамических характеристик булевого типа») ситуации, здесь будем иметь дело с информацией уже не булевого, а произвольного, заранее неизвестного типа. То есть в регистре потребуется использование поля ресурса ЗначениеХарактеристики. При попытке реализации данного регистра в конфигу- рации встанет один существенный вопрос: какой тип зна- чения должен быть у ресурса ЗначениеХарактеристики? Действительно, характеристики будут иметь не только разный смысл, но и различные типы значений. Получается, что для ввода произвольных данных в поле ресурса тип значения последнего должен быть составным и включать в себя все возможные типы значений. Но для каждой характеристики тип значения должен быть персональными. Чтобы не получилось, что пользо- ватель может ввести цвет «01.01.2006 г.», а потом пытать- ся понять «и как с этим работать?» Для решения задачи хранения информации о соответст- вии видов характеристик и типов их значений в составе конфигурации следует использовать объект План видов ха- рактеристик. План видов характеристик по своему устройству очень похож на справочник. Он поддерживает работу пользова- телей с видами характеристик («элементами») и списка- ми видов характеристик, может поддерживать иерархию, может включать в состав своих объектов реквизиты и табличные части, возможно использование предопреде- ленных видов характеристик, заданных разработчиком. Однако самой важной особенностью объектов планов ви- дов характеристик, отличающей их от других объектов, является использование свойства Тип значения. Это свой- ство позволяет определить список возможных типов дан- ных, используемых для отдельных видов характеристик (то есть для каждого элемента плана видов характери- стик) (рис. 6.79).
Редактирование типа данных X Я Значения характеристик Контрагенты Возможно указание как примитивные типов так и ссылочных так и составных типы данных |00100 Код. Наименование |Вес Дгмна | 15 ] Точность | 2| О Неотрицательное |[ ОК ~^| | Отмена ОК Записать Закрыть Рис. 6.79. Тип значения вида характеристики То есть для вида характеристики Цвет можно определить тип значения СправочникСсылка.Цвета, для вида характери- стики Год выпуска — тип значения Дата, для Уровня шума — Число, и так далее. Кроме этого, возможно использование составных типов значений, в состав которых могут вхо- дить как примитивные типы (Дата, Число, Строка, Булево), так и ссылочные типы данных (ДокументСсылка.<имя>, Спра- вочникСсылка. <имя> и так далее, включая ПланВидовХаракте- ристикСсылка.<имя>). Пример создания и использования плана видов характе- ристик ВидыХарактеристикНоменклатуры приведен в соста- ве демонстрационной конфигурации «Хранение инфор- мации и учет движения средств», которая находится на прилагаемом компакт-диске. Для того чтобы при описании типов значений для новых видов характеристик (элементов этого плана видов харак- теристик) пользователь мог выбирать значения только из определенного разработчиком списка, при конфигуриро- вании используется свойство Тип значения характеристик (рис. 6.80). ® Пгнн видов характеристик ВидыХарактеристикНоменкгвт _ О X | ► Основные Иераршя Данные Нумерация Формы Маметы Подсистемы Ввод на основании Праш Имя Синоним: Комментарий |ВидыХарактеристикНоменкгвтуры| [Виды характеристик но менкгвтурь] Допогнитеяьные значения характеристик Указание типов значений, которые будут впоследствии доступны при создании видок характеристик Рис. 6.80. Свойство Тип значения характеристик Обратите внимание: на схеме видно, что в состав типов значений характеристик плана ВидыХарактеристикНоменк- латуры включено использование справочника ЗначенияХа- рактеристик. Введение подобного справочника в состав решения помо- гает обеспечить самостоятельный ввод новых возможных значений новых характеристик самим пользователем в тех ситуациях, когда в составе конфигурации нет объек- тов для отображения новой сущности. Например, в процессе эксплуатации программы возникла необходимость создания новых характеристик Область применения, Вариант оплетки, Формат бумаги и так далее. Вместо того чтобы под каждую сущность создавать свой справочник или перечисление, все значения таких допол- нительных характеристик можно хранить в справочнике ЗначенияХарактеристик (рис.5.81). Значения характеристики “Область применения" Значения характеристики "Формат бумаги" Рис. 6.81. Название рисунка Однако для того, чтобы при выборе значений характери- стик из этого справочника информация разных видов ха- рактеристик не перемешивалась, нужно подчинить эле- менты справочника элементам плана вида характеристик. Это реализуется следующим образом: ♦ устанавливается владелец справочника ЗначенияХарак- теристик — план видов характеристик ВидыХарактери- стикНоменклатуры; ♦ свойство Дополнительные значения характеристик объекта конфигурации плана вида характеристик заполняется указанием справочника ЗначенияХарактеристик (рис. 6.82). Этого достаточно, например, для того, что бы система «взяла на себя» вопросы реализации основной функцио- нальности, касающейся заполнения, хранения и отобра- жения связей между видом характеристики и возможны- ми ее значениями (рис. 6.83). Таким образом, создав план видов характеристик, разра- ботчик определяет возможности хранения в базе данных перечня видов характеристик и определяет область до- пустимых значений этих характеристик. Однако вернемся к началу решения нашей задачи. Необходимо организовать хранение значений дополни- тельных характеристик номенклатурных позиций в реги- стре сведений. В составе демонстрационной конфигура- ции «Хранение информации и учет движения средств», которая находится на прилагаемом компакт-диске, для этого используется регистр сведений ХарактеристикиНо- менклатуры (рис. 6.84).
53 Спражчиик Зн<зче»«<>яХ<оактгх)истик Основные Иераржя | ► Владельцы Данные Нумерация [Действия Слисок владельцев справочника План Видо е Хара гсгери стм к. Видь Хара ктври св' 1) Указание плана видов характеристик в качестве владельца справочника Я Пгмн еждов характеристик ВиаыХаракгеристмкНоменкгат _ П X Формы Макеты Подсистемы Вводив OCHOf Права | ► Оо«ииые Иерархия Дэ*<ые Нумерация Формы Макеты Подсистемы В вод на основании Права Интерфейсы Обмен Прочее 2] Указание способа хранения по умолчанию для значений дополнительных характеристик Имя Оеюним. Комментарий £ | ВидыХарактеристикНоменкгётуры | [Виды характеристик но мен кгитурь[ Тип значения характеристик |СправочникСсылка ЗначенияХаф-.] Дологннтельнае значения характеристик | Закрыть ] [ Справка Рис. 6.82. Свойство Дополнительные значения характеристик Н Действия - 1$} Перейти(?) «HL3™ Наименование [(>бгвстьприменения Тип значения П пр заочник ссылка Значения характеристик Открытие формы списка подчиненного справочника с отбором по владельцу так реализуется системой ивввмшизн^ Меню "Перейти" реализовано системой ОК Записать Закрыть Рис. 6.83. Использование команды Перейти Т ип значения "СправочникСсылка В оменклатура" цсаатчры ____ Е) 0 ХарактеристикиНт □ • JL Измерения г-1» Объект | - - t— Бихарактеристики = Й- ' • Ресурсы ! g Значе r-g рфиз 1 арактеристики Тип значения "ПланВидовХарактеристикСсылка. > ВидыХарактеристикН оменк латуры" Тип значения ‘Характеристика ВидыХарактеристикН оменк латуры" Рис. 6.84. Структура регистра сведений ХарактеристикиНоменклатуры Для измерения Объект — тип значения СправочникСсылка. Номенклатура, свойство — Ведущее. Тип значения измерения ВидХарактеристики — ПланВидовХарактеристикСсылка.ВидыХа- рактеристикНоменклатуры, свойство — Ведущее. Тип значения ресурса ЗначениеХарактеристики — Характеристика.ВидыХа- рактеристикНоменклатуры. В результате регистром сведений будет поддерживаться уникальность записей по набору значений измерений Но- менклатура — ВидХарактеристики, а для значений ресурса ЗначениеХарактеристики тип значения будет определяться теми, что указаны в составе соответствующего плана ви- дов характеристик. Однако необходимо понимать, что мы описали все необ- ходимое для хранения характеристик, но не для организа- ции заполнения. С точки зрения системы измерения Номенклатура и ВидХа- рактеристики никак не связаны между собой. А при вводе значений в поле ресурса по умолчанию никак не учиты- вается выбранный в поле измерения вид характеристи- ки — система будет предлагать заполнять поле любым из типов, описанных в плане видов характеристик. В описании структуры регистра никак не задается ин- формация о логической связи полей, в которых хранятся виды характеристик и значения характеристик. Более того, зачастую это сделать было бы просто невозможно. Дело в том, что в реальном решении такая связь может быть очень сложной. И хранение соответствия номенкла- турных позиций и видов их характеристик может выпол- няться в других объектах конфигурации (например, в от- дельном регистре сведений, хранящем связи «многие ко многим» между номенклатурными группами и видами характеристик, между отдельными номенклатурными по- зициями и группами видов характеристик и т. д.). А данные связи могут влиять на связи между видами характеристи- ки и возможными их значениями. Поэтому реализация всех этих связей выполняется разработчиком конфигура- ции в рамках специфики поставленной задачи. Допустим, необходимо реализовать достаточно простой вариант, когда для любой номенклатурной позиции мож- но использовать любой вид характеристики и нужно лишь обеспечить удобство редактирования записей реги- стра в отношениях между видом характеристики и воз- можными значениями. В демонстрационной конфигурации «Хранение инфор- мации и учет движения средств», которая находится на прилагаемом компакт-диске, пример реализации этой за- дачи сделан с использованием формы записи регистра сведений ХарактеристикиНоменклатуры. Для ограничения типов значений характеристики типами конкретного выбранного вида характеристики у поля ввода ЗначениеХарактеристики установлено свойство Связь по типу. В качестве значения данного свойства выбра- но поле менеджера записи регистра ВидХарактеристики (рис. 6.85). Таким образом, если пользователь сначала заполнит поле ВидХарактеристики, то при заполнении поля ЗначениеХа- рактеристики тип значения уже будет предопределен сис- темой. Однако после этого пользователь может опять вернуться к редактированию поля ВидХарактеристики и выбрать там уже другое значение. Для того чтобы исключить ситуацию, когда после таких действий тип значения поля значения характеристики не может соответствовать содержимому поля вида значения (например, вид — Год выпуска, а значение — Мокрый ас- фальт), необходимо использовать соответствующим обра- зом обработчик события ПриИзменении поля ВидХарактери- стики (листинг 6.37). Листинг 6.37. Обработчик события ПриИзменении Процедура ВидХарактеристикиПриИзменении(Элемент) ЗначениеХарактеристики = ВидХарактеристики.ТипЗначения. ПривестиЗначение(ЗначениеХарактеристики); КонецПроцедуры
гг Запись X*ip*i* теристики номеикпагфы »-*- -'wiEl >j ®£-J Номенкгвтдоа | |Т^ас| Рис. 6.85. Свойство Связь по типу Варианты хранения значений характеристик При создании прикладного решения может встать задача организации хранения неуникальных дополнительных характеристик отдельных типов. Так, характеристика Об- ласть применения для некоторых номенклатурных пози- ций может несколько значений: Связь, Медицина, Обучение и т. д. Характеристика Ограничения по отгрузке также мо- жет иметь много значений: Только по предоплате, Только транспортом компании, Наличие визы начальника охраны для одного объекта. В этом случае хранение значений характеристик можно организовать не в регистре сведений, а при помощи дру- гих объектов. Например, если значения характеристик нужно по какой-то причине хранить в самом объекте, то поставленную задачу можно решить посредством исполь- зования табличной части этого объекта. В демонстрационной конфигурации «Хранение инфор- мации и учет движения средств», которая находится на прилагаемом компакт-диске, к справочнику Номенклатура добавлена табличная часть ДополнительнаяИнформация, включающая в себя реквизиты ДополнительноеСвойство (тип значения ПланВидовХарактеристикСсылка.ВидыХарактери- стикНоменклатуры) и ЗначениеСвойства (тип значения Харак- теристика. ВидыХарактеристикНоменклатуры). (рис. 6.87). В данной процедуре выполняется приведение значения характеристики к типу выбранного вида характеристики. Теперь если пользователь будет менять вид характери- стики, а существующее значение характеристики не бу- дет соответствовать допустимым для выбранного вида типам характеристики, то значение характеристики будет приводиться к выбранному типу. Остальная функциональность вопросов ввода, модифи- кации, удаления данных посредством менеджера записи регистра реализуется системой и описана в разделе «Соз- дание, изменение, удаление записей регистра сведений», с. ИЗ. Таким образом, схему организации хранения дополни- тельных характеристик номенклатуры в рассмотренном решении в общем виде можно представить так (рис. 6.86). Тип значения "ЛланВмдовХарактеристмкСсылка мд «Характеристики омеик л атчрыи Ё й| Номенкгвтура □ S Реквизиты Табличные части S iji] Гкхтогьмтел^аяИнформация ——f—-----► — Джх гтмтвглноеСаоЛство -—i— ЭсчтжСзойстям Рис. 6.87. Структура справочника Номенклатура В результате в самом объекте справочника могут хра- ниться множественные значения дополнительных харак- теристик (рис. 6.88). характеристик ВидыХарактеристикНоменклатуры Рис. 6.88. Форма элемента справочника Номенклатура
Для обеспечения сервиса по организации корректного ввода данных в строки табличной части выполнены дора- ботки, аналогичные рассмотренным в разделе «Хранение дополнительных характеристик произвольного типа. Ис- пользование плана видов характеристик», с. 131. То есть задействованы свойства Связь по типу поля ввода Значе- ниеСвойства и использован обработчик события ДляИзмене- ния поля ДополнительноеСвойство (листинг 6.38). Листинг 6.38. Обработчик события ПриИзменении Процедура ДополнительнаяИнформацияДополнительноеСвойствоПриИзменении( Элемент) ТекущиеДанные = ЭлементыФормы.ДополнительнаяИнформация. ТекущиеДанные; ТекущиеДанные.ЗначениеСвойства = ТекущиеДанные. ДополнительноеСвойство. ТипЗначения. ПривестиЗначение( ТекущиеДанные.ЗначениеСвойства); КонецПроцедуры В целом, схему организации хранения произвольных до- полнительных характеристик номенклатуры в самом объ- екте можно представить так (рис. 6.89). Рис. 6.89. Схема хранения значений характеристик Подводя итог сказанного в этой главе, хотелось бы отме- тить, что: ♦ всю необходимую для функциональности прикладного решения информацию можно хранить в информацион- ной базе (базе данных) или конфигурации; ♦ как именно хранить — будет зависеть от того, зачем это нужно. То есть ответ на этот вопрос будет содержаться в условиях конкретных задач; ♦ система 1С:Предприятие предоставляет много вариан- тов хранения информации.
Глава 7. Документы и последовательности Место документов в концепции системы 1С:Предприятие При создании бизнес-приложений для решения задач учета, планирования, принятия решений, управления и т. д., как правило, используются определенные информацион- ные модели. И, как правило, одно из центральных мест любой подобной модели занимает понятие события. Например, один из наиболее активно используемых ва- риантов исторически сложившейся информационной мо- дели учетных решений можно представить в виде сле- дующей схемы (рис. 7.1). Рис. 7.1. Информационная модель учетного решения Основа учета — регистрация событий, происходящих с учи- тываемыми показателями. Она может выполняться по- средством внесения записей в журналы, записью прово- док и т. д. В общем, посредством документирования. Причем документирование должно производиться не в «вольной» форме, а согласуясь с заранее разработанны- ми и стандартизованными обозначениями, зачастую све- денными в виде неких классификаторов. Конечно же, документирование нужно не как самоцель, а для обоснования предоставляемой о состоянии учиты- ваемых показателей информации. Так называемой отчет- ной информации. При выдаче же отчетной информации большое значение придается наглядности, удобству и бы- строте ее получения. Для того чтобы обеспечить максимальную быстроту по- лучения отчетной информации, идеальным было бы ее получение сразу, минуя этап длительного перебора запи- сей событий и подсчета их влияния на показатели. Поэто- му отражение результата влияния зарегистрированных событий на показатели обычно производится заранее. То есть не в момент, когда потребуется отчет, а в момент, ко- гда событие только регистрируется. Для запоминания же состояния учитываемых показателей, таким образом, ис- пользуются специальные регистры учета. Например, для классического бухгалтерского учета посредством двой- ной записи итоги хозяйственной деятельности в виде сальдо «оседают» на бухгалтерских счетах. Рассмотрим, что предлагает платформа «1С:Предприя- тие 8.0» для реализации информационных моделей биз- нес-приложений. Система «1 С:Предприятие 8.0» позволяет строить при- кладные решения, оперируя совокупностями объектов: ♦ соответствующими прикладным сущностям; ♦ выбираемыми из набора жестко определенных в плат- форме прототипов объектов. Общую схему возможных вариантов взаимодействия прикладных объектов системы для решения той или иной задачи можно представить следующим образом (рис. 7.2): Условно-постоянная информация Константы Справочники Перечисления Планы видов характеристик Планы счетов Планы видов расчета Т Рис. 7.2. Варианты взаимодействия прикладных объектов Можно отметить, что данная схема позволяет полностью реализовать функциональность предыдущей и при этом может обеспечить существенное расширение и дополне- ние ее. Фактически она позволяет строить модели на более вы- соком уровне абстрагирования. Например, справочники, планы видов характеристик, пе- речисления, константы, планы счетов и планы видов рас- четов могут использоваться не только для обеспечения заполнения документов, но и для заполнения некоторых видов регистров напрямую. А вообще — для хранения ин- формации, не привязанной ко времени. Документы предназначены для ввода первичной информа- ции, связанной с регистрацией событий, воздействующих
на учитываемые в системе показатели. Если посмотреть на прикладные решения, то подавляющее большинство документов использует привязку ко времени — поле Дата, которое есть у всех документов. То есть можно говорить, что документы — это объекты для регистрации информации, для которой важна привязка ко времени. Для облегчения обеспечения действий, связанных с вводом, отображени- ем, логикой учета документов, при необходимости ис- пользуются такие объекты, как нумераторы, журналы до- кументов, последовательности. Отчеты и обработки могут обеспечивать не только вывод информации в удобном для пользователя виде, но и ввод. То есть могут использоваться для обеспечения интерфей- са выполнения воздействий на объекты, отвечающие за хранение информации. Однако сами для хранения ин- формации не используются. Регистры же можно воспринимать как объекты, предна- значенные для хранения «вторичной» информации о со- стоянии показателей со сложными привязками к моментам времени и периодам. Обычно эта информация получает- ся в процессе переработки исходной информации, вводи- мой документами. Например, факт болезни нужно регистрировать посред- ством документа Больничный. Информация документа, при его проведении будет отражена в регистре расчета зарплаты с тем, чтобы впоследствии, после проведения расчетных операций (включающих, например, вытесне- ние оклада за период болезни) из регистра можно было взять информацию о начисленном по болезни пособии и о начисленной заработной плате вообще. Однако, опять же, можно смотреть на использование ре- гистров шире. Есть возможность использования регист- ров сведений (периодических или непериодических) с независимым режимом записи. То есть, если это оправда- но с точки зрения решения прикладной задачи, для таких регистров данные могут вводиться непосредственно, ми- нуя этап работы с документом. Итак, подведем краткий итог: документирование собы- тий — основа практически любой модели бизнес-прило- жений. Без документирования информация, получаемая из системы, была бы необоснованной, а значит, — воз- можно, недостоверной. Таким образом, основное назначе- ние документов — регистрация информации о происхо- дящих событиях с привязкой ко времени. Документы Функциональность документов Для выполнения задач своего предназначения документы имеют соответствующий состав и обеспечивают возмож- ность следующих основных действий: ♦ заполнение; ♦ запись; ♦ проведение; ♦ формирование движений по регистрам; ♦ расположение на оси времени; ♦ пометка на удаление; ♦ удаление. Такой набор функциональности заложен в систему и обес- печивает быструю разработку и удобство использования документов. Разберем эти возможные действия подробнее. Заполнение документов Заполнение документа может производиться разными способами в зависимости от прикладной задачи и необхо- димого уровня сервиса для пользователя. Самый простой вариант заполнения — ручной ввод доку- мента (рис. 7.3). Данный вариант обеспечивается чаще всего посредством формы, имеющей в качестве основно- го реквизита объект документа. Тогда ряд элементов управления формы обеспечивают отображение и ввод значений в реквизиты формы, а ряд — инициацию про- цесса записи документа, когда данные реквизитов фор- мы записываются в сами объекты. Формы, основным реквизитом которых назначен объект документа, и эле- менты управления этих форм обладают расширениями, позволяющими реализовывать специфичное поведение системы для облегчения работы разработчика с доку- ментами. Открытие формы 1ового документа I гальэова- реквизитов Ноеьги документ 'ЗаказПокупателя' Запись оформлен него документа Рис. 7.3. Ручной ввод документа Копирование. Вариант, когда новый документ создается копированием существующего, причем его данные запол- няются данными существующего документа (рис. 7.4). Может инициироваться интерактивными действиями поль- зователя или программно — методом Скопировать(). Оба действия приводят к одному событию ПриКолировании и могут быть перехвачены обработчиком события, распо- лагаемым в модуле документа. В самом обработчике может быть реализовано заполне- ние нового документа в зависимости от требуемого алго- ритма (не обязательно только данными исходного доку- мента).
Рис. 7.4. Создание документа копированием Заполнение. Вариант создания нового документа, кото- рый инициируются интерактивным действием Ввод на ос- новании или программно — методом Заполнить О (рис. 7.5). Поскольку можно заполнять документ на основании данных любого объекта, то говорить об однозначном соответст- вии данных источника и документа-получателя не при- ходится. Поэтому само заполнение данных документа осуществляется в рамках обработчика события Обработка- Заполнения. Процедура обработчика располагается в моду- ле документа и содержит в качестве параметра объект-ис- точник. Программное заполнение документов. Может выполнять- ся за счет операций присвоения значений реквизитам до- кумента для объекта документа (рис. 7.6). В данном слу- чае выбор элементов управления и событий, в обработке которых будут производиться эти действия, предостав- лен разработчику конфигурации. Создание нового доку- мента при этом может производиться посредством мето- да СоздатьДокументО. Рис. 7.5. Создание документа вводом на основании Рис. 7.6. Программное заполнение документа К данному способу прибегают обычно в случаях, когда создание нового документа должно производиться не вручную, не копированием-заполнением, а в результате каких-то других действий пользователя. Расположение на оси времени Поскольку документ является регистратором события — одной из важных задач документа является фиксация времени, когда событие имело место. Поэтому все доку- менты имеют поле Дата. И более того, система не позволя- ет записать документы с не установленной датой (равной значению даты по умолчанию). Согласно значениям этого поля все записанные докумен- ты могут быть расположены на единой временной оси в хронологическом порядке (рис. 7.7). 12:30:45 12:30:47 12:30:40 Рис. 7.7. Расположение документов на оси времени Причем даже если ряд документов имеет одинаковое зна- чение поля Дата, система 1 С: Предприятие имеет средства для обеспечения однозначного хронологического поряд- ка — объект МоментВремени, содержащий дату и ссылку на документ (рис. 7.8). РеализацияТоваров №4 Дата 23.06.2005 12:30:45 РеализацияТоваров №2 Дата 23.06.2005 12:30:46 РеализацияТоваров №3 Дата 23.06.2005 12:30:46 РеализацияТоваров N91 Дата 23.08.2005 12:30:47 Моментвремени: Дата: 23.08.2005 12:30:46 Ссылка: РеализацияТоваров№2 Моментвремени: Дата: 23.06.2005 12:30:46 Ссылка: РеализацияТоваров№3 Рис. 7.8. Использование момента времени Объект МоментВремени используется системой автоматиче- ски при решении задачи отображения списков докумен- тов в хронологическом порядке. Так же его используют, когда требуется получить данные из регистров именно на момент времени документа. Однако необходимо заметить, что за счет использования момента времени можно только получить хронологию расположения документов, изменить же ее в пределах од- ной секунды невозможно. Хронологический порядок до- кументов определяется системой при обращении к дан- ным — по датам, а для одинаковых дат — по ссылкам документов. И для документов с одинаковым временем не зависит ни от порядка создания документов, ни от но- мера документа, ни от чего-то подобного. Если необходимо изменить хронологию документов — нужно менять значения поля Дата документов, «разводя» их в разные секунды. Кроме того, в случаях, когда требуется обеспечить ввод и проведение документов реальным временем можно
воспользоваться возможностями механизма оперативно- го проведения документов и оперативной отметки време- ни. Это позволяет распределять документы на временной оси автоматически с соблюдением как минимум секунд- ного интервала. О работе данного механизма подробно рассказывается в разделе «Проведение документов». Запись документов Запись объекта документа — физический процесс, заклю- чающийся в сохранении значений реквизитов документов в базе данных. Может инициироваться интерактивными действиями пользователя или программно — методом За - писатьО. Запись документа имеет несколько возможных режимов (просто — запись, проведение, отмена проведения). О про- исходящих при этих режимах записи процессах будет рассказано ниже. Общий же смысл использования этих режимов — обеспече- ние логических процессов бизнес-решения с использовани- ем определенных «сценариев», заложенных в систему (уда- ление существующих движений, формирование новых, установка значения поля Проведен и прочее). Разработчик вправе принимать решения о необходимости применения того или иного сценария или механизма (рис. 7.9). Запись документа (физический процесс) Отмена v- г ... документа (логический процесс) Пхведение документа (логический гроцесс) ______________________ Запсь документа (логически* гроцесс)___________________ Учетные механизмы Рис. 7.9. Запись документа Проведение документов Обсуждая это действие, необходимо разделять два понятия: ♦ «проведен» — состояние документа; ♦ «проведение» — как процесс. Проведенность как состояние может быть установлена различными способами: классически — в результате вы- полнения процесса проведения, и просто присвоением значения Истина свойству документа Проведен. С прикладной точки зрения проведенным считается до- кумент, если обработка данного документа полностью за- вершена и принято решение, что данный документ должен участвовать в учете. То есть событие, регистрируемое до- кументом, полностью описано и учтено в информацион- ной модели. Для отражения этого состояния документа используется системное поле Проведен. Процесс проведения документа в системе является част- ным случаем записи документа. Если состояние проведения было достигнуто в процессе проведения документа, то, значит, были обработаны все события, связанные с записью документа в режиме про- ведения. А именно, в обработчиках этих событий обычно и содержатся указания — что, где и как должно измениться в объектах информационной базы для реализации биз- нес-логики, заложенной в решение (рис. 7.10). Рис. 7.10. Проведение документа Кроме того, зачастую используется процесс, обратный проведению, — отмена проведения. Выполнение этого процесса приводит к записи документа с отменой прове- дения. При этом выполняются обработчики, связанные с ним (рис. 7.11). Рис. 7.11. Отмена проведения документа Если же свойство Проведен просто установлено или снято для документа, и документ был записан, то в результате для такого документа был выполнен процесс обычной за- писи документа. То есть часть событий не произошло для такого документа, а значит, не были обработаны соответ- ствующим образом (рис. 7.12). Рис. 7.12. Использование свойства Проведен Однако для каких-нибудь регламентных или вспомога- тельных обработок может оказаться важной такая воз- можность: получить проведенные документы без процесса проведения или непроведенные документы без процесса отмены проведения.
Формирование движений по регистрам По своему назначению регистры служат для запомина- ния и переработки информации, внесенной в систему, как правило, документами. Поэтому для записей любых реги- стров (только за исключением регистров сведений с уста- новленным режимом записи — Независимый) обязательно наличие заполненного поля Регистратор. В этом поле должна находиться ссылка на документ, которому подчи- нен этот набор записей. Такие наборы записей называют движениями (рис. 7.13). Поведение системы во многом определяется наличием связи документов и подчиненных им движений. Напри- мер, движения отдельно от своих регистраторов сущест- вовать не могут. Поэтому при удалении документов сис- тема производит поиск движений этого документа в таблицах всех регистров, для которых данный документ может быть регистратором, и удаляет их. Именно поэто- му, например, не рекомендуется «про запас» указывать регистры, для которых документ может быть регистрато- ром. Нужно указывать только те, которые действительно требуются для обеспечения бизнес-логики, заложенной в решение. Сами же движения могут: ♦ создаваться при проведении документов; ♦ создаваться при записи документов; ♦ формироваться в виде набора записей регистра (обяза- тельно — с отбором по регистратору); ♦ формироваться интерактивно (например, документом Ручная операция). То есть и не проведенные документы могут иметь движе- ния по регистрам. Это обеспечивает возможность доста- точно гибкого отражения ситуаций, возникающих в авто- матизируемых задачах. Что может быть использовано, когда обработка документа пользователем еще не завер- шена, но документ уже должен изменить некие учетные данные. Например, так может выглядеть задача последовательной обработки документа Заказ покупателя различными под- разделениями компании. Для отслеживания различных стадий обработки этого до- кумента используется регистр сведений Оперативное- УправлениеЗаказами (рис. 7.14). Заполнение регистра производится при реализации про- межуточных операций обработки документа (рис. 7.15). Сначала документ выписывается менеджером и записы- вается. При этом в регистре сведений ОперативноеУправле- ниеЗаказами формируется запись, указывающая, что дан- ный заказ находится в стадии «ФинансовомуКонтролю. Далее ответственный сотрудник финансового отдела про- веряет возможность удовлетворения данного заказа с точки зрения допустимости долга покупателя и соблюде- ния ценовых порогов. В случае положительного решения выставляется флаг Отпуск разрешен. При записи документа с установленным флагом модифицируется запись в реги- стре сведений ОперативноеУправлениеЗаказами, теперь для данного документа актуально состояние «Размещению. Далее обработку документа выполняет менеджер отдела запасов. Он работает со всеми заказами, имеющими ста- тус «Размещению. Если принимается решение об отгрузке из наличных свободных остатков, устанавливается фла- жок Отгрузка из свободных остатков и заказ записывается. При записи такого заказа — его статус меняется на значе- ние «Резервированию. Если же будет принято решение о вы- боре варианта Размещение в заказе поставщику выполняется проведение документа с формированием движений по ре- гистру ЗаказыПоставщикам. Заказы покупателей, перечисленные в регистре сведений ОперативноеУправлениеЗаказами и имеющие статус «Резер- вированию, проверяются и окончательно проводятся уже товароведом на складе. В таких случаях формируются движения по регистру Резервы (табл. 7.1). Таблица 7.1. Промежуточные операции обработки документа № Пользователь Стадия обработки Движения по регистрам Комментарий 1 Менеджер Заполнение Регистр сведений Оперативное управление заказами Формирование записи по заказу: статус КФинансовомуКонтролю 2 Финансовый отдел Контроль кредитной линии Регистр сведений Оперативное управление заказами Формирование записи по заказу: статус КРазмещению 3 Отдел запасов Решение об отгрузке из свободных остатков или заказе поставщику Регистр сведений Оперативное управление заказами Модификация записи по заказу: статус КРезервированию — если принято решение об отгрузке из свободных остатков Регистр остатков Заказы поставщикам Проведение документа с формированием дви- жений по регистру Заказы поставщикам (движения по регистру Оперативное управле- ние заказами автоматически удаляются) 4 Склад Отметка о постановке в очередь на отгрузку Регистр остатков Резервы Проведение документа с формированием дви- жений по регистру Резервы (движения по регистру Оперативное управле- ние заказами автоматически удаляются)
F Список Цены tюставщиг ов _ С X Действия* (*♦) ’Й TJ ® Рис. 7.13. Движения документа Рис. 7.14. Регистр сведений ОперативноеУправлениеЗаказами . Менеджер !. Финанасовый Документ” Действия- 3. Отдел запасов поквпатеяя Рис. 7.15. Промежуточные операции обработки документа
Обратите внимание: хотя движения по регистрам для об- рабатываемого заказа формируются на каждой стадии об- работки, но «финальное проведение» выполняется только на последней стадии. Причем разработчик может выпол- нять его в рамках обработчика события ОбработкаПроведе- ния, а может и самостоятельно — очищая старые движе- ния, формируя новые и устанавливая свойство Проведен данного документа. Пометка на удаление документа Так же как и при работе с проведением, необходимо раз- личать: ♦ состояние документа «ПометкаУдаления»; ♦ процесс «ПометкаУдаления». Документ считается помеченным на удаление в том слу- чае, если в системное поле документа ПометкаУдаления за- писано значение Истина. Проведение документа, помечен- ного на удаление, имеет свои особенности. Например, такой документ не может быть проведен (рис. 7.16). I »•*. документа Рис. 7.16. Проведение документа, помеченного на удаление Сам же процесс «ПометкаУдаления» обычно иницииру- ется интерактивно или методом объекта документа Уста- новитьПометкуУдаления(ИСТИНА) и приводит к тому, что доку- мент записывается с соответствующим значением поля ПометкаУдаления. При этом если документ был проведен, инициируется еще отмена проведения документа и уда- ление движений данного документа (4.17). Обратите внимание: отмена проведения и удаление дви- жений производится при установке пометки удаления, только если документ был проведен. Если документ не был проведен, но имел движения, то при установке по- метки удаления удаление движений не будет произведено. Если же для помеченного на удаление документа инте- рактивно снимается пометка удаления или применяется метод УстановитьПометкуУдаления(ЛОЖЬ), то инициируется запись документа с изменением значения на Ложь в поле ПометкаУдаления (рис. 7.18). Кроме того, значение свойства ПометкаУдаления объекта документа можно устанавливать программно и просто за- писывать документ. В таких случаях инициации события ОбработкаУдаленияПроведения не происходит. И если при этом документ был изначально не проведен, он записыва- ется помеченным на удаление. Если же подобные дейст- вия выполняются для проведенного документа, то сис- тема выдает предупреждение о невозможности записи документа и проведенного, и помеченного на удаление (рис. 7.19). А вот возможность помеченного на удаление документа иметь движения может быть полезной, если по какой-то причине необходимо отражать в учете данные документа, готовящегося к удалению. Например, пока не будет про- веден документ, его заменяющий. Пометка на удаление Рис. 7.17. Установка пометки на удаление Рис. 7.18. Снятие пометки удаления Рис. 7.19. Использование поля ПометкаУдаления Сами «события» «Установка пометки на удаление» и «Сня- тие пометки удаления» с точки зрения документа выде- ленными процессами не являются. Поскольку в любом случае идет речь о записи помеченного на удаление доку- мента (или со снятой пометкой), то все необходимые дей- ствия можно выполнить в обработчиках событий, связан- ных с записью документа. Например, если для документа ПоступлениеТоваров требу- ется «перехватить» изменение значения свойства Помет- каУдаления для уже записанного документа, можно посту- пить следующим образом (листинг 7.1).
Листинг 7.1. Обработчик события ПередЗаписью Процедура ПередЗаписьюСОтказ, РежинЗаписи, РежинПроведения) // Ограничить действия: только для записанных документов Если Не ЭтоНовыйО Тогда // Получить поиетку удаления текущего документа // из базы данных Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | ПоступлениеТоваров.ПометкаУдаления |ИЗ Документ.ПоступлениеТоваров КАК ПоступлениеТоваров |ГДЕ ПоступлениеТоваров.Ссылка = &ТекущийДркумент"; Запрос.УстановитьПараметрС"ТекущийДркумент". Ссылка); Результат = Запрос.ВыполнитьО; Выборка = Результат.ВыбратьО; Выборка.Следующий(); // Сравнить текущее значение пометки удаления // и взятое из базы данных Если ПометкаУдаления <> Выборка.ПометкаУдаления Тогда Если ПометкаУдаления Тогда И Выполнить действия при установке // пометки удаления... Иначе // Выполнить действия при снятии пометки удаления // ... КонецЕсли; КонецЕсли; КонецЕсли; КонецПроцедуры Удаление документов Может производиться в составе механизма контроля ссылочной целостности. А может иметь место и непо- средственное удаление объектов. Использование меха- низма контроля ссылочной целостности при удалении объектов или не использование его определяется разра- ботчиком и администратором конфигурации. Если документ имеет движения по регистрам, то при не- посредственном удалении документа система автомати- чески удалит их. Событие ПередУдалениен может обрабатываться в модуле объекта документа. Например, если требуется позволить непосредственное удаление только тех документов, которые не имеют дви- жений, достаточно сделать следующее (листинг 7.2). Листинг 7.2. Обработчик события ПередУдалением Процедура ПередУдалением(Отказ) Для Каждого НаборЗаписейРегистра из Движения Цикл // Прочитать движения по каждому регистру НаборЗаписейРегистра.Прочитать(); // Проверить наличие записей в движениях // по конкретноиу регистру. Если НаборЗаписейРегистра.Количество()>0 Тогда Сообщить ("Документ " + МетаданныеО .ПредставлениеО + " Hs " + Номер + " от " + Дата + " имеет движения!"); Отказ = Истина; КонецЕсли; КонецЦикла; КонецПроцедуры Состав документов Что в себя включают документы? Рассмотрим этот вопрос, учитывая области абстрагирова- ния, использующиеся для работы с объектами в системе. Потому что в каждой области абстрагирования документ описывается по-разному. Можно говорить о составе документа, как прикладного объекта, используемого для организации прикладного ре- шения. Можно — как об объекте метаданных (прототипе прикладных объектов — документов), позволяющего ор- ганизовать работу в отношении реализации прикладной задачи в рамках конфигурации. Можно — о составе объ- ектов базы данных (таблиц, полей, индексов), посредст- вом которых организовано непосредственное хранение данных документов (рис. 7.20). Рис. 7.20. Понятие «Документ» Поскольку основной задачей документов, как объектов прикладной области является регистрация событий, струк- тура документов определяется именно этой задачей. Тогда что за информацию можно отражать в системе при регистрации события? Прежде всего, сам факт того, что событие произошло и — когда оно произошло. Поэтому, как правило, для каждого события необходимо регистрировать порядковый номер этого события и дату происхождения. Соответственно, в состав любого документа включаются поля Номер и Дата. Это минимально возможный состав регистратора собы- тия. Действительно, могут иметь место ситуации, когда больше никакой информации относительно данных доку- мента и не требуется. Например, для документов, отра- жающих регламентные операции («завершение периода», «снятие итогов» и т. п.). Для ситуаций, когда при регистрации события необходимо запоминать информацию, имеющую единичные значения для одного события, должны использоваться реквизиты документов. Например, Поставщик при регистрации факта поставки товаров. Для ситуации, когда при регистрации события необходи- мо запоминать информацию, имеющую множественные значения, необходимо использовать табличные части до- кументов. Например, табличная часть Товары при регист- рации факта поставки множества товаров. Как объект конфигурации для обеспечения решения за- дач прикладной области документ обладает свойствами (автонумерация, проведение и т. д.) и имеет в своем со- ставе подчиненные объекты:
♦ Реквизиты документов — объекты, используемые для запоминания информации об объекте (документе), имеющей единичные значения для каждого экземпляра документа; ♦ Табличные части документов — объекты, используемые для запоминания информации дополнительной инфор- мации об объекте, представляемой в виде таблиц; ♦ Формы — объекты, используемые для обеспечения ин- терактивного ввода, просмотра и редактирования ин- формации. ♦ Макеты — объекты (табличные документы), обычно используемые при формировании печатных форм объ- екта. Для обеспечения возможности манипулирования данными при написании алгоритмов обработки информации доку- ментов используются соответствующие объекты встро- енного языка. На самом нижнем уровне абстрагирования используются объекты информационной базы, обеспечи- вающие выполнение задач вышестоящих уровней. Структура таблиц базы данных На уровне объектов базы данных информация о докумен- тах хранится в следующих таблицах: ♦ основная таблица документа, для каждого объекта ме- таданных Документ; ♦ таблица табличной части документа, для каждой таб- личной части каждого объекта метаданных Документ. Структура полей этих таблиц следующая. Основная таблица документов: ♦ Ссылка — уникальный идентификатор, позволяющий однозначно определить данную запись; ♦ ПометкаУдаления — Булево; ♦ Проведен — Булево; ♦ Дата — дата регистрируемого документа; ♦ Номер — номер регистрируемого документа (поле суще- ствует, если документ как объект конфигурации имеет длину номера, отличную от нуля; ♦ Реквизит! — тип значения поля определяется типом значения реквизита; ♦ ... ♦ РеквизитМ — ... Таблица табличной части документа: ♦ Ссылка — ссылка на документ, которому подчинена дан- ная запись. Содержит то же значение, что и поле Ссылка основной таблицы документов; ♦ НомерСтроки — предопределенный реквизит табличной части, тип значения Число; ♦ Реквизит! — тип значения поля определяется типом значения реквизита; ♦ ... ♦ РеквизитМ — ... Допустим, в конфигурации для регистрации контактов: деловых встреч, звонков, писем, используется документ Событие (рис. 7.21). Событие □ 2 Реквизиты — ВидСобытия — Контрагент — ОписаниеСобьп-ия — Ответственный Ё i:g Т абличные части Ёх:11 СторонниеЛица | Контрагент 1..— Лицо Рис. 7.21. Документ Событие В базе было записано 4 документа: 01.10.2005 был оформлен документ с номером Т-001, в ко- тором зафиксировано проведение переговоров с контр- агентом КомбиТранс и сторонней организацией Баязет. Далее 02.10.2005 был зафиксирован телефонный звонок Баязет документом Т-002. Далее задним числом был введен документ Т-003, в кото- ром зафиксированы переговоры с контрагентом Коринф. Последним документом с номером Т-004 был зафиксиро- ван случайный звонок в офис. Данные этого документа в информационной базе будут храниться в таблице документа и таблице табличной час- ти документа. Таблица документа будет иметь следую- щий вид (табл. 7.2). Таблица 7.2. Таблица документа Событие (начало) Ссылка Пометка Удаления Проведен Дата Номер Док! Ложь Ложь 01.10.2005 10:00:00 Т-001 ДокЗ Ложь Истина 02.10.2005 11:00:00 Т-003 Док2 Ложь Ложь 01.10.2005 13:00:30 Т-002 Док4 Истина Ложь 02.10.2005 15:00:00 Т-004 Таблица 7.2. Таблица документа Событие (окончание) Вид События Контрагент Описание События Ответствен- ный Переговоры КомбиТранс Переговоры Иванов Телефонный звонок Баязет Выяснение реквизитов Петров Выезд к заказчику Коринф Переговоры Иванов Телефонный звонок Ошиблись номером Иванов Обратите внимание: записи в самой таблице упорядоче- ны согласно хронологии ввода информации. Таблица табличной части документа будет содержать записи только для тех документов, у которых она была заполнена (табл. 7.3).
Таблица 7.3. Таблица табличной части документа Событие Ссылка НомерСтроки Контрагент Лицо Док1 1 Баязет Семенов Док1 2 Баязет Горбунков Если к реквизитам документа добавить еще реквизит, система при изменении конфигурации базы данных доба- вит к таблице документа еще одну колонку. Причем для «старых» записей значения этого поля будут заполнены соответствующими типу значения реквизита значениями по умолчанию. Аналогичные действия в отношении таблицы табличной части документа будут произведены, если к реквизитам табличной части документа добавить еще один реквизит. Для обеспечения должного быстродействия при обраще- нии к данным информационной базы для таблиц хране- ния информации документов создаются следующие ин- дексы: ♦ Ссылка; ♦ Дата + Ссылка; ♦ Номер + Ссылка — если для данного документа длина но- мера не равна нулю; ♦ Реквизит + Ссылка — если для данного реквизита свойст- во Индексировать установлено в значение Индексировать; ♦ Реквизит + Дата + Ссылка — если для данного реквизита свойство Индексировать установлено в значение Индекси- ровать с доп. упорядочиванием; ♦ Реквизит — если документ включен в критерий отбора через данный реквизит. Табличная модель обращения к данным (посредством за- просов) дает возможность получения информации из этих таблиц в виде таблицы документа (табл. 7.4). Отдельные вопросы типового использования документов Нумерация документов Для решения бизнес-задач зачастую серьезным вопросом является нумерация документов. Например, существует даже такое понятие как «документы строгой учетности», предъявляющие определенные требования к порядку ве- дения нумерации документов. Для обеспечения этого и других вопросов в системе соз- даны следующие возможности: На уровне объекта конфигурации «Документ» можно управлять свойствами: ♦ Длина номера — определяет разрядность поля, отводимо- го под номер документа; ♦ Контроль уникальности — определяет необходимость кон- троля неповторяемости номеров средствами системы перед записью объекта; ♦ Автонумерация — определяет необходимость формирова- ния новых номеров средствами системы при попытке создания новых объектов; ♦ Периодичность (Непериодический, В пределах года, В пределах квартала, В пределах месяца, В пределах дня) — определяет границы периодов контроля уникальности и повторяе- мости номеров автонумерации; ♦ Тип номера (Строка, Число) — определяет тип поля Номер; Таблица 7.4. Состав таблицы документа Поле Тип Назначение Ссылка ДокументСсылка.<Имя> Содержит ссылку на документ Пометка удаления Булево Содержит признак пометки на удаление Номер Число, Строка Содержит номер документа Дата Дата Содержит дату документа Проведен Булево Содержит признак проведенности документа Представление Строка Виртуальное поле, не хранится в базе данных. Строковое представление, содержащее имя документа, его номер и дату. Не может использоваться для операций сравнения в тексте запроса МоментВремени МоментВремени Виртуальное поле, не хранится в базе данных. Содержит объект МоментВремени (который включает в себя дату и ссылку на документ) <Реквизиты> Произвольный, определяется типом реквизита Каждое из полей содержит значения реквизитов документа. Имена полей совпадают с названиями реквизитов, заданными для объекта конфигурации <Табличные части> РезультатЗапроса Каждое из полей содержит табличные части документа. Имена полей совпадают с названиями табличных частей, заданными для объекта конфигурации. Сами значения полей содержат результаты запросов по табличным частям документа. Результат запроса к табличной части состоит из колонок с именами, соответствующими именам реквизитов табличной части документа и колонки НомерСтроки
♦ Нумератор — используется для возможности организа- ции сквозной нумерации документов разных видов. Автоматическая нумерация Автоматическая нумерация позволяет создавать новые документы с заведомо уникальными номерами в пределах указанной периодичности. Для включения этой возмож- ности достаточно установить флаг Автонумерация. Тогда система будет присваивать каждому новому документу номер, на единицу больший самого большого номера сре- ди документов данного вида (в том периоде, к которому относится дата документа). Причем независимо от того, создается этот новый документ интерактивно или про- граммным способом. Само значение самого старшего номера определяется по таблице документов. Далее происходит обращение к спе- циальной таблице выданных номеров на предмет «неза- нятости» вычисленного самого старшего номера. И если номер не занят (в соответствующем периоде), то система записывает вычисленный номер в эту таблицу. Если за- нят — система пытается еще на единицу увеличить номер и опять проверяет его на «незанятость». Вычисленный в конечном итоге уникальный номер устанавливается до- кументу (рис. 7.22). Установка нового номера Рис. 7.22. Алгоритм установки нового номера Очистка записей занятых номеров производится в мо- мент записи документа. Таким образом, при автонумерации обеспечивается выда- ча новых номеров, уникальных как в отношении уже за- писанных, так и еще не записанных документов. При работе со строковыми номерами алгоритм дополня- ется еще начальным приведением строковых номеров к числу. Причем к числовому формату цифры номеров приводятся от последней к первой, пока процесс не дойдет до символа, который невозможно распознать как число. После этого символы левой части номера считаются пре- фиксами. Система определяет самый «длинный» пре- фикс, а при одинаковом количестве разрядов у несколь- ких префиксов — последний по порядку алфавитного возрастания. Далее определяется самый большой номер с данным префиксом. Именно он впоследствии будет инкрементироваться для определения следующего номера. Приведем пример работы данного алгоритма. Допустим, в таблице документов содержатся записи со следующими номерами (табл. 7.5). Самый «длинный» префикс Т_2а. Поскольку самый стар- ший номер с таким префиксом Т_2а2, то автонумерацией будет создан следующий номер: Т_2аЗ. Ниже проиллюстрированы на схемах возможные вариан- ты использования автонумерации. Если у свойства Периодичность документа установлено зна- чение Непериодический, тогда в результате автонумерации будем видеть такую картину (рис. 7.23). Номера документов: |ooii8 | |ooii9 | |ooi2Q | |ooizi Дата: 31.12.2005г. 01.01.2006г. Рис. 7.23. Непериодическая автонумерация Если у свойства Периодичность документа установлено зна- чение В пределах года, тогда в результате автонумерации будем видеть такую картину (рис. 7.24). Номера документов: |оои8 | jooiis | jooooi | |оооог Дата: 31.12.2005г. 01.01.2006г. Рис. 7.24. Автонумерация в пределах года Однако нельзя забывать о том, что при автонумерации следующий номер, выдаваемый системой, всегда на еди- ницу больше самого старшего. Например, если в послед- нем примере (с периодичностью — год) изменить дату «прошлогоднего документа», то можно получить такую картину: дата документа с номером 00118 была изменена на 01.01.2006. В результате последующие номера, форми- руемые автонумерацией, начинаются от 00119 (рис. 7.25). Номера документов: |оои9 | |ooooi | |ооне | |оои9 | Дата: 31.12.2005г. 01.01.2006г. Рис. 7.25. Работа автонумерации при изменении даты документа
Использование лидирующих нулей Если автонумерация применяется для номеров строково- го типа, то в этом случае используются лидирующие нули в составе номера. Все пробелы перед самим номером — замещаются нулями. Например, 00031. Это необходимо для обеспечения корректности поиска и сортировки по номеру. Иначе документ с номером 31 располагался бы раньше документа с номером 7 (рис. 7.26). Гортириммз ПО возрастанию (алфавитная) 118 31 Сортировка по возрастанию (алфавитная) 00007 00031 00118 Рис. 7.26. Использование лидирующих нулей Листинг 7.4. Использование метода Установить НовыиНомерО Процедура ОрганизацияПрийзменении(Элеиент) // Установить новый номер согласно префиксу организации УстановитьНовыйНомер(0рганизация.Префикс); КонецПроцедуры ПРИМЕЧАНИЕ Эти примеры приведены в демонстрационной конфигура- ции «Хранение информации и учет движения средств», ко- торая находится на прилагаемом компакт-диске, для доку- мента ПриходныйКассовыйОрдер. Результатом подобных действий можно добиться того, что вне зависимости от порядка оформления документов по разным организациям нумерация будет сквозной именно по каждой из организаций. Вернее, по префиксу каждой организации (рис. 7.27). Параллельное ведение нумераций документов одного вида Например, выписываемые от разных юридических лиц накладные должны иметь нумерации, сквозные в пре- делах каждого отдельного юридического лица. Для ре- шения этой проблемы устанавливается строковый тип номеров документа и автонумерация. Далее необходимо программно назначать префиксы автонумерации в обра- ботчиках соответствующих событий. В результате систе- ма формирует новый номер по вышеописанным прави- лам, но только еще в пределах назначенного префикса автонумерации. Для назначения префикса автонумерации можно исполь- зовать обработчик события При установке нового номера или метод объекта документа УстановитьНовыйНоиерО. Например, если необходимо установить новый номер в пределах префикса автонумерации, значение которого хранится в реквизите Префикс организации, указанной в реквизите документа Организация, тогда можно поступить следующим образом (листинг 7.3). Листинг 7.3. Установка нового номера в пределах префикса автонумерации Процедура ПриУстановкеНовогоНомераССтандартнаяОбработка, Префикс) Префикс = Организация.Префикс; КонецПроцедуры Событие При установке нового номера возникает в момент, когда начинается формирование нового номера (напри- мер, при вводе нового документа, копировании докумен- та или вводе на основании). Если в процедуре-обработчи- ке этого события параметру Префикс назначить значение, то именно это значение и будет использовано в качестве префикса автонумерации для установки нового номера. Если же, кроме того, номер документа необходимо ме- нять в ответ на изменение значения реквизита Организа- ция, то в соответствующем обработчике события можно применить метод объекта документа УстановитьНовыйНо- мер(). Он устанавливает новый номер документа в преде- лах периода, в соответствии с установленной датой доку- мента для заданного префикса автонумерации (листинг 7.4). |аВ-00012 | |ис 00116 ] [аВ-00013 | |Р0000001 | |мЙ)00Н | |иС-0С1Н7 | |лв-аю12 | |дв-ооо13 | |ав-ооон | |Р0000001 | |йС-00116 | |йС-СС1Н7 | * Рис. 7.27. Автонумерация с использованием префиксов Хотелось бы предостеречь от попыток использования префиксов, которые целиком входят в состав других пре- фиксов. Например: префиксов АИ и А В этом случае, как разбирали выше, при попытке формирования нового но- мера с префиксом А получим следующий номер от пре- фиксации АИ. Организация сквозной нумерации при помощи нумераторов Кроме разделения нумерации может возникнуть обрат- ная задача — обеспечение общей сквозной нумерации. Обычно это требуется, когда имеется несколько видов до- кументов для отражения похожих хозяйственных опера- ций, но необходимо организовать для них сквозную ну- мерацию, невзирая на вид документа (рис. 7 28). Документ: Реализация |дв-ооо12 [__________________________[ab-ooois [ (нупля/продажа) * Документ: Реализация _________________|ab-oooi3 | [дв-ооон |_______ (комиссия) * Рис. 7.28. Использование нумераторов Для решения такой задачи используется объект конфигу- рации Нумератор В нем описываются: ♦ Длина номера, ♦ Контроль уникальности; ♦ Периодичность; ♦ Тип номера. Далее у всех документов — объектов конфигурации, для которых нужна сквозная нумерация, указывается этот нумератор и устанавливается свойство Автонумерация.
В результате формирование нового номера производится при обращении уже не к одной таблице документов ин- формационной базы, а к таблицам документов, которым назначен данный нумератор. Запись документов Запись документа может производиться в форме доку- мента либо не в форме документа. В первом случае запись документа инициируется расши- рением формы документа (для функционирования этого расширения необходимо, что бы основным реквизитом формы был объект документа). Работа расширения фор- мы обеспечивает специфичное, удобное для пользовате- ля, поведение формы при редактировании и записи доку- мента. Во втором случае — форма документа не используется, а обращение идет непосредственно к объекту документа. При реализации записи документа в форме, кроме самой записи, выполняются еще действия, определяемые рас- ширением формы: установка даты документа, установка режима проведения, запрет определенных действия поль- зователя и т. д. Подробно эти действия рассматриваются в разделе «Особенности работы формы документа», с. 157. При записи документа не в форме выполняется только запись документа (рис. 7.29). Запись документа в Запись документа не форме в форме Рис. 7.29. Запись документа При выполнении самой записи документа производятся следующие действия: ♦ контроль уникальности номера документа', * проверка версии документа. Проверяется идентичность версий объекта документа и версии записей базы дан- ных, хранящих данные этого документа. В случае если версии не совпадают, транзакция прерывается и выда- ется предупреждение «Операция не может быть выпол- нена из-за несоответствия версии или отсутствия запи- си базы данных (возможно запись была изменена или удалена)!» Это необходимо, например, при следующей ситуации: некой обработкой программно было обеспе- чено, что для двух пользователей были открыты формы одного и того же документа. Первый пользователь из- менил значение Контрагента в документе, второй — зна- чение Номенклатуры. На момент первой попытки записи измененного документа версии объекта документа и за- писей базы данных совпадут — документ будет записан. Но при попытке записи документа другим пользователем версии не совпадут, и система не позволит записать «па- раллельно измененный» документ, поскольку данное действие может породить коллизии; ♦ запись данных в таблицы документов; ♦ запись данных в таблицы табличных частей докумен- тов. Причем данное действие оптимизировано по ско- рости исполнения. Это происходит за счет автоматиче- ского различения ситуаций, когда необходимо записать (модифицировать) данные всех записей, подчиненных записываемому документу, или только одной записи. Причем если модифицированы были значения рекви- зитов документа, а не табличной части документа, то данное действие вообще не выполняется; ♦ запись данных в таблицы журналов, если данные доку- мента используются в этих журналах; ♦ запись данных в таблицы регистрации изменений пла- нов обменов, если данный документ входит в состав об- мениваемых данных. Причем сама запись документа может вызываться инте- рактивно или программно. Интерактивно запись инициируется действиями пользо- вателей, приводящими к выполнению системных дейст- вий: ♦ Записать; * Записать и закрыть; ♦ Провести; ♦ Отмена проведения. Программно в контексте формы документа запись может быть инициирована посредством метода ЗаписатьВФорнеО расширения формы документа. Причем методу может быть передано значение параметра Режим записи из систем- ного перечисления РежимЗаписиДокумента. В данном систем- ном перечислении всего три значения: Запись, ОтменаПрове- дения, Проведение. В зависимости от значения параметра будет различно поведение системы. Например, для значе- ния Запись — будет вызвана запись данного документа без проведения, для значения Проведение — запись с проведе- нием, для значения случая ОтменаПроведения — запись с от- меной проведения. Действие Записать В случае записи документа, вызванной системным дейст- вием Записать или применением метода ЗаписатьВФормеСРе- жимЗаписиДокумента.Запись), кроме самой записи иници- ируются следующие события (рис. 7.30). Часть событий относится к контексту формы документа, и могут быть перехвачены соответствующими обработчи- ками событий, располагаемыми в модуле формы доку- мента. Часть событий относится к контексту объекта до- кумента и могут быть перехвачены там. В обработчиках ПередЗаписью посредством установки пара- метру Отказ значения Истина можно предотвратить после- дующий набор действий. То есть, например, если уста- новлен отказ в записи документа на уровне контекста формы документа, то последующие в показанной выше схеме события уже не произойдут, поскольку платформа прекращает выполнение данной последовательности дей- ствий.
Запись в форме Действия Записать и закрыть. Провести В случае записи документа, вызванной системными действиями: «Записать и закрыть» (если у документа не запрещено проведение), «Провести» или примене- нием метода ЗаписатьВФорне(РежимЗаписиДокумента.Прове- дение), кроме самой записи инициируются следующие события (рис. 7.31). Запись в форме с проведением Рис. 7.31. Вызов событий при выполнении действий Записать и закрыть. Провести То есть добавляется еще одно событие — ОбработкаПрове- дения. Процедура-обработчик этого события может нахо- диться только в модуле объекта документа, предназначе- на для указания действий, которые нужно выполнить при проведении документа, и также имеет параметр Отказ. Действия с ним аналогичны предыдущему случаю. То есть последующие события уже не выполняются, если в параметр Отказ установлено значение Истина. Действие Отмена проведения В случае записи документа, вызванной системными дей- ствиями «Отмена проведения» или применением метода ЗаписатьВФорме(РежинЗаписиДокумента.ОтменаПроведения), кроме самой записи инициируются следующие события (рис. 7.32). Запись в форме с отменой проведения Рис. 7.32. Вызов событий при выполнении действия Отмена проведения То есть в этом случае появляется еще событие Обработка- УдаленияПроведения. Процедура-обработчик этого события также может располагаться только в модуле объекта до- кумента, содержит указание действий, которые должны быть выполнены при отмене проведения, и имеет пара- метр Отказ. Применение этого параметра аналогично вы- шеразобранным случаям. В случаях если запись документа производится не в фор- ме, отличия состоят в том, что при выполнении этого дей- ствия не задействуются события, связанные с формой. Например, запись с проведением будет производиться следующим образом (рис. 7.33). Запись объекта документа с проведением Рис. 7.33. Последовательность событий при программной записи объекта документа с проведением
Проведение документов Ввод информации в документ, в общем случае, может осу- ществляться не за один раз. Кроме того, часть информации, необходимой для полной регистрации события в учетных механизмах, — может становиться известной не сразу, а часть информации — может быть получена в результате анализа и обработки исходной. Поэтому в системе есть воз- можность различать состояния документа: «введен» и «про- веден». Для этого чаще всего разделяются операции ввода первичной информации (заполнение документа) и отраже- ния данных документа в учете (обработка первичной ин- формации и формирование движений) (рис. 7.34). Рис. 7.34. Последовательность работы с документом Обработку информации для отражения в учете и форми- рование движений по регистрам обычно выполняют при проведении документа. Данный механизм удобен для вы- полнения подобных действий. Рассмотрим более глубоко варианты проведения доку- ментов. Их использование определяется значениями свойств документа как объекта конфигурации, а именно: в Проведение; = Оперативное проведение; Удаление движений. Свойство Проведение объекта метаданных Свойство Проведение объекта конфигурации Документ мо- жет иметь значение Разрешить или Запретить. В первом случае проведение документа соответствует вы- шеописанному (разделение операций заполнения доку- мента и отражения его данных в учетных механизмах). То есть именно для таких документов имеют смысл работа с полем Проведен и процесс «Проведение». Если же свойство метаданных имеет значение Запретить, это означает, что такой документ вообще не должен про- водиться. Такая ситуация может использоваться для до- кументов: ♦ для которых нет необходимости в «индикации» того, что выполнены изменения в учетных механизмах, либо когда такие изменения документами не производятся; ♦ которые используются для интерактивного ввода дви- жений (например, документ Ручная операция). Поскольку в случае ручной операции нет разделения информации на исходную (информацию документа) и обработанную (информация, записываемая в регистр со ссылкой на документ), то информация сразу же вводится в регистр (рис. 7.35). Рис. 7.35. Ручная операция Для документов, у которых запрещено проведение, сис- темное поле Проведен при записи получает значение Ложь. Но во всех табличных полях, отображающих данные типа ДокунентСписок.<иня> или ЖурналДокунентовСписок.<имя>, пик- тограмма документов, у которых запрещено проведение, похожа на пиктограмму проведенных документов. Таким образом, система подсказывает пользователю, что больше никакой обработки для данных документов не требуется (рис. 7.36). Проведение форм, основным реквизитом которых явля- ется объект или список документа, учитывает значение свойства Проведение. Например, в командной панели фор- мы документа с запрещенным проведением система не создает кнопок с действиями «Провести» или «Отмена проведения». Рис. 7.36. Пиктограмма документа, для которого запрещено проведение
Однако система не запрещает попыток программной за- писи таких документов с проведением или отменой про- ведения. Не запрещает, но все подобные попытки реали- зует по схеме обычной записи документа. Свойство Оперативное проведение объекта метаданных Свойство Оперативное проведение объекта конфигурации Документ может иметь значение Разрешено или Запрещено. Для документов, у которых данное свойство имеет значе- ние Разрешено, — разрешено использование механизма оперативного проведения. Поскольку посредством документов производится реги- страция событий, причем на временной оси, то в общем случае положение проводимого документа может быть отнесено к прошлому, настоящему или будущему. Как правило, документы, относимые к прошлому, — реги- стрируют уже произошедшие события. Обычно такой способ регистрации называют «задним числом». В настоящем регистрируются события, которые только- только происходят. Такой способ регистрации называют «реальным временем». Кроме того, бывают ситуации, когда событие должно быть зарегистрировано в будущем. Например, при реше- нии задач планирования (рис. 7.37). Общие случаи регистрации событии Прошлое Событие уже произошло Регистрация задним числом Настоящее Будущее Событие совершается Событие будет совершено Регистрация реальным временем Регистрация в будущем Рис. 7.37. Общие случаи регистрации событий Оперативное проведение используется в ситуациях, ко- гда есть необходимость отличать проведение в реальном режиме времени (оперативное) от другого и выполнять различные действия для одного и другого режимов. Вариант использования данного механизма может, на- пример, включать разделение случаев (рис. 7.38): ♦ когда документ проводится в реальном времени и есть необходимость поучаствовать в проведении документа, помогая пользователю правильно ввести информацию; ♦ когда проведение документа просто отражает уже свер- шившийся факт и надо просто зафиксировать в учет- ных механизмах совершенное событие. Регистрации событий с точки зрения механизма ijnepoTv«Huro проведения Прошлое Событие уже произошло Настоящее Будущее Событие совершается Событие будет совершено Неоперативное проведение Оперативное проведение Неоперативное проведение Рис. 7.38. Оперативное и неоперативное проведение С точки зрения технологических средств, механизм опе- ративного проведения включает в себя: ♦ запрет проведения будущей датой; ♦ использование механизма оперативной отметки време- ни для принудительного изменения значения даты до- кумента в случаях, когда это требуется; ♦ передачу в обработчик события ОбработкаПроведения па- раметру Режим значения Оперативный системного пере- числения РежимПроведенияДокумента. В каких случаях можно намеренно не использовать меха- низм оперативного проведения? В любых, когда его использование не требуется логикой решаемой задачи. Например: ♦ когда нет нужды использовать разные алгоритмы про- ведения документов для оперативного или неоператив- ного режимов; ♦ когда не требуется при проведении документов обеспе- чивать однозначность их положения на временной оси посредством выдачи оперативных отметок времени. При отказе от использования механизма оперативного проведения главное не нарушить логику его использова- ния для других документов. Например, если для проведения документа Поступление товаров используется один и тот же алгоритм для любого вида проведения, — это еще не означает, что можно уста- новить запрет использования режима оперативного про- ведения. Его проведение будущей датой изменит данные оперативных итогов регистров именно будущей датой. То есть будет иметь место различие между актуальными итогами регистров и итогами на момент оперативной от- метки времени. Что может привести к нарушению логики использования механизма оперативного проведения для документов Реализация товаров. Свойство Удаление движений объекта метаданных Свойство Удаление движений объекта конфигурации Доку- мент может иметь значение Удалять движения автоматически или Не удалять движения автоматически. В первом случае система сама автоматически удаляет ста- рые записи движений, связанные с данным документом, в следующих ситуациях: ♦ при записи документа с проведением (старые записи удаляются, а новые формируются); ♦ при пометке документа на удаление (процесс, а не со- стояние); ♦ при отмене проведения документа (процесс, а не со- стояние). В случае же значения Не удалять движения автоматически для свойства Удаление движений автоматическое удаление дви- жений для этих ситуаций производиться не будет. Данное поведение системы разработчик конфигурации может ис- пользовать в случаях реализации нетиповой логики фор- мирования движений документов. Например, ответственность за правильность оформления заказов покупателей лежит на отделе продаж. Однако за- казы выборочно контролируется финансовым отделом. При обнаружении нарушений в назначении цен доку- мент снимается с проведения, что означает необходи-
мость дальнейшей его доработки. Но движения по реги- страм учета при этом удаляться не должны, чтобы не исключать данный заказ из учета вообще. Использование механизма оперативного проведения Рассмотрим, как работает механизм при интерактивном проведении из формы документа. Пусть документу как объекту метаданных разрешено оперативное проведение, и свойство ИспользоватьРежимПроведения расширения фор- мы документа имеет значение Авто. Запрет проведения будущей датой При проведении документа система, прежде всего, прове- рит положение даты документа относительно системной даты. Если дата документа соответствует дню позже системной даты, пользователь получит предупреждение: «Дата опе- ративно проводимого документа больше текущей. Доку- мент не может быть проведен оперативно». Проведение при этом не состоится. Если дата документа соответствует дню меньше систем- ной даты, документ будет проведен неоперативно. Если обе даты определяют один и тот же день, система принимает решение, что документ может быть проведен оперативно, то есть — реальным временем. Механизм оперативной отметки времени Для того чтобы документы располагались последователь- но и не попадали внутрь одной секунды, так как внутри одной секунды порядок следования будет неопределен, система выполняет автоматическое изменение времени документа. Дата документа получает значение оператив- ной отметки времени, которая рассчитывается системой по определенному алгоритму. Далее управление передается обработчику события Обра- ботка проведения, при этом параметр Режим получает зна- чение РежимПроведенияДокумента.Оперативный (рис. 7.39). Рис. 7.39. Использование оперативной отметки времени Механизм оперативной отметки времени позволяет при параллельной работе пользователей записывать опера- тивно проводимые документы с возрастающей последо- вательностью значений свойства Дата. Дата оперативно проводимого документа получается равной текущему системному времени системной даты или на секунду больше предыдущей выданной оперативной отметки вре- мени (рис. 7.40). Выдача отметки времени при оперативном проведении Рис. 7.40. Формирование оперативной отметки времени Если одновременно проводить оперативно несколько до- кументов, то результат работы данного механизма можно представить следующим образом (рис. 7.41). Выдача оперативной отметки времени Рис. 7.41. Использование оперативной отметки времени Механизм получения оперативной отметки времени един для сеанса работы с базой данных, то есть с момента вхо- да в базу первого пользователя и до выхода из нее послед- него. Выдача оперативной отметки времени не зависит от того, кому выдавалась последняя оперативная отметка времени, — этому пользователю или другому, при инте- рактивной работе или программно. Обеспечивается это тем, что последняя выданная оперативная отметка време- ни хранится в отдельной таблице до момента выхода из программы последнего пользователя (включая и режим работы «Конфигуратор»). Получение оперативной отметки времени может вы- полняться не только автоматически, но и разработчи- ком, посредством метода ПолучитьОперативнуюОтметкуВреме- ни () (листинг 7.5). Листинг 7.5. Получение оперативной отметки времени НоваяОперативнаяОтнеткаВренени = ПслучитьОперативнуюОтметкуВремениС);
Хочется обратить внимание на ограничение формирова- ния даты документа при интерактивном проведении до- кумента — «в пределах дня». Если в рамках одного дня уже выдана оперативная отметка времени со временем 23:59:59, то следующий, оперативно проводимый документ того же дня выдаст пользователю сообщение о невозмож- ности провести данный документ оперативно (в рамках того же дня). Сделано это потому, что дата документа мо- жет иметь юридическое значение. Поэтому принятие ре- шения о дате документа и режиме проведения документа в таких случаях отдается пользователю (рис. 7.42). Выдача оперативной отметки времени Рис. 7.42. Получение оперативной отметки времени следующим днем Налицо определенное ограничение, накладываемое сис- темой. Однако в практике ввода документов реальным временем столкнуться с ним почти невозможно. Для вос- произведения такой ситуации требуется, чтобы, напри- мер, 61 одновременно работающий пользователь в тече- ние последней минуты уходящего дня начал проведение оперативно проводимых документов. Если же все же подобная ситуации при автоматизации некого предприятия с ночным режимом работы имеет ме- сто, 61-й и последующие документы, скорее всего, можно уже датировать следующим днем либо обеспечить их воз- можность проведения в неоперативном режиме. Ведь не- возможность оперативного проведения еще не означает невозможность проведения вообще. Для работы механизмов оперативного проведения и по- лучения оперативной отметки времени в файл-серверной версии использования программы используется систем- ное время и системная дата компьютера пользователя, в клиент-серверном варианте использования программы — системное время и системная дата компьютера, на кото- ром находится сервер ЮПредприятия. Данное положение накладывает определенные требова- ния в отношении обеспечения синхронизации системных дат на компьютерах пользователей. Если при использовании файл-серверного варианта кто- либо из пользователей поменяет системную дату на сле- дующий день и проведет какой-нибудь документ опера- тивно, то система будет вынуждена выдать оперативную отметку времени, соответствующую завтрашнему дню. В результате для пользователей, работающих реальным временем, на сегодняшний день оперативные отметки времени уже не могут быть выданы. При попытках опера- тивного проведения документов будут получаться соот- ветствующие предупреждения. Чтобы восстановить нормальную работу механизма опе- ративного проведения, придется завершить все сеансы работы пользователей с базой данных, включая режим «Конфигуратор». Когда завершится сеанс использования базы данных, значение последней выданной оперативной отметки времени будет «сброшено». Далее следует обяза- тельно вернуть в нормальное положение системную дату «компьютера-нарушителя». При следующем сеансе рабо- ты с базой данных первое значение оперативной отметки времени будет соответствовать текущему системному времени текущей системной даты. Для клиент-серверного варианта использования програм- мы подобная ситуация приведет к попытке оперативного проведения документа с датой, большей системной даты компьютера, на котором установлен сервер ЮПредпри- ятия. В результате пользователь сразу получит сообще- ние об ошибке. Вышерассмотренное поведение системы характерно для ситуаций ввода документов реальным временем. Однако в процессе своей работы пользователи могут иницииро- вать и проведение из формы уже записанных и даже про- веденных ранее документов. Если это происходит с доку- ментом, дата которого соответствует тому же дню, что и системная дата, то пользователь перед началом проведе- ния должен будет выбрать режим проведения документа в специальном системном окне (рис. 7.43). Выбор режима проведения р Режим проведения----------- О Неопедлпчлюе проведение | Отмена 1| Справка | Рис. 7.43. Выбор режима проведения Дальнейшее поведение системы определяется ответом и соответствует описанному выше. Если же пользователь попытается инициировать прове- дение документа, ранее записанного с прошлой датой, но не проведенного, то получит системное предупреждение, позволяющее отказаться от проведения или провести до- кумент в неоперативном режиме (рис. 7.44). Рис. 7.44. Предупреждение о невозможности оперативного проведения документа Данные возможности реализованы в системе для того, чтобы помочь пользователю принять решение о выборе режима проведения для каждой конкретной ситуации. Кроме того, запись документов с проведением может еще вызываться и программно. В таком случае можно указать режим проведения в пара- метре «Режим проведения» (листинг 7.6). Листинг 7.6. Указание режима проведения документа Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Оперативный):
Тогда поведение системы в отношении установки даты документа и передачи параметра обработчику события Обработка проведения будет соответствовать оперативному проведению. Однако необходимо помнить, что дата документа при этом должна соответствовать дню системной даты компь- ютера. Иначе обработка проведения пойдет по схеме не- оперативного проведения. Проблемы выдачи оперативной отметки времени после 23.59.59 при программной записи документов с оператив- ным проведением нет. Поскольку программное проведе- ние означает вмешательство неких алгоритмов в ход фор- мирования, заполнения и записи документов, то в данном случае может оказаться, что некому реагировать на пре- дупреждение о невозможности оперативного проведения в рамках того же дня. Поэтому система для подобного до- кумента просто сформирует дату на секунду большую по- следней оперативной отметки времени. Если потребуется не допустить формирования и проведения документов с датой будущего дня, это можно обеспечить программно, в составе соответствующих обработчиков. Передача значения Оперативный в параметр Режим обработчика события ОбработкаПроведения Итак, при оперативном проведении документов система позволяет добиться расстановки документов в идеальной хронологической последовательности (каждое событие зарегистрировано на момент его отражения в учете) и, кроме того, известить об этом обработчик проведения. То есть с точки зрения отражения документа в учете сам ме- ханизм оперативного проведения не выполняет никаких действий, он только передает параметр в обработчик про- ведения. Что это дает разработчику? Дает возможность отличать ситуации проведения документов реальным временем от иных ситуаций. А это уже впоследствии может быть ис- пользовано для решения прикладных задач. Может использоваться следующая градация действий при проведении документов: ♦ при оперативном проведении — помощь пользователю посредством контроля возможности операции и пра- вильности ее оформления, после этого — отражение ее в учетных механизмах; ♦ при неоперативном проведении — отражение в учетных механизмах факта свершившегося события без всякой обработки. То есть, например, при проведении документа Реализа- цияТоваров алгоритм обработки оперативного проведения сначала будет проводить контроль остатков (сравнивая количество, указанное в документе, с количеством остат- ка из актуальных итогов соответствующего регистра). В случае нехватки товара на складе (а значит, невозмож- ности отгрузки), пользователь будет получать соответст- вующее сообщение, и документ проводиться не будет. В случае же если пользователь проводит документ, соот- ветствующий уже произошедшему событию (неоператив- но), нужда в контроле остатка отпадает. Например, вчера отключилось электричество, и не успели отразить в про- грамме операцию отгрузки двух холодильников со скла- да. Вводя сегодня данные о событии вчерашней отгрузки, контролировать возможность данной операции уже бес- смысленно, поскольку холодильники уже отгружены (листинг 7.7). ПРИМЕЧАНИЕ Пример алгоритма проведения документа РеализацияТова- ров содержится в демонстрационной конфигурации «Хра- нение информации и учет движения средств», которая на- ходится на прилагаемом компакт-диске. Листинг 7.7. Пример процедуры ОбработкаПроведения Процедура 0бработкаПроведения(0тказ, Режим) Если Режим = РежимПроведенияДокумента.Оперативный Тогда // Получить данные для выполнения контроля остатка Запрос = Новый Запрос; Запрос.Текст = ” ВЫБРАТЬ ТаблицаДокумента.Номенклатура, СУММА(ТаблицаДокумента.Количество) КАК Количество, ТоварыНаСкладахОстатки.КоличествоОстаток, СУММА(ТаблицаДокумента.Сумма) КАК Сумма ИЗ Документ.РеализацияТоваров.Состав КАК ТаблицаДокумента ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах. Остатки( Номенклатура В (ВЫБРАТЬ РАЗЛИЧНЫЕ РеализацияТоваровТовары.Номенклатура ИЗ Документ. РеализацияТоваров. Состав КАК РеализацияТоваровТовары ГДЕ РеализацияТоваровТовары.Ссылка = &ТекущийДокумент) И Склад = &Склад) КАК ТоварыНаСкладахОстатки ПО ТаблицаДокумента.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура ГДЕ ТаблицаДокумента.Ссылка = &ТекущийДокумент СГРУППИРОВАТЬ ПО ТаблицаДокумента.Номенклатура. ТоварыНаСкладахОстатки.КоличествоОстаток"; Запрос.УстановитьПараметрС'ТекущийДокумент", Ссылка); Запрос.УстановитьПараметр("Склад”. Склад); Результат = Запрос.ВыполнитьО; Выборка = Результат. ВыбратьО; Пока Выборка.Следующий() Цикл Если НЕ Выборка.Номенклатура.Услуга Тогда // Выполнить контроль остатка Остаток = ?(Выборка.КоличествоОстаток = Null, О, Выборка.КоличествоОстаток); Нехватка = Выборка.Количество - Остаток; Если Нехватка > 0 Тогда Сообщить("Нехватка товара " + СокрЛП(Выборка.Номенклатура) + ” + Нехватка): Сообщить("Реализация товаров " + Номер + ' от ” + Дата + " не проводится!”); // Отменить проведение документа Отказ = Истина; КонецЕсли; Если Не Отказ Тогда // Сформировать движения по регистру
11 ТоварыНаСкладах (расход) Движение = Движения.ТоварыНаСкладах. ДобавитьО; Движение.ВидДвижения « ВидДвиженияНакопления.Расход; Движение.Период = Дата; Движение.Номенклатура = Выборка.Ноненклатура; Движение.Склад = Склад; Движение.Количество = Выборка Количество; КонецЕсли, КонецЕсли; Если Не Отказ Тогда // Сформировать движения по регистру Продажи Движение = Движения.Продажи.Добавить(); Движение.Период = Дата; Движение.Номенклатура = Выборка.Ноненклатура; Движение.Контрагент = Контрагент; Движение.Количество = Выборка.Количество; Движение.Сумма = ?(Выборка.Количество = 0. 0, Выборка.Сумма): Движение Цена = ?(Выборка.Количество = 0, 0 Выборка Сумма / Выборка.Количество): КонецЕсли; КонецЦикла: Иначе // При неоперативном проведении - просто отразить // отгрузку в учетных механизмах Для Каждого ТекСтрокаСостав Из Состав Цикл // Сформировать движения по регистру // ТоварыНаСкладах (расход) Если НЕ ТекСтрокаСостав.Номенклатура.Услуга Тогда Движение = Движения.ТоварыНаСкладах ДобавитьО; Движение.ВидДвижения = ВидДвиженияНакопления.Расход; Движение.Период = Дата: Движение.Номенклатура = ТекСтрокаСостав.Номенклатура; Движение.Склад = Склад; Движение.Количество = ТекСтрокаСостав.Количество; КонецЕсли; // Сформировать движения по регистру Продажи Движение = Движения Продажи.ДобавитьО; Движение.Период = Дата; Движение.Номенклатура = ТекСтрокаСостав Номенклатура; Движение.Контрагент = Контрагент; Движение.Количество = ТекСтрокаСостав.Количество; Движение.Сумма = ?(ТекСтрокаСостав.Количество = 0, 0, ТекСтрокаСостав.Сумма); Движение.Цена = ?(ТекСтрокаСостав.Количество = 0, 0, ТекСтрокаСостав.Цена); КонецЦикла; КонецЕсли; КонецПроцедуры ПРИМЕЧАНИЕ В запросе используется группировка по полям Номенклату- ра и КоличествоОстаток для того, чтобы обеспечить кор- ректность контроля остатка при наличии «дублей строк» (один товар — дважды в документе). Далее, в цикле пере- бора выборки результата запроса по каждой номенклатур- ной позиции, не относящейся к услугам, вычисляется Не- хватка. В случае положительного значения нехватки- проведение документа отменяется. Если отмены проведе ния не произошло, формируются движения по нужным ре- гистрам. При оперативном проведении выполняется контроль достаточности остатка товаров на складе. Для этого в за- просе соединением получается таблица с данными доку- мента и данными итогов регистра ОстаткиТоваровНаСкла- дах. При неоперативном проведении никаких контрольных действий не выполняется, просто в цикле перебора строк табличной части документа формируются движения по нужным регистрам. В данном случае, в отличие от опера- тивного проведения, контролировать дубли строк не нужно. В данном примере, кстати, в процессе выполнения кон- трольных операций при оперативном проведении более «плотно» используются возможности, предоставляемые именно механизмом оперативного проведения. Поскольку контроль, как правило, обусловлен состояни- ем учетных показателей, их необходимо при проведении документа получать на момент времени, соответствую- щий документу Если каждый документ, формирующий движения в коли- чественном учете, будет проводиться с поддержкой меха- низма оперативного проведения, и движения его будут датироваться именно датой документа, то можно быть уверенным в двух фактах; не будет ситуации, когда два документа претендуют на одно и то же время (механизм выдачи оперативной от- метки времени распределит их с интервалом в секунду); текущий проводимый документ находится на временной оси всегда позже последнего оперативно проведенного документа. А это важно при получении остатков из регистров. Так как кроме движений и помесячных остатков, таблицы регист- ров хранят еще подсчитанные итоги, актуальные на мо- мент времени последней записи в них. И если мы уверены, что «за» оперативной отметкой времени не было движе- ний, то тогда для получения актуальных данных контроля остатка можно использовать виртуальную таблицу остат- ков регистра без указания параметра Период (или с указа- нием значения Неопределено в качестве его значения). Данная операция будет выполняться быстрее, нежели в качестве параметра передать значение момента времени документа. Потому что при отсутствии параметра систе- ма не будет пытаться обращаться к таблице записей реги- стра для «досчета» остатков до нужной временной точки, а сразу возьмет данные последних актуальных итогов из таблицы итогов данного регистра (рис. 7.45).
Но нужно понимать, что для обеспечения корректности использования механизма оперативного проведения при данном алгоритме работы, необходимо обеспечить, чтобы никакими способами не были сформированы движения в будущем. Иначе использование актуальных итогов реги- стров в обработке проведения будет невозможно (вернее, придется рассчитывать регистры на момент времени до- кумента, но тогда какой смысл в оперативной работе, если при этом итоги регистров не будут актуальны на мо- мент оперативно проводимого документа). В основном это обеспечивается системой: стандартные команды форм не позволяют пользователю оперативно проводить документы будущей датой и не предлагают в таких случаях проводить документы неоперативно. Кро- ме того, при выполнении попытки программной записи с проведением в оперативном режиме (листинг 7.8) сис- тема сначала выполняет проверку положения даты доку- мента относительно дня оперативной отметки времени. Листинг 7.8. Оперативное проведение документа Записать(РежинЗаписиДокунента.Проведение, РежимПроведенияДокумента.Оперативный); И если документ пытаются записать в будущем, выдается соответствующее предупреждение о невозможности вы- полнения данной операции. Но вот программное неоперативное проведение докумен- тов система не запрещает. Кроме того, при формировании движений, возможно, добиться ситуации, чтобы Период движения не совпадал со значением Дата документа. То есть, в принципе, движения могут быть сформированы будущей датой. Ответственность за недопущение подоб- ных фактов — на разработчике. В завершение хотелось бы отметить, что использование механизма оперативного проведения может быть состав- ной частью более сложных алгоритмов. Например, для того, чтобы во время активного ввода информации сокра- тить количество действий по отражению документов в учете (а значит — обеспечить большую скорость проведе- ния документов), часть этих действий не выполняются при неоперативном проведении, а часть — относятся на действия, выполняемые регламентными обработками. Стратегия отражения документов в учетных механизмах выглядит тогда следующим образом: ♦ при оперативном проведении — помощь пользователю посредством контроля возможности операции и пра- вильности ее оформления, отражение совершаемого события только в механизмах, обеспечивающих кон- трольные функции при оперативном проведении дру- гих документов; ♦ при неоперативном проведении — отражение факта свершившегося события без всякой обработки, и толь- ко в учетных механизмах, обеспечивающих контроль при оперативном проведении; ♦ при проведении специальной регламентной обработ- ки — отдельно для каждого зарегистрированного собы- тия: контроль возможности и правильности его оформ- ления, отражение данного события во всех оставшихся учетных механизмах. Примером подобного использования механизма опера- тивного проведения можно считать задачу проведения документа, отражающего реализацию товаров со склада не только в количественном, но и в количественно-стоимо- стном учете. Постановка задачи может быть следующей: при реализации товаров со склада реальным временем (оперативное проведение) необходимо предварительно выполнить ряд проверок правомерности этой операции (наличие достаточного остатка на складе, контроль пред- оплаты со стороны покупателя). Эти проверки и сама регистрация факта отгрузки в количественном учете то- варов на складе выполняются в обработке проведения до- кумента. В случае же когда требуется проведение документа реа- лизации задним числом (неоперативное проведение) - это означает необходимость отражения уже свершивше- гося факта. Тогда не требуется проверять предоплату и наличие товаров на складе, поскольку товар уже отгру- жен клиенту. Нужно просто отразить факт отгрузки в ко- личественном учете товаров на складе при проведении документа. Окончательное же отражение произошедших событий в механизме количественно-стоимостного учета товаров на складе производится посредством отдельной регламент- ной обработки, которая будет выполняться не в период активного ввода первичной информации, а впоследствии. При ее выполнении будут собраны все необходимые дан- ные для всех еще не полностью отраженных событий, проведены все необходимые проверки и расчеты и припи- саны необходимые движения к документам реализации. Периодичность выполнения этой обработки определяет- ся пользователем. Например, чтобы быть достаточной для получения регламентной отчетности (рис. 7.46). Проведение документа "РеализацияТоваров" Нет активной работы пользователей Проведение регламентной обработки документов Регламентное формирование движении Проведение всего комплекса проверок и расчетов Оформление реализации в количественно-стоимостном учете Рис. 7.46. Проведение документа Реализация товаров В случаях отказа от использования оперативного прове- дения разработчику достаточно лишь установить свойст- ву Оперативное проведение документа как объекта метадан- ных значение — Запретить. И тогда все необходимые элементы работы механизма проведения придется реали- зовывать самостоятельно. То есть, например, при про- ведении документа предварительно проводить контроль даты документа, контроль возможности проведения до- кумента и т. д.
Особенности работы формы документа Если основной реквизит формы имеет тип значения Доку- иентОбъект.<имя>, то для данной формы действует рас- ширение формы документа. Посредством его решаются вопросы специфичной функциональности формы доку- мента. Расширение помогает обрабатывать различные ко- манды пользователя, выполнять предварительные про- верки и другие сервисные действия. Кроме того, действие расширения формы документа рас- пространяется и на механизмы записи и проведения доку- мента. При этом не важно, была вызвана запись документа интерактивными действиями пользователя в форме доку- мента, или средствами языка — методом ЗаписатьВФормеО. Рассмотрим ряд примеров работы этих механизмов. Установка даты документа при открытии формы При открытии формы нового документа, если дата доку- мента изначально не установлена, то есть, равна значе- нию даты по умолчанию, то происходит установка дате документа значения рабочей даты. Причем время документа будет установлено в зависимо- сти от следующих настроек: если рабочая дата равна те- кущей дате компьютера (дни, без времени) и свойство АвтоВремя расширения формы документа имеет значение НеИспользовать, то время документа будет установлено по текущему времени компьютера. В остальных случаях дате документа присваивается время начала дня (00:00:00) (рис. 7.47). Установка даты нового документа при открытии формы Рис. 7.47. Установка даты нового документа при открытии формы документа Установка даты нового документа при записи нового документа в форме При записи документа в режиме оперативного проведе- ния значение даты документа устанавливается согласно выданной оперативной отметки времени. Тут настройки свойств расширения формы роли не играют. Но при неоперативном проведении документа, если вре- мя документа «нулевое» (0:00:00), оно будет изменено согласно настроек свойства АвтоВремя (рис. 7.48). Исклю- чение — когда АвтоВремя имеет значение НеИспользовать. Тогда время документа не меняется. Установка даты нового Рис. 7.48. Установка даты нового документа при записи документа в форме Запрет интерактивной записи проведенного документа без проведения (перепроведения) Запрет интерактивной записи документа без проведения (перепроведения) используется, что бы не создавалась, например, такая ситуация: сначала документ реализации был заполнен и проведен, при проведении сформированы движения по регистру, с указанием количества, соответ- ствующему количеству в документе. После этого пользо- ватель исправил данные документа и сохранил без прове- дения (рис. 7.49). Документ "РализацияТоваров"- Товар: Яблоки Количество: 10 Движения по регистру “Т »ыН к (МДАм”: Документ ''РализацияТоваров*': Товар: Яблоки Количество; 100000 Движения регистра "Т лНдСмаеддм Вид движения: Расход Товар: Яблоки Количество: 10 1. Заполнение документа, запись с проведением, движений по регистру Вид движения; Расход Товар: Яблоки Количество; 10 2. Внесение исправлений в документ, запись без проведения документа Рис. 7.49. Название рисунка В результате таких манипуляций данные в документе бу- дут записаны новые, а данные в движениях по регистру останутся от прошлого проведения документа, то есть ни- как текущим данным документа они соответствовать не будут.
Предотвращение подобных ситуаций достигается за счет установки свойства расширения формы документа ПриЗа - писиПерепроводить в значение Истина. Тогда отказ в обработ- ке проведения приведет к откату транзакции — документ не будет и перезаписан. Установка режима проведения Для случаев, когда документу запрещено оперативное проведение — конечно же, никаких вариантов подбора ре- жима проведения быть не может, — Неоперативный. Для случаев, когда оперативное проведение разрешено, сам выбор варианта поведения должен быть обусловлен логикой применения данного механизма. То есть в неко- торых ситуациях система должна выбирать режим жест- ко, в некоторых — право выбора режима можно предоста- вить пользователю. Для этого разработчик обладает рядом возможностей, предоставляемых системой посред- ством разграничения прав и расширениями формы доку- мента. При записи документа в форме установку режима проведе- ния документа выполняет расширение формы документа. Для реализации данного функционала система использу- ет вариант (Авто, Оперативный, Неоперативный, Запрашивать), указанный в качестве значения свойства ИспользоватьРе- жииПроведения расширения формы документа. Вариант Авто Вариант «Авто» устанавливается посредством выбора значения Авто у свойства ИспользоватьРежииПроведения рас- ширения формы документа. При использовании данного варианта, в зависимости от ситуации и настроек, происходит первичный подбор ре- жима проведения из вариантов Оперативный, Неоперативный, Запрашивать. Если у пользователя нет права на неоперативное прове- дение, подбирается вариант Оперативный. Если документ не проведен, так же подбирается вариант Оперативный. Для ранее проведенного документа происходит проверка положения даты документа относительно системной даты. Если дата документа (без учета времени) равна систем- ной дате, то система предоставляет возможности обеспе- чить выбор оперативного проведения документа. Если время документа больше системной даты, — это означает автоматический выбор режима Оперативный, если меньше (то есть документ на хронологической оси находится раньше оперативной отметки времени) — пользователю предоставляется право выбора варианта проведения, — подбирается режим Запрашивать. Если дата документа (без учета времени) больше систем- ной даты, пользователю выдается предупреждение Дата оперативно проводимого документа больше текущей. Документ не может быть проведен! Если дата документа (без учета времени) меньше систем- ной даты — выбирается вариант проведения Неоперативный (рис. 7.50). Вариант Оперативный Вариант «Оперативный» устанавливается посредством выбора значения Оперативный у свойства ИспользоватьРежии- Проведения расширения формы документа или выбирается согласно вышеприведенного алгоритма после режима Авто. Вариант подбора режима проведения "Авто" Рис. 7.50. Использование режима проведения Авто В данном варианте, если дата документа (без учета време- ни) меньше системной даты, поведение системы опреде- ляется наличием права на неоперативное проведение у пользователя. Если он этим правом не обладает — выда- ется предупреждение о том, что Дата оперативно проводи- мого документа меньше текущей. Документ не может быть про- веден! и запись документа отменяется. Если он этим правом обладает, система предлагает пользователю ис- пользовать неоперативный режим проведения. Если пользователь соглашается, производится запись с неопе- ративным режимом проведения документа, если отказы- вается, запись документа не производится. Если дата документа (без учета времени) равна систем- ной даты, производится запись документа с оперативным проведением. Если дата документа (без учета времени) больше систем- ной даты, выдается предупреждение о том, что Дата опера- тивно проводимого документа больше текущей. Документ не может быть проведен! и запись документа отменяется (рис. 7.51). Вариант подбора режима пре i ч.-дьм<м “Оперативный" Рис. 7.51. Использование режима проведения Оперативный
Вариант Запрашивать Вариант «Запрашивать» устанавливается посредством выбора значения Запрашивать у свойства ИспользоватьРежим- Проведения расширения формы документа или выбирается системой после режима Авто. Поведение системы при этом варианте определяется, пре- жде всего, положением даты документа (без времени) по отношению к системной дате. При равенстве этих дат далее проверяется, имеет ли пра- во пользователь проводить документ неоперативно. Если пользователь такого права не имеет, система проводит данный документ в оперативном режиме. Если такое право есть — пользователю выдается диалог с режимом выбора проведения (рис. 7.52). Вариант га режима проведения "1 «тр>1милть". Дата документа (без учета времени) равна системной дате Рис. 7.52. Использование режима проведения Запрашивать при условии равенства даты документа и системной даты Если дата документа (без учета времени) меньше систем- ной даты — поведение системы определяется опять же наличием права на неоперативное проведение у пользо- вателя. Если пользователь таким правом не обладает — выдается предупреждение: Дата оперативно проводимого документа меньше текущей. Документ не может быть проведен! и запись документа отменяется. Если обладает — произ- водится запись с неоперативным режимом проведения документа (рис. 7.53). Если дата документа (без учета времени) больше систем- ной даты, система не позволяет проводить документ опе- ративно. Поэтому если права неоперативного проведения нет, сразу выдается предупреждение о невозможности проведения, и запись документа не производится. Анало- гично, если такое право есть, но после выдачи диалога с режимом выбора проведения пользователь выбрал Опера- тивный вариант. Если же пользователь выбирает режим Неоперативно, про- изводится запись с неоперативным режимом проведения (рис. 7.54). Вариант подбора режима проведения "Залрашшть”. Дата документа (без учета времени) больше системной даты Рис. 7.54. Использование режима проведения Запрашивать при условии, что дата документа больше системной даты Вариант Неоперативный Вариант «Неоперативный» устанавливается посредством выбора значения Неоперативный у свойства ИспользоватьРе- жимПроведения расширения формы документа или выбира- ется системой после режима Авто. При использовании данного варианта запись документа из формы всегда производится в неоперативном режиме. Причем наличие или отсутствие права пользователя на неоперативное проведение не контролируется (рис. 7.55). Вариант подбора режима проведения "Неоперативный" Запись документа в режиме 1-ЕОПЕРДТИВНОГО проведения Рис. 7.55. Использование режима проведения Неоперативный Вариант подбора режима «догний 'Загфлыжъи: Дата документа (без учета времени) меньше системной даты Рис. 7.53. Использование режима проведения Запрашивать при условии, что дата документа меньше системной даты Прочие функции Кроме выбора режима проведения и установки даты до- кумента расширение формы документа реализует также следующий функционал: ♦ при открытии формы проведенного документа, если у пользователя нет права Интерактивное изменение дан- ных, — форма переводится в режим ТолькоПросмотр; ♦ при открытии формы документа, у которого есть таб- личные поля, связанные с движениями основного рек- визита (объекта документа), эти движения автоматиче- ски считываются из базы данных и отображаются;
♦ при записи в форме (даже если и программной — по- средством ЗаписатьВФормеО) система выполняет провер- ку прав на интерактивное проведение или интерактив- ную отмену проведения. Ввод на основании Ввод на основании является одним из вариантов реализа- ции заполнения нового объекта данными другого объек- та. Чаще всего это действие применяется для документов, но может использоваться для ряда других объектов (Справочники, Планы видов характеристик, Планы сче- тов, Планы расчетов, Планы обменов, Бизнес-процессы, Задачи). Причем вводится в общем случае — любой объ- ект на основании любого. Механизм работы ввода на основании включает в себя формирование нового объекта и вызов обработчика собы- тия ОбработкаЗаполнения создаваемого объекта. Договор N112/09 Владелец: ООО "Мистраль" Вид договора: Купли-продажи Срок поставки: 12.12.2005 г. Табличная часть “Спецификация" Генератор МХО123 3 Пульт ЕхТУб_________ 1 Станция Д6 1 Заказ покупателя N 389 Контрагент: ООО "Мистраль" Договор: 112/09__________ Размещение. Резерв Срок поставки: 12.12.2005г. Табличная часть “Товары" Г енератор МХО123 3 Пульт ExTY6 1 Рис. 7.57. Указание объектов, являющихся основанием для ввода ♦ в автозаполняемых командных панелях форм, у кото- рых основным реквизитом является объект документа ЗаказПокупателя и объект элемента справочника Догово- ра, а так же в командных панелях, связанных с таблич- ными полями списков данных объектов, появляется но- вое подменю ВвестиНаОсновании (рис. 7.58) с действием РеализацияТоваров. Если же данное подменю уже было, то к нему просто добавится указанное действие. Е Рис. 7.58. Кнопка Ввести на основании Реализация товаров Ввод на • сновании Ввод на < сновании Контрагент: ООО "Мистраль" Договор: 112/09 Склад: Срок поставки: 12.12.2005г. Табличная часть “Товары" Г енератор МХО123 3 Пульт ЕхТУб 1 Рис. 7.56. Пример использования ввода на основании Например, необходимо реализовать заполнение докумен- та, реализующего отгрузку товаров, на основании объ- екта, содержащего информацию о том, что именно надо отгрузить. Исходным объектом, применяемым в конкрет- ном случае, может быть, например, документ ЗаказПо- купателя или элемент справочника ДоговорыКонтрагентов (рис. 7.56). Ввод на основании может быть организован за счет ин- терфейсных средств или программно. Интерактивный ввод на основании Интерфейсные возможности реализуются за счет соот- ветствующих расширений форм и элементов форм. Кро- ме того, необходимо, чтобы в свойствах объекта конфигу- рации было указано, на основании каких объектов он может вводиться (рис. 7.57). В результате: ♦ разработчику будет доступен вызов конструктора ввода на основании для документа РеализацияТоваров; Посредством конструктора ввода на основании (или без его использования) в составе модуля объекта документа РеализацияТоваров может быть реализована процедура — обработчик события ОбработкаЗаполнения. Поскольку параметром данной процедуры система пере- дает ссылку на объект-источник, то у разработчика появ- ляется возможность заполнить данные документа инфор- мацией объекта-источника. Для нашего примера ее текст может быть таким (листинг 7.9). Листинг 7.9. Пример процедуры ОбработкаЗаполнения Процедура ОбработкаЗаполнения(Основание) Если ТипЗнч(Основание) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда // Заполнить шапку Договор = Основание.Договор; Контрагент = Основание. Контрагент; ОснованиеРеализации = Основание.Ссылка: // Заполнить табличную часть данными // табличной части основания Для Каждого ТекСтрокаСостав Из Основание.Состав Цикл НоваяСтрока = Состав. ДобавитьО; НоваяСтрока.Количество = ТекСтрокаСостав.Количество; НоваяСтрока.Номенклатура = ТекСтрокаСостав.Номенклатура; НоваяСтрока.Сумма = ТекСтрокаСостав.Сумма; НоваяСтрока.Цена = ТекСтрокаСостав.Цена; КонецЦикла; ИначеЕсли ТипЗнч (Основание) = Тип("СправочникСсылка. ДоговорыКонтрагентов") Тогда // Заполнить шапку
Контрагент = Основание.Владелец: ДатаПоставки = Основание.ДатаПоставки; Договор = Основание.Ссылка: ОснованиеРеализации = Основание.Ссылка: // Заполнить табличную часть данными // табличной части основания Для Каждого ТекСтрокаСпецификация Из Основание.Спецификация Цикл НоваяСтрока = Состав.ДобавитьО: НоваяСтрока.Количество = ТекСтрокаСпецификация.Количество: НоваяСтрока.Цена = ТекСтрокаСпецификация.Количество: НоваяСтрока.Номенклатура = ТекСтрокаСпецификация.Номенклатура: НоваяСтрока.Сумма = ТекСтрокаСпецификация.Сумма; КонецЦикла: КонецЕсли; КонецПроцедуры ПРИМЕЧАНИЕ Данный пример приведен в демонстрационной конфигу- рации «Хранение информации и учет движения средств», которая находится на прилагаемом компакт-диске. В результате если пользователь в соответствующей фор- ме выберет из подменю ВводНаОсновании действие Реали- зацияТоваров, то произойдет создание нового документа и вызов обработчика события ОбработкаЗаполнения. То есть произойдут следующие события (рис. 7.59). ВНИМАНИЕ Событие ПриУстановкеНовогоНомера вызывается, только если для данного документа назначена автонумерация. Кроме того, произойдет заполнение значения свойства расширения формы документа ПараметрОснование. Ему так- же будет присвоено значение ссылки на объект источник. Это свойство можно активно использовать в обработчи- ках событий формы. Например, требуется запретить интерактивный ввод до- кумента РеализацияТоваров на основании документа За- казПокупателя, если у последнего не заполнен контрагент. Ввод на основании Контекст формы вводимого документа <Г1ере дОткрытием > <ОбработкаЗаполнения> <ПриУстановкеНовогоНомера > <ПриОткрытии> Рис 7.59. Последовательность событий при интерактивном вводе на основании Для реализации этой задачи достаточно написать проце- дуру обработчика открытия формы документа Реализа- цияТоваров, например, следующим образом (листинг 7.10). В случае выполнения условий, то есть если объектом-ис- точником будет документ ЗаказПокупателя с невыбранным контрагентом, произойдет выдача предупреждения поль- зователю и отказ от открытия формы нового документа, вводимого на основании. Листинг 7.10. Пример процедуры ПередОткрытием Процедура ПередОткрытием(Отказ, СтандартнаяОбработка) Если ТипЗнч(ПараметрОснование) = Тип("ДокументСсылка.ЗаказПокупателя”) Тогда Если ПараметрОснование.Контрагент.ПустаяО Тогда ПредупреждениеГНе заполнено поле ’Контрагент’!"): Отказ = Истина; КонецЕсли; КонецЕсли; КонецПроцедуры Программный ввод на основании Программный способ заполнения документа данными из других объектов реализуется посредством метода Запол- нить(). Например, если в переменной СсылкаНаИсходныйОбъект содержится ссылка на некий заказ покупателя или на не- кий договор контрагента, то программное создание до- кумента РеализацияТоваров с заполнением данных из ис- ходного объекта и последующая его запись могут быть выполнены следующим образом (листинг 7.11). Листинг 7.11. Пример создания нового документа на основании НовыйДокунент = Документы.РеализацияТоваров. СоздатьДркументО; НовыйДокумент.Дата = ТекущаяДатаО: НовыйДокунент.Заполнить(СсылкаНаИсходныйОбъект); НовыйДокунент.ЗаписатьО; Сначала новый документ будет создан в оперативной па- мяти, заполнено свойство Дата текущим временем, далее посредством метода Заполнить О управление будет переда- но обработчику события ОбработкаЗаполнения. Обратите внимание: в результате применения программ- ного заполнения документов контекст формы не задейст- вуется (рис. 7.60). Заполнение <ОбработкаЗаполнения> <ПриУстановкеНовогоНомера> Рис. 7.60. Последовательность событий при программном вводе на основании Событие ПриУстановкеНовогоНомера, опять же, произойдет, только если для документа используется автонумерация. После заполнения документ записывается. Причем в со- ответствии с установкой параметров метода ЗаписатьО по умолчанию — в данном примере документ будет записан без проведения. Получение документов, введенных на основании Кроме того, при решении прикладных задач иногда воз- никает необходимость получения всех документов, свя- занных с неким исходным объектом.
Например, в рамках некого договора был оформлен За- казПокупателя, на основании документа ЗаказПокупателя был введен РеализацияТоваров, на основании Реализации- Товаров были введены СчетФактура и ПриходныйКассовый- Ордер». Впоследствии часть товара было возвращено, то есть на основании РеализацииТоваров был введен Возврат- ТоваровОтПокупателя. Кроме того, аналогичная цепочка документов может быть оформлена в отношении другого ЗаказПокупателя (рис. 7.61). Рис 7.61. Цепочка документов, введенных на основании Поскольку все события происходили в рамках договор- ных отношений одного договора, пользователю может оказаться необходимо увидеть все документы, касающие- ся этого договора, в одном списке. Для реализации этого в состав всех объектов, которые нужно отобрать по данному договору, можно включить реквизит, ссылающийся на данный договор. Пусть он на- зывается Договор. Далее для реализации отбора подчиненных договору до- кументов можно использовать запросы или, например, критерии отбора. КритерийОтбора — объект конфигурации, представляющий собой одну из составляющих механизма отборов инфор- мации. Критерии отбора позволяют разработчику реали- зовать предопределенные правила отборов информации за счет создания дополнительных индексов в таблицах объектов в базе данных. Для вышеприведенного примера можно создать новый критерий отбора ДокументыПоДоговору. Тип критерия отбора указывается в соответствии с типом данных, по которым будут отбираться объекты. То есть в данном примере — СправочникСсылка.ДоговораКонтрагентов, но в общем случае — может быть и составным. В составе критерия отбора указываются реквизиты объек- тов, по которым нужно будет производить отбор. В данном случае это реквизит Договор документов ЗаказПокупателя, РеализацияТоваров, СчетФактура, ПриходныйКассовыйОрдер, ВозвратТоваровОтПокупателя. В результате для таблиц объектов (в данном случае для таблиц документов) в базе данных будут созданы индек- сы по полям, хранящим значения этих реквизитов. Обратите внимание: в состав критерия отбора можно выбрать несколько реквизитов одного и того же доку- мента или несколько реквизитов табличной части доку- мента. Согласно информации о типе критерия отбора система создает в подменю Перейти форм списка или форм объек- тов команды перехода для вызова формы критерия отбо- ра. В приведенном выше примере такие команды будут созданы в подменю Перейти формы списка и форы эле- мента справочника ДоговорыКонтрагентов. Если же требуется обеспечить переходы другими средст- вами, то это можно реализовать программно. Достаточно лишь иметь в наличии ссылку на значение отбора. То есть для вышеприведенного примера критерия отбора и переменной СсылкаНаЗначениеОтбора это может быть реализовано так (листинг 7.12). Листинг 7.12. Пример использования критерия отбора ФормаОтбора = КритерииОтбора.ДокументыПоДоговору. ПолучитьФормуО; ФормаОтбора.ПаранетрОтборПоЗначению = СсылкаНаЗначениеОтбора; ФормаОтбора.Открыть(); Сначала получение формы нужного критерия отбора, да- лее установка значения свойству ПараметрОтборПоЗначению расширения формы критерия отбора и открытие формы. Кроме того, может возникнуть потребность программно- го получения коллекции подчиненных документов (или других объектов), то есть соответствующих отбору по оп- ределенному значению. Это можно реализовать посред- ством объектной техники (листинг 7.13) или посредством запроса (листинг 7.14). Листинг 7.13. Пример использования объектной техники МассивСсылокНаОбъекты = КритерииОтбора.ДокументыПоДоговору.Найти( СсылкаНаЗначениеОтбора); Листинг 7.14. Пример использования запроса ВЫБРАТЬ ДокументыПоДоговору.Ссылка ИЗ КритерийОтбора.ДркументыПоДрговоруС&Значение) КАК ДокументыПоДоговору В качестве значения параметру Значение необходимо бу- дет передать ссылку на значение отбора. Для функционирования конкретного критерия отбора в базе данных для исходных таблиц были созданы соот- ветствующие индексы. Поэтому обеспечивается доста- точно быстрая работа этого механизма. Однако при отображении данных конкретного отбора же- лательно избегать ситуаций, когда количество отобран- ных по значениям критерия отбора объектов очень вели- ко. Дело в том, что критерий отбора не поддерживает механизм динамического считывания данных. То есть со- ответствующие данные считываются полностью. Специальные случаи использования документов. Ручная операция Кроме типовой стратегии использования документов в конфигурации, когда движения формируются при про-
ведении документов, система допускает и другие вариан- ты участия документов в учетных механизмах. Так, в ча- стности, допускается и программное и интерактивное изменение записей регистров, в том числе и подчиненных регистратору. Причем от регистратора может использо- ваться только ссылка для определения отбора по регист- ратору. Остальное может быть выполнено вообще без ис- пользования данных документа. Такая возможность не нарушает общую модель использо- вания документов и регистров, а лишь дополняет ее для решения заранее не предусмотренных задач. Например, когда пользователям нужно предоставить возможность отражения в учетных механизмах операций, для которых в конфигурации не предусмотрено специальных доку- ментов (в бухгалтерском учете их обычно называют «руч- ными операциями»). Либо когда при регистрации события пользователь заполняет ровно те поля, которые требуется заполнять в регистре. И ввод этой учетной информации не требует никакой дополнительной обработки. Рассмотрим подробнее возможность интерактивного фор- мирования движений. Например, в рамках демонстрационной конфигурации «Хранение информации и учет движения средств», кото- рая находится на прилагаемом компакт-диске, создан до- кумент РучнаяОперация, данными которого будут только Дата и Номер. Поскольку проведение данного документа не предусматривается, свойству Проведение данного докумен- та указано значение Запретить. Однако в разделе свойства Движения отмечен регистр, для которого данный документ может быть регистратором (ТоварыНаСкладах) (рис. 7.62). Рис. 7.62. Документ РучнаяОперация Далее при создании формы документа на панели необхо- димо разместить табличное поле, отображающее данные Движения.ТоварыНаСкладах (рис. 7.63). Пользователь при работе с данным документом сможет интерактивно формировать или модифицировать дви- жения данного документа по регистру ТоварыНаСкладе и записывать документ. При записи документа данные, отображаемые в этом табличном поле, будут записаны в регистр (рис. 7.64). Однако необходимо иметь в виду, что поведение подоб- ного документа может быть неожиданным для пользова- телей, привыкших работать с документами по стандарт- ной схеме. Рис 7.63. Источник данных табличного поля Отображение данных Форма документа Отображение данных документа № | | ОТ | Отображение данных регистра Хранение данных Рис. 7.64. Схема документа Ручная операция Например, при установке пометки удаления на такой до- кумент не будет срабатывать отмена проведения и удале- ние движений документа. Ведь документ и не проводился (ему было запрещено проведение). А как же обеспечить удаление движений? Вариантов несколько: ♦ удалить сам документ. Тогда система удалит связанные с ним движения, поскольку записи регистра подчинены регистратору и в данном случае без регистратора суще- ствовать не могут; ♦ интерактивно удалить движения документа в таблич- ном поле, их отображающем, и записать документ; ♦ программно очистить движения, то есть набор записей с отбором по данному регистратору, и записать его. Кроме того, возможна ситуация, что необходимо не уда- лять движения документа, а лишь исключить их действие на итоги регистра. Для этого можно снять активность за- писей движений. Необходимо помнить, что хотя Актив- ность является свойством записей, однако установлена или снята она может быть только для всего набора запи- сей данного регистратора по данному регистру. Снятие активности может быть инициировано интерактивно, по- средством действия ПереключитьАктивность командной па- нели, связанной с табличным полем. Программно же это может быть выполнено следующим образом (листинг 7.15). Листинг 7.15. Изменение активности записей Для Каждого ЗаписьНабораЗаписей Из Движения.ТоварыНаСкладах Цикл ЗаписьНабораЗаписей.Активность = Ложь; КонецЦикла;
Кроме того, «неожиданным» для пользователя может оказаться тот факт, что при копировании подобного до- кумента содержимое табличного поля документа автома- тически копироваться не будет. Ведь там отображаются движения документа по регистру, а они не относятся к данным документа. Данный вопрос должен прорабаты- ваться разработчиком. Для реализации подобной функциональности необходи- мо воспользоваться обработчиком события ПриКопировании объекта документа (листинг 7.16). Листинг 7.16. Использование обработчика события ПриКопировании Процедура ПриКопировании(ОбъектКопмрования) // Перебрать движения документа-источника ДвиженияОбъектаКопирования = РегистрыНакопления. ТоварыНаСкладах.ВыбратьПоРегистраторуС ОбъектКопирования.Ссылка); Пока ДвиженияОбъектаКопирования.СледующийО Цикл // Создать новую запись в движениях текущего документа НовоеДвижение = Движения. ТоварыНаСкладах.ДрбавитьО; // Заполнить поля новой записи регистра НовоеДвижение.ВидДвижения = ДвиженияОбъектаКопирования.ВидДвижения; НовоеДвижение.Период = ДвиженияОбъектаКопирования.Период; НовоеДвижение.Номенклатура = ДвиженияОбъектаКопирования.Номенклатура; НовоеДвижение.Склад = ДвиженияОбъектаКопирования.Склад: НовоеДвижение.Количество = ДвиженияОбъектаКопирования.Количество; КонецЦикла; КонецПроцедуры Поскольку обработчик события ПриКопировании в качестве параметра получает объект копируемого документа, то в са- мой процедуре считываются его движения. Далее в цикле перебора набора записей документа источника формируют- ся новые записи уже в коллекции движений нового доку- мента. Значения полей новых записей заполняются значе- нием полей записей из движений документа-источника. При интерактивном формировании движений документа в общем случае поле Период записей регистра доступно для редактирования. Что позволяет устанавливать произ- вольный период начала действия любой записи на итоги регистра. В ряде прикладных задач, однако, подобную «вольность» требуется пресечь. Для принудительной син- хронизации поля Период, например, по значению даты до- кумента можно использовать следующее (листинг 7.17). Листинг 7.17. Синхронизация даты движений с датой документа Для Каждого ЗаписьНабораЗаписей Из Движения.ТоварыНаСкладах Цикл ЗаписьНабораЗаписей.Период = Дата; КонецЦикла; Саму синхронизацию, в зависимости от реализуемого алгоритма работы с документом, можно располагать или в обработчике события ПередЗаписью в модуле формы до- кумента, или в модуле объекта документа. В первом слу- чае синхронизация будет производиться при интерактив- ной записи документа, во втором — при программной записи — тоже. Кроме того, как определяли в начале этого раздела, фор- мирование движений не обязательно может идти от доку- мента. Движения могут быть сформированы программно, посредством объекта НаборЗаписей регистра (просто с уста- новленным отбором по нужному регистратору). Для син- хронизации значения поля Дата записей регистра со значе- нием поля Дата документа и для таких случаев необходимо использовать обработчик события ПередЗаписью самого на- бора записей (листинг 7.18). Листинг 7.18. Пример процедуры ПередЗаписью модуля набора записей регистра Процедура ПередЗаписью(0тказ, Замещение) // Получить дату регистратора ДатаРегистратора = ЭтотОбъект.Отбор.Регистратор. Значение.Дата; // Принудительно установить значение поля "Период" // каждой записи Для Каждого ЗаписьНабораЗаписей Из ЭтотОбъект Цикл ЗаписьНабораЗаписей.Период = ДатаРегистратора: КонецЦикла; КонецПроцедуры Выше мы рассмотрели ситуации и задачи, которые могут возникнуть при интерактивном формировании движений документов, которым проведение запрещено. Подобным образом могут решаться еще задачи для про- водимых документов. Например, если пользователь дол- жен иметь возможность в дополнение к сформированным при проведении документа движениям добавлять новые или вручную корректировать существующие движения. То есть так же можно создать табличное поле для инте- рактивной работы с набором записей данного документа по нужному (нужным) регистрам. Но,при этом разработчику обязательно нужно учитывать и корректно отрабатывать возможные попытки перепрове- дения документа с «интерактивно откорректированными» движениями. Если ничего не предпринимать, а свойство документа Удаление движений будет иметь значение Удалять движения автоматически, то система при перепроведении уда- лит старые движения и сформирует новые такими, какими их формирует обработка проведения. То есть результаты ручной коррекции будут потеряны. Что именно должна выполнять конфигурация в подоб- ной ситуации — зависит от постановки задачи. Все воз- можные предпосылки для ее решения у системы есть. Это и отключение автоматического удаления движений, и возможность отключения активности записей, и воз- можность реализации отказа в проведении документа и т. д. Журналы документов Журнал документов — объект конфигурации, предназначен- ный для обеспечения работы с документами нескольких видов в одном списке. Посредством журналов легко обеспечивается интерак- тивный вызов следующих действий (например, посредст- вом командной панели формы журнала):
♦ добавление нового документа; ♦ копирование документа; ♦ пометка на удаление документа/снятие пометки на уда- ление документа; ♦ удаление документа; ♦ открытие формы документа (для редактирования доку- мента); ♦ проведение документа; ♦ отмена проведения документа; ♦ установка времени документа (перед предыдущим до- кументом, за следующим документом, перенести на на- чало дня, перенести на конец дня); ♦ ввод на основании; ♦ переход к связанной информации (в том числе — ото- бражение списков движений документа); ♦ установка отбора и сортировки; ♦ история отборов; ♦ вывод данных из списка табличного поля в табличный документ; ♦ изменение настройки списка отображаемых в таблич- ном поле колонок; ♦ отбор по значению в текущей колонке; ♦ установка интервала дат в списке документов; ♦ поиск документа по номеру. Эти возможности предоставляют расширение формы журнала документов и расширение табличного поля жур- нала документов. С прикладной точки зрения журналы документов — сред- ство группирования связанных по смыслу документов. Например, журнал КассовыеДокументы может включать в себя документы ПриходныйКассовыйОрдер, РасходныйКас- совыйОрдер, Чек, ОтчетКассовойСмены и так далее. Для отображения данных только одного вида документов создавать журнал документов не стоит. Потому что фор- мируемая по умолчанию или созданная в конфигурации форма списка документа целиком реализует ту же функ- циональность без лишних структурных затрат. По сути дела, журналы документов — вторичные данные системы, представляющие собой еще одно представление списка документов. Рис. 7.65. Включение документов в различные журналы Каждый документ может входить в один или несколько журналов или не входить ни в один. Все определяется на- личием необходимости работы с рядом документов в со- ставе одного списка (рис. 7.65). Состав журналов В состав журнала как объекта конфигурации включаются регистрируемые документы и графы (рис. 7.66). Рис 7.66. Окно редактирования журнала документов При регистрации документа сразу же обеспечиваются возможности отображения в списке журнала таких по- лей, как ♦ ВидДокумента; ♦ Дата; ♦ Номер; ♦ ПометкаУдаления; ♦ Проведен. Наличие дополнительных граф в составе журнала дает воз- можность пользователю получать в списке журнала сведе- ния о документах, дополнительные к вышеперечисленным. Графа журнала представляет собой перечень реквизитов документов, регистрируемых в журнале, значения которых нужно отображать в списке в одной колонке (рис. 7.67). Таблица документа "Реализация" Таблица документа "ПлатежноеПоручение" Рис. 7.67. Регистрация реквизитов документов в графе журнала В списке журнала по каждому конкретному экземпляру документа информация будет отображаться для пользо- вателя в составе только одной строки списка. Поэтому в каждую графу журнала можно включить только один ре- квизит для каждого вида документа и невозможно вклю- чать реквизиты табличной части документа.
Кроме того, рекомендуется включать в состав одной гра- фы данные одного типа значений или близких по смыслу типов значений. Например, графа ДокументОснование бу- дет включать в себя данные значений соответствующих реквизитов разных видов документов. При этом типы значений реквизитов могут быть различными, но они близки по смыслу. На уровне объектов базы данных информация журналов документов хранится в отдельных таблицах — для каждо- го журнала документов. Эти таблицы имеют следующий состав полей и содержат следующую информацию: ♦ Ссылка — ссылка на регистрируемый в журнале документ; ♦ ПометкаУдаления — пометка удаления регистрируемого документа (Булево); ♦ Проведен — пометка проведенности регистрируемого документа (Булево); ♦ Дата — дата регистрируемого документа; ♦ Номер — номер регистрируемого документа (поле суще- ствует, если хоть один из регистрируемых документов имеет номер с длиной, отличной от нуля); ♦ Графа1 — содержимое соответствующих реквизитов ре- гистрируемых документов. Тип значения поля опреде- ляется типом значений реквизитов регистрируемых до- кументов; ♦ ... — ... ♦ ГрафаМ — ... Согласно вышеописанному можно сделать вывод о том, что состав и тип значения полей таблиц разных журналов отличаются. Кроме того, при добавлении новых докумен- тов к перечню зарегистрированных может меняться не только тип значения полей, но и состав полей. Например, если ранее все зарегистрированные докумен- ты имели номера нулевой длины, то добавление нового, с номером не нулевой длины, приведет к добавлению поля Номер в составе таблицы журнала. Заполнение журналов Заполнение/редактирование таблицы журнала происхо- дит при записи/удалении документов в рамках той же транзакции. Причем только в ситуациях: ♦ запись нового документа; ♦ запись документа, у которого есть изменения в рекви- зитах самого документа (изменения в табличных час- тях не приводят к необходимости «перезаполнения» за- писей в таблицах журналов); ♦ запись документа с измененной датой или номером, с из- менением признака проведения или пометки удаления; ♦ удаление документа. Таким образом, функциональность журналов обеспечи- вается с минимальными временными затратами на ее поддержание. Сколько документов можно зарегистрировать в составе одного журнала? В принципе, число документов, регистрируемых в составе одного журнала, не ограничено, могут быть зарегистриро- ваны хоть все документы конфигурации. При решении данного вопроса необходимо только помнить о необходи- мости обеспечения параллельности работы пользовате- лей и обеспечения достаточного уровня быстродействия системы при выполнении операций записи/удаления до- кументов. В отношении обеспечения параллельности работы: ♦ при файл-серверном варианте использования програм- мы транзакционные блокировки устанавливаются на уровне таблиц базы данных. Поэтому документы, вхо- дящие в один журнал, одновременно не смогут быть за- писаны; ♦ при клиент-серверном варианте использования про- граммы блокировки устанавливаются на уровне запи- сей. Поэтому блокировки SQL-сервера допускают бо- лее высокую параллельность выполнения транзакций. В отношении скорости записи/удаления документов: чем меньше количество журналов, в которых регистрируется документ, тем быстрее проходит его запись или удаление. А для документов, которые не имеют табличных частей, «накладные расходы» на регистрацию документов в жур- налах могут быть даже сопоставимы с затратами на собст- венно запись данных в таблицу документов. Поэтому к вопросу организации журналов в составе функ- ционально наполненных конфигураций надо подходить внимательно. Так же внимательно надо подходить к вопросу определе- ния граф журнала. Большое количество граф может ска- заться на производительности системы при просмотре журнала. Поэтому при отображении динамических спи- сков объект ТабличноеПоле управляет набором полей, счи- тываемых из базы данных. Считываются только те поля, которые связаны с соответствующими видимыми колон- ками табличного поля. Это сделано для уменьшения объ- ема выбираемой из базы данных информации. При этом необходимо заметить, что ряд наиболее важных полей считывается всегда. В отношении списков журналов — это Ссылка, ПометкаУдаления, Дата, Проведен. В отношении организации упорядочивания и отборов в динамических списках журналов необходимо отметить, что оптимальным является отбор и сортировка только по полю Дата. Отбор и сортировка по графам не может выполняться системой эффективно и при больших объ- емах данных могут существенно замедлять просмотр журнала. Последовательности документов Последовательность документов — средство группирова- ния документов в едином хронологическом порядке для обеспечения ведения единой логики событий в рамках некого механизма учета. В отличие от журналов докумен- тов, которые используются в основном для группирования документов в «интерфейсных интересах»
(для визуализации), последовательности группируют до- кументы для обеспечения правильного отражения дан- ных документов в учете. Поскольку учетных механизмов в составе одной конфи- гурации может быть несколько, то и последовательностей может быть адекватное количество. Кроме того, сами мо- дели применения объекта Последовательность могут отли- чаться. В качестве первого примера рассмотрим использование последовательности для учета правильности списания партий товаров со склада. Проведение ряда документов (документов реализации) обусловлено состоянием данных, хранящихся в базе данных, на момент времени регистра- ции документов (остатки партий в регистре ПартииТова- ров). Изменение же этих исходных данных впоследствии, после проведения документа, ставит под сомнение пра- вильность прошлого отражения данного документа в учете. Например, документ реализации Рнк-1 оформлен и про- веден после двух приходных накладных, оприходовав- ших товар (рис. 7.68). При проведении было реализовано списание партий по методу «FIFO» (первый пришел — первый ушел). То есть расходная накладная использовала данные об остатках партий на момент ее проведения. В результате все опера- ции были отражены в учете партий в виде следующих за- писей регистра ПартионныйУчет (табл. 7.6). Регистрация событий Отражение в учете Рис. 7.69. Нарушение последовательности проведения документов Для новой ситуации движения документа Реализация, по- лученные в результате старого проведения, — некоррект- ны (табл. 7.7). Ведь для списания 9 пультов одной партии Пнк-1 теперь недостаточно! К аналогичному печальному результату можно прийти и в случае любого изменения записей регистра задним числом (рис. 7.70). ПоступлениеТоваров Пнк1 Поступление!оваров Пнк-2 Реализация Рнк-1 Ручная корректировка остатков РК-1 Номенкл. Кол Сум Номенкл. Кол Сум Номенкл. Кол Номенкл. Период Кол Сум Пульт VH 10 100 Пульт VH 5 60 Пульт VH 9 Пульт VH 31 08.2005 5 60 I J I I ПоступлениеТоваров Пнк-1 4оменкл. Кол Сум ТультУН 10 100 ПоступлениеТоваров Пнк-Z Номенкл. Кол Сум Пульт VH 5 60 Реализация РНК-1 Номенкл. Кол Пульт VH 9 т Регистрация событий Отражение в учете Рис 7.68. Набор документов Видно, что при реализации была частично списана пар- тия Пнк-1. Далее было произведено изменение одной из исходных приходных накладных с последующим ее перепроведени- ем (рис. 7.69). Регис рация событии Отражение в учете Рис. 7.70. Пример изменения записей регистра «задним числом» В результате записи в регистре (учете) будут следующи- ми (табл. 7.8). То есть движения документа Реализция не отвечают требованиям метода списания «FIFO». Для исправления ситуации объект Последовательность по- зволяет в таких случаях оперировать понятием граница последовательности. Это и есть момент времени макси- мально глубокого в прошлом изменения записей регист- ра (регистров), от которых зависит проведение докумен- тов, зарегистрированных в последовательности. Именно с этого момента времени возможны коллизии правильно- сти ведения учета. То есть до границы последовательно- сти документы проведены заведомо правильно, после — возможно неправильно. Таблица 7.6. Записи регистра ПартионныйУчет Период Регистратор Вид движения Товар Партия Кол-во Сумма 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 Приход Пульт VH Пнк-1 10 100 23.08.2005 15:30:45 ПоступлениеТоваров №2 23.08.2005 15:30:45 Приход Пульт VH Пнк-2 5 60 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 Расход Пульт VH Пнк-1 9 90
Таблица 7.7. Записи регистра ПартионныйУчет Период Регистратор Вид движения Товар Партия Кол-во Сумма 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 Приход Пульт VH Пнк-1 7 70 23.08.2005 15:30:45 ПоступлениеТоваров №2 23.08.2005 15:30:45 Приход Пульт VH Пнк-2 5 60 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 Расход Пульт VH Пнк-1 9 90 Таблица 7.8. Записи регистра ПартионныйУчет Период Регистратор Вид движения Товар Партия Кол-во Сумма 01.08.2005 00:00:00 Ручная корректировка остатков РК-1 29.08.2005 17:00:00 Приход Пульт VH РК-1 2 16 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 Приход Пульт VH Пнк-1 10 100 23.08.2005 15:30:45 ПоступлениеТоваров №2 23.08.2005 15:30:45 Приход Пульт VH Пнк-2 5 60 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 Расход Пульт VH Пнк-1 9 90 Сам процесс восстановления логики учета может быть реализован путем последовательного перепроведения до- кументов, зарегистрированных в последовательности, на- чиная от границы последовательности, и называется вос- становлением последовательности. Другой вариант использования объекта Последователь- ность: пользователи в течение дня вводят поток заявок от покупателей и внутренних заявок. Причем в силу специ- фики автоматизируемого предприятия часто имеет место ситуация ввода нескольких заявок от одних и тех же поку- пателей или для одних и тех внутренних подразделений. Кроме того, возможен ввод «запоздавших» заявок про- шлых дней. Документы записываются, но не проводятся. По окончании рабочего времени офиса автоматически включается обработка Консолидация заявок, которая соби- рает все непроведенные заявки (разных видов), начиная от границы последовательности, консолидирует их, оформ- ляет соответствующим образом и проводит уже обобщен- ные заявки. Впоследствии исходные заявки удаляются. После этого граница последовательности смещается на момент времени последней проведенной консолидиро- ванной заявки (рис. 7.71). Рис. 7.71. Использование последовательности для консолидации заявок Первый приведенный пример можно назвать классиче- ским. Он касается давно существующей задачи «борьбы с коллизиями из-за работы пользователей задним числом». Данная задача полностью или в большей своей части мо- жет быть решена за счет встроенных в платформу автома- тических средств объекта Последовательность. Второй приведенный пример показывает, что разработ- чик при использовании объекта Последовательность не обя- зательно должен замыкаться только на «коллизиях работы задним числом». Благодаря наличию различных программ- ных средств и возможностей логика применения после- довательностей документов определяется самим разра- ботчиком. Устройство последовательностей Для создания объекта конфигурации Последовательность разработчик должен указать, какие документы необходи- мо регистрировать в последовательности, и список реги- стров, данные которых используются этими документами при своем проведении (рис. 7.72). Хотелось бы обратить внимание на то, что автоматиче- ское отслеживание изменения таких данных осуществля- ется только для регистров. То есть: ♦ регистров накопления; ♦ регистров сведений; ♦ регистров бухгалтерии; ♦ регистров расчета.
Рис. 7.72. Свойства, относящиеся к использованию последовательности Но это не мешает при необходимости реализовать про- граммными средствами изменение положения границы последовательности при изменении данных других объ- ектов. Например, для последовательности документов, критичных к изменению условий в элементе справочника Договоры, при записи модифицированного элемента дан- ного справочника можно программно установить границу последовательности на момент времени самого первого документа по этому договору. Кроме того, последовательность может иметь разрезы. Это реализуется включением измерений в данные после- довательности. Например, если добавить в последова- тельность измерение Организация, то с прикладной точки зрения общая последовательность будет разбита на ряд последовательностей. Каждая из них может функциони- ровать в рамках отдельной организации. То есть, напри- мер, будет возможно произвести восстановление после- довательности документов только одной организации, не затрагивая остальных. С другой стороны, наличие изме- рений не препятствует работе с последовательностью в целом. Для хранения данных объекта Последовательность в базе данных существует две таблицы: таблица регистрации документов в последовательности и таблица границ по- следовательности». Состав колонок обеих таблиц сходен: Период, Регистратор, Измерение!,..., Измерением. Различно функциональное ис- пользование этих таблиц. Данные, хранящиеся в таблице регистрации документов, используются для решения вопросов, связанных с кол- лекцией зарегистрированных в последовательности доку- ментов. Причем в разрезе измерений. Для определенной комбинации значений измерений по одному регистрато- ру в таблице регистрации документов может храниться только одна запись. Впоследствии данные этой таблицы могут использовать- ся, например, для получения упорядоченного по хроно- логии набора документов, которые требуется перепровес- ти для восстановления последовательности. Или просто для получения массива ссылок на документы, записи по которым соответствуют некому отбору по измерениям последовательности. Данные в таблице границ последовательностей хранят значения моментов времени границ последовательностей (Период + Регистратор) по каждому набору значений изме- рений последовательности. То есть уникальность записей таблицы границ последовательностей определяется набо- ром значений измерений. Если измерений у последова- тельности нет — значит, в этой таблице будет только одна запись. Пример содержимого таблиц при наличии измерений у последовательности приведен в табл. 7.9 и 7.10. Таблица 7.9. Пример таблицы регистрации документов в последовательности Период Регистратор Органи- зация Склад 01.08.2005 00:00:00 Ручная коррек- тировка остатков РК-1 29.08.2005 17:00:00 Сигма Главный 13.08.2005 15:00:01 ПоступлениеТ оваров №17 13.08.2005 15:00:01 Сигма Торговый 23.08.2005 15:30:45 ПоступлениеТоваров №2 23.08.2005 15:30:45 Сигма Торговый 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 Марон Главный Таблица 7.10. Пример таблицы границ последовательности Органи- зация Склад Период Регистратор Сигма Главный 01.08.2005 00:00:00 Ручная корректировка остатков РК-1 от 29.08.2005 17:00:00 Сигма Торговый 13.08.2005 15:00:01 ПоступлениеТоваров №17 13.08.2005 15:00:01 Марон Главный 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 Работа с последовательностями Работа с последовательностью включает в себя три про- цесса: ♦ регистрация документа в последовательности; ♦ перемещение границы последовательности назад; ♦ перемещение границы последовательности вперед (вос- становление границы). В принципе, эти процессы, во-первых, независимы, во- вторых, — могут выполняться системой автоматиче- ски или посредством программных действий, заложен- ных разработчиком.
Управление регистрацией документов в последовательности Для автоматической регистрации документа в последова- тельностях необходимо, чтобы свойство Заполнение после- довательностей документа, как объекта конфигурации, было установлено в значение Заполнять автоматически. Если последовательность имеет измерения, то для обес- печения автоматического заполнения полей этих измере- ний в формируемой записи таблицы регистрации доку- ментов последовательности настраивается соответствие между реквизитами документа и измерениями последо- вательности документа (рис. 7.73). Рис 7.73. Соответствие между реквизитами документа и измерениями последовательности В случае указания соответствия между реквизитами до- кумента (не табличной части) и измерениями последо- вательности — при записи документа в таблице регист- рации документов в последовательности формируется запись, в которой поля автоматически заполняются зна- чениями из документа. В случае же если при настройке такого соответствия ука- зывается реквизит табличной части документа, то в таблице регистрации документов будет сформировано столько записей, сколько уникальных значений будет иметь данный реквизит табличной части документа в за- писываемом документе (рис. 7.74). Поступление товаров N°| loz] ОТ [23.08.200510:00:00 | Склад; [главный Номенклатура Кол Цена Сумма Пульт VH 15 10 150 Шнур ЛК4 1000 3 3000 Таблица записей регистрации документов в последовательности Период Регистратор Склад Нинспкл.. 23.08.2005 10:00:00 Пнк-102 от Главный Пульт VH 23.08.2005 10:00:00 Пнк-102 от Главный Лнур ЛК4 Рис. 7.74. Пример формирования записей в таблице регистрации документов в последовательности Если указывается несколько реквизитов одной таблич- ной части — будет сформировано столько записей, сколь- ко уникальных комбинаций из них указано в табличной части документа (рис. 7.75). Если же в соответствиях с измерениями последователь- ностей будут указаны реквизиты различных табличных частей, то документ будет зарегистрирован столько раз, сколько уникальных комбинаций значений можно соста- вить (рис. 7.76). Исходя из вышесказанного, к вопросу добавления измере- ний в последовательность нужно подходить осмотрительно. Если для заполнения значений измерений использовать реквизиты табличных частей, да еще и разных — то коли- чество записей в таблице регистрации документов в последовательности может быть очень велико. Что может сказаться на производительности системы. Поступление товаров Таблица записей регистрации документов в пос ледс* . । т ле -нм ти N°| 1021 ОТ |23.08.200510-00:00 [ Период Регистратор Склад томен* л... Номенклатура Склад Кол Пульт VH Главный 15 { 23.08.200510:00:00 Гйк-102от Главный Пульт VH Шнур ПК4 №3(Борисов) 300 ' 23.08.2005 10:00:00 Пнк-102 от Ч93(Бор ШнурЛК4 Пульт VH Г лавный 1 Рис. 7.75. Пример формирования записей в таблице регистрации документов в последовательности Пересортица N°| 2| ОТ f23.O8.2OO510’00:00 Склады Склад Главный №3(Борисов) Товары Номенклатура Пульт VH ШнурЛК4 Пульт VH Таблица записей регистрации документов в послед.чип < ги Период Регистратор Склад Номенкл... 23.08.2005 10:00:00 Пс-2от Главный Пульт VH 23.08.2005 10:00:00 Пс-2от Главный Шнур ЛК4 23.08.2005 10:00:00 Пс-2 от №3(Бор... Пульт VH 23.08.2005 10:00:00 Пс-2 от №3(Бор... Шнур ЛК4 Рис. 7.76. Пример формирования записей в таблице регистрации документов в последовательности Регистрация документа в последовательности выполня- ется при записи документа. Процесс записи документа включает в себя следующие этапы (рис. 7.77). Процесс записи документа Рис. 7.77. Действия, выполняемые при записи документа
В случае же записи документа с проведением очередность этапов процесса будет следующей (рис. 7.78). Добавляется обработка проведения документа и процесс переноса границы последовательности вперед при вы- полнении необходимых для этого условий. Процесс записи документа с проведением Рис. 7.78. Действия, выполняемые при записи документа с проведением В случае же записи документа с отменой проведения по- следовательность действий будет следующей (рис. 7.79). Разработчику нужно помнить, что при создании новой последовательности документов автоматическая регист- рация старых документов в ней не производится. Для осуществления регистрации нужно будет или перезапи- сать существующие документы или написать обработку, которая зарегистрирует все нужные документы в после- довательности. Если средств автоматической регистрации недостаточно или их использование неудобно, для управления регист- рацией документа в последовательности документов слу- жит набор записей регистрации в последовательности до- кументов. У объекта документа есть свойство ПринадлежностьПоследо- вательностям. Его значением является коллекция наборов записей регистрации в последовательности документов. Для каждой последовательности, в которые входит доку- мент, — свой набор записей регистрации в последователь- ности документов (рис. 7.80). При автоматическом способе регистрации (напомним — для этого у документа как объекта конфигурации дол- жен стоять признак автоматического заполнения после- довательности) наборы записей таблиц регистрации документов в последовательностях автоматически запол- няются до записи документа и записываются после запи- си документа в одной транзакции. Поэтому, если требуется программно очистить эти наборы записей, и создать новые, можно это сделать в обработчи- ке события ПередЗаписью или ПриЗаписи объекта документа (не путать с аналогичными обработчиками событий Пере- дЗаписью формы документа). S Документ РеализацияТоваров X Процесс записи документа с отменой пронедннил Рис. 7.79. Действия, выполняемые при записи документа с отменой проведения Основные Данные Нумерация Движения ► Последовательности Журналы Формы Макеты Заполнение гюслед|]мп*^ы«ст «й Входит В лпгк»! 1яе»ъиосп€ 0 ПартионныйУчет 0 УчетНДС [ Действия | <Назад-| [ Далее> | [ Закрыть""] [ Справка" Рис. 7.80. Последовательности, в которые входит документ Например, в составе последовательности документов Пар- тионныйУчет есть измерение Номенклатура. В табличной части Товары документа могут содержаться номенкла- турные позиции, соответствующие услугам. По таким значениям измерения регистрировать документ в после- довательности не нужно. Для того чтобы документ реги- стрировался в последовательности только по товарам (исключая услуги), можно сделать следующее (лис- тинг 7.19). Листинг 7.19. Пример процедуры ПередЗаписью Процедура ПередЗаписью(0тказ, РежимЗаписи, РежимПроведения) НаборЗаписейРегистрации = ПринадлежностьПоследовательностям.ПартионныйУчет; // Очистить автоматически сформированный набор // записей регистрации НаборЗаписейРегистрации.Очистить();
И Получить выборку товаров из табличной части документа Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ |ИЗ I РеализацияТоваровСостав.Номенклатура Документ. РеализацияТоваров. Состав КАК РеализацияТоваровСостав I ГДЕ РеализацияТоваровСостав.Ссылка = &Ссылка И (НЕ РеализацияТоваровСостав.Номенклатура.Услуга)"; Запрос.УстановитьПараметр("Ссылка", Ссылка ); Результат = Запрос.ВыполнитьО: Выборка = Результат.ВыбратьО; // Добавить новые записи регистрации и заполнить их Пока Выборка.Следующий() Цикл НоваяЗапись = НаборЗаписейРегистрации.ДобавитьО; НоваяЗапись.Номенклатура = Выборка.Номенклатура: НоваяЗапись.Период = Дата; КонецЦикла; КонецПроцедуры Краткий комментарий: у элемента коллекции наборов записей регистрации документов в последовательности, соответствующему последовательности ПартионныйУчет, сначала очищаются все записи. Далее запросом получа- ются все номенклатурные позиции, входящие в таблич- ную часть Товары текущего документа и не являющиеся услугами. В цикле перебора выборки из результата за- проса добавляются в набор новые записи регистрации данного документа в последовательности ПартионныйУчет. Обратите внимание: в данном примере из-за того, что объект НаборЗаписейРегистрации был получен посредством свойства ПринадлежностьПоследовательностям объекта доку- мента, при формировании новых записей достаточно было заполнить только значения измерений последова- тельности и поле Период, а поле Регистратор автоматиче- ски заполняется ссылкой на документ. Если же потребуется очистить всю таблицу записей реги- страции документов в последовательности, то данную операцию легко выполнить программно. Запросом счи- тать все регистраторы, на которые имеются ссылки в таб- лице записей регистрации документов. А затем по всем регистраторам записать пустой набор записей (листинг 7.20). Листинг 7.20. Пример очистки таблицы регистрации документов в последовательности Процедура ОчисткаТаблицыРегистрацииПоследовательностиПартионныйУчетО // Получить все документы, зарегистрированные // в последовательности Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ | ПартионныйУчет.Регистратор |ИЗ Последовательность.ПартионныйУчет КАК ПартионныйУчет"; Результат = Запрос.ВыполнитьО; Выборка = Результат.ВыбратьО; // Создать набор записей таблицы регистрации // последовательности (при этом он пуст) НаборЗаписейРегистрации = Последовательности.ПартионныйУчет.СоздатьНаборЗаписей(); // Перебрать выборку из результата запроса Пока Выборка.СледующийО Цикл // Установить отбор по очередному зарегистрированному // документу в наборе записей НаборЗаписейРегистрации.Отбор.Регистратор. Установить(Выборка.Регистратор); // Записать пустой набор записей с замещением исходного НаборЗаписейРегистрации.ЗаписатьО; КонецЦикла; КонецПроцедуры Как видно из примера, для чтения данных таблиц регист- рации документов в последовательностях можно приме- нять запросы. Кроме того, у разработчика есть возможность проверить, принадлежит ли данный документ последовательности и посредством метода Принадлежит О объекта Последователь- ностьМенеджер.<имя>. Например, нужно проверить принад- лежность документа последовательности ПартионныйУчет (листинг 7.21). Листинг 7.21. Проверка принадлежности документа последовательности ФлагПринадлежности = Последовательности.ПартионныйУчет. Принадлежит(СсылкаНаПроверяемыйДокумент); Или, например, проверить, принадлежит ли данный до- кумент последовательности по конкретному значению измерения Номенклатура (листинг 7.22). В приведенном примере если документ зарегистрирован в данной последовательности по нужному значению из- мерения, переменная ФлагПринадлежности получит булево значение Истина, если нет — Ложь. Листинг 7.22. Проверка принадлежности последовательности // Подготовить структуры отбора по значениям измерений последовательности, ОтборПоИзмерениям = Новый Структура; ОтборПоИзмерениям.ВставитьСНоменклатура", СсылкаНаТовар); // Проверить принадлежность к последовательности // в отношении нужного значения измерения ФлагПринадлежности = Последовательности.ПартионныйУчет. Принадлежит(СсылкаНаПроверяемыйДокумент, ОтборПоИзмерениям); В общем случае, при формировании записей набора запи- сей регистрации документов в последовательности поле Период может заполняться произвольным значением. То есть момент времени самого документа и момент времени регистрации документа в последовательности могут от- личаться. Так же, в общем случае, может отличаться от даты документа и значение поля Период записей движе- ний по регистрам. Это может понадобиться для реализации какой-нибудь особой логики. Например, для решения задач сложного многоитерационного планирования, когда в течение ме- сяца могут вводиться, дополняться, частично отменяться планы, касающиеся как текущего месяца, так и следующего. Поэтому движения по регистру могут регистрироваться и на момент времени документа, и на начало текущего ме- сяца, и на начало следующего. Вероятные коллизии уст- раняются посредством использования объекта Последова- тельность. И поскольку документы планирования имеют разные приоритеты для разрешения коллизий планиро-
вания, то регистрироваться в последовательности могут не только на момент времени документа (рис. 7.81). Регистрация в учете 01.09.2005 Регистрация в последовательности 01.08.2005 12:00:00 11.08.2005 10:11:00 ----- -----► 01.09.2005 00:00:01 Рис. 7.81. Пример использования нестандартной регистрации документов в последовательности Кроме того, для некоторых задач может оказаться полез- ным, что документ в разных последовательностях может регистрироваться на разные моменты времени, или в од- них последовательностях регистрироваться, а в других — нет. Например, при раздельной работе с последователь- ностями ПартионныйУчет и Торговля. Перемещение границы последовательности назад Перенос границы последовательности выполняется при записи набора записей регистров. Сам процесс автоматического перемещения границы по- следовательности назад состоит из следующих операций (рис. 7.82): ♦ проверка того, что граница последовательности больше момента времени записи регистра; ♦ перемещение границы последовательности на момент времени записи регистра. тельности документа, которому подчинены измененные записи регистра. Важно понимать, что границу последовательности пере- мещают назад не документы, а движения регистров. Сде- лано это потому, что модификация (а также добавление или удаление) записей регистра не обязательно может быть связана с проведением или удалением документа. В платформе есть средства, позволяющие просто «припи- сывать» движения к документам, не используя объекты документов. Например, возможна следующая ситуация: граница по- следовательности Планирование установлена на дату: 01.09.2005 00:00:00. Затем 10.09.2005 обработкой Перепла- нирование к документу ПланПродаж №16, выписанному (и проведенному) с датой 18.08.2005 12:00:00, были «при- писаны» движения по регистру ПланыПродаж с указанием периода движений 31.09.2005 00:00:00. При этом старые движения документа не замещались. Кроме этого, сам до- кумент был ранее зарегистрирован в последовательности на дату 01.08.2005 00:00:00. Измерений у последователь- ности нет. В результате этого действия граница последовательно- сти будет перемещена назад при записи записей регист- ра именно на момент времени добавленных записей (рис. 7.83). То есть для перемещения назад границы последователь- ности ни дата документа, ни дата регистрации документа в последовательности значения не имеют. Но перенос (установка) границы последовательности программными средствами доступен разработчику на произвольный мо- мент времени. ОБРАБОТКА Граница последовательности не сбивается Регистрация в учете (регистры) 11.08.2005 10:11:00 31.09.2005 01.09.2005 00:00:00 00:00:00 Регистрация в учете (регистры) ГП ГЛ Граница Момент времени последовательности записываемой записи регистра Регистрация событий (документы) | Пл-0 1014 | 11.08.2005 10:11:00 Граница последовательности сбивается Регистрация в I* K*e;v же т ети Регистрация в учете (регистры) 01.08.2005 12:00:00 Рис. 7.83. Пример автоматического сбивания границы последовательности Момент времени Граница последовательности записываемой записи регистра Рис 7.82. Автоматическое сбивание границы последовательности Например, если требуется установить границу последова- тельности ПартионныйУчет на момент времени, состоящий из значений переменных ДатаУстановки, ДокументУстанов- ки по значению измерения Номенклатура, содержащемуся в переменной НоменклатураУстановки (листинг 7.23). На уровне таблиц базы данных результатом перемещения границы последовательности назад является модифика- ция записей в таблице границ последовательностей. То есть запись с ключом, соответствующим нужной комби- нации значений измерений, заменяется на запись с тем же ключом, но со значениями полей Период и Регистратор, соответствующими моменту регистрации в последова- Листинг 7.23. Перенос границы последовательности на произвольный момент времени // Подготовить параметры установки границы последовательности: // Момент времени установим МоментУстановки = Новый МоментВремени(ДатаУстановки, ДокументУстановки);
И Подготовить структуру отбора по значениям измерений последовательности, ОтборПоИзмерениям = Новый Структура; ОтборПоИзмерениям.Вставить(“Номенклатура", НоменклатураУстановки); // Установить границы последовательности "Партионный учет" Последовательности.ПартионныйУчет.УстановитьГраницу( МоментУстановки, ОтборПоИзмерениям); Также есть средства для получения данных таблицы гра- ниц последовательности. Данные о значениях границ последовательности можно получить запросом или с помощью методов ПолучитьГра- ницыО и ПолучитьГраницуО объекта ПоследовательностьМе- неджер.<иня>. Например, получение таблицы текущих границ последо- вательностей может выглядеть следующим образом (лис- тинг 7.24). Листинг 7.24. Пример получения границ последовательности ТаблицаГ раницПоследовательности = Последовательности.ПартионныйУчет. ПолучитьГ раницы("Номенклатура"): Для использования метода ПолучитьГраницыО обязательно указание названий измерений (через запятую), которые будут разрезами в таблице границ. Кроме того, можно ис- пользовать второй параметр метода, указав там структуру отбора по значениям измерений. Результатом вышеприведенного примера будет таблица значений, включающая в себя колонки со значениями измерений (в данном случае — Номенклатура) и колонку МоментВремени, в которой будут содержаться моменты времени границ последовательностей по хранящимся в последовательности комбинациям значений измерений. Кроме того, можно получать первую на временной оси границу последовательности для ситуации последователь- ности с измерениями (рис. 7.84). Реализуется это следую- щим образом (листинг 7.25). ГП по номенклатуре "Самовар" Самовар ГП по номенклатуре "Утюг" Утюг ГП по номенклатуре "Холодильник" Холодильник Граница Последовательности “ПартионныйУчет" Пос вед*>глтежл«к те "ПартионныйУчет" Рис. 7.84. Пример границ последовательности ПартионныйУчет Листинг 7.25. Получение минимальной границы последователь ности ТекущаяГ раницаПоследовательности = Последовательности.ПартионныйУчет.ПолучитьГраницу(); В заключение хотелось бы еще раз обратить внимание на то, что в случае наличия измерений в последовательности перемещение границы последовательности назад проис- ходит только для тех комбинаций значений измерений, которые уже присутствуют в таблице границ последова- тельности. То есть если в вышерассмотренном примере, где существу- ют границы последовательности по номенклатурным пози- циям: Самовар, Утюг, Холодильник сформировать в регистре задним числом записи с другими номенклатурными пози- циями (не записывая документ), то граница последователь- ности ПартионныйУчет перемещаться назад не будет. Восстановление последовательности Процесс переноса границы последовательности вперед называется восстановление последовательности. Необходимым условием автоматического восстановления последовательности является установка значения Переме- щать свойству Перемещение границы при проведении последо- вательности, как объекта конфигурации. Сам процесс автоматического восстановления последова- тельности выполняется только при проведении докумен- та и состоит из следующих операций (рис. 7.85): ♦ проверка того, что момент регистрации документа боль- ше, чем граница последовательности; ♦ проверка того, что в последовательности нет других проведенных документов в интервале между границей последовательности и моментом регистрации документа; ♦ установка границы последовательности на момент ре- гистрации документа. ГП Последовательность восстанавливается в последовательности документы I I I Момент времени регистрации проводимого документа ГП ГП Послед: выт г-ъхзгть не восстанавливается Зарегистрированные в последовательности документы I I I I Момент времени регистрации проводимого документа Рис. 7.85. Автоматическое восстановление границы последовательности На уровне таблиц базы данных результатом восстановле- ния границы последовательности является модификация записей в таблице границ последовательностей. То есть запись с ключом, соответствующим нужной комбинации значений измерений, заменяется на запись с тем же клю- чом, но со значениями полей Период и Регистратор, соот- ветствующими моменту регистрации в последовательности документа, проведение которого привело к восстановле- нию последовательности. Автоматическое перемещение границы последовательно- сти вперед происходит только при проведении докумен- та. Не важно — нового или уже ранее проведенного, лишь
бы соблюдались все условия алгоритма. Главное, что вос- становление происходит именно при записи с проведе- нием. Сделано это по следующей причине: проведение доку- мента — это сложный процесс, включающий в себя удале- ние предыдущих движений, установку признака прове- денности, запись документа, запись движений документа и т. д., вплоть до «подтягивания» границы последователь- ности. Если разработчик отказался от этого процесса и просто формирует новые записи в регистре для некого документа-регистратора (даже если тот является следую- щим после момента времени границы последовательно- сти), то говорить о том, что с прикладной точки зрения последовательность восстановлена — слишком оптими- стично и, в принципе, неверно. Например, нет никакой уверенности, что при перепроведении такого документа не возникнет коллизий. Но, если такая уверенность есть или она обеспечена со- ответствующим комплексом мероприятий, предусмот- ренным разработчиком, то в случае необходимости для реализации неавтоматического переноса границы после- довательности (назад или вперед) можно использовать программные средства — метод УстановитьГраницу() объек- та ПоследовательностьМенеджер.<имя>. Использование механизма восстановления последова- тельности в прикладном смысле может быть разносто- ронним. При последовательном проведении всех документов, вхо- дящих в последовательность, начиная с момента границы последовательности, — последовательность восстанавли- вается. И, наоборот, при восстановлении последовательности пе- репроводятся проведенные документы, входящие в после- довательность, но находящиеся за границей последова- тельности. Здесь хотелось бы отметить ряд особенностей. Во-первых, хотя автоматическая регистрация документов в последовательности происходит при записи документа (при любой записи документа, не обязательно — при про- ведении), но при восстановлении последовательности производится перепроведение только проведенных доку- ментов. То есть только тех документов, у которых стоит признак проведения (рис. 7.86). Зарегит в последовательности документы |йр lap |g~~l► Перепроводимые при восстановлении последовательности документы Рис 7.86. Проведение документов при восстановлении последовательности Во-вторых, перепроводиться будут документы в хроно- логии, определяемой моментами регистрации докумен- тов в последовательности, а не моментами времени самих документов. Это может оказаться существенным, если документы регистрируются в последовательности на от- личные от своих моменты времени (рис. 7.87). Рис. 7.87. Порядок проведения документов при восстановлении последовательности В-третьих, если в составе последовательности есть изме- рения, а восстановление последовательности проводится общее (без разрезов по измерениям), то порядок перепро- ведения документов, которые нужно перепровести, опять же однозначно определяется хронологией регистрации документов в последовательности. Сам процесс восстановления последовательности доку- ментов по определенную дату может быть инициирован: ♦ посредством системной команды Проведение документов (рис. 7.88); ♦ программно, с помощью метода Восстановить() объекта Последов атель ноет ьМенеджер.<им я>. В последнем случае последовательность можно восстано- вить «в целом» (можно даже без указания — по какой мо- мент времени) (листинг 7.26), а можно и в пределах ука- занных комбинаций измерений последовательности. Рис. 7.88. Команда восстановления последовательностей Листинг 7.26. Пример использования метода Восстановит^) Последовательности. ПартионныйУчет. Восстановить (); Например, необходимо восстановить последовательность документов ПартионныйУчет по момент времени докумен- та из переменной СсылкаНаДокумент по значению изме- рения Номенклатура, хранящемуся в переменной Товар. Вариант выполнения такого действия представлен в лис- тинге 7.27. Листинг 7.27. Пример восстановления границы последовательности // Сформировать момент времени, по который // будет восстанавливаться последовательность МоментВосстановленияПо = Новый Моментвремени( СсылкаНаДокумент.Дата, СсылкаНаДокумент): // Сформировать таблицу отбора ТаблицаКомбинацийИзмерений = Новый ТаблицаЗначений:
И Добавить колонки с именами, соответствующими // именам измерений последовательности ТаблицаКомбинацийИзмерений.Колонки.Добавить("Номенклатура"); // Добавить строку(и) со значением(ями) отбора СтрокаТаблицы = ТаблицаКомбинацийИзмерений.Добавить(); СтрокаТаблицы.Номенклатура = ссылкаНаТовар; // Восстановить последовательность Последовательности.ПартионныйУчет. Восстановить( МоментВосстановленияПо, ТаблицаКомбинацийИзмерений); Параллельный ввод документов, участвующих в последовательности Как было описано выше, в базе данных информация по- следовательностей документов хранится в двух таблицах: ♦ таблице записей регистрации документов в последова- тельности; ♦ таблице границ последовательностей. Выполнение различных действий с последовательностью в клиент-серверном варианте использования программы порождает блокирование этих таблиц в различных диапа- зонах: ♦ при регистрации документа в последовательности про- исходит добавление или модификация набора записей таблицы регистрации документов в последовательно- сти, подчиненного регистратору. Поэтому заблокиро- ванным оказывается как минимум диапазон записей, соответствующих одному регистратору (плюс две гра- ничные записи «вокруг» этого диапазона); ♦ при перемещении границы последовательности назад происходит модификация записей границ по соответст- вующим комбинациям значений измерений. Поэтому блокируются записи таблицы границ последовательно- сти, соответствующие данным комбинациям значений измерений. А если измерений в последовательности нет — то вся таблица целиком; ♦ при перемещении границы последовательности вперед. Этот процесс происходит только при проведении до- кумента, поэтому блокируются обе таблицы. Таблица регистрации документов в последовательности оказы- вается заблокированной в диапазоне от границы после- довательности по момент времени регистрации про- водимого документа в последовательности. То есть, заблокированными могут оказаться записи, подчинен- ные документам непроведенным, но зарегистрирован- ным в последовательности в указанном интервале. Таб- лица границ последовательностей будет заблокирована целиком. Если у последовательности есть измерения, то вышеописанные блокировки при данном действии будут касаться только записей с комбинациями значе- ний измерений, совпадающими со значениями измере- ний записей регистрации; ♦ в файловом варианте работы системы в любом случае происходит блокировка таблиц целиком. Согласно данному описанию механизма блокировок видно, что «узким местом» обеспечения параллельности ввода и проведения документов для клиент-серверного варианта работы системы являются действия, связанные с автомати- ческим перемещением границы последовательности. То есть если документ зарегистрирован в последователь- ности, то при его проведении система может предпринять попытку автоматического перемещения границы после- довательности на момент регистрации данного докумен- та, что приведет к блокировке таблицы границ последова- тельности целиком или в диапазоне соответствующей комбинации значений измерений последовательности. Параллельно проводимый документ, входящий в ту же последовательность, при попытке заблокировать те же за- писи или таблицу не сможет этого сделать. В результате вместо параллельного проведения для таких документов получим последовательное. Одним из вариантов выхода из ситуации является отклю- чение автоматического перемещения границы последова- тельности при проведении документов. Для этого свойст- ву Перемещение границы при проведении последовательности, как объекта конфигурации, устанавливается значение Не перемещать. В этом случае при проведении документа, даже если он регистрируется в последовательности, система не пред- принимает попытки перемещения границы (границ) по- следовательности. А блокировки, возникающие при реги- страции разных документов в последовательности, — не мешают друг другу. То есть тогда работа с объектом По- следовательность не препятствует параллельному проведе- нию документов. Необходимо лишь не забыть позже реализовывать пере- мещение границы последовательности, например, слу- жебной обработкой.
Глава 8. Реализация задач учета движения средств Оперативный учет. Описание задач, решаемых регистрами накопления Практически все теории, тем или ином образом связан- ные с технологиями учета, управления, принятия реше- ний и т. д., — базируются на понятии «показатель». Пока- затель - данные, по которым можно судить о развитии, ходе, состоянии чего-нибудь. Оперативный учет — учет, позволяющий максимально быстро получать информацию о значениях показателей, учитываемых в автоматизируемой системе. Платформа системы 1С:Предприятие предлагает удобное для учета показателей средство — регистры. Посредством их использования обеспечиваются необходимое быстро- действие, функциональная гибкость и простота решения этих информационных задач. Как правило, информационные модели при этом включа- ют не только одни регистры. Обычно используется сле- дующая схема (рис. 8.1): ♦ документами регистрируются события, приводящие к из- менению значений показателей; ♦ сами значения показателей хранятся в регистрах; ♦ посредством отчетов пользователи получают информа- цию о состоянии показателей и проводят ее анализ. Рис. 8.1. Общая схема оперативного учета Какие же именно показатели используются при решении задач учета движения средств? И какие регистры нужно для них использовать? При автоматизации учета движения средств чаще прихо- дится сталкиваться с ситуацией, когда в момент регистра- ции изменений показателя фиксируется не конечное ито- говое значение показателя, а его приращение. Например, при регистрации поступления товаров на склад — количество поступивших товаров, а не находя- щихся в остатке, при регистрации выдачи денег подотчет- нику — фиксируется выданная сумма, а не оставшаяся в кассе и тому подобное. А вот при получении данных из системы учета уже требуются накопленные (итоговые) значения показателей. Такие показатели называют показателями накопления. Для решения задачи учета показателей накопления в сис- теме 1С:Предприятие используются регистры накопле- ния. Регистр накопления — объект конфигурации, предназначен- ный для хранения итоговых (накопленных) значений по- казателей и хранения движений (приращений) показа- телей. Помимо итоговых значений показателей регистр может хранить и промежуточные итоги, рассчитанные для указанных периодов. Информация о приращениях показателей (заметьте, они могут быть как положительными, так и отрицательными) вносится в регистр накопления только посредством дви- жений, то есть посредством наборов записей регистра, подчиненных документу-регистратору. Этим обеспечива- ется обоснованность регистрации изменений показате- лей — регистрацией событий, приводящих к этим измене- ниям. Упрощенно можно сравнить регистр накопления с неким «черным ящиком», «на вход» которого подаются значе- ния приращений, а «на выходе» можно получить накоп- ленные значения приращений (рис. 8.2). Как можно заметить из приведенного рисунка, показа- тели накопления имеют различный прикладной смысл. Различают следующие виды накапливаемых показателей: ♦ показатели остатков; ♦ оборотные показатели. Итоги показателей остатков отражают значения учиты- ваемых показателей на некоторый момент времени. Итоги оборотных показателей отражают значения сово- купного изменения показателя за временной интервал между двумя моментами времени (период). В случае если эти изменения могут быть как положительным, так и от- рицательным можно оперировать такими понятиями, как Приход и Расход (рис. 8.3). Таким образом, можно сказать, что показатели остатка и оборотные показатели характеризуют один и тот же процесс, но с разных сторон.
Рис. 8.3. Различные виды накапливаемых показателей говые значения показателей остатков и, кроме того (сум- Важно отметить, что показатели остатка имеют абсолют- ные итоги относительно момента начала ведения учета. При этом изменения в приращениях (движениях) любых прошлых периодов влияют на текущее значение итога. Рассмотрим пример, приведенный на рис. 8.4. Изменения показателя Деньги в кассе фиксируются по- средством документов Приходный кассовый ордер (ПКО) и Расходный кассовый ордер (РКО). Оформление поступле- ния денег в январе месяце повлияет на остатки как на на- чало февраля, так и начало марта и т. д. В противоположность рассмотренному примеру итоги оборотных показателей за разные периоды — независи- мы. Рассмотрим пример на рис. 8.5. Изменения показателя Сумма проданного регистрируются посредством документа Расходная накладная (Рнк). Вве- денные изменения в объемах продаж января месяца бу- дут касаться только января, но никак не коснутся фев- ральских объемов продаж. Для гибкого и эффективного решения задач прикладной области система 1 С:Предприятие позволяет использо- вать два вида регистров накопления. мируя приращения этих показателей за периоды), позво- ляют получать обороты. Например, при решении задачи учета товаров на складах может понадобиться как значе- ние остатка товаров на момент времени, так и оборот по- ступлений или расходов товара за периоды времени. Если же для некоторых сущностей накопление остатков смысла не имеет и требуется накапливать только оборо- ты, тогда следует использовать оборотные регистры на- копления. Например, учет оборотов продаж компании. О продажах всегда можно говорить только в отношении временного периода. ВНИМАНИЕ Перечисленные виды регистров накопления не являются, в общем случае, взаимозаменяющими. Каждый из них предназначен для решения своего собственного круга при- кладных задач. Например, для решения задач, связанных с учетом только оборотных показателей, не следует исполь- зовать регистры остатков и, наоборот, не следует пытаться вести учет показателей остатков на оборотных регистрах. Подобные попытки могут привести как минимум к неоп- равданному снижению быстродействия прикладного реше- ния или вообще к некорректности данных учета.
Структура регистра накопления В состав регистра накопления, как объекта конфигура- ции, входят измерения, ресурсы и реквизиты (рис. 8.6). • Регистр накопления ТоварыНаСкладах _ □ X Основные | ► Данные Регистраторы Формы Макеты Подсистемы Права Интерфейсы Обмен данными Прочее t I g Ц Номенклатура 5.Ц. Склад Ё Ресурсы i :™g Количество Ё = Реквизиты 5—«- бидОперации | Дейст&ия ~^ | <Назад~~] f Далее» | | Закрыть 11 Справка Рис. 8.6. Состав регистра накопления Ресурсы используются для хранения информации, как о приращениях, так и о самих значениях показателей. По сути, каждый ресурс хранит данные одного показателя. Однако регистры могут быть не только одномерными. Например, для решения задачи учета количества това- ров нерационально оперировать большим количеством ресурсов (показателей) типа КоличествоХолодильников, Ко- личествоПылесосов, КоличествоПультовУН и т. д. Лучше использовать один ресурс (показатель) Количество, но ввести разрез учета — По номенклатурным позициям. В регистрах накопления разрезы учета реализуются с по- мощью измерений. В состав регистра можно включить более одного измере- ния, поэтому в общем случае регистр накопления можно представить как n-мерную систему разрезов учета (изме- рений), в узлах которой хранятся совокупные данные ре- сурсов (итоги) (рис. 8.7). Барометр G5 Станция G121 Номенклатура Рис. 8.7. Многомерная модель регистра накопления На представленной схеме — двумерная модель хранимой в регистре информации по итогам. Разрезы учета (изме- рения) Номенклатура и Склад. Узлами пересечений этих разрезов учета будут всевозможные комбинации значе- ний номенклатурных позиций на складах. Итог показате- ля Количество в каждом узле пересечения отражает дан- ные: сколько (в количественном выражении) конкретной номенклатуры находится на конкретном складе. Данные этой графической двумерной модели можно пред- ставить в виде табличной модели (табл. 8.1). Таблица 8.1. Табличное представление данных регистра Номенклатура Склад Количество Барометр G5 Главный 30 Барометр G5 Фили-2 15 Пульт VH Фили-2 И Станция G121 Главный 5 Каждая строка содержит значение итога ресурса Количе- ство для конкретной комбинации значений разрезов уче- та Номенклатура и Склад. Из достоинств табличной модели сейчас хотелось бы от- метить универсальность. Если графическое отображение более чем трехмерного пространства тяжело или вообще невозможно для человеческого восприятия, то табличная модель, в принципе, — не ограничивает количество разре- зов учета. Впоследствии будет рассмотрено, что хранение итогов регистров в базе данных основано именно на ис- пользовании табличной модели. Реквизиты — дополнительные характеристики движе- ний, то есть первичных записей регистра. Реквизиты не влияют на итоги, хранимые в регистре. На вышеприве- денной схеме, отражающей итоги, нет места реквизитам. Однако реквизиты могут быть использованы при реше- нии задач анализа выполненных движений. То есть таких задач, в которых работа идет только с приращениями по- казателей, безотносительно их итоговых значений. Например, если при формировании движений регистра ТоварыНаСкладах заполнять соответствующие значения: поступление, реализация в розницу, реализация оптом, списа- ние, перемещение и т. д. для реквизита КодОперации, то впоследствии можно будет анализировать: ♦ какая из операций производится чаще других, какая реже; ♦ какие операции не выполняли в течение последнего квартала и т. п. Итак, в отношении задач, решаемых регистрами накопле- ния, структура регистра как объекта конфигурации по- зволяет вести многомерный учет как приращений, так и итогов показателей накопления, с возможностью при не- обходимости использования дополнительных характери- стик движений. Для обеспечения данных возможностей предусмотрена соответствующая структура таблиц базы данных и поря- док работ с ними. Данные каждого регистра накопления хранятся в базе данных в двух таблицах: ♦ таблица движений регистра накопления; ♦ таблица итогов регистра накопления. Существует два вида регистров накопления и каждый предназначен для ведения учета показателей своего вида (остатков или оборотов), и как разбирали выше, зада- чи учета показателей этих видов различны. Поэтому структура таблиц базы данных для регистров накопления
разных видов тоже отличается. Она оптимизирована под решение соответствующих задач. Для регистра остатков состав колонок таблицы движений следующий: ♦ Период — дата записи. Совместно с полями Регистратор и НомерСтроки определяет положение данной записи на временной оси; ♦ Регистратор — ссылка на документ, которому подчинена данная запись; ♦ НомерСтроки — уникальный номер данной записи в на- боре записей регистра, подчиненных документу, ука- занному в поле Регистратор; ♦ ВидДвижения — значение системного перечисления Вид- ДвиженияНакопления, обозначающее направление при- ращения указанных в записи ресурсов на итоги по этим ресурсам (Приход или Расход); ♦ Активность — тип Булево. Содержит признак влияния за- писи на итоги регистра; ♦ <Измерение> — значение измерения. Количество таких полей равно количеству измерений, определенных в данных регистра, как объекта конфигурации; ♦ <Ресурс> — значение ресурса. Количество таких полей равно количеству ресурсов, определенных в данных ре- гистра, как объекта конфигурации; ♦ <Реквизит> — значение реквизита. Количество таких по- лей равно количеству реквизитов, определенных в дан- ных регистра, как объекта конфигурации. Таблица движений регистра хранит данные о выполнен- ных по регистру движениях. Таблица итогов регистра остатков хранит итоги на мо- мент времени последнего движения (актуальные итоги). Дополнительно к этому могут храниться промежуточные итоги, если установлен период рассчитанных итогов. Период рассчитанных итогов влияет только на произво- дительность при получении итогов на некоторую проме- жуточную дату; если он установлен, итоги будут получе- ны быстрее. Структура таблицы итогов следующая: ♦ Период — дата, на которую актуально состояние храни- мого в таблице итога; ♦ <Измерение> — значение измерения — разреза учета хранимых итогов. Количество таких полей равно коли- Таблица 8.2. Пример заполнения таблицы движений регистра остатков Период Регистратор Номер- Строки Вид дви- жения Актив- ность Номен- клатура Склад Коли- чество Сумма 03.07.2005 15:00:00 Поступление товаров №1 13.08.2005 15:00:00 1 Приход Истина Пульт VH Главный 1 10 13.08.2005 15:00:01 Поступление товаров №2 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 9 90 13.08.2005 15:00:01 Поступление товаров №2 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 490 23.08.2005 15:30:45 Поступление товаров №3 23.08.2005 15:30:45 1 Приход Ложь Пульт VH Фили-2 5 60 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Расход Истина Пульт VH Главный 8 80 31.08.2005 23:59:59 Поступление товаров №4 31.08.2005 23:59:59 1 Приход Истина Пульт PW Фили-2 1 17 01.09.2005 00:00:00 Поступление товаров №5 01.09.2005 00:00:00 1 Приход Истина Пульт VH Фили-2 1 18 Таблица 8.3. Пример заполнения таблицы остатков регистра накопления Период Номенклатура Склад Количество Сумма Итоги июля 2005 года 01.08.2005 00:00:00 Пульт VH Главный 1 10 Итоги августа 2005 года (граница рассчитанных итогов) 01.09.2005 00:00:00 Пульт VH Главный 2 20 01.09.2005 00:00:00 Пульт PW Главный 7 490 01.09.2005 00:00:00 Пульт PW Фили-2 1 17 Актуальные итоги 01.11.3999 00:00:00 Пульт VH Фили-2 1 18 01.11.3999 00:00:00 Пульт VH Главный 2 20 01.11.3999 00:00:00 Пульт PW Главный 7 490 01.11.3999 00:00:00 Пульт PW Фили-2 1 17
честву измерений, определенных в данных регистра, как объекта конфигурации; ♦ <Ресурс> — значение итога ресурса. Количество таких полей равно количеству ресурсов, определенных в дан- ных регистра, как объекта конфигурации. Пример заполнения таблицы движений регистра остат- ков приведен в табл. 8.2. Для вышеприведенного примера заполнения таблицы движе- ний регистра таблица итогов регистра, после расчета итогов по 31.08.2005, будет выглядеть так, как показано в табл. 8.3. Обратите внимание: данные таблицы итогов содержат значения итогов ресурсов для всех возможных комбина- ций значений измерений. Исключения составляют итоги, если для данной комбинации значений измерений значе- ния всех ресурсов равны нулю. Такие записи в таблице итогов не хранятся за ненадобностью. Потому что с при- кладной точки зрения ситуация «нет итогов по данной комбинации значений измерений» равносильна ситуации «по данной комбинации значений измерений все итоги равны нулю». Впоследствии, в разделе «Получение данных из регист- ров накопления», с. 198 рассмотрим, как при решении задач получения данных о значениях показателей (ресур- сов) система может оптимальным, с точки зрения быст- родействия, способом обращаться к данным как таблицы движений, так и таблицы итогов регистра. Структура таблиц оборотного регистра, хранимых в базе данных, схожа. Отличие заключается только в том, что для оборотных регистров не существует понятия вид дви- жения и понятия актуальные итоги. Состав колонок таблицы движений оборотного регистра следующий: ♦ Период — дата записи. Совместно с полями Регистратор и НомерСтроки определяет положение данной записи на временной оси; ♦ Регистратор — ссылка на документ, которому подчинена данная запись; ♦ НомерСтроки — уникальный номер данной записи в на- боре записей регистра, подчиненных документу, ука- занному в поле Регистратор; ♦ Активность — тип Булево. Содержит признак влияния за- писи на итоги регистра; ♦ «Измерение» — значение измерения. Количество таких полей равно количеству измерений, определенных в дан- ных регистра, как объекта конфигурации; ♦ «Ресурс» — значение ресурса. Количество таких полей равно количеству ресурсов, определенных в данных ре- гистра, как объекта конфигурации; ♦ «Реквизит» значение реквизита. Количество таких по- лей равно количеству реквизитов, определенных в дан- ных регистра, как объекта конфигурации. Структура таблицы итогов тоже схожа: ♦ Период — период (месяц), за который накоплен оборот итогов ресурсов; ♦ «Измерение» — значение измерения — разреза учета хранимых итогов. Количество таких полей равно коли- честву измерений, определенных в данных регистра, как объекта конфигурации; ♦ «Ресурс» — значение итога оборота ресурса. Количество таких полей равно количеству ресурсов, определенных в данных регистра, как объекта конфигурации. Но вот сами данные, хранимые в таблице итогов, и меха- низмы их использования коренным образом отличаются от регистра остатков. Для оборотного регистра в таблице итогов хранятся посчитанные суммарные обороты (ито- ги) ресурсов за каждый месяц, в рамках которого были зарегистрированы движения в данном регистре. Пример заполнения таблицы движений оборотного реги- стра Продажи представлен в табл. 8.4. Для вышеприведенного примера заполнения таблицы движений таблица итогов регистра будет заполнена сле- дующим образом (табл. 8.5). В разделе «Получение данных из регистров накопления», с. 198 будет рассмотрено, в каких случаях и какими сред- ствами достигается оптимальное быстродействие при по- лучении данных оборотных регистров. Здесь же следует сказать, что как для регистров остатков, так и для оборотных регистров система 1С:Предприятие индексирует таблицы движений и таблицы итогов. При этом для таблиц движений регистров создаются следую- щие индексы: Таблица 8.4. Пример заполнения таблицы движений оборотного регистра Период Регистратор Номер- Строки Номен- клатура Товар Контр- агент Коли- чество Сумма 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Истина Пульт VH Ялта-Лтд 9 135 29.08.2005 15:00:01 Реализация №2 29.08.2005 15:00:01 1 Истина Пульт VH Компания «Риона» 10 150 13.09.2005 15:00:00 Реализация №3 13.09.2005 15:00:00 1 Истина Пульт VH Компания «Риона» 1 15 23.09.2005 10:00:00 Реализация №3 23.09.2005 10:00:00 1 Истина Пульт VH Компания «Риона» 1 15 23.09.2005 15:30:45 Реализация №4 23.09.2005 15:30:45 1 Ложь Пульт PW Крона 1 90 01.11.2005 08:59:59 Реализация №5 01.10.2005 08:59:59 1 Истина Пульт PW Ялта-Лтд 1 95
Таблица 8.5. Пример заполнения таблицы итогов оборотного регистра Период Номенклатура Контрагент Количество Сумма Итоги августа 2005 года 01.08.2005 00:00:00 Пульт VH Ялта-Лтд 9 135 01.08.2005 00:00:00 Пульт VH Компания «Риона» 10 150 Итоги сентября 2005 года 01.09.2005 00:00:00 Пульт VH Компания «Риона» 2 30 Итоги ноября 2005 года 01.11.2005 00:00:00 Пульт PW Ялта-Лтд 1 95 ♦ Период + Регистратор + НомерСтроки; ♦ Регистратор + НомерСтроки; ♦ Измерение + Период + Регистратор + НомерСтроки — если для измерения Измерение свойство Индексировать уста- новлено в значение Индексировать; ♦ Реквизит + Период + Регистратор + НомерСтроки — если для реквизита Реквизит свойство Индексировать установ- лено в значение Индексировать. Для таблиц итогов создается следующий индекс: ♦ Период + Измерение! + Измерение? + ... + Измерением — по всем измерениям регистра. Использование индексов позволяет еще более сократить время выполнения операций с данными регистра. Однако необходимо иметь в виду, что SQL Server накладывает определенное ограничение на количество полей, входя- щих в составной индекс — не более 16 полей в индексе. Поэтому работа с регистрами, имеющими очень большое количество измерений, может быть неэффективна по ско- рости из-за невозможности использования индексных таблиц. Подробнее об индексировании таблиц базы данных мож- но прочитать в разделе «Индексы таблиц базы данных», с. 788. Механизмы заполнения таблиц регистров накопления в базе данных Как было определено выше, данные каждого регистра на- копления хранятся в двух таблицах базы данных: ♦ таблице движений регистра накопления; ♦ таблице итогов регистра накопления. В таблицу движений регистра записи могут вводиться пользователем вручную, генерироваться в процессе вы- полнения обработок либо при проведении документов. Подробно это описано ниже, в разделе «Запись данных в таблицу движений регистра накопления», с. 183. При формировании данных таблицы итогов важно обес- печение их непротиворечивости данным таблицы движе- ний. Чтобы, например, не получилось, что по данным таб- лицы движений за все время в кассу предприятия пришло 100 рублей, ушло 50 рублей, но таблица итогов содержит данные об остатке 1000 рублей. Поэтому заполнение таблицы итогов осуществляется системой согласно данным активных записей таблицы движений, при расчете итогов (автоматическом или ини- циированным специальными методами, подробно это описано в разделе «Механизмы заполнения таблицы ито- гов регистра накопления», с. 193). То есть пользователь или разработчик не могут непосредственно записывать данные в таблицу итогов регистра накопления, зато могут инициализировать действия системы, производящие рас- чет и заполнение итогов (рис. 8.8). Если признак расчета итогов регистра включен, то расчет и заполнение данными таблицы итогов регистра произво- дится автоматически при записи набора записей. Прове- рить значение признака расчета итогов можно с помощью метода ПолучитьИспользованиеИтоговО менеджера регистра накопления (листинг 8.1). Рис. 8.8. Заполнение таблицы итогов регистра накопления Листинг 8.1. Пример использования метода ПолучитьИспользованиеИтоговО ПризнакИспользованияИтогов = РегистрыНакопления.ПартииТоваров. ПолучитьИспользованиеИтоговО; Если ПризнакИспользованияИтогов Тогда Сообщить("Итоги рассчитываются!"); КонецЕсли;
При необходимости разработчик может отключать или включать расчет итогов при записи движений. Это может понадобиться для того, чтобы повысить скорость записи набора записей регистра при массовых загрузках данных. Например, требуется загрузить массив информации по документам и их движениям (листинг 8.2). Листинг 8.2. Пример отключения использования итогов регистра накопления // Отключить использование итогов регистра РегистрыНакопления.ПартииТоваров. УстановитьИспользованиеИтогов(Ложь); Для Каждого Элеиент из МассивИнфориации Цикл // Выполнить действия по загрузке документов (регистраторов) // и наборов записей регистра // ... // Записать загруженные наборы записей И ... КонецЦикла; // Включить использование итогов регистра // (одновреиенно выполнится пересчет итогов) РегистрыНакопления.ПартииТоваров. УстановитьИспользованиеИтогов(Истина); В приведенном примере обеспечивается ситуация, когда заполнение таблицы итогов выполняется единоразово, а не при каждой записи набора записей загружаемых до- кументов. Дело в том, что при включении использования итогов система производит пересчет всех итогов с момен- та самого раннего движения, сделанного после отключе- ния активности итогов. В отношении использования подобных приемов необхо- димо понимать, что при отключенном расчете итогов ре- гистра система не может обеспечить непротиворечивость данных таблиц движений и итогов регистра. Поэтому по- пытки обращений к итогам такого регистра будут откло- няться системой с выдачей соответствующих предупреж- дений об этом. Запись данных в таблицу движений регистра накопления Для понимания работы механизмов формирования или модификации записей в таблице движений регистра на- копления необходимо, прежде всего, исходить из положе- ния о том, что все записи в регистрах уникальны с точки зрения комбинации значений в ключевых полях. Регистры накопления не поддерживают независимого фор- мирования записей без использования документа-регист- ратора. Этим достигается обоснованность информации ре- гистров — данными документов. То есть обоснованность информации объектов, осуществляющих учет показате- лей, данными объектов, осуществляющих первичную ре- гистрацию событий, приводящих к изменению значений показателей. С другой стороны, к одному регистратору мо- жет быть отнесено более одной записи движения. Поэтому для регистров накопления в таблице движений ключевы- ми являются поля Регистратор и НомерСтроки (рис. 8.9). Ключевые поля Рис. 8.9. Набор записей регистра накопления Для обеспечения манипулирования записями регистра при формировании или модифицировании движений ис- пользуется объект встроенного языка системы РегистрНа- копленияНаборЗаписей.<иия>. В отношении регистров накоп- ления эти действия выполняются при использовании обязательного отбора по регистратору. То есть запись мо- дифицированных данных в таблицу движений регистра накопления не может выполняться отдельно для каждого движения, а только «блоками», то есть наборами записей, подчиненных одному регистратору. Поле НомерСтроки система заполняет автоматически, при добавлении или вставке новой записи в набор записей, отобранных по первому ключевому полю — Регистратор. Поле НомерСтроки содержит порядковый номер записи в на- боре записей, подчиненных одному регистратору. Кроме того, в регистре накопления не могут существо- вать записи с пустым значением поля «регистратор», то есть не подчиненные ни одному регистратору или «под- чиненные пустому регистратору». Это противоречило бы принципу «обоснованности данных регистра накопления». Таким образом, в отношении движений регистров накоп- ления можно констатировать строгую связь с двумя клас- сами объектов конфигурации: ♦ с регистрами, как «хранителями» движений; ♦ с документами, как с «обоснованием» формирования и наличия движений. Соответственно, для заполнения или модификации дан- ных таблицы движений есть две возможности: ♦ посредством создания набора записей регистра с обяза- тельным отбором по регистратору; ♦ посредством использования свойства объекта докумен- та Движения, представляющего собой коллекцию наборов записей, подчиненных данному регистратору. ПРИМЕЧАНИЕ Можно сказать, что свойство Движения объекта документа представляет собой определенный «сервис», призванный облегчить труд разработчика по созданию движений доку- мента. В этом свойстве содержатся пустые наборы записей по всем регистрам, по которым документ может выполнять движения. Для этих наборов записей уже установлен отбор по регистратору, соответствующему текущему документу.
Сами же действия по записи могут инициироваться как программно (при выполнении обработок), так и интерак- тивно. Примеры подобных действий приводятся ниже. Свойство Движения объекта документа Свойство Движения — это свойство объекта документа (До- кументОбьект.<Имя>). Состав наборов записей, входящих в эту фиксированную коллекцию, определяется системой, исходя из информации, хранящейся в метаданных (кон- фигурации). Модификация этого состава может осуществляться при работе с документом как с объектом конфигурации (рис. 8.10). й Документ РеализацияТоваров _ П х Основные Данные Нумерация | > Движения Проведение: Удаление движений | Удалять движения аетомагичЁр Журналы Формы Макеты Подсистемы Ввод на основании Права Интерфейсы Обмен данными Прочее В- Регистры накопления -faHCT^fop движении^ Список регистров, наборы записей которых будут включены в коллекцию Д виже ния Продажи -ЕезереыН оменк латуры | Действия^] | <Назад J | Далее> | | Закрыть ] | Справка' Рис. 8.10. Регистры, для которых документ является регистратором Кроме этого, состав наборов записей, создаваемых систе- мой в свойстве Движения, может быть изменен при редак- тировании регистра как объекта конфигурации (рис. 8.11). f* Регистр накопления ТоварыНаСкладах _ О X Основные Данные | ► Регистраторы Фиркы Макеты Подсистемы Права Интерфейсы Обмен данными Прочее Регистраторы: F?] Я) РеализацияТоваров Н РучнаяОперация Г~|ЗаписьДвижений ЗаказПокупателя Г~| Событие У этих документов набор записей регистра будет входить в состав коллекции Движения Реализация? оварое РучнаяОперация | Действия"^] | < Назад~~| [ Далее/ } [ Закрыть | | Справка Рис. 8.11. Документы, которые могут создавать движения в регистре Благодаря использованию данного свойства облегчается работа разработчика, которому необходимо сформировать или модифицировать набор (наборы) записей регистра (регистров), подчиненных данному документу (рис. 8.12). Важно понимать, что платформа во многих механизмах использует обращение к элементам коллекции Движения. Например, при удалении документа система будет для каждого регистра, в котором он может быть регистрато- ром, проверять наличие движений документа с целью их удаления. Поэтому не рекомендуется включать в коллек- цию Движения элементы «с запасом». И наоборот, если не указано, что документ может быть регистратором для не- кого регистра, то система никоим образом не позволит за- писать в данный регистр движения данного документа. Рис. 8.12. Свойство Движения объекта документа Формирование наборов записей посредством свойства Движения объекта документа Формирование новых наборов записей включает в себя операции, состоящие из: ♦ добавления новых записей к набору записей; ♦ заполнения полей записей; ♦ запись набора записей. Например, требуется сформировать движения по регист- ру ТоварыНаСкладах на основании данных документа По- ступлениеТоваров. Причем информация для заполнения полей записей движений в основном находится в таблич- ной части Состав документа. Данная операция может быть выполнена так, как показа- но в листинге 8.3. Листинг 8.3. Пример формирования движений документа // Перебрать коллекцию строк табличной части документа Для Каждого ТекСтрокаСостав Из Состав Цикл // Добавить новую запись к набору записей регистра // ТоварыНаСкладах Движение = Движения. ТоварыНаСкладах. ДобавитьО; // Заполнить поля добавленной записи Движение.ВидДвижения = ВидДвиженияНакопления.Приход; Движение.Период = Дата; Движение.Номенклатура = ТекСтрокаСостав.Номенклатура; Движение.Склад = Склад; Движение.Количество = ТекСтрокаСостав.Количество; Движение.ВидОперации = ВидОперации; КонецЦикла; // Запись заполненного набора записей движений в регистр Движения.ТоварыНаСкладах.Записать();
Краткий комментарий: формирование новых записей движений и их заполнение выполняется в цикле пере- бора строк табличной части документа. Для каждой строки добавляется новая запись к набору записей ре- гистра ТоварыНаСкладах, полученному как элемент кол- лекции свойства Движения данного объекта документа. Поскольку метод ДобавитьО возвращает сам добавлен- ный объект, новая запись получается в переменную Движение. Дальнейшее заполнение полей записи осу- ществляется посредством этой переменной. В конце выполняется запись в таблицу движений регистра всего сформированного набора записей. Хотелось бы обратить внимание на особенности приме- нения метода ЗаписатьО набора записей регистра накоп- ления. Данный метод может применяться с использо- ванием параметра Замещать. Параметр может принимать значения типа Булево, по умолчанию — значение Истина. Действие данного параметра проявляется в случае, если на момент записи нового (или модифицированного) на- бора записей в регистре присутствуют еще записи, подчи- ненные данному же регистратору. Например, в регистре ТоварыНаСкладах присутствует на- бор записей, подчиненный регистратору ПоступлениеТова- ров №1 (табл. 8.6). Записывается новый набор записей (табл. 8.7). Тогда если при записи набора записей для параметра За- мещать будет указано значение ложь (листинг 8.4), то за- писи, существовавшие в регистре накопления, будут со- хранены, и к ним будут добавлены новые записи из записываемого набора (табл. 8.8). Листинг 8.4. Запись набора записей с добавлением Движения.ТоварыНаСкладах.Записать(Ложь); Если же запись набора записей будет выполняться с за- мещением (листинг 8.5), то старый набор записей будет замещен, и после выполнения операции регистр будет со- держать записи, показанные в табл. 8.9. Листинг 8.5. Запись набора записей с замещением Движения.ТоварыНаСкладах.Записать(Истина): // альтернативный вариант вызова Движения. ТоварыНаСкладах.ЗаписатьО; Таблица 8.6. Состав записей регистра накопления Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 10 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 Таблица 8.7. Записываемый набор записей Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 Приход Истина Пульт VH Главный 10 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 Приход Истина Пульт PW Главный 7 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 Приход Истина Шнур R-100 Главный 100 Таблица 8.8. Состав записей регистра накопления Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 10 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 3 Приход Истина Пульт VH Главный 10 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 4 Приход Истина Пульт PW Главный 7 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 5 Приход Истина Шнур R-100 Главный 100
Таблица 8.9. Состав записей регистра накопления Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 10 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 3 Приход Истина Шнур R-100 Главный 100 Данная возможность позволяет решать различные при- кладные задачи, связанные с: ♦ добавлением новых движений к старым; ♦ замещением старых движений новыми. Хотелось бы отметить, что все вышеописанные действия по формированию движений типизированы, и большая часть кода посвящена заполнению полей регистра значе- ниями полей документа. Поэтому для облегчения написа- ния соответствующего кода разработчик может использо- вать конструктор движений документа (рис. 8.13). Рис. 8.13. Конструктор движений документа Программное изменение данных регистра можно исполь- зовать при проведении документа, а можно и без прове- дения. Поскольку заполнение учетных данных чаще всего вы- полняется во время операции проведения документа, то конструктор движений документа создает соответствую- щий код именно в рамках процедуры обработчика собы- тия ОбработкаПроведения. формирование движений при проведении документа Проведение документов чаще всего используется для фор- мирования движений документов. Этому способствует удобство функциональных решений, заложенных в плат- форму. Например: ♦ с точки зрения платформы отдельного процесса «прове- дение» не существует, есть запись документа с проведе- нием, причем в рамках одной транзакции. Подробно это описано в разделе «Запись документов», с. 139. Таким образом, в момент выполнения обработчика события ПроведениеДокумента документ уже записан. То есть раз- работчику не надо беспокоиться о предотвращении по- пыток проведения незаписанных документов (рис. 8.14); Запись объекта документа с проведением Рис. 8.14. Последовательность событий при записи документа с проведением ♦ если свойство Удаление движений документа, как объекта конфигурации, имеет значение Удалять движения автоиа- тически, то при записи документа с проведением сначала удаляются все старые движения, подчиненные данно- му документу. То есть на момент выполнения обработ- чика события ОбработкаПроведения в регистрах не будет наборов записей с движениями данного документа (разработчику не приходится беспокоиться об их очи- стке). ♦ при записи с проведением система автоматически запи- шет модифицированные и незаписанные наборы запи- сей, находящиеся в свойстве Движения. Это еще один «сервис», обеспечиваемый свойством Движения. Отсюда следуют два важных вывода. Во-первых, если наборы записей необходимо записывать с добавлением, то это нужно выполнять в явном виде, так как при автомати- ческой записи движений они будут записаны с замеще- нием. Во-вторых, последовательность обращения к ре- гистрам при автоматической записи движений будет одна и та же для разных документов. Это позволяет снизить вероятность взаимных блокировок при прове- дении документа в конкурентных режимах работы.
Таким образом, в отношении формирования движений по регистрам накопления зачастую доработки сформиро- ванной конструктором процедуры обработчика события ОбработкаПроведения могут быть сведены к удалению строк кода, связанных с непосредственной записью сформиро- ванных при проведении движений (листинг 8.6). Листинг 8.6. Пример процедуры ОбработкаПроведения Процедура ОбработкаПроведения(Отказ, Режим) // {{_КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ // Данный фрагмент построен конструктором. // При повторном использовании конструктора внесенные // вручную изменения будут утеряны!!! // Перебрать коллекцию строк табличной части документа Для Каждого ТекСтрокаСостав Из Состав Цикл // Добавить новую запись к набору записей. // Регистр ТоварыНаСкладах Движение = Движения.ТоварыНаСкладах.ДобавитьО; // Заполнить поля добавленной записи Движение.ВидДвижения = ВидДвиженияНакопления.Приход; Движение.Период = Дата; Движение.Номенклатура = ТекСтрокаСостав.Номенклатура; Движение.Склад = Склад; Движение.Количество = ТекСтрокаСостав.Количество; Движение.ВидОперации = ВидОперации: КонецЦикла; // Запись движений будет произведена неявно // Движения.ТоварыНаСкладах.Записать(); // }}_КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ КонецПроцедуры В случаях если необходимо программно вызвать саму об- работку проведения, инициируется запись документа с проведением. Пример программного вызова проведения документа в оперативном режиме приведен в листинге 8.7. Листинг 8.7. Пример программного вызова проведения документа Документ. Записать (РежимЗаписиДокумента. Проведение, РежимПроведенияДокумента. Оперативный): В демонстрационной конфигурации «Хранение инфор- мации и учет движения средств», которая находится на прилагаемом компакт-диске, в обработке ДействияСДви- жениямиРегистраНакопления приводится пример перепро- ведения документов РеализацияТоваров в интервале с Да- таНачала по ДатаКонца (листинг 8.8). Листинг 8.8. Пример перепроведения документов РеализацияТ ова ров // Получить ссылки на проведенные документы в требуемом // интервале Запрос = Новый Запрос: Запрос. Текст = "ВЫБРАТЬ РеализацияТоваров.Ссылка ИЗ Документ.РеализацияТоваров КАК РеализацияТоваров ГДЕ РеализацияТоваров.Дата МЕЖДУ ВДатаНачала И ВДатаОкончания И РеализацияТоваров.Проведен": Запрос.УстановитьПараметрС"ДатаНачала". ДатаНачала); Запрос.УстановитьПаранетр("ДатаОкончания". ДатаКонца); Результат = Запрос.ВыполнитьО; // Перебрать ссылки полученных документов Выборка = Результат. ВыбратьО; Пока Выборка.Следующий() Цикл // Перепровести каждый документ неоперативно Документ = Выборка.Ссылка.ПолучитьОбъектО; Документ.Записать(РежимЗаписиДокумента.Проведение); КонецЦикла; Здесь инициировалось проведение в неоперативном ре- жиме. Значение по умолчанию параметра РежинПроведения метода объекта документа ЗаписатьО — именно РежинПро- веденияДокунента.Неоперативный. Говоря о записи документа, необходимо отдельно упомя- нуть случай, когда документ записывается с проведением в форме самого документа. Запись в форме позволяет использовать функциональ- ность, определяемую расширением формы документа; ус- тановка даты документа, установка режима проведения, запрет определенных действия пользователя и т. д. Под- робно эти действия рассматриваются в разделе «Особен- ности работы формы документа», с. 157. В качестве примера записи в форме в демонстрационной конфигурации «Хранение информации и учет движения средств», которая находится на прилагаемом компакт- диске, в форме документа РеализацияТоваров в командную панель ОсновныеДействия добавлена кнопка Провести не- оперативно. Действия, выполняемые по нажатию этой кнопки, представлены в листинге 8.9. Листинг 8.9. Пример записи документа с проведением в форме Процедура ОсновныеДействияФорныПровестиНеоперативно(Кнопка) // Установить использование режима неоперативного // проведения ИспользоватьРежимПроведения = ИспользованиеРежимаПроведения.Неоперативный: // Выполнить проведение в форме ЗаписатьВФорне(РежимЗаписиДокумента.Проведение): КонецПроцедуры В данном примере используются свойство и метод рас- ширения формы документа; свойство ИспользоватьРежин- Проведения и метод ЗаписатьВФормеО. Формирование движений в объекте документа, но без проведения документа С прикладной точки зрения часто возникает потребность сформировать движения для документов, чья обработка еще полностью не завершена и завершена будет, возможно, не в этом сеансе работы с программой, а через некоторое время. Поэтому платформа 1С:Предприятия позволяет в способе формирования движений не ограничиваться только проведением документа. Однако нужно помнить, что кроме выполнения самих движений, при формировании движений вне процеду- ры, обрабатывающей проведение документа, необхо- димо:
♦ контролировать, чтобы документ был сохранен на мо- мент записи движений в регистр (записи должны со- держать ссылку на регистратор); ♦ решать, что делать со старыми движениями документа; ♦ явно записывать сформированные наборы записей дви- жений. Пример формирования движений без проведения доку- мента приведен в демонстрационной конфигурации «Хра- нение информации и учет движения средств», которая находится на прилагаемом компакт-диске. В форме доку- мента ПоступлениеТоваров создана кнопка ФормированиеДви- жений. Процедура действия данной кнопки (листинг 8.11) передает управление процедуре ФормированиеДвижений- БезПроведения() модуля объекта документа (листинг 8.10). Листинг 8.10. Пример формирования движений документа без проведения Процедура ФормированиеДвиженийБезПроведения!) Экспорт // Проверить и записать документ, если ранее не записан Если ЭтоНовый!) Тогда Записать!); КонецЕсли; // Очистить старые движения документа Движения.ТоварыНаСкладах.Очистить!); Для Каждого ТекСтрокаСостав Из Состав Цикл // Сформировать и заполнить запись движения Движение = Движения.ТоварыНаСкладах.Добавить!); Движение.ВидДвижения = ВидДвиженияНакопления.Приход; Движение.Период = Дата; Движение.Номенклатура = ТекСтрокаСостав.Номенклатура; Движение.Склад = Склад; Движение.Количество = ТекСтрокаСостав.Количество; Движение.ВидОперации = ВидОперации; КонецЦикла; // Записать движения регистров с замещением старых // наборов записей Движения.ТоварыНаСкладах.Записать(); КонецПроцедуры Краткий комментарий: сначала необходимо убедиться, что ссылка на данный документ уже есть в базе данных, то есть документ не новый. Если нет — документ записы- вается, поскольку без ссылки на регистратор движения в регистре накопления сформированы быть не могут. Да- лее отрабатывается ситуация многократного вызова про- цедуры посредством нажатия кнопки в открытой форме документа — очищается набор записей движений данного документа по регистру ТоварыНаСкладах. Это необходимо для предотвращения «размножения» движений докумен- та после каждого выполнения процедуры. Потом форми- руется новый набор записей в цикле перебора строк таб- личной части Состав документа. Далее сформированный набор записей записывается в регистр. Хотелось бы обратить внимание на то, что в данной про- цедуре выполнялась принудительная очистка набора за- писей. Объясняется это следующим: основным реквизи- том формы документа является объект документа. После первого нажатия кнопки в форме документа и вызова нашей процедуры будет заполнен элемент коллекции, со- держащейся в свойстве объекта документа Движения, — на- бор записей регистра ТоварыНаСкладах, подчиненный дан- ному документу. После второго нажатия кнопки, если бы этот набор записей не очищался, то к тем записям, кото- рые были в наборе записей, добавлялись бы еще записи, в цикле перебора строк документа. А потом уже «попол- ненный» набор записей (то есть исходные записи плюс соответствующие строкам табличной части документа) записывался бы в регистр. Также следует обратить внимание на то, что в заголовке процедуры, выполняющей эти действия, указано ключе- вое слово Экспорт. В результате данная процедура доступна в контексте объекта документа. Вызов данной процедуры в демонстрационной конфигурации «Хранение инфор- мации и учет движения средств», которая находится на прилагаемом компакт-диске, выполняется из модуля формы данного документа. Основным реквизитом фор- мы документа как раз и является объект документа, по- этому процедура будет доступна в контексте формы доку- мента (см. листинг 8.11). Листинг 8.11. Пример вызова процедуры из формы документа Процедура ОсновныеДействияФормыФормированиеДвижений(Кнопка) // Передать управление процедуре модуля объекта документа ФормированиеДвиженийБезПроведения(); КонецПроцедуры В принципе, вызов этой процедуры может быть реализо- ван почти из любого модуля программы, для этого надо лишь получить объект документа (например, из ссылки на документ) (листинг 8.12). Листинг 8.12. Пример вызова процедуры из модуля обработки // Получить объект документа Документ = СсылкаНаДокумент.ПолучитьОбъектО; // Вызвать процедуру модуля объекта документа, формирующую // движения Документ.ФормированиеДвиженийБезПроведения!); Модификация существующих движений документа Кроме задачи формирования новых движений без про- ведения документа разработчикам иногда приходится решать задачи изменения информации в движениях (мо- дификации движений), снятия активности движений до- кумента или, вообще, удаления движений. Технология их решения — абсолютно та же. Это запись наборов записей регистра. Только соответствующим образом модифици- рованных. Для модификации движений можно сначала прочитать набор записей движений, далее модифицировать записи и записать уже модифицированный набор записей дви- жений. Обратите внимание: элемент коллекции свойства доку- мента Движения представляет собой набор записей регист- ра. Но он, пока не прочитан, — пуст (рис. 8.15). Поэтому для того, чтобы модифицировать записи регист- ра, необходимо сначала прочитать данные наборы запи- сей (рис. 8.16). В демонстрационной конфигурации «Хранение инфор- мации и учет движения средств», которая находится на
прилагаемом компакт-диске, в форме документа Поступ- лениеТоваров приведен пример заполнения поля реквизи- та Поставщик регистра ТоварыНаСкладах значением из кон- станты ОсновнойПоставщик (листинг 8.13). Рис. 8.15. Коллекция Движения содержит пустые наборы записей нии поля Активность, и может выполняться аналогично. Однако с прикладной точки зрения свойство записи дви- жения Активность — особое. Во-первых, наличие активных движений документа в ре- гистре означает, что данный документ отражен в неком аспекте учета. Вернее, в учете отражено событие, зафик- сированное данным документом. Во-вторых, наличие движений документа со снятой ак- тивностью означает, что движения данного документа не используются в учетном механизме. В-третьих, наличие движений документа в регистре, из которых часть активна, а часть не активна, с точки зрения практического применения — нонсенс. Например, попро- буйте представить себе ситуацию: «Отгружено пять пы- лесосов и холодильник, но не совсем. Холодильник — не отгружен». Поэтому платформа не допускает записи набора записей движений регистра, если часть записей в этом наборе активна, а часть нет (рис. 8.17). Рис. 8.16. Чтение набора записей Листинг 8.13. Пример модификации движений документа //Получить значение основного поставщика ОсновнойПоставщик = Константы.ОсновнойПоставщик.ПолучитьО; // Прочитать набор записей движений по регистру // "ТоварыНаСкладах" НаборЗаписей = Движения.ТоварыНаСкладах; НаборЗаписей. Прочитать (); Объект манипулирования данными документа Набор записей регистра N. подчиненный данному документу Активность ИСТИНА ИСТИНА ИСТИНА Набор записей регистра N, подчиненный данному документу Активность ИСТИНА ЛОЖЬ ИСТИНА Набор записей регистра N. подчиненный данному документу Активность ложь ложь ложь База данных Таблица движений регистра N Регистратор Т аблица движений регистра N Регистратор Таблица движений регистра N Рис. 8.17. Варианты использования свойства Активность В системе предусмотрена возможность установки и сня- тия активности целиком для всего набора записей по- средством метода УстановитьАктивностьО набора записей регистра накопления. В демонстрационной конфигурации «Храпение инфор- мации и учет движения средств», которая находится на прилагаемом компакт-диске, в форме документа Поступ- лениеТоваров приводится пример снятия активности всех движений документа по регистрам (листинг 8.14). // Модифицировать каждую запись в прочитанных движениях Если НаборЗаписей.Количество()<> 0 Тогда Для Каждого Движение Из НаборЗаписей Цикл Движение.Поставщик = ОсновнойПоставщик; КонецЦикла; // Записать измененный набор записей НаборЗаписей.Записать(); КонецЕсли; Снятие активности движений — по сути дела, та же зада- ча модификации движений документа, только в отноше- Листинг 8.14. Пример снятия активности записей // Перебрать наборы записей по регистрам Для Каждого НаборЗаписей Из Движения Цикл И Прочитать движения по регистру НаборЗаписей.Прочитать(); // Снять активность НаборЗаписей.УстановитьАктивность(Ложь); // Записать набор записей НаборЗаписей.Записать(); КонецЦикла;
И, наконец, операция удаления движений документа. Она сводится к записи пустого набора записей регистра. В си- туации, когда набор записей регистра прочитан и не пуст, можно использовать его предварительную очистку. В де- монстрационной конфигурации «Хранение информации и учет движения средств», которая находится на прила- гаемом компакт-диске, в форме документа Поступление- Товаров при выполнении действия ОчиститьДвиженияДо- кумента выполняется процедура с текстом, который представлен в листинге 8.15. Листинг 8.15. Пример удаления движений документа // Перебрать наборы записей по регистрам Для Каждого НаборЗаписей Из Движения Цикл // Очистить набор записей движений по регистру НаборЗаписей.Очистить(); //Записать набор записей НаборЗаписей.Записать О; КонецЦикла; Однако если бы была полная уверенность, что ни один из наборов записей регистров для данного объекта докумен- та на момент выполнения процедуры не прочитан, то предварительную очистку можно было бы не делать (лис- тинг 8.16). Листинг 8.16. Пример удаления движений документа // Перебрать наборы записей по регистрам Для Каждого НаборЗаписей Из Движения Цикл //Записать набор записей НаборЗаписей.Записать(); КонецЦикла Интерактивное формирование наборов записей с помощью свойства Движения объекта документа Описанный выше функционал системы касался вопросов наиболее часто встречающихся решений задач формиро- вания движений документов. То есть пользователь отве- чает за правильность ввода информации в документ, а разработчик — за правильность работы обработок, ин- терпретирующих и записывающих в регистры учетную информацию, полученную согласно данным документов. Однако иногда могут встречаться ситуации, когда не тре- буется никакой дополнительной обработки для вводимой пользователем информации. То есть тогда можно обеспе- чить ввод информации напрямую в данные регистра, без промежуточной регистрации ее в данных документа. Для регистров накопления в любой ситуации возможно содержание информации только с использованием доку- мента-регистратора. Поэтому в таких случаях для обеспе- чения и требования «обоснованности» данных регистра наличием регистратора, и желания уменьшения избыточно- сти хранения информации в базе данных возможно приме- нение технологии, условно называемой «ручная операция». В форме документа отображаются данные и документа, и движений регистра, которые починены данному доку- менту (рис. 8.18). Отображение данных Форма документа Отображение данных документа N’l I от1 h Отображение данных регистра Хранение данных Рис. 8.18. Редактирование движений вручную В состав демонстрационной конфигурации «Хранение информации и учет движения средств», которая находит- ся на прилагаемом компакт-диске, входит документ Руч- наяОперация. Его создание и технологические вопросы, возникающие при его использовании, подробно описаны в разделе «Специальные случаи использования докумен- тов. Ручная операция», с. 162. Хотелось бы только еще раз подчеркнуть, что для облег- чения работы разработчика здесь использовалось свойст- во Движения объекта документа. И табличное поле на фор- ме документа отображает данные одного из элементов этой коллекции — набора записей движений по регистру ТоварыНаСкладах. Пользователь, работая с формой документа, на самом деле интерактивно модифицирует считанные данные на- бора записей движений регистра, подчиненных данному документу (рис. 8.19). Гкйетшя- у. 1Я1 bgf'' Номер. [ Обновление информации. отоЦ -аввлмтА табличным полем, согласно данным регистра 031220051 I Доставка 031220051 . |1С Бу»аптерня^ Dam 10312200513.1пЗГ: Интерактивная дстановка/снятие активности для всего 2 [а«ии„ Расжзд Г^ижрд Рис. 8.19. Форма документа РучнаяОперация А вопросы отображения данных регистра в табличном поле, одновременной установки/снятия активности дви- жений, записи модифицированных данных из реквизита формы в таблицу движений регистра и т. д. берет на себя система посредством возможностей, предоставляемых рас- ширением формы документа. Причем системой отрабатывается большинство ситуа- ций, которые могут привести к коллизиям. Например, если пользователь после внесения изменений в содержи- мое табличного поля, но до записи модифицированных данных в регистр, нажмет кнопку Q (обновить), то он получит предупреждение (рис. 8.20).
Рис. 8.20. Предупреждение при перечитывании данных Запись набора записей регистра без использования свойства Движения В разделе «Свойство Движения объекта документа», с. 184, были описаны действия с объектом документа, приводящие к чтению, модификации, добавлению и запи- си наборов записей в регистр. Те же самые результаты можно получить и без использования объекта документа, а работая непосредственно с набором записей (рис. 8.21). Рис. 8.21. Использование набора записей регистра накопления В данном случае для модификации движений документа не используется объект документа (используется только ссылка на документ). Поэтому при выполнении обрабо- ток массового формирования или модификации движений, связанных не с единичными документами, а с большими массивами документов, уместнее применение приемов работы, основанных на использовании набора записей ре- гистра, так как этот способ является менее ресурсоемким. Например, в состав конфигурации уже заполненной базы данных ввели новый оборотный регистр Продажи со сле- дующей структурой (рис. 8.22). -Ifa Продажи Ё JL. Измерения L. Номенклатура L- Контрагент Й fa Ресурсы | p-g Количество 1 | Сумма Eg Реквизиты L-— ВидОперации Рис. 8.22. Структура регистра Продажи Он должен заполняться при проведении документа Реа- лизацияТоваров данными документа (включая данные его табличной части Состав), поэтому в обработку проведения данного объекта конфигурации были внесены соответст- вующие изменения. Однако существует уже достаточно много оформленных и проведенных еще в то время, когда нового регистра не было, документов РеализацияТоваров. Как для них сформировать движения по новому регистру? Можно, конечно, перепровести все ранее проведенные РеализацияТоваров. Однако при проведении документа не только выполняются движения по новому регистру. Фор- мируются движения по другим регистрам, записываются данные в таблицу документа, в таблицы журналов доку- ментов и т. д., и т. п. Поэтому данное решение может ока- заться неудобным в отношении скорости исполнения или по другим причинам. В данной ситуации более эффективным выглядит приме- нение следующей обработки. Из базы данных запросом выбрать ссылки на проведенные документы Реализация- Товаров и другие данные этих документов, необходимые для формирования движений. Эти данные можно полу- чить из таблицы документа. Перебирая выборку ре- зультата запроса, применять отбор по регистраторам (ссылкам на документы) для формирования наборов записей движений, подчиненных этим документам (ли- стинг 8.17). Листинг 8.17. Пример формирования движений документов Процедура ФормированиеДвиженийПоПродажаиДляВсехРеализацияТоваров Нажатие(Элемент) // Обратиться к набору записей регистра НаборЗаписейРегистра = РегистрыНакопления. Продажи. СоздатьНаборЗаписейО: // Прочитать из базы данных данные, // необходимые для формирования движений Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ РеализацияТоваровСостав.Ссылка КАК Ссылка, РеализацияТоваровСостав.Ссылка.Дата, РеализацияТоваровСостав.Ссылка.Контрагент, РеализацияТоваровСостав.Номенклатура. РеализацияТоваровСостав.Количество, РеализацияТоваровСостав.Цена. РеализацияТоваровСостав.Сумма ИЗ Документ.РеализацияТоваров.Состав КАК РеализацияТоваровСостав ГДЕ РеализацияТоваровСостав.Ссылка.Проведен ИТОГИ ПО Ссылка": Результат = Запрос.ВыполнитьО; // Перебрать все документы из результата запроса ВыборкаДокументов = Результат.Выбрать( ОбходРезультатаЗапроса.ПоГруппировкам); Пока ВыборкаДокументов.Следующий() Цикл // Установить отбор набора записей по регистратору, //к которому будут приписаны движения НаборЗаписейРегистра.Отбор.Регистратор. Установить(ВыборкаДокументов.Ссылка); // Перебрать данные о составе документа, И необходимые для заполнения формируемых движений ВыборкаДетальныхЗаписей = ВыборкаДокументов. Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаДетальныхЗаписей.СледующийО Цикл Пока Выборка.Следующий() Цикл И Сформировать движения по регистру Продажи НоваяЗапись = НаборЗаписейРегистра.ДобавитьО; НоваяЗапись.Период = ВыборкаДетальныхЗаписей.Дата; НоваяЗапись.Номенклатура = ВыборкаДетальныхЗаписей.Номенклатура; НоваяЗапись.Контрагент = ВыборкаДетальныхЗаписей.Контрагент; НоваяЗапись.Количество = ВыборкаДетальныхЗаписей.Количество: НоваяЗапись.Сумма = ВыборкаДетальныхЗаписей.Сумма; НоваяЗапись.Цена = ВыборкаДетальныхЗаписей.Цена; КонецЦикла; И Записать сформированные для очередного // документа движения НаборЗаписейРегистра.Записать(); // Очистить набор записей регистра // перед использованием для следующего документа НаборЗаписейРегистра.Очистить О; КонецЦикла: КонецПроцедуры Данный пример приведен в составе обработки Действия- СДвижениямиРегистраНакопления демонстрационной кон- фигурации «Хранение информации и учет движения средств», которая находится на прилагаемом компакт- диске. Еще раз хотелось бы подчеркнуть, что данная обработка вообще не обращается к объектам документов. По сути дела движения «приписываются» к документам «без ве- дома объектов документов». Подобным же образом можно решать не только задачи формирования новых движений документов, но и моди- фикации существующих движений. Примеры чтения движений регистров накопления будут приведены ниже, в разделе «Получение движений регистров накопления», с. 198. Частным случаем операций модификации наборов запи- сей регистров накопления является удаление движений. Задача «удалить движения регистра «Продажи» в преде- лах заданного временного интервала» может быть решена следующим образом (листинг 8.18). Листинг 8.18. Пример удаления движений документа Процедура УдалитьДвиженияПоПродажамНажатие(Эленент) // Обратиться к набору записей регистра НаборЗаписейРегистра = РегистрыНакопления.Продажи.СоздатьНаборЗаписей(); // Получить из базы данных ссылки на документы, // у которых нужно удалить движения Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ Продажи.Регистратор ИЗ РегистрНакопления.Продажи КАК Продажи ГДЕ Продажи.Период МЕВДУ &ДатаНачала И ВДатаОкончания"; Запрос.УстановитьПараметрС'ДатаНачала", ДатаНачала); Запрос.УстановитьПараметрС“ДатаОкончания”, ДатаКонца); Результат = Запрос.ВыполнитьО; // Перебрать все документы из результата запроса Выборка = Результат.ВыбратьО; // Установить отбор набора записей по регистратору, //к которому будут приписаны движения НаборЗаписейРегистра.Отбор.Регистратор. Установить(Выборка.Регистратор); // Записать пустой набор записей движений // для очередного документа НаборЗаписейРегистра.Записать(); КонецЦикла; КонецПроцедуры В данном примере использовался следующий прием: на- бор записей регистра, непрочитанный из базы, — пуст. Если записать пустой набор записей регистра с замеще- нием, это приведет к удалению движений замещаемого в рамках отбора набора записей. В заключение хотелось бы только еще раз подчеркнуть — для регистров накопления все действия с модификацией наборов записей регистра можно выполнять только в рамках отбора по регистратору, то есть документу, кото- рому подчинен этот набор записей. Интерактивное формирование движений с помощью формы набора записей Выше, в разделе «Интерактивное формирование наборов записей с помощью свойства Движения объекта докумен- та», с. 190, рассматривался пример, когда в рамках формы документа пользователю предоставлялись возможности интерактивного формирования/модификации движений документа. В случае если пользователю необходимо предоставить те же интерактивные возможности, но без использования формы документа, задача может быть решена посредст- вом использования формы набора записей. В демонстрационной конфигурации «Хранение инфор- мации и учет движения средств», которая находится на прилагаемом компакт-диске, в форме списка документа РучнаяОперация приведен подобный пример. В состав регистра ТоварыНаСкладах включена форма Фор- маНабораЗаписей, основной реквизит которой имеет тип РегистрНакопленияНаборЗаписей. ТоварыНаСкладах. Вызов данной формы может осуществляться любой обра- боткой. Единственно, для возможности выполнения дей- ствий по модификации наборов записей регистра накоп- ления, необходимо помнить об обязательности установки отбора по регистратору. В демонстрационной конфигурации «Хранение инфор- мации и учет движения средств», которая находится на прилагаемом компакт-диске, вызов формы набора запи- сей регистра ТоварыНаСкладах реализуется из формы спи- ска документа РучнаяОперация (рис. 8.23). Обработчик ВызовФормыНабораЗаписей события Действие реализован следующим образом (листинг 8.19).
Рис. 8.23. Форма списка документа РучнаяОперация Рис. 8.24. Форма набора записей регистра Листинг 8.19. Пример использования формы набора записей Процедура ДействияФорныВызовФорныНабораЗаписей(Кнопка) // Получить ссылку на текущий документ ТекущийДокумент = ЭлементыФормы.ДокументСписок.ТекущаяСтрока; // Прочитать набор записей по текущему документу НаборЗаписей = РегистрыНакопления.ТоварыНаСкладах.СоздатьНаборЗаписейО; НаборЗаписей.Отбор.Регистратор.Установить(ТекущийДокумент); НаборЗаписей.Прочитать О; // Открыть форму набора записей ФормаНабораЗаписей = НаборЗаписей.ПолучитьФорму("ФормаНабораЗаписей"); ФормаНабораЗаписей.Открытье); КонецПроцедуры Краткий комментарий: сначала определяется ссылка на документ активной строки табличного поля формы спи- ска. Далее из базы данных читается набор записей с отбо- ром по текущему документу. Для прочитанного набора записей открывается форма ФормаНабораЗаписей. В форме набора записей пользователь может интерак- тивно модифицировать как сам набор записей (удалять, добавлять, копировать и т. д.), так и содержимое полей за- писей, входящих в набор записей. Впоследствии модифи- цированный набор может быть сохранен, то есть записан в регистр (рис. 8.24). Обеспечение выполнения этих действий и устранение возможных коллизий реализуется средствами расшире- ния формы набора записей регистра. Механизмы заполнения таблицы итогов регистра накопления Таблицы итогов регистров накопления заполняются ав- томатически вследствие добавления, удаления или моди- фикации наборов записей в таблице движений регистра, если для этого регистра не отключен режим расчета ито- гов. Расчет итогов производится согласно записям таблицы движений регистра, если свойство Активность этих запи- сей имеет значение Истина. Но для разных видов регистров накопления заполнение данных таблицы итогов выполняется по разным прави- лам. Это объясняется спецификой учитываемых посред- ством регистров показателей. Подробно данная специфика была описана ранее, в разделе «Оперативный учет. Опи- сание задач, решаемых регистрами накопления», с. 177. Механизм заполнения таблицы итогов регистра остатков В таблице итогов регистра остатков хранятся актуальные итоги и могут храниться итоги рассчитанных периодов. Актуальные итоги — это итоговые значения учитываемых в регистре ресурсов (показателей) на момент времени за- ведомо больший, нежели любое значение поля Период за- писей таблицы движений. Для определенности актуаль- ные итоги регистров остатков датированы на 01.11.3999 00:00:00. Итоги рассчитанных периодов содержат данные конеч- ных значений ресурсов для каждого месяца, предшест- вующего границе рассчитанных итогов. При записи набора активных записей в таблице движе- ний всегда рассчитываются и перезаписываются актуаль- ные итоги в таблице итогов, если у регистра установлен признак использования итогов. Данные итогов периодов в таблице итогов появляются вследствие расчета итогов. Такой расчет может быть ини- циирован посредством системной команды Управление итогами (рис. 8.25). Также расчет итогов может быть выполнен программно (листинг 8.20). Листинг 8.20. Программный расчет итогов регистра РегистрыНакопления.ТоварыНаСкладах. УстановитьПериодРассчитанныхИтогов(Дата(2005, 08, 31));
Г раница рассчитанных итогов может устанавливаться для всех регистров остактов сразу. Рис. 8.25. Управление итогами Например, пусть таблица движений регистра накопления будет заполнена данными, как показано в табл. 8.10. Для вышеприведенного примера заполнения таблицы движений регистра, таблица итогов регистра после расче- та итогов по 31.08.2005 будет выглядеть так, как показано в табл. 8.11. Обратите внимание, августовские итоги хранятся с указа- нием периода 01.09.2005 00:00:00, потому что итоги рас- считаны на начало сентября. То есть при их расчете учтены все записи, которые зафиксированы в августе, включая 31.08.2005 23:59:59 (рис. 8.26). Таблица 8.10. Таблица движений регистра накопления остатков Период Регистратор Номер Строки Вид дви- жения Актив- ность Номен- клатура Склад Коли- чество Сумма 03.07.2005 15:00:00 ПоступлениеТоваров №1 13.08.2005 15:00:00 1 Приход Истина Пульт VH Главный 1 10 13.08.2005 15:00:01 ПоступлениеТоваров №2 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 9 90 13.08.2005 15:00:01 ПоступлениеТоваров №2 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 490 23.08.2005 15:30:45 ПоступлениеТоваров №3 23.08.2005 15:30:45 1 Приход Ложь Пульт VH Фили-2 5 60 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Расход Истина Пульт VH Главный 8 80 31.08.2005 23:59:59 ПоступлениеТоваров №4 31.08.2005 23:59:59 1 Приход Истина Пульт PW Фили-2 1 17 01.09.2005 00:00:00 ПоступлениеТоваров №5 01.09.2005 00:00:00 1 Приход Истина Пульт VH Фили-2 1 18 Таблица 8.11. Таблица итогов регистра накопления остатков Период Номенклатура Склад Количество Сумма Итоги июля 2005 года 01.08.2005 00:00:00 Пульт VH Главный 1 10 Итоги августа 2005 года (граница рассчитанных итогов) 01.09.2005 00:00:00 Пульт VH Главный 2 20 01.09.2005 00:00:00 Пульт PW Главный 7 490 01.09.2005 00:00:00 Пульт PW Фили-2 1 17 Актуальные итоги 01.11.3999 00:00:00 Пульт VH Фили-2 1 18 01.11.3999 00:00:00 Пульт VH Главный 2 20 01.11.3999 00:00:00 Пульт PW Главный 7 490 01.11.3999 00:00:00 Пульт PW Фили-2 1 17
Регистрация движений Г раница рассчитанных итогов Актуальные итоги Рис 8.26. Хранение рассчитанных итогов регистра накопления остатков Наличие посчитанных по конец каждого месяца итогов положительно сказывается на быстродействии обраще- ний к остаткам регистра. Как будет еще более подробно описано ниже, в разделе «Получение остатков», с. 202, расчет остатков начинается с определения ближайшего равного или большего итога (хранимого в таблице итогов регистра) с последующим «досчетом» остатка на нужный момент времени по таблице движений. Но зачастую может сложиться ситуация, что граница рас- считанных итогов очень сильно «отстает» от периода са- мой последней записи в регистре. Данное положение не сказывается на функциональности регистра, сказывается только на быстродействии обращений к его остаткам. По- скольку досчет тогда будет производиться, скорее всего, по большему количеству записей. При добавлении, удалении, модификации записей таб- лицы движений регистра система автоматически произ- водит пересчет всех рассчитанных итогов, начиная с того периода (месяца), к которому относится значение поля Период записей. Так же пересчитываются актуаль- ные итоги. Этот процесс захватывает все записи итогов, в которых указаны значения измерений модифицируе- мых записей. Главное, чтобы значение поля Активность модифицируемых записей таблицы движений было Ис- тина. Например, пусть к записям регистра добавляются записи, выделенные в табл. 8.12. В этом случае будет производиться перерасчет итогов только по комбинации значений измерений Пульт PW и Фили-2 (табл. 8.13). Ведь свойство Активность движений документа Поступление товаров №7 имеет значение Ложь. Таблица 8.12. Добавление записей в таблицу движений регистра остатков Период Регистратор Номер Строки Вид дви- жения Актив- ность Номен- клатура Склад Коли- чество Сумма 03.07.2005 15:00:00 Поступление товаров №1 13.08.2005 15:00:00 1 Приход Истина Пульт VH Главный 1 10 13.08.2005 15:00:01 Поступление товаров №2 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 9 90 13.08.2005 15:00:01 Поступление товаров №2 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 490 15.08.2005 11:00:01 Поступление товаров №6 13.08.2005 15:00:01 1 Приход Истина Пульт PW Фили-2 10 120 15.08.2005 11:01:01 Поступление товаров №7 13.08.2005 15:00:01 1 Приход Ложь Пульт PW Главный 1 1 23.08.2005 15:30:45 Поступление товаров №3 23.08.2005 15:30:45 1 Приход Ложь Пульт VH Фили-2 5 60 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Расход Истина Пульт VH Главный 8 80 31.08.2005 23:59:59 Поступление товаров №4 31.08.2005 23:59:59 1 Приход Истина Пульт PW Фили-2 1 17 01.09.2005 00:00:00 Поступление товаров №5 01.09.2005 00:00:00 1 Приход Истина Пульт VH Фили-2 1 18 Таблица 8.13. Таблица итогов регистра накопления остатков Период Номенклатура Склад Количество Сумма 01.08.2005 00:00:00 Пульт VH Главный 1 10 01.09.2005 00:00:00 Пульт VH Главный 2 20 01.09.2005 00:00:00 Пульт PW Главный 7 490 01.09.2005 00:00:00 Пульт PW Фили-2 И 137 01.11.3999 00:00:00 Пульт VH Фили-2 1 18 01.11.3999 00:00:00 Пульт VH Главный 2 20 01.11.3999 00:00:00 Пульт PW Главный 7 490 01.11.3999 00:00:00 Пульт PW Фили-2 И 137
Таблица 8.14. Записи, добавляемые в регистр остатков Период Регистратор Номер Строки Вид дви- жения Актив- ность Номен- клатура Склад Коли- чество Сумма 02.09.200 5 10:00:00 РеализацияТоваров №2 02.09.2005 10:00:00 1 Расход Истина Пульт VH Главный 2 20 02.09.200 5 10:00:00 РеализацияТоваров №2 02.09.2005 10:00:00 2 Расход Истина Пульт PW Главный 1 70 Таблица 8.15. Таблица итогов регистра накопления остатков Период Номенклатура Склад Количество Сумма 01.08.2005 00:00:00 Пульт VH Главный 1 10 01.09.2005 00:00:00 Пульт VH Главный 2 20 01.09.2005 00:00:00 Пульт PW Главный 7 490 01.09.2005 00:00:00 Пульт PW Фили-2 И 137 01.11.3999 00:00:00 Пульт VH Фили-2 1 18 01.11.3999 00:00:00 Пульт PW Главный 6 420 01.11.3999 00:00:00 Пульт PW Фили-2 И 137 Таблица 8.16. Таблица итогов регистра накопления остатков Период Номенклатура Склад Количество Сумма 01.08.2005 00:00:00 Пульт VH Главный 1 10 01.09.2005 00:00:00 Пульт VH Главный 2 20 01.09.2005 00:00:00 Пульт PW Главный 7 490 01.09.2005 00:00:00 Пульт PW Фили-2 И 137 01.10.2005 00:00:00 Пульт VH Фили-2 1 18 01.10.2005 00:00:00 Пульт PW Главный 6 420 01.10.2005 00:00:00 Пульт PW Фили-2 И 137 01.11.3999 00:00:00 Пульт VH Фили-2 1 18 01.11.3999 00:00:00 Пульт PW Главный 6 420 01.11.3999 00:00:00 Пульт PW Фили-2 и 137 В случае если в результате расчета актуальных итогов или итогов периода окажется, что по некой комбинации значений измерений итоги всех ресурсов «выводятся в ноль», то данная запись удаляется системой из таблицы итогов при общем пересчете итогов. Например, если к вышеприведенным примерам в табли- цу движений добавить еще записи, представленные в табл. 8.14, то таблица итогов регистра после общего пере- счета итогов в результате будет заполнена так, как пока- зано в табл. 8.15. Если впоследствии будет произведен расчет итогов по 30.09.2005, то таблица итогов примет вид, представлен- ный в табл. 8.16. Механизм заполнения таблицы итогов оборотного регистра При добавлении, удалении или модификации наборов за- писей в таблице движений всегда рассчитываются итоги в том периоде (месяце), к которому принадлежит значе- ние поля Период записи. В отличие от регистра остатков этот процесс не зависит от периода рассчитанных итогов базы данных (рис. 8.27). Для расчета итогов учитываются только записи, у кото- рых поле Активность имеет значение Истина. Пример заполнения таблицы движений оборотного реги- стра Продажи представлен в табл. 8.17.
Регистрация движений Рассчитанные итог 01 08.2005 00:00:00 (обороты августа) 01 09.2005 00:00:00 (обороты сентября) 01 11 2005 00 00:00 (обороты ноября) Рис 8.27. Хранение рассчитанных итогов оборотного регистра накопления Для вышеприведенного примера заполнения таблицы дви- жений система заполнит таблицу итогов регистра сле- дующим образом (табл. 8.18). Обратите внимание: поле Период заполняется значением даты начала периода (месяца), по которому хранятся итоги. Хотя для оборотного регистра не существует понятий «расход» и «приход», однако при необходимости можно использовать формирование движений с отрицательны- ми значениями ресурсов. Например, для отражения ситуации «возврат от покупа- теля» в регистр Продажи можно добавить такую запись (табл. 8.19). В результате система пересчитает ноябрьские итоги по комбинации значений измерений ПультУН, Ялта-Лтд. Поскольку при общем пересчете итогов для оборотного регистра также удаляются записи, содержащие нулевые значения всех ресурсов, то содержание таблицы итогов после этого будет следующим (табл. 8.20). Таблица 8.17. Таблица движений оборотного регистра накопления Период Регистратор Номер Строки Активность Номенклатура Контрагент Количество Сумма 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Истина Пульт VH Ялта-Лтд 9 135 29.08.2005 15:00:01 Реализация Кв 2 29.08.2005 15:00:01 1 Истина Пульт VH Компания «Риона» 10 150 13.09.2005 15:00:00 Реализация №3 13.09.2005 15:00:00 1 Истина Пульт VH Компания «Риона» 1 15 23.09.2005 10:00:00 Реализация №3 23.09.2005 10:00:00 1 Истина Пульт VH Компания «Риона» 1 15 23.09.2005 15:30:45 Реализация №4 23.09.2005 15:30:45 1 Ложь Пульт PW Крона 1 90 01.11.2005 08:59:59 Реализация №5 01.10.2005 08:59:59 1 Истина Пульт PW Ялта-Лтд 1 95 Таблица 8.18. Таблица итогов оборотного регистра накопления Период Номенклатура Контрагент Количество Сумма Итоги августа 01.08.2005 00:00:00 Пульт VH Ялта-Лтд 9 135 2005 года 01.08.2005 00:00:00 Пульт VH Компания «Риона» 10 150 Итоги сентября 2005 года 01.09.2005 00:00:00 Пульт VH Компания «Риона» 2 30 Итоги ноября 2005 года 01.11.2005 00:00:00 Пульт PW Ялта-Лтд 1 95 Таблица 8.19. Запись, добавляемая в оборотный регистр накопления Период Регистратор Номер Строки Активность Номенклатура Контрагент Количество Сумма 17.11.2005 17:30:00 ВозвратОтПокупателя №1 17.11.2005 17:30:00 1 Истина Пульт VH Ялта-Лтд -1 -95 Таблица 8.20. Таблица итогов оборотного регистра накопления Период Номенклатура Контрагент Количество Сумма 01.09.2005 00:00:00 Пульт VH Ялта-Лтд 9 135 01.09.2005 00:00:00 Пульт VH Компания «Риона» 10 150 01.10.2005 00:00:00 Пульт VH Компания «Риона» 2 30
Получение данных из регистров накопления Вопросы получения данных из регистров накопления мо- гут касаться как получения движений, так и получения итоговых значений учитываемых в регистре показателей. Получение движений может требоваться как для реше- ния технологических задач работы с информацией ре- гистров, так и для решения аналитических задач, но ка- сающихся только приращений учитываемых в регистрах показателей. Приемы и средства решения этих задач, как правило, не зависят от вида регистра, то есть одинаковы для регистров остатков и оборотных регистров. Это объ- ясняется тем, что в любом случае обращение к данным движений в регистрах (хоть запросом, хоть посредством объектной модели) интерпретируется в запрос СУБД к таблице движений регистра. А приемы работы с одной таблицей базы данных практически одинаковы, тем более что состав полей и их содержимое, хотя бы и для разных видов регистров накопления, весьма схожи. Получение движений можно производить посредством следующих приемов (табл. 8.21). Таблица 8.21. Способы получения движений Табличная модель Объектная модель Регистр остатков Оборотный регистр Регистр остатков Оборотный регистр Запрос к основной таблице регистра Методы Выбрать () и ВыбратьПоРегистраторуС) менеджера регистра А вот приемы получения разных видов итогов и эффек- тивности этих действий по скорости выполнения для раз- ных видов регистров, как будет рассматриваться ниже, сильно отличаются. Тут проявляются различия в при- роде показателей, учитываемых в регистрах остатков и оборотных регистрах (описаны в разделе «Оперативный учет. Описание задач, решаемых регистрами накопле- ния», с. 177), требующие различий в хранении данных промежуточных итогов (описаны в разделе «Структура регистра накопления», с. 179). В целом действия, которые выполняются при получении итогов регистров, можно классифицировать следующим образом (табл. 8.22). Следует заметить, что для любого действия, связанного с получением итогов регистра накопления, справедливы следующие утверждения: ♦ итоги ресурсов собираются только по активным запи- сям; ♦ итоги можно получать только по тем регистрам, у кото- рых использование итогов включено. При попытке по- лучения итогов для регистра накопления с отключен- ными итогами выдается сообщение об ошибке. Получение движений регистров накопления С точки зрения методических приемов чтение данных движений регистров накопления одинаково: как для за- дач последующей модификации движений, так и для за- дач анализа движений регистров накопления. Например, для последующей обработки необходимо вы- брать содержимое движений документов РеализацияТова- ров по регистру ТоварыНаСкладах с отбором по складу СкладОтбора. При этом необходимо посчитать количество движений, выполненных каждым регистратором. Решение этой задачи может быть таким. В запросе обраща- емся к данным основной таблицы регистра ТоварыНаСкладах, в качестве выходных указываем поля, соответствующие по- лям таблицы движений. Отбор выполняем по значению поля Склад и вхождению значений поля Регистратор в табли- цу документов РеализацияТоваров. Вводим промежуточные итоги количества значений поля НомерСтроки в разрезе по регистраторам (в принципе, подсчет количества можно было реализовать по любому из полей) (листинг 8.21). Листинг 8.21. Пример получения движений регистра накопления Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладах.Период. ТоварыНаСкладах.Регистратор КАК Регистратор, ТоварыНаСкладах.НомерСтроки КАК НомерСтроки, ТоварыНаСкладах.Активность, ТоварыНаСкладах.ВидДвижения, ТоварыНаСкладах.Номенклатура, ТоварыНаСкладах.Склад. ТоварыНаСкладах.Количество, Тов арыНаСкладах.Поставщик ИЗ РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах ГДЕ ТоварыНаСкладах.Склад = &Склад И ТоварыНаСкладах.Регистратор ССЫЛКА Документ.РеализацияТоваров Таблица 8.22. Способы получения остатков Табличная модель Объектная модель Регистр остатков Оборотный регистр Регистр остатков Оборотный регистр Получение остатков Запрос к таблице остатков Метод Остатки() менеджера регистра Получение оборотов Запрос к таблице оборотов Метод Обороты О менеджера регистра Получение остатков и оборотов Запрос к таблице остатков и оборотов
|итоги КОЛИЧЕСТВО(НонерСтроки) | ПО | Регистратор": Запрос.УстановитьПаранетрС"Склад", СкладОтбора); Результат = Запрос.ВыполнитьО; ВыборкаРегистратор = Результат.Выбрать( ОбходРезультатаЗапроса.ПоГруппировкам); Пока ВыборкаРегистратор.СледующийО Цикл // Выполнить действия в цикле перебора регистраторов //... ВыборкаДвижения = ВыборкаРегистратор. ВыбратьО; Пока ВыборкаДвижения.СледующийО Цикл // Выполнить действия в цикле перебора движений //... КонецЦикла: КонецЦикла; Дальнейшее развитие приведенного алгоритма может идти в различных направлениях. Можно вывести в табличный документ содержимое движений регистра, а можно ре- зультат запроса использовать для модификации данных наборов записей с последующей записью измененных движений в регистр. Рассмотрим более подробно вопросы быстродействия сис- темы при получении движений регистра накопления тем или иным способом. Вопросы быстродействия системы при получении движений Как правило, при решении задач, связанных с чтением движений из регистров накопления, для повышения эф- фективности решений большее значение имеют вопросы: ♦ использования состава регистра накопления; ♦ использование табличной или объектной модели обра- щения к данным. Рассмотрим пример. Пусть необходимо подсчитать по данным регистра ТоварыНаСкладах, в каком количестве по- ставлялись товары в разрезе поставщиков. Данная задача может быть решена несколькими спосо- бами. Например, можно использовать внутреннее соединение основной таблицы регистра ТоварыНаСкладах и таблицы документа ПоступлениеТоваров (листинг 8.22). Листинг 8.22. Пример получения движений с использованием соединения с таблицей документа ВЫБРАТЬ ПоступлениеТоваров.Контрагент КАК Поставщик, ТоварыНаСкладах.Номенклатура. СУММА(ТоварыНаСкладах.Количество) КАК Количество ИЗ РегисгрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваров КАК ПоступлениеТоваров ПО ТоварыНаСкладах.Регистратор = ПоступлениеТоваров.Ссылка ГДЕ ТоварыНаСкладах.Период МЕВДУ ВДатаНачала И ВДатаКонца СГРУППИРОВАТЬ ПО ТоварыНаСкладах.Номенклатура, ПоступлениеТоваров.Контрагент Условием соединения является равенство значений поля Регистратор таблицы регистра и поля Ссылка таблицы до- кумента. Подобный способ получения движений в общем случае может оказаться неудобным, например, если поставки фиксируются несколькими видами документов. В этом случае усложнится текст запроса и замедлится его вы- полнение за счет большого количества соединений. Более удобным является подход с использованием рекви- зита регистра. Если для решения данной задачи в состав регистра включить реквизит Поставщик (тип значения — СправочникКонтрагентыСсылка), то значение поля реквизита можно будет заполнять при проведении только нужных документов. И тогда, независимо от количества видов до- кументов поставки, задача будет решаться запросом толь- ко к основной таблице регистра (листинг 8.23). Листинг 8.23. Пример получения движений регистра накопления ВЫБРАТЬ ТоварыНаСкладах.Поставщик, ТоварыНаСкладах.Номенклатура. СУММА(ТоварыНаСкладах.Количество) КАК Количество ИЗ РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах ГДЕ ТоварыНаСкладах.Период МЕВДУ ВДатаНачала И ВДатаКонца И ТоварыНаСкладах.Поставщик <> &ПустойПоставщик СГРУППИРОВАТЬ ПО ТоварыНаСкладах.Поставщик, Тов арыНаС кладах.Номен клатура Дополнительное условие «по непустым поставщикам» отсечет из подсчета результатов (и из самих результатов) записи, которые сформированы ненужными документа- ми. Например, перемещениями, реализацией и прочими (при проведении этих документов поле Поставщик не за- полнялось). Значение же параметра ПустойПоставщик может быть ус- тановлено следующим образом (листинг 8.24). Листинг 8.24. Установка значения параметра ПустойПоставщик Запрос.УстановитьПаранетрС"ПустойПоставщик”, Справочники.Контрагенты.ПустаяСсылкаС)); Необходимо иметь в виду, что при использовании рек- визитов составного типа незаполненное при проведении документа поставки значение реквизита будет иметь тип Неопределено. Поэтому для варианта, когда реквизит По- ставщик имеет составной тип, значение параметра Пустой- Поставщик может быть установлено следующим образом (листинг 8.25). Листинг 8.25. Пример установки параметра ПустойПоставщик Запрос.УстановитьПаранетрС"ПустойПоставщик", Неопределено); Если же при проведении документов реквизит может как не заполняться, так и заполняться пустыми значениями, возможно, придется в запросе учесть ряд вариантов зна- чения реквизита (листинг 8.26).
Листинг 8.26. Пример установки параметров запроса Запрос.УстановитьПаранетр("ПустойПоставщик". Неопределено); Запрос.УстановитьПаранетр("ПустойПоставщи«Контрагент", Справочники.Контрагенты.ПустаяСсылка()); Запрос.УстановитьПаранетр("ПустойПоставщикФизЛицо". Справочники.ФизическиеЛица.ПустаяСсылкаО); В приведенном примере предполагается, что реквизит По- ставщик имеет составной тип, включающий типы Справоч- никСсылка.Контрагенты и СправочникСсылка.ФизическиеЛица. Итак, за счет изменения состава регистра, использования реквизитов можно применять более эффективные по ско- рости алгоритмы для получения движений регистров на- копления. Обращение к данным одной таблицы базы дан- ных всегда будет проходить быстрее, нежели обращение к данным той же таблицы, но в соединении с другими таб- лицами базы данных. Таким образом, за счет «структур- ных изменений» ряд задач можно сводить только к рабо- те с таблицей движений регистра накопления. При обращении к данным таблицы движений регистра разработчик может применять обращение посредством выборки (объектная модель работы с данными) или по- средством запроса (табличная модель чтения данных). С точки зрения обращения к информации базы данных выборка — это тот же самый запрос. При одинаковых ус- ловиях и выборка, и прямое обращение запросом работа- ют одинаково эффективно. Разница в том, что выборка не так «гибка», зато получает данные порциями (это особенно важно, если ожидается большой объем данных в резуль- тате запроса). Для получения данных выборка использу- ет механизм динамического чтения данных. Посредством этого механизма чтение данных осуществляется по бло- кам, а не целиком сразу всех. Кроме того, при использова- нии выборки объекты считываются целиком. Работа же посредством запроса позволяет считывать содержимое только тех полей, которые используются в запросе. Дан- ная функциональность подробно описана в разделе «Вы- борка», с. 63. Операция перебора всех движений регистров с помощью выборки может осуществляться, например, следующим образом (листинг 8.27). Листинг 8.27. Пример получения движений регистра накопления с помощью выборки ВыборкаДвижений = РегистрыНакопления.ТоварыНаСкладах.Выбрать(); Пока ВыборкаДвижений.Следующий() Цикл // Выполнить действие с очередный движением //... КонецЦикла; Кроме таких простых операций возможно выполнять и более «тонкие» действия. Например, в ходе работы пользователя требуется оперативно определять факт того, что были поставки определенного поставщика в за- данном временном интервале. При решении данной задачи у реквизита Поставщик реги- стра ТоварыНаСкладах свойству Индексировать следует уста- новить значение Индексировать (рис. 8.28). В результате в базе данных будет создан составной ин- декс по полям Поставщик + Период + Регистратор + Номер- Строки. Гг Регистр накопления ТоварыНаСкладах _ П X Основные | ► Данные Регистраторы Формы Макеты Подсистемы Права Интерфейсы Обмен данными Прочее Ejl— Измерения |- U Номенклатура 5 Ц Склад ЁЙй Ресурсы ; Количество EJ S Реквизиты :.— ВидОперации — jQQ Свойства Реквизит Рис. 8.28. Индексирование реквизита регистра накопления Данные этого индекса система использует и при обраще- нии к движениям посредством запроса, и при обращении к движениям посредством выборки. Использование выборки позволит получить данные не медленнее, нежели посредством запроса (листинг 8.28). Листинг 8.28. Получение движений регистра накопления с помощью выборки ОтборПоПоставщику = Новый Структура("Поставщик", ПоставщикОтбора); ВыборкаДвижений = РегистрыНакопления.ТоварыНаСкладах.Выбрать( НачалоИнтервала, КонецИнтервала, ОтборПоПоставщику); Если ВыборкаДвижений.Следующий() Тогда Сообщить("В указанном интервале были поставки от " + ПоставщикОтбора.Наименование): Иначе Сообщить("В указанном интервале поставок от ” + ПоставщикОтбора.Наименование + ” не было"); КонецЕсли; Очевидно, что в переменные ПоставщикОтбора, НачалоИн- тервала, КонецИнтервала нужно передать соответствующие значения. ВНИМАНИЕ Необходимо помнить о том, что при использовании мето- да ВыбратьО в качестве параметра Отбор может использо- ваться структура, имеющая только один элемент! Для бо- лее гибких или сложных отборов следует использовать получение данных посредством запроса! Теперь чуть подробнее остановимся на использовании параметров НачалоИнтервала и КонецИнтервала. При работе с запросом можно произвольным образом ис- пользовать условия больше/меньше, равно/не равно, больше или равно, между и так далее как в отношении значений поля Период записей движений, так и Регистра- тор или НомерЗаписи. Чтобы добиться подобной гибкости в отношении границ временного интервала выборки, можно использовать раз-
личные варианты значений параметров НачалоИнтервала и КонецИнтервала. В параметр НачалоИнтервала передается начало интервала, в котором будут выбираться записи регистра накопления. Он может задаваться значениями типа Дата, МонентВренени и Граница. Если значение данного параметра не указано, то будут выбираться записи с самой ранней включительно. В параметр КонецИнтервала передается конец интервала, в ко- тором будут выбираться записи регистра накопления. Он может задаваться значениями типа Дата, МонентВренени и Гра- ница. Если значение данного параметра не указано, то будут выбираться записи по самую последнюю включительно. В результате при передаче значений типа Дата или Монент- Вренени в выборку получим записи включая значения На- чалоИнтервала и КонецИнтервала (рис. 8.29). КонецИнтервала НачалоИнтервала Регистрация движений Интервал выборки Рис. 8.29. Получение записей включая границы интервала Если требуется получить записи, исключая граничные, необходимо использовать объект Граница. Пример получе- ния выборки в интервале дат, исключая границы интер- вала, приведен в листинге 8.29 и на рис. 8.30. Листинг 8.29. Пример получения записей исключая границы интервала ГраницаНачалаИнтервала = Новый ГраницаСНачалоИнтервала. ВидГраницы.Исключая); ГраницаКонцаИнтервала = Новый Граница(КонецИнтервала, ВидГраницы.Исключая); ВыборкаДвижений = РегистрыНаколления.ТоварыНаСкладах.Выбрать( ГраницаНачалаИнтервала. Г раницаКонцаИнтервала); Пока ВыборкаДвижений.СледующийО Цикл // Выполнить действие с очередным движением //... КонецЦикла; Регистрация движений Интервал выборки Рис. 8.30. Получение записей исключая границы интервала Кроме выборок всех записей можно при необходимости осуществлять выборку записей, подчиненных некому до- кументу. Это может быть реализовано посредством мето- да ВыбратьПоРегмстраторуО. Например, если в переменной РегистраторОтбора содер- жится ссылка на регистратор, по которому нужно ото- брать все его движения, то код, получающий такую вы- борку, представлен в листинге 8.30. Поскольку, как обсуждалось выше, в разделе «Структура регистра накопления», с. 179, для таблицы движений ре- гистра поле Регистратор является индексируемым, то бы- стродействие подобной выборки будет достаточно высо- ким, не медленнее, чем применение запроса (листинг 8.31). Листинг 8.30. Пример получения движений по регистратору ВыборкаДвижений = РегистрыНаколления.ТоварыНаСкладах. ВыбратьПоРегистратору(РегистраторОтбора); Пока ВыборкаДвижений.СледующийО Цикл // Выполнить действие с очередным движением // ... КонецЦикла: Листинг 8.31. Пример получения движений регистратора с помощью запроса Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладах.Период, ТоварыНаСкладах.Регистратор, ТоварыНаСкладах.НомерСтроки, ТоварыНаСкладах.Активность, ТоварыНаСкладах.ВидДвижения. ТоварыНаСкладах.Номенклатура, ТоварыНаСкладах.Склад. ТоварыНаСкладах.Количество. ТоварыНаСкладах.Поставщик ИЗ РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах ГДЕ ТоварыНаСкладах.Регистратор = &РегистраторОтбора"; Запрос.УстановитьПараиетрС"РегистраторОтбора". РегистраторОтбора): Результат = Запрос. ВыполнитьО; Выборка = Результат.ВыбратьО: Пока Выборка.Следующий О Цикл // Выполнить действие с очередный движением //... КонецЦикла; А теперь рассмотрим один из примеров, когда в условиях усложнения задачи применение объектной модели обра- щения к информации базы данных уже менее эффектив- но, чем обращение посредством запроса. Например, в составе оборотного регистра Продажи есть реквизит ВидОперации (рис. 8.31). Продажи Й JL. Измерения = | •t-». Номенклатура ! 5..t— Контрагент Й-& Ресурсы | Количество 5 -1 Сумма Й-с Реквизиты — ВидОперации Рис. 8.31. Структура регистра Продажи При проведении документов продажи формируются дви- жения по этому регистру. Необходимо предпринять некие действия по фактам про- изведенных розничных продаж (вид операции — Реализа- цияВРозницу) с ценой, меньшей закупочной. Закупочная цена хранится в одноименных реквизитах элементов спра- вочника Номенклатура. Поиск таких фактов посредством запроса может быть вы- полнен так, как показано в листинге 8.32.
Листинг 8.32. Пример получения движений регистра накопления с помощью запроса Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ Продажи.Регистратор. Продажи.Номенклатура ИЗ РегистрНакопления.Продажи КАК Продажи ГДЕ Продажи.Период МЕЖДУ ВДатаНачала И ВДатаКонца И Продажи.ВидОперации = &РозничнаяПродажа И Продажи.Суниа / Продажи.Количество < Продажи.Номенклатура.ЗакупочнаяЦена": Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала): Запрос.УстановитьПараметр(“ДатаКонца", ДатаКонца): Запрос.УстановитьПараметр("РозничнаяПродажа”, Перечисления.ВидыОпераций.РеализацияВРозницу); Результат = Запрос.ВыполнитьО: Выборка = Результат.ВыбратьО; Пока Выборка.СледующийО Цикл // Выполнить действия по факту продажи дешевле // закупочной цены... КонецЦикла; Посредством выборки движений регистра аналогичный результат может быть получен так, как показано в лис- тинге 8.33. Листинг 8.33. Пример получения движений регистра накопления с помощью выборки Выборка = РегистрыНакопления.Продажи.Выбрать( ДатаНачала. ДатаКонца): Пока Выборка.СледующийО Цикл Если Выборка.ВидОперации = Перечисления.ВидыОпераций.РеализацияВРозницу И Выборка.Сумма/Выборка.Количество < Выборка.Номенклатура.ЗакупочнаяЦена Тогда // Выполнить действия по факту продажи дешевле // закупочной цены // ... КонецЕсли; КонецЦикла: Использование выборки в данной ситуации является очень неэффективным решением. В первом случае условие превышения закупочной цены будет обеспечено выполнением неявного левого внешне- го соединения всей таблицы регистра с таблицей спра- вочника за один раз. Во втором случае проверка условия Выборка.Сумма/Выбор- ка.Количество < Выборка.Номенклатура.ЗакупочнаяЦена потре- бует обращений к данным справочника в базе данных для каждого элемента коллекции движений. Это был только один из примеров, когда в условиях более сложных задач чтения движений применение запросов более эффективно, нежели применение выборки. А вообще, посредством запроса возможен доступ практи- чески ко всему содержимому таблицы движений регистра накопления. Для этого используется так называемая ос- новная таблица регистра накопления. Это реальная таб- лица, содержащая данные таблицы движений регистра в базе данных. Состав полей этой таблицы представлен в табл. 8.23. Основная таблица для оборотного регистра имеет почти аналогичный состав. Отличие заключается в том, что она не содержит поле ВидДвижения. Получение остатков Получение итогов остатков регистра накопления, конеч- но же, возможно только в отношения регистра накопле- ния остатков. Таблица 8.23. Состав полей основной таблицы регистра накопления остатков Поле Тип Назначение Период Дата Содержит период, к которому относится запись регистра Регистратор ДокументСсылка.«имя» Содержит ссылку на документ — регистратор движения НомерСтроки Число Содержит номер строки, определяемый как порядковый номер записи в наборе записей, подчиненных документу регистратору Активность Булево Содержит признак активности записи, то есть влияния на получение итогов регистра МоментВремени МоментВремени Виртуальное поле, не хранится в базе данных. Содержит объект МоментВремени (который включает в себя дату и ссылку на документ) ВидДвижения ВидДвиженияНакопления Содержит вид движения данной записи (Приход или Расход) «Измерение» Произвольный, определяется типом измерения Каждое из полей содержит значения измерений регистра. Имена полей совпадают с именами измерений, заданными для объекта конфигурации «Ресурс» Число Каждое из полей содержит значения ресурса регистра. Имена полей совпадают с именами ресурсов, заданными для объекта конфигурации «Реквизит» Произвольный, определяется типом реквизита Каждое из полей содержит значения реквизитов регистра. Имена полей совпадают с именами реквизитов, заданными для объекта конфигурации
Применение табличного или объектного подхода для ре- шения этой задачи определяется сложностью и необходи- мой гибкостью совершаемых при этом действий. Виртуальная таблица остатков Для получения данных по остаткам из регистра накопле- ния остатков запросом используется виртуальная табли- ца остатков. Ее данные представляют собой итоги ресур- сов в разрезе измерений (табл. 8.24). Параметры виртуальной таблицы остатков представлены в табл. 8.25. Виртуальная таблица остатков не хранится в базе дан- ных, а строится в момент обращения к ней. Для построе- ния виртуальной таблицы всегда используются данные таблицы итогов регистра базы данных и, при необходи- мости, таблицы движений регистра. При этом учитыва- ются значения параметров виртуальной таблицы. Сам алгоритм построения этой виртуальной таблицы включает в себя следующие этапы: ♦ подбирается больший или равный значению параметра Период момент времени, на который рассчитаны остатки; ♦ на этот момент времени получаются остатки из табли- цы итогов; ♦ если момент времени, на который считаются остатки, не совпадает с моментом времени итогов, то остатки досчитываются по движениям за период с момента тре- буемого запроса остатков по момент итогов. Реализует- ся это за счет объединения отобранных записей табли- цы итогов и таблицы движений регистра; ♦ группирование результата виртуальной таблицы. Вы- полняется согласно составу выходных полей запроса, использующего поля виртуальной таблицы. Для получения результата запроса система преобразует текст запроса, написанного на встроенном языке системы «1 С:Предприятие 8.0», в запрос СУБД. В данный запрос включается соответствующий текст подзапроса, полу- чающийся согласно описанному выше алгоритму. В отношении сортировки записей, полученных виртуаль- ной таблицей остатков, необходимо заметить, что если разработчик в запросе не применит ключевые слова УПО- РЯДОЧИТЬ ПО или АВТОУПОРЯДОЧИВАНИЕ, то, в общем случае, сис- тема не будет производить упорядочивание записей. То есть таблица результата виртуальной таблицы «само- группируется», но не «самосортируется». Можно сделать ряд выводов о скорости получения вирту- альной таблицы остатков. Она зависит от следующих факторов: ♦ требуются ли только актуальные итоги; ♦ требуются ли остатки на момент времени, находящийся до границы рассчитанных итогов; ♦ как много записей находится между требуемым момен- том расчета итогов и ближайшим (более поздним) мо- ментом уже рассчитанных итогов в таблице итогов. Например, в базе данных таблицы движений и итогов ре- гистра остатков заполнены так, как показано в табл. 8.26 и табл. 8.27. Рассмотрим случай, когда требуется получить итоги ре- гистра с помощью кода, приведенного в листинге 8.34. Листинг 8.34. Пример получения итогов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстатки.Склад КАК Склад, ТоварыНаСкладахОстатки.КоличествоОстаток КАК Количество ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период) КАК ТоварыНаСкладахОстатки Таблица 8.24. Состав полей виртуальной таблицы Остатки регистра накопления остатков Поле Тип Назначение •«Измерение» Произвольный, определяется типом измерения Каждое из полей содержит значения измерений регистра. Имена полей совпадают с именами измерений, заданными для объекта конфигурации «Ресурс» Число Каждое из полей содержит значения итога ресурса регистра. Имена полей совпадают с именами ресурсов, заданными для объекта конфигурации Таблица 8.25. Параметры виртуальной таблицы Остатки регистра накопления остатков Параметр Тип Назначение «Период» Дата, Моментвремени, Г раница Используется для указания периода, НА значение которого будут рассчитаны остатки. Если параметр не задан, итоги рассчитываются ПО самую последнюю запись «Условие» Конструкция языка запросов — условие Строится по полям измерений, регистра накопления (или по подчиненным им полям). Используется для ограничения состава исходных записей, по которым при построении виртуальной таблицы будут собираться итоги. Если параметр не указан для сбора итогов будут анализироваться все активные записи регистра
Таблица 8.26. Таблица движений регистра накопления Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 10 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 23.08.2005 15:30:45 ПоступлениеТоваров №2 23.08.2005 15:30:45 1 Приход Ложь Пульт VH Фили-2 5 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Расход Истина Пульт VH Главный 9 31.08.2005 23:59:59 ПоступлениеТоваров №3 31.08.2005 23:59:59 1 Приход Истина Пульт PW Фили-2 1 01.09.2005 00:00:00 ПоступлениеТоваров №4 01.09.2005 00:00:00 1 Приход Истина Пульт PW Фили-2 2 11.09.2005 13:59:00 ПоступлениеТоваров №5 11.09.2005 13:59:00 1 Приход Истина Пульт PW Фили-2 1 11.12.2005 11:00:00 ПоступлениеТоваров №5 11.12.2005 11:00:00 1 Приход Истина Пульт PW Фили-2 1 Таблица 8.27. Таблица итогов регистра накопления Период Номенклатура Склад Количество 01.09.2005 00:00:00 Пульт VH Главный 1 01.09.2005 00:00:00 Пульт PW Главный 7 01.09.2005 00:00:00 Пульт PW Фили-2 1 01.11.3999 00:00:00 Пульт VH Главный 1 01.11.3999 00:00:00 Пульт PW Главный 7 01.11.3999 00:00:00 Пульт PW Фили-2 5 В зависимости от значения, переданного параметру вир- туальной таблицы остатков Период, система будет выпол- нять следующие действия: 1. Если передать значение Неопределено (листинг 8.35) или значение даты по умолчанию (листинг 8.36), то будут по- лучены актуальные данные непосредственно из таблицы итогов, без обращений к таблице движений (табл. 8.28). Листинг 8.35. Установка параметра запроса значением Неопределено Запрос.УстановитьПараиетр("Период", Неопределено): Листинг 8.36. Установка параметра запроса значением даты по умолчанию Запрос.УстановитьПараиетр("Период", Дата(1, 1. 1)); Таблица 8.28. Результат выполнения запроса Номенклатура Склад Количество Пульт VH Главный 1 Пульт PW Главный 7 Пульт PW Фили-2 5 2. Если передать значение типа дата, совпадающее с датой рассчитанных итогов (листинг 8.37), то будут получены данные на начало даты «1 сентября 2005 года» непосред- ственно из таблицы итогов, без обращений к таблице дви- жений (табл. 8.29). Листинг 8.37. Установка параметра запроса значением даты Запрос.УстановитьПараиетр("Период", Дата(2005. 9, 1)): Таблица 8.29. Результат выполнения запроса Номенклатура Склад Количество Пульт VH Главный 1 Пульт PW Главный 7 Пульт PW Фили-2 1 ПРИМЕЧАНИЕ Заметьте, движения документа ПоступлениеТоваров №4, сформированные на эту же дату, учтены не будут. Потому что момент времени этих движений «позже» начала даты.
3. Если передать значение типа дата, не совпадающее с да- той рассчитанных итогов, то возможны несколько вари- антов. Рассмотрим каждый из них: а) Значение даты находится «в середине» рассчитанного периода (листинг 8.38). Листинг 8.38. Установка параметра запроса значением даты Запрос.УстановитьПараметр("Период". Дата(2005, 8, 20)): В этом случае сначала будут получены данные на начало даты «1 сентября 2005 года» из таблицы итогов (табл. 8.30). Таблица 8.30. Данные, полученные из таблицы итогов Номенклатура Склад Количество Пульт VH Главный 1 Пульт PW Главный 7 Пульт PW Фили-2 1 Затем будут получены записи из таблицы движений в ин- тервале между началом 20 августа 2005 и началом 1 сен- тября 2005 года. Причем только те, у которых поле Актив- ность имеет значение Истина. Поскольку «досчитываться» значения остатков будут в обратную сторону, то данные ресурсов таблицы движений получаются со знаком об- ратным виду движения (табл. 8.31). Таблица 8.31. Данные, полученные из таблицы движений Номенклатура Склад Количество Пульт VH Главный 9 Пульт PW Фили-2 -1 Далее эти записи объединятся, группируются, убираются записи, содержащие нулевые значения всех ресурсов (табл. 8.32). Таблица 8.32. Результат выполнения запроса Номенклатура Склад Количество Пульт VH Главный 10 Пульт PW Главный 7 б) Значение даты находится «в конце» рассчитанного пе- риода (листинг 8.39). Листинг 8.39. Установка параметра запроса значением даты Запрос.УстановитьПараметр("Период”, Дата(2005, 8, 31)): В этом случае сначала будут получены данные на начало даты «1 сентября 2005 года» из таблицы итогов (табл. 8.33). Таблица 8.33. Данные, полученные из таблицы итогов Номенклатура Склад Количество Пульт VH Главный 1 Пульт PW Главный 7 Пульт PW Фили-2 1 Затем будут получены записи из таблицы движений в ин- тервале между началом 31 августа 2005 и началом 1 сен- тября 2005 года, с учетом вида движений и «обратного подсчета» (табл. 8.34). Таблица 8.34. Данные, полученные из таблицы движений Номенклатура Склад Количество Пульт PW Фили-2 -1 Далее записи объединятся, и по этим данным будут по- считаны остатки на нужный период (табл. 8.35). Таблица 8.35. Результат выполнения запроса Номенклатура Склад Количество Пульт VH Главный 1 Пульт PW Главный 7 в) Значение даты представляет собой конец дня послед- ней даты рассчитанного периода (листинг 8.40). Листинг 8.40. Установка параметра запроса значением даты Запрос.УстановитьПараметрС"Период". КонецДня(Дата(2005, 8, 31))); В этом случае сначала будут получены данные на начало даты «1 сентября 2005 года» из таблицы итогов (табл. 8.36). Таблица 8.36. Данные, полученные из таблицы итогов Номенклатура Склад Количество Пульт VH Главный 1 Пульт PW Главный 7 Пульт PW Фили-2 1 Затем будут получены записи из таблицы движений в ин- тервале между концом 31 августа 2005 и началом 1 сен- тября 2005 года, с учетом вида движении и «обратного подсчета». К таким записям как раз и относится датиро- ванное последней секундой дня движение документа По- ступлениеТоваров №3 (табл. 8.37). Таблица 8.37. Данные, полученные из таблицы движений Номенклатура Склад Количество Пульт PW Фили-2 -1 Далее записи объединятся, и по этим данным будут по- считаны остатки на нужный период (табл. 8.38). Таблица 8.38. Результат выполнения запроса Номенклатура Склад Количество Пульт VH Главный 1 Пульт PW Главный 7
г) Значение даты является началом даты не рассчитанно- го периода (листинг 8.41). Листинг 8.41. Установка параметра запроса значением даты ПериодВключая = Новый Граница(Дата(2005, 9. 1). ВидГ раницы.Включая) Запрос.УстановитьПараметр("Период". ПериодВключая); Значение параметра больше, чем начало дня «01.09.2005», поэтому будут взяты данные из таблицы итогов на боль- ший период, то есть актуальные итоги (табл. 8.39). Таблица 8.39. Данные, полученные из таблицы итогов Номенклатура Склад Количество Пульт VH Главный 1 Пульт PW Главный 7 Пульт PW Фили-2 5 Будут взяты записи из таблицы движений в интервале между значением параметра и периодом актуальных ито- гов (с учетом операции «обратного подсчета»). Заметьте, движения, датированные «01.09.2005 00:00:00», сюда не попадают (табл. 8.40). Таблица 8.40. Данные, полученные из таблицы движений Номенклатура Склад Количество Пульт PW Фили-2 -1 Пульт PW Фили-2 -1 Далее записи объединятся, и по этим данным будут по- считаны остатки на нужный период (табл. 8.41). Таблица 8.41. Результат выполнения запроса Номенклатура Склад Количество Пульт VH Главный 1 Пульт PW Главный 7 Пульт PW Фили-2 3 Аналогично поступила бы система, если бы в качестве па- раметра было передано значение типа МонентВренени с да- той 01.09.2005 00:00:00 и ссылкой на какой-нибудь доку- мент. Кроме того, хотелось бы заметить, что если бы в послед- нем примере граница рассчитанных итогов стояла бы не в конце августа, а хотя бы в конце сентября, то не при- шлось бы досчитывать от актуальных итогов. Достаточно было бы досчитать от ближайшего, но большего периода рассчитанных итогов. Использование в любых «не ровных» ситуациях именно «обратного досчета» объясняется тем, что при решении оперативных задач вправе ожидать более напряженной работы с актуальными итогами или близкими к текуще- му моменту, нежели получение остатков прошлых меся- цев или даже лет. Усложнение же механизма расчета итогов остатков «ана- лизатором» ситуации — от какого периода итогов «бли- же» до нужного значения параметра — нецелесообразно. Поскольку для обеспечения работы «анализатора» при- шлось бы получать записи таблицы движений в обе сто- роны (и назад и вперед). То есть «анализатор» сам рабо- тал бы дольше, чем «обратный досчет». Таким образом, можно сделать вывод, что быстродейст- вие получения остатков реальным временем (актуаль- ных) вообще не зависит от общего объема накопленной в базе данных информации. Для получения же данных на прошедшие моменты вре- мени в случае использования расчета промежуточных ежемесячных итогов среднее быстродействие построения виртуальной таблицы получения остатков определяется не общим объемом базы данных, а количеством движе- ний по регистру, формируемым в течение месяца. Это очень важно для недопущения деградации системы при многолетней эксплуатации базы данных. Кроме того, хотелось бы обратить внимание, что на каж- дом этапе выполнения алгоритма, когда система получает данные из той или иной таблицы базы данных, применя- ются отборы только тех записей, которые удовлетворяют условиям, описанным в параметрах виртуальной табли- цы остатков. Использование метода Остатки() менеджера регистра накопления В ситуациях, когда при получении данных об остатках не применяется сложных отборов, либо эти данные впослед- ствии не нужно соединять с другими данными, можно ис- пользовать также и объектную модель доступа к дан- ным — метод Остатки() менеджера регистра накопления. Например, если требуется сообщить остатки на складах по некой товарной позиции, как это показано в листин- ге 8.42. Листинг 8.42. Пример получения остатков регистра накопления с использованием объектной модели Отбор = Новый Структура!"Номенклатура". ТоварОтбора); ТаблицаОстатков = РегистрыНаколления.ТоварыНаСкладах.Остатки! МонентВренени, Отбор. "Склад", "Количество"): Для Каждого СтрокаТаблицы Из ТаблицаОстатков Цикл Сообщить("Склад " + СтрокаТаблицы.Склад + ” + СтрокаТаблицы.Количество); КонецЦикла: Метод Остатки!) возвращает таблицу значений, содержа- щую данные об остатках регистра, вычисленных на мо- мент значения параметра МонентВренени. При этом будет использован отбор согласно значению параметра Отбор, а сама таблица значений свернута по полю Склад, с сум- мированием значений поля Количество. Механизм построения результата метода Остатки!) прак- тически тот же, что и в случае применения виртуальной таблицы получения остатков. В качестве типов значения переменных, передаваемых параметру МонентВренени, возможны те же, что использова-
лись для виртуальной таблицы получения остатков. То есть Дата, МонентВренени, Граница. Особенности применения различных значений и их использование системой при подсчете данных будут рассмотренным ниже, в разделе «Особенности использования периодов и моментов вре- мени при получении остатков», с. 207. Различия проявляются в условиях отбора информации. Посредством параметра Отбор типа Структура можно стро- ить только простейшие отборы на равенство значений из- мерений. Например, как показано в листинге 8.43. Листинг 8.43. Пример получения остатков регистра накопления Отбор = Новый Структура("Номенклатура, Склад", ТоварОтбора. СкладОтбора); Но варианты более сложных отборов, например отбор по двум значениям измерения Номенклатура, для метода Ос- татки О не приемлемы. Последние два параметра метода Остатки О касаются опе- рации «свертки» полученных в запросе СУБД данных пе- ред выгрузкой в таблицу значений. Однако если значения данных параметров не указывать, то результирующая таблица значений будет содержать колонки, соответст- вующие всем измерениям и/или всем ресурсам. «Недостаточная» гибкость объектной модели чтения ито- гов регистров объясняется тем, что в платформе на объ- ектные методы возлагаются в основном задачи обеспечения записи, модификации и динамического чтения данных реальных таблиц базы данных. А задачи гибкого, «тонко- го», эффективного чтения для обеспечения последующего анализа состояния учитываемых в системе показателей возлагаются на более подходящие для этого инструмен- ты — объекты Запрос, ПостроительОтчета, АнализДанных и т. п. Особенности использования периодов и моментов времени при получении остатков Рассмотрим различные ситуации получения остатков за- просом (листинг 8.44) или с помощью метода Остатки О (листинг 8.45). Листинг 8.44. Пример получения остатков на «Период» запросом ВЫБРАТЬ ТоварьНаСкладахОстатки.Номенклатура КАК Номенклатура. ТоварыНаСкладахОстатки.Склад КАК Склад, ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(^Период) КАК ТоварыНаСкладахОстатки Листинг 8.45. Пример получения остатков на «Период» методом Остатки () ТаблицаОстатков = РегистрыНакопления.ТоварыНаСкладах.Остатки(Период); Параметр Период виртуальной таблицы остатков и метода Остатки () может получать значения типа Дата, МоментВрене- ни и Граница, кроме того, может быть вообще не указан или иметь значение Неопределено, или содержать значение даты по умолчанию — ‘00010101000000’. Последние три случая (не указан, или Неопределено, или значение даты по умолчанию) приводят к построению таблицы остатков с данными актуальных остатков (учи- тывающих все активные записи регистра). В случае если в качестве параметра передается значение типа Дата, важно помнить следующие моменты. Дата в системе «1 С:Предприятие 8.0» включает в свой состав время. Даже если время не указано явно, оно при- нимает значение 00:00:00. То есть если в качестве пара- метра передать «31 декабря 2005 года» (данное значение может быть получено так: ’2005123Г), то в результа- те таблица остатков будет построена на дату 31.12.2005 23:59:59 (рис. 8.32). Рис. 8.32. Получение остатков на дату Таблица получения остатков строится на начало даты, то есть — не включая. В вышеприведенных примерах ис- пользования виртуальной таблицы остатков запросом и выполнения метода ОстаткиО, если в таблице движений регистра будут присутствовать записи со значением поля Период, равным дате 31.12.2005 23:59:59, — они не будут учтены (рис. 8.33), если получать данные на конец дня. Рис. 8.33. Получение остатков не включая дату границы интервала Если необходимо учесть и их тоже, следует применять параметр Период с типом значения Граница. Параметр Период типа МоментВремени для получения остатков используют, если требуются итоги, полученные с точностью большей, чем до секунды. Например, если не- сколько документов имеют одинаковое время, но при проведении каждого из них требуется получать данные, актуальные на момент времени документа (рис. 8.34).
Таблица 8.42. Таблица движений регистра накопления Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 23.08.2005 15:30:45 ПоступлениеТоваров №2 23.08.2005 15:30:45 1 Приход Истина Пульт VH Фили-2 5 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Расход Истина Пульт VH Фили-2 4 27.08.2005 12:30:45 Реализация №2 27.08.2005 12:30:45 1 Приход Истина Пульт VH Фили-2 1 РеализацияТоваров №4 Дата 23.08.200512:30:45 Реализация! оваров №2 Дата 23 08.200512:30 46 Реализация!оваров №3 Дата 23.08.200512:30:46 РеализацияТоваров №1 Дета 23.08.200512:30’47 23.08.200512:30:45 23.08.200 512:30:46 23.08.200512:30:47 МоментВремени: Момент времени Дата: 23.08.200512:30:46 Дата: 23.08.2005 1 2:30 46 Ссылка. Реализация!оваров№2 Ссылка: Реализация!оваров№3 Рис. 8.34. Момент времени документа Объект МоментВремени состоит из даты и ссылки на доку- мент, и может быть получен посредством применения ме- тода МоментВремени О ссылки или объекта документа (лис- тинг 8.46). Листинг 8.46. Получение момента времени документа МоментВремениДокумента = СсылкаНаДокумент.МоментВремениО; Также значение типа МоментВремени может быть получено с помощью конструктора (листинг 8.47). Листинг 8.47. Получение момента времени с помощью конструктора МоментВремениДокумента = Новый МоментВремени(СсылкаНаДокумент.Дата. Документ); В случае использования конструктора возможно указа- ние даты, не совпадающей с датой документа. Рассмотрим следующий пример получения остатков на момент времени документа. Например, есть следующие записи таблицы движений регистра остатков (табл. 8.42). Если получить остатки на дату 27.08.2005 12:30:45, то по- лучим следующий результат (см. табл. 8.43). Таблица 8.43. Полученные итоги Номенклатура Склад Количество Пульт VH Фили-2 5 Если получить остатки на момент времени, включающий дату 27.08.2005 12:30:45 и ссылку на документ Реализация №1, получим такие же итоги (см. табл. 8.43). А вот если получить остатки на момент времени, вклю- чающий дату 27.08.2005 12:30:45 и ссылку на документ Реализация №2, получим следующий результат (табл. 8.44). При получении таблицы остатков с указанием параметра Период типа МоментВремени, полученного из даты докумен- та и ссылки на документ, необходимо иметь в виду, что данные получаются — «исключая» записи движений са- мого документа (рис. 8.35). Таблица 8.44. Полученные итоги Номенклатура Склад Количество Пульт VH Фили-2 1 РеализацияТоваров №4 Дата 23.08.200512:30:45 Реализация! оваров №2 Дата 23.08.200512:30:46 Реализация! оваров №3 Дата 23.08.200512:30:46 Реализация! оваров №1 Дата 23.08.20051230:47 23.08.200512:30:45 23 08 200* 5 1 230 46 23.08.2005 1 2:30 47 Момент времени: Дата: 23.08.2005 1 2:30:46 Ссылка: Реализация!оваров№2 Момент времени: Дета, 23.08.2005 1 230:46 Ссылка: Реализация!оваров№3 На момент времени: Дата: 23 08 2005 12:30:46 Ссылка: Реализация!оваров№3 Рис. 8.35. Получение остатков на момент времени документа Для случаев, когда необходимо получить данные об остат- ках, включая движения, относящиеся к дате или моменту времени, применяют значения параметра «Период» с ти- пом значения «Граница». Объект «Граница» получается посредством применения соответствующего конструктора. Именно в конструкторе указывается вид границы. В случае получения остатков на конец дня граница может быть создана так, как показано в листинге 8.48. Листинг 8.48. Создание границы с помощью конструктора ГраницаПоДату = Новый Граница(КонецДня(ДатаОтчета), ВидГраницы.Включая); В этом случае остатки будут получены включая движе- ния на дату формирования отчета (рис. 8.36). В случае получения остатков на момент времени до- кумента граница может быть создана так, как показано в листинге 8.49. Листинг 8.49. Создание границы с помощью конструктора ГраницаПоДокумент = Новый Граница(СсылкаНаДокумент.МонентВренени(), ВидГ раницы.Вклочая);
Рис. 8.36. Получение остатков, включая движения на дату формирования отчета В этом случае остатки будут получены включая движе- ния указанного документа (рис. 8.37). Рис. 8.37. Получение остатков, включая движения указанного документа Получение оборотов Задачи получения итогов оборотов могут решаться и для регистров остатков, и для оборотных регистров. И в том и в другом случае возможно чтение информации как по- средством запроса, так и посредством метода ОборотыО. Разберем подробнее, в чем разница применения этих под- ходов. Виртуальная таблица оборотов Виртуальная таблица оборотов регистра накопления ос- татков позволяет получать итоговые значения оборотов ресурсов (далее будем называть: «оборотов») за времен- ной интервал (далее будем называть: «период»). Итого- вые значения могут быть получены в разрезе комбинаций значений измерений и/или в развороте дополнительной периодичности. Виртуальная таблица оборотов имеет следующий состав полей: ♦ Период — это поле имеет тип Дата. Оно существует только в случаях, если указано значение параметра вир- туальной таблицы оборотов Периодичность: Год, Полугодие, Квартал, Месяц, Декада, Неделя, День, Регистратор или Запись. Данное поле содержит начальную дату периода, к кото- рому относится оборот регистра; ♦ Регистратор — это поле имеет тип ДокунентСсылка.<иня>. Оно существует только в случаях, если указано значе- ние параметра виртуальной таблицы оборотов Периодич- ность: Регистратор или Запись. Данное поле содержит ссылку на документ-регистратор, к которому относится оборот регистра; ♦ НомерСтроки — это поле имеет тип Число. Оно существу- ет только в случаях, если указано значение параметра виртуальной таблицы оборотов Периодичность: Запись. Содержит значение поля НомерСтроки записи движения регистра; ♦ «Измерение» — это поле может иметь произвольный тип, который определяется типом измерения. Количе- ство таких полей равно количеству измерений регистра накопления. Каждое из этих полей содержит значения измерений регистра. Имена полей совпадают с назва- ниями измерений, заданными для объекта конфигура- ции; ♦ <Ресурс>Оборот — это поле имеет тип Число. Количество таких полей равно количеству ресурсов регистра нако- пления. Каждое из полей содержит значения, посчитан- ные как сумма приходов за минусом суммы расходов ресурса регистра накопления по всем движениям внут- ри соответствующего периода. Имена полей составля- ются из названий ресурсов с добавлением слова «Обо- рот»; ♦ <Ресурс>Приход — это поле имеет тип Число. Количество таких полей равно количеству ресурсов регистра нако- пления. Каждое из полей содержит значения, посчитан- ные, как сумма приходов ресурса регистра накопления по всем движениям внутри соответствующего периода. Имена полей составляются из названий ресурсов с до- бавлением слова «Приход»; ♦ <Ресурс>Расход — это поле имеет тип Число. Количество таких полей равно количеству ресурсов регистра накоп- ления. Каждое из полей содержит значения, посчитан- ные как сумма расходов ресурса регистра накопления по всем движениям внутри соответствующего периода. Имена полей составляются из названий ресурсов с до- бавлением слова «Расход». В отличие от регистра накопления остатков, оборотный регистр накапливает только обороты. То есть для ресур- сов оборотного регистра не существует понятий «При- ход» и «Расход». Поэтому состав полей виртуальной таблицы оборотов оборотного регистра накопления несколько «короче» со- става полей аналогичной таблицы регистра накопления остатков: ♦ Период — это поле имеет тип Дата. Оно существует только в случаях, если указано значение параметра вир- туальной таблицы оборотов Периодичность: Год, Полугодие, Квартал, Месяц, Декада, Неделя, День, Регистратор или Запись. Данное поле содержит начальную дату периода, к кото- рому относится оборот регистра; ♦ Регистратор — это поле имеет тип ДокументСсылка.«имя>. Оно существует только в случаях, если указано значе- ние параметра виртуальной таблицы оборотов Периодич- ность: Регистратор или Запись. Данное поле содержит ссылку на документ-регистратор, к которому относится оборот регистра; ♦ НомерСтроки — это поле имеет тип Число. Оно существу- ет только в случаях, если указано значение параметра виртуальной таблицы оборотов Периодичность: Запись.
Содержит значение поля НомерСтроки записи движения регистра; ♦ «Измерение» — это поле может иметь произвольный тип, который определяется типом измерения. Количе- ство таких полей равно количеству измерений регистра накопления. Каждое из этих полей содержит значения измерений регистра. Имена полей совпадают с назва- ниями измерений, заданными для объекта конфигура- ции; ♦ <Ресурс>Оборот — это поле имеет тип Число. Количество таких полей равно количеству ресурсов регистра накоп- ления. Каждое из полей содержит значения, посчитан- ные, как сумма значений ресурса регистра накопления по всем движениям внутри соответствующего периода. Имена полей составляются из названий ресурсов с до- бавлением слова «Оборот». Параметры виртуальной таблицы оборотов для любого регистра накопления следующие: ♦ НачалоПериода — это поле может иметь тип Дата, МоментВ- ренени или Граница. Используется для указания начала периода расчета оборотов. Значение этого параметра по умолчанию включается в период расчета оборотов. Если параметр не задан, обороты рассчитываются с са- мой первой записи. ♦ КонецПериода — Дата, МонентВренени, Граница. Используется для указания конца периода расчета оборотов. Значе- ние этого параметра по умолчанию включается в период расчета оборотов. Если параметр не задан, обороты рас- считываются по самую последнюю запись. ♦ Периодичность — содержит конструкцию языка запросов. Задается одним из следующих вариантов: Период, За- пись, Регистратор, День, Неделя, Декада, Месяц, Квартал, Полу- годие, Год. Используется для указания дополнительного разворота оборотов по периодичности. При указании значения Период обороты представляются за весь период (с «НачалоПериода» по «КонецПериода») без допол- нительных разворотов. В остальных случаях — с раз- воротом по записям, регистраторам, неделям, декадам, месяцам, кварталам, полугодиям, годам соответствен- но. Значение по умолчанию — Период. ♦ Условие — содержит конструкцию языка запросов — ус- ловие. Строится по полям измерений, регистра накоп- ления (или подчиненных им полям). Используется для ограничения состава исходных записей, по которым при построении виртуальной таблицы оборотов будут собираться обороты. Если параметр не указан, для сбо- ра оборотов будут анализироваться все активные запи- си регистра. Виртуальная таблица оборотов не хранится в базе дан- ных, а строится в момент обращения к ней. В качестве иллюстрации работы виртуальной таблицы оборотов рассмотрим следующий пример. Пусть таблица движений регистра ТоварыНаСкладах заполнена так, как показано в табл. 8.45. Для получения оборотов используется запрос, текст ко- торого представлен в листинге 8.50. Листинг 8.50. Пример получения оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОбороты.Период, ТоварыНаСкладахОбороты.Номенклатура. ТоварыНаСкладахОбороты.Склад, ТоварыНаСкладахОбороты.КоличествоОборот. ТоварыНаСкладахОбороты.КоличествоПриход. ТоварыНаСкладахОбороты.КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты( , , Месяц, ) КАК ТоварыНаСкладахОбороты Тогда в результате выполнения приведенного запроса бу- дет получен следующий результат (табл. 8.46). Как видите, в данном примере при использовании допол- нительного разворота итогов по месяцам в поле Период для каждой записи указывается начальная дата месяца. Таблица 8.45. Таблица движений регистра ТоварыНаСкладах Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 10 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 23.08.2005 15:30:45 ПоступлениеТоваров №2 23.08.2005 15:30:45 1 Приход Ложь Пульт VH Фили-2 5 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Расход Истина Пульт VH Главный 9 31.08.2005 23:59:59 ПоступлениеТоваров №3 31.08.2005 23:59:59 1 Приход Истина Пульт PW Фили-2 1 01.09.2005 00:00:00 ПоступлениеТоваров №4 01.09.2005 00:00:00 1 Приход Истина Пульт PW Фили-2 2 11.09.2005 13:59:00 ПоступлениеТоваров №5 11.09.2005 13:59:00 1 Приход Истина Пульт PW Фили-2 1 11.12.2005 11:00:00 ПоступлениеТоваров №5 11.12.2005 11:00:00 1 Приход Истина Пульт PW Фили-2 1
Таблица 8.46. Результат выполнения запроса Период Номенклатура Склад Количество Оборот Количество Приход Количество Расход 01.08.2005 00:00:00 Пульт VH Главный 1 10 9 01.08.2005 00:00:00 Пульт PW Главный 7 7 0 01.08.2005 00:00:00 Пульт PW Фили-2 1 1 0 01.09.2005 00:00:00 Пульт PW Фили-2 3 3 0 01.12.2005 00:00:00 Пульт PW Фили-2 1 1 0 Таблица 8.47. Таблица движений регистра накопления Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 10 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 23.08.2005 11:30:45 РучнаяОперация №1 23.08.2005 11:30:45 1 Приход Истина Пульт VH Фили-2 5 24.08.2005 11:30:45 РучнаяОперация №1 23.08.2005 11:30:45 2 Расход Истина Пульт PW Главный 7 23.08.2005 11:30:45 РучнаяОперация №1 23.08.2005 11:30:45 3 Расход Истина Пульт VH Фили-2 1 Таблица 8.48. Результат выполнения запроса Период Регистратор Номенклатура Склад Количество Оборот Количество Приход Количество Расход 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 Пульт VH Главный 10 10 0 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 Пульт PW Главный 7 7 0 23.08.2005 11:30:45 РучнаяОперация №1 23.08.2005 11:30:45 Пульт VH Фили-2 4 4 0 24.08.2005 11:30:45 РучнаяОперация №1 23.08.2005 11:30:45 Пульт PW Главный -7 0 7 В случае же использования дополнительного разворота итогов по регистраторам или записям в поле период со- держится значение поля Период записи движения по ре- гистру. Это верно даже для ситуации, когда поле Период записей движений, подчиненных одному регистратору, заполнено разными значениями. В качестве иллюстрации рассмотрим следующий пример. Пусть таблица движений регистра накопления содержит записи, приведенные в табл. 8.47. Для получения оборотов используется запрос, текст ко- торого представлен в листинге 8.51. Тогда в результате выполнения приведенного запроса бу- дет получен следующий результат (табл. 8.48). Для сравнения выполним запрос, текст которого приве- ден в листинге 8.52. Листинг 8.51. Пример получения оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОбороты.Период. ТоварыНаСкладахОбороты.Регистратор, ТоварыНаСкладахОбороты.Номенклатура, ТоварыНаСкладахОбороты.Склад, ТоварыНаСкладахОбороты.КоличествоОборот, ТоварыНаСкладахОбороты.КоличествоПриход, ТоварыНаСкладахОбороты.КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты! , , Регистратор, ) КАК ТоварыНаСкладахОбороты
Таблица 8.49. Результат выполнения запроса Регистратор Номенклатура Склад Количество Оборот Количество Приход Количество Расход ПоступлениеТоваров №1 13.08.2005 15:00:01 Пульт VH Главный 10 10 0 ПоступлениеТоваров №1 13.08.2005 15:00:01 Пульт PW Главный 7 7 0 РучнаяОперация №1 23.08.2005 11:30:45 Пульт VH Фили-2 4 4 0 РучнаяОперация №1 23.08.2005 11:30:45 Пульт PW Главный -7 0 7 Листинг 8.52. Пример получения оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОбороты.Регистратор. ТоварыНаСкладахОбороты.Номенклатура, ТоварыНаСкладахОбороты.Склад, ТоварыНаСкладахОбороты.КоличествоОборот, ТоварыНаСкладахОбороты.КоличествоПриход. Тов арыНаСкладахОбороты.Количест воРасход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты! , , Регистратор, ) КАК ТоварыНаСкладахОбороты Результат выполнения запроса представлен в табл. 8.49. Как видите, записи результата запроса оказываются сгруп- пированы по полям Период и Регистратор, даже если нет выходного поля Период. Это объясняется тем, что для оп- ределения момента времени, с которого движения регист- ра начинают действовать на итоги, «регистратор» являет- ся уточнением «периода». Итак, результаты и методики применения виртуальной таблицы оборотов для регистров остатков и оборотных регистров весьма схожи. Но вот алгоритмы получения этих результатов средствами системы сильно разнятся. Алгоритм, применяемый системой для получения оборотов регистра остатков Для построения виртуальной таблицы оборотов регистра накопления остатков всегда используются данные таблицы движений регистра (из базы данных). При этом учитывают- ся значения параметров виртуальной таблицы оборотов. Сам алгоритм построения этой виртуальной таблицы включает в себя следующие этапы: ♦ получение записей из таблицы движений регистра со- гласно установленным значениям параметров вирту- альной таблицы; ♦ группирование полученных записей согласно указанной в параметрах виртуальной таблицы периодичности. Сортировка не выполняется. И хотя зачастую порядок за- писей в результате оказывается соответствующим желае- мому, но для гарантированного упорядочивания в тексте запроса надо указывать ключевые слова УПОРЯДОЧИТЬ ПО или АВТОУПОРЯДОЧИВАНИЕ. Таким образом, скорость построения виртуальной таб- лицы оборотов регистра остатков не зависит от периода рассчитанных итогов, а зависит от количества записей движений регистра, попавших в требуемый период по- строения таблицы. Для обеспечения максимальной скорости выполнения за- проса по этой виртуальной таблице также важно пра- вильное применение отборов по измерениям. Правила применения таких отборов описаны в разделе «Примене- ние отборов в запросах, использующих виртуальные таб- лицы регистров накопления», с. 230. Алгоритм, применяемый системой для получения оборотов оборотного регистра Для построения виртуальной таблицы получения оборо- тов оборотного регистра накопления могут использовать- ся или только данные таблицы движений регистра, или только таблицы итогов (из базы данных), или и данные таблицы движений и таблицы итогов. Для эффективного применения той или иной стратегии учитываются значе- ния параметров виртуальной таблицы оборотов. Сам алгоритм построения этой виртуальной таблицы включает в себя следующие этапы: ♦ получение записей из базы данных из таблицы движе- ний или таблицы итогов регистра согласно установлен- ным значениям параметров виртуальной таблицы; ♦ группирование полученных записей согласно указан- ной в параметрах виртуальной таблицы периодично- сти. При выполнении первого этапа анализируется, можно ли использовать данные таблицы итогов регистра для фор- мирования запроса. В таблице итогов регистра хранятся данные месячных оборотов. Эти данные будут использо- ваны в случаях, когда дополнительная периодичность не задана или задана равной или большей месяцу и в интер- вал формирования виртуальной таблицы попадают це- лые месяцы. Остальная информация при необходимости получается из таблицы движений. В качестве иллюстрации работы виртуальной таблицы оборотов рассмотрим следующие примеры. Пусть таблица движений оборотного регистра Продажи заполнена следующим образом (табл. 8.50).
Таблица 8.50. Таблица движений оборотного регистра Продажи Период Регистратор Номер Строки Активность Номенклатура Контрагент Количество Сумма 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Истина Пульт VH Ялта-Лтд 9 135 29.08.2005 15:00:01 Реализация №2 29.08.2005 15:00:01 1 Истина Пульт VH Компания «Риона» 10 150 13.09.2005 15:00:00 Реализация №3 13.09.2005 15:00:00 1 Истина Пульт VH Компания «Риона» 1 15 23.09.2005 10:00:00 Реализация №3 23.09.2005 10:00:00 1 Истина Пульт VH Компания «Риона» 1 15 23.09.2005 15:30:45 Реализация №4 23.09.2005 15:30:45 1 Ложь Пульт PW Крона 1 90 01.11.2005 08:59:59 Реализация №5 01.10.2005 08:59:59 1 Истина Пульт PW Ялта-Лтд 1 95 Таблица 8.51. Таблица итогов оборотного регистра накопления Продажи Период Номенклатура Контрагент Количество Сумма 01.08.2005 00:00:00 Пульт VH Ялта-Лтд 9 135 01.08.2005 00:00:00 Пульт VH Компания «Риона» 10 150 01.09.2005 00:00:00 Пульт VH Компания «Риона» 2 30 01.11.2005 00:00:00 Пульт PW Ялта-Лтд 1 95 Соответственно, таблица итогов будет заполнена так, как показано в табл. 8.51. Рассмотрим выполнение запроса, представленного в лис- тинге 8.53. Листинг 8.53. Пример получения оборотов регистра накопления ВЫБРАТЬ ПродажиОбороты.Номенклатура. ПродажиОбороты.КоличествоОборот КАК Количество, ПродажиОбороты.СуммаОборот КАК Сумма ИЗ РегистрНакопления.Продажи.ОборотыС&НачалоПериода. &КонецПериода. , ) КАК ПродажиОбороты 1. Если параметрам запроса присвоить значения даты по умолчанию или Неопределено (листинг 8.54), то алгоритм построения виртуальной таблицы оборотов будет ис- пользовать данные только таблицы итогов (табл. 8.52). Листинг 8.54. Пример установки параметров запроса Запрос.УстановитьПараметрС"НачалоПериода", Неопределено); Запрос.УстановитьПараметрС "КонецПериода", Неопределено): Таблица 8.52. Промежуточная выборка данных из таблицы итогов Номенклатура Количество Сумма Пульт VH 9 135 Пульт VH 10 150 Пульт VH 2 30 Пульт PW 1 95 После этапа группирования результат виртуальной таб- лицы будет выглядеть так, как показано в табл. 8.53. Таблица 8.53. Результат выполнения запроса Номенклатура Количество Сумма Пульт VH 21 315 Пульт PW 1 95 2. Если параметрам запроса присвоить значения так, что в период входит только целое число месяцев (лис- тинг 8.55), то алгоритм построения виртуальной табли- цы будет использовать данные только таблицы итогов (табл. 8.54). Листинг 8.55. Пример установки параметров запроса Запрос.УстановитьПараметрС"НачалоПериода", Дата(2005, 8, 01)); Запрос.УстановитьПараметрС"КонецПериода", Дата(2005, 9, 30, 23. 59. 59)); Таблица 8.54. Промежуточная выборка данных из таблицы итогов Номенклатура Количество Сумма Пульт VH 9 135 Пульт VH 10 150 Пульт VH 2 30 После этапа группирования результат виртуальной таб- лицы будет выглядеть так, как показано в табл. 8.55.
Таблица 8.55. Результат выполнения запроса Номенклатура Количество Сумма Пульт VH 21 315 3. Если параметрам запроса присвоить значения так, что в период входит не только целое число месяцев (лис- тинг 8.56), то алгоритм построения виртуальной таблицы оборотов будет сначала использовать данные таблицы итогов по целым месяцам (в нашем случае — за сентябрь) (табл. 8.56). Листинг 8.56. Пример установки параметров запроса Запрос.УстановитьПараметрСНачалоПериода", Дата(2005, В, 20)): Запрос.УстановитьПараметрС"КонецПериода", Дата(2005. 9, 30. 23, 59, 59)): Таблица 8.59. Промежуточная выборка данных из таблицы движений Номенклатура Количество Сумма Пульт VH 9 135 Пульт VH 10 150 Пульт VH 1 15 Пульт VH 1 15 Таблица 8.60. Результат выполнения запроса Номенклатура Количество Сумма Пульт VH 21 315 Таблица 8.56. Промежуточная выборка данных из таблицы итогов Номенклатура Количество Сумма Пульт VH 2 30 Затем, по «не поместившимся в целые месяцы» движе- ниям данные будут получены из таблицы движений (табл. 8.57). Таблица 8.57. Промежуточная выборка данных из таблицы движений Номенклатура Количество Сумма Пульт VH 9 135 Пульт VH 10 150 Записи этих таблиц будут объединены и после этапа группирования, результат виртуальной таблицы будет выглядеть так, как показано в табл. 8.58. Таблица 8.58. Результат выполнения запроса Номенклатура Количество Сумма Пульт VH 21 315 Обратите внимание: результат не отличается от результа- та предыдущего примера. Однако из-за того, что значение параметра НачалоПериода не совпадало с началом месяца, система была вынуждена обращаться как к таблице ито- гов, так и к таблице движений регистра. 4. Если параметрам запроса присвоить значения так, что в период не входит целое число месяцев (листинг 8.57), то алгоритм построения виртуальной таблицы оборотов бу- дет использовать только данные таблицы движений реги- стра (табл. 8.59). Листинг 8.57. Пример установки параметров запроса Запрос.УстановитьПараметрСНачалоПериода". Дата(2005, 8, 20)); Запрос.УстановитьПараметрС"КонецПериода", Дата(2005, 9. 23. 23, 59. 59)): После этапа группирования результат виртуальной таб- лицы будет выглядеть так, как показано в табл. 8.60. Как видите, хотя интервал между значениями параметров превышал 30 дней, однако он не включал в себя целых месяцев. Этого было достаточно, чтобы виртуальная таб- лица оборотов строилась по таблице движений. 5. Если параметр Периодичность имеет значение, меньшее месяца (листинг 8.58), то независимо от значений пара- метров НачалоПериода и КонецПериода виртуальная таблица оборотов будет строиться по записям таблицы движений регистра. Листинг 8.58. Пример установки параметров запроса ВЫБРАТЬ ПродажиОбороты.Номенклатура, ПродажиОбороты.КоличествоОборот КАК Количество, ПродажиОбороты.СуммаОборот КАК Сумма ИЗ РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Неделя, ) КАК ПродажиОбороты Таким образом, видно, что получение виртуальной табли- цы оборотов оборотного регистра может выполняться гораздо быстрее, нежели для виртуальной таблицы обо- ротов регистра остатков, за счет использования накоп- ленных месячных итогов оборотов. Для обеспечения максимальной скорости выполнения за- проса по этой виртуальной таблице также важно пра- вильное применение отборов по измерениям. Правила применения таких отборов описаны в главе «Применение отборов в запросах, использующих виртуальные таблицы регистров накопления», с. 230. Метод Обороты() В ситуациях, когда при получении данных об оборотах не применяется сложных отборов либо эти данные впослед- ствии не нужно соединять с другими данными, а допол- нительная периодичность оборотов не требуется, можно использовать объектную модель чтения информации — метод ОборотыО. Данный метод применим только для регистров накопле- ния, у которых включено использование итогов. При по- лучении результата используются только записи актив- ных движений. Например, пусть таблица движений регистра ТоварыНа- Складах заполнена следующим образом (табл. 8.61).
Таблица 8.61. Таблица движений регистра накопления Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 13.08.200 5 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 10 13.08.200 5 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 23.08.200 5 15:30:45 ПоступлениеТоваров №2 23.08.2005 15:30:45 1 Приход Ложь Пульт VH Фили-2 5 27.08.200 5 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Расход Истина Пульт VH Главный 9 31.08.200 5 23:59:59 ПоступлениеТоваров №3 31.08.2005 23:59:59 1 Приход Истина Пульт PW Фили-2 1 01.09.200 5 00:00:00 ПоступлениеТоваров №4 01.09.2005 00:00:00 1 Приход Истина Пульт PW Фили-2 2 11.09.200 5 13:59:00 ПоступлениеТоваров №5 11.09.2005 13:59:00 1 Приход Истина Пульт PW Фили-2 1 11.12.200 5 11:00:00 ПоступлениеТоваров №5 11.12.2005 11:00:00 1 Приход Истина Пульт PW Фили-2 1 Тогда после выполнения кода, приведенного в листин- ге 8.59, будет получен результат, показанный в табл. 8.62. Листинг 8.59. Пример получения оборотов регистра накопления ТаблицаОборотов = РегистрыНакопления. ТоварыНаСкладах.ОборотыО; Таблица 8.62. Результат выполнения метода ОборотыО Номенклатура Склад Количество Приход Количество Расход Пульт VH Главный 10 9 Пульт PW Главный 7 0 Пульт PW Фили-2 5 0 Кроме полных оборотов, посредством метода ОборотыО возможно и получение данных в некотором временном интервале, с отбором на равенство значений измерений. Например, если требуется сообщить обороты по некой товарной позиции (ссылка на нее — в переменной Товар- Отбора) в интервале между НачалоПериода и КонецПериода (листинг 8.60). Листинг 8.60. Пример получения оборотов регистра накопления Отбор = Новый СтруктураС"Номенклатура",ТоварОтбора); ТаблицаОборотов = РегистрыНакопления.ТоварыНаСкладах.ОборотыС НачалоПериода, КонецПериода, Отбор. "Номенклатура", ); Для Каждого СтрокаТаблицы Из ТаблицаОборотов Цикл Сообщить("Номенклатура " + СтрокаТаблицы.Склад + Приход " + СтрокаТаблицы.КоличествоПриход + Расход " + СтрокаТаблицы.КоличествоРасход); КонецЦикла; В качестве типов значения переменных, передаваемых параметрам НачалоПериода и КонецПериода, возможны те же, что использовались для виртуальной таблицы получения оборотов, то есть Дата, МоментВремени и Граница. Особенно- сти применения различных значений и их использование системой при подсчете данных будут рассмотренным ниже, в разделе «Особенности использования периодов и моментов времени при получении оборотов», с. 216. Посредством параметра Отбор типа Структура можно стро- ить простейшие отборы на равенство значений измере- ний. Например, так (листинг 8.61). Листинг 8.61. Пример установки отбора при получении оборотов регистра накопления Отбор = Новый СтруктураС'Номенклатура, Склад". ТоварОтбора. СкладОтбора); Последние два параметра метода ОборотыС) касаются опе- рации «свертки» данных в запросе СУБД перед выгруз- кой в таблицу значений. Однако если значения данных параметров не указывать, то результирующая таблица значений будет содержать колонки, соответствующие всем измерениям и/или всем ресурсам. В приведенном примере (см. листинг 8.60) было указано только измере- ние Номенклатура, в результате произошла свертка по ко- лонке Номенклатура с суммированием значений колонок КоличествоПриход и КоличествоРасход. Применение метода ОборотыО для оборотного регистра практически аналогично применению этого метода для регистра остатков. Единственное отличие состоит в названии колонок таб- лицы значений, получаемой в результате применения ме- тода. В данном случае их имена совпадают с именами измерений и ресурсов.
Например, если требуется на основе данных регистра Продажи сообщить об объемах продаж по конкретной но- менклатурной позиции (ссылка на нее — в переменной ТоварОтбора) в интервале между НачалоПериода и КонецПе- риода, в разрезе покупателей, то можно использовать сле- дующий фрагмент кода (листинг 8.62). Листинг 8.62. Пример получения оборотов оборотного регистра накопления Отбор = Новый СтруктураС"Номенклатура", ТоварОтбора): ТаблицаОборотов = РегистрыНакопления.Продажи.ОборотыС НачалоПериода, КонецПериода, Отбор, "Контрагент", ): Для каждого СтрокаТаблицы Из ТаблицаОборотов Цикл Сообщить("Покупатель " + СтрокаТаблицы.Контрагент + Количество " + СтрокаТаблицы.Количество + Сумма " + СтрокаТаблицы.Сумма): КонецЦикла: Особенности использования периодов и моментов времени при получении оборотов Параметр Период виртуальной таблицы оборотов и метода ОборотыО может получать значения типа Дата, МоментВреме- ни и Граница, кроме того, может быть вообще не указан, иметь значение Неопределено или значение даты по умол- чанию. Последние случаи (не указан, Неопределено или значение даты по умолчанию) приводят к построению таблицы оборотов с данными, учитывающих все активные записи регистра. В случае, если в качестве параметра передается значение типа Дата, важно помнить следующие моменты. Дата в системе «1С Предприятие 8.0» включает в свой состав время. Даже если время не указано явно, оно при- нимает значение 00:00:00. То есть если в качестве пара- метра НачалоПериода передать значение 1 декабря 2005 года (данное значение может быть получено так: '20051201'), а в качестве параметра КонецПериода передать 31 декабря 2005 года ('20051231'), то в результате и виртуальная таб- лица получения оборотов, и результат метода ОборотыО будут построены с даты 01.12.2005 00:00:00 по дату 31.12.2005 00:00:00. То есть в обороты, по сути, вой- дут данные продаж только первой секунды 31 декабря (рис. 8.38). Для предотвращения возможных недоразумений по это- му поводу удобно использовать функцию КонецДняО. Эта функция возвращает значение последней секунды дня указанной в качестве параметра даты (листинги 8.63 и 8.64). Листинг 8.63. Пример получения оборотов регистра накопления на конец дня Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладахОбороты.Номенклатура, ТоварыНаСкладахОбороты.Склад, | ТоварыНаСкладахОбороты.КоличествоОборот, ТоварыНаСкладахОбороты.КоличествоПриход, ТоварыНаСкладахОбороты.КоличествоРасход |ИЗ РегистрНакопления.ТоварыНаСкладах.ОборотыС | «НачалоПериода, «.КонецПериода) КАК ТоварыНаСкладахОбороты"; Запрос.УстановитьПараметрС"НачалоПериода", НачалоПериода); Запрос.УстановитьПараметрС"КонецПериода", КонецДня(КонецПериода)): Листинг 8.64. Пример получения оборотов регистра накопления на конец дня ТаблицаОборотов = РегистрыНакопления.ТоварыНаСкладах.ОборотыС НачалоПериода1. КонецДня(КонецПериода!)): В обоих случаях в результате будут получены данные ос- татков с даты 01.12.2005 00:00:00 по дату 31.12.2005 23:59:59 включительно (рис. 8.39). Движения Рис. 8.38. Получение оборотов на даты указанного интервала Рис. 8.39. Получение оборотов на конец дня Таблица оборотов строится с включением записей, соот- ветствующих граничным периодам. То есть с начала се- кунды значения параметра НачалоПериода по конец се- кунды параметра КонецПериода (рис. 8.40). В вышеприведенных примерах, если вместо конца дня 31.12.2005 23:59:59 указать дату 01.01.2006 00:00:00 и если в таблице движений регистра будут присутствовать записи со значением поля Период, равным дате 01.01.200600:00:00, то они будут учтены. То есть с прикладной точки зрения
получится, что в результат запроса войдут данные первой секунды 2006 года. Рис. 8.40. Включение граничных записей при получении оборотов Параметр Период типа МоментВремени для получения оборотов используют, если требуются итоги, полученные с точностью большей, чем до секунды. Например, если не- сколько документов имеют одинаковое время, но для ре- шения задачи нужно получение оборотов с начала месяца по момент времени текущего документа (рис. 8.41). Данная задача может быть решена посредством метода «Обороты!)» или применения запроса с указанием значе- ний параметров НачалоПериода и КонецПериода, вычис- ляемых следующим образом (листинг 8.65). Листинг 8.65. Пример указания границ периода с использованием момента времени НачалоПериода = НачалоМесяца(СсылкаНаДокуиент.Дата): КонецПериода = Новый МоментВремени(СсылкаНаДокуиент.Дата. СсылкаНаДокумент); В обоих случаях обороты будут получены, включая дви- жения документа, ссылка на который содержится в пере- менной СсылкаНаДокумент. Для случаев, когда необходимо получить данные об обо- ротах, исключая движения, относящиеся к дате или мо- менту времени, применяют значения параметра Период с типом значения Граница. Объект Граница получается посредством применения со- ответствующего конструктора. Именно в конструкторе указывается вид границы. Например, если требуется получить обороты в интерва- ле дат, исключая первую и последнюю секунды, можно использовать следующий код (листинг 8.66). Листинг 8.66. Пример задания границ интервала с использованием объекта Граница ГраницаСДатыИсключая = Новый ГраницаСНачалоПериода. ВидГраницы.Исключая); ГраницаНаДатуИсключая = Новый Граница(КонецДня(КонецПериода). ВидГраницы.Исключая); Если требуется получить обороты с начала месяца (вклю- чая) по момент времени документа, исключая движения самого документа, тогда можно поступить следующим образом (листинг 8.67, рис. 8.42). Реализация! оваров N-1 Дата 23.08.200512:30:45 Реализация! оваров №2 Дата 23.08.200512:30:46 Реализация! оваров №3 Дата 23.08.200512:30:46 П еремещениеИ1! Дата 23.08.2005 12:30.46 23.08.2005 12:30:45 2308.200512:30:46 Момент времени Дата: 23.08.20051230:46 Ссылка: Реализация!оваровИ12 Момент времени Дата. 23.08.200512:30:46 Ссылка: РеализацияТоеаров№3 Момент времени Дата 23.08.20051230:46 Ссылка: Перемещение!!^ Обороты по границу (исключая): момент времени: Дата: 23.00 2005 12:30:40 Ссылка: Реализация!оваровТ^З Рис. 8.41. Использование момента времени при получении оборотов Реализация!оваров №1 Дата 23.08.200512:30:45 РеализацияТоваров №2 Дата 23.08.2005 12:30:46 РеализацияТоваров N-3 Дата 23.08.200512:30:46 Перемещение^! Дата 23.08.200512.30:46 23.08.200512:3045 23.08.200512:30:46 Момент времени: Дата: 23.08.200512:30:46 Ссылка: Реализация! оваров№2 Момент времени: Дата: 23.08 20051230 46 Ссылка: РеализацияТоваров№3 Момент времени Дата. 23.08.200512:30:46 Ссылка: ПеремещениеЫМ Обороты по границу (исключая]: момент времени: Дата: 23.08.2005 12:30:48 Ссылка. РеализацияТоваров№3 Рис. 8.42. Использование границы при получении оборотов
Листинг 8.67. Пример задания границ интервала ГраницаСНачалаМесяца = НачалоМесяца(СсылкаНаДокумент.Дата); ГраницаНаДокумент = Новый Граница(СсылкаНаДокумент.МоментВремени(), ВидГраницы.Исключая); Получение остатков и оборотов в одной таблице Для решения прикладных задач управления ресурсами предприятий система предоставляет возможности учета этих ресурсов (впрочем, как и любых других показате- лей) на регистрах накопления. Как правило, в подобных ситуациях речь идет о показателях остатков. Потому что именно показатели остатков позволяют ответить на во- прос, какое именно значение имел этот показатель в тот или иной момент времени. Но для полноценного контроля зачастую мало информации только о значениях остатков. Требуется видеть одновременно и статическую картину, и как она была получена (динамику развития ситуации). Например, для контроля наличия товара на складах пред- приятия пользователю часто необходимо видеть картину и остатков и оборотов за некий промежуток времени (табл. 8.63). То есть информацию и о начальном остатке значения ре- сурса (КоличествоНачальныйОстаток), и о том, какой за ука- занные промежуток времени был оборот данного ресурса (КоличествоОборот), и о том, как этот оборот был получен (КоличествоПриход, КоличествоРасход), и о том, какое ко- нечное значение ресурса после этого получилось (Количе- ствоОстаток). Увидев такую картину «укрупнено», пользователь может потребовать показать ее более детально, с дополнитель- ной периодичностью до дня, когда происходили события в отношении товаров на складах (табл. 8.64). Обратите внимание: в результате «подробного» варианта представления данных «длина» таблицы может увели- чиваться на несколько порядков. И тогда для быстрого осмысления «локальных участков» информации важно, чтобы значение полей НачальныйОстаток и КонечныйОста- ток отражали реальную картину дня и были согласованы с информацией об остатках по предыдущему и последую- щему периоду (дням). То есть значения полей остатков верхнего уровня группирования информации (по но- менклатуре) в данном отчете не получены простым сум- мированием таких же полей нижнего уровня группирова- ния информации (по дням), а скорее «перенесены» из соответствующих записей нижнего уровня. А ведь пользователь может потребовать еще большей де- тальности, уже внутри дня. Получение подобной отчетности только средствами от- дельного получения остатков и отдельного получения оборотов, с последующим манипулированием этой ин- формацией, в принципе возможно, но достаточно трудо- емко. Поэтому в рамках платформы системы «1 (^Предприя- тие 8.0» предусмотрены специальные механизмы для решения подобных задач. Они основаны на примене- нии виртуальной таблицы остатков и оборотов регист- ра накопления остатков и включают в себя реализацию достаточно сложных алгоритмов, решающих одновре- менно вопросы требуемой функциональности и воз- Таблица 8.63. Показатели остатков и оборотов Номенклатура Количество- Начальный- Остаток Количество- КонечныйОстаток Количество- Оборот Количество- Приход Количество- Расход Пульт PW 1 15 14 15 1 Пульт VH 10 И 1 10 9 Таблица 8.64. Детальные показатели остатков и оборотов Номенклатура Период Количество- НачальныйОстаток Количество- КонечныйОстаток Количество- Оборот Количество- Приход Количество- Расход Пульт PW 1 15 14 15 1 Пульт PW 13.08.2005 0:00:00 1 8 7 7 0 Пульт PW 17.08.2005 0:00:00 8 И 3 3 0 Пульт PW 31.08.2005 0:00:00 И 15 4 5 1 Пульт VH 10 И 1 10 9 Пульт VH 13.08.2005 0:00:00 10 20 10 10 0 Пульт VH 27.08.2005 0:00:00 20 И -9 0 9
можной оптимизации с точки зрения быстродействия. Разработчик же может пользоваться уже готовыми ре- зультатами. Но для эффективного использования данных механиз- мов важно понимать их возможности и принципы реа- лизации. Ниже эти вопросы рассматриваются более под- робно. Виртуальная таблица остатков и оборотов Виртуальная таблица остатков и оборотов регистра накоп- ления остатков позволяет получать итоговые значения и остатков, и оборотов ресурсов за временной интервал. Итоговые значения могут быть получены в разрезе ком- бинаций значений измерений и/или в развороте допол- нительной периодичности. Виртуальная таблица остатков и оборотов содержит сле- дующие поля: ♦ Период — это поле имеет тип Дата. Поле существует только в случаях, если указано значение параметра вир- туальной таблицы остатков и оборотов Периодичность: Год, Полугодие, Квартал, Месяц, Декада, Неделя, День, Регистра- тор или Запись. Данное поле содержит начальную дату периода, к которому относится оборот регистра; ♦ Регистратор — это поле имеет тип ДокунентСсылка.<иия>. Это поле существует только в случаях, если указано значение параметра виртуальной таблицы остатков и оборотов Периодичность: Регистратор или Запись. Данное поле содержит ссылку на документ-регистратор, к ко- торому относится оборот регистра; ♦ НомерСтроки —это поле имеет тип Число. Это поле суще- ствует только в случаях, если указано значение пара- метра виртуальной таблицы остатков и оборотов Перио- дичность: Запись. Содержит значение поля НомерСтроки записи движения регистра; ♦ «Измерение» — тип произвольный, определяется типом измерения. Количество таких полей равно количеству измерений регистра накопления. Каждое из полей со- держит значения измерений регистра. Имена полей совпадают с названиями измерений, заданными для объекта конфигурации; ♦ <Ресурс»Оборот — это поле имеет тип Число. Количество таких полей равно количеству ресурсов регистра накоп- ления. Каждое из полей содержит значения, посчитан- ные как сумма приходов за минусом суммы расходов ресурса регистра по всем движениям внутри соответст- вующего периода. Имена полей составляются из назва- ний ресурсов с добавлением слова «Оборот»; ♦ «РесуроПриход — это поле имеет тип Число. Количество таких полей равно количеству ресурсов регистра накоп- ления. Каждое из полей содержит значения, посчитан- ные, как сумма приходов ресурса регистра по всем дви- жениям внутри соответствующего периода. Имена полей составляются из названий ресурсов с добавлением сло- ва «Приход»; ♦ <Ресурс>Расход — это поле имеет тип Число. Количество таких полей равно количеству ресурсов регистра на- копления. Каждое из полей содержит значения, посчи- танные как сумма расходов ресурса регистра по всем движениям внутри соответствующего периода. Имена полей составляются из названий ресурсов с добавлени- ем слова «Расход»; ♦ <Ресурс>НачальныйОстаток — это поле имеет тип Число. Количество таких полей равно количеству ресурсов ре- гистра накопления. Каждое из полей содержит значение остатка ресурса на начало соответствующего периода. Имена полей составляются из названий ресурсов с до- бавлением слова «НачальныйОстаток»; ♦ «РесуроКонечныйОстаток — это поле имеет тип Число. Количество таких полей равно количеству ресурсов ре- гистра накопления. Каждое из полей содержит значе- ние остатка ресурса на конец соответствующего перио- да. Имена полей составляются из названий ресурсов с добавлением слова «КонечныйОстаток». Виртуальная таблица остатков и оборотов имеет следую- щие параметры: ♦ «НачалоПериода» — Дата, МоиентВреиени или Граница. Ис- пользуется для указания начала периода расчета ито- гов. Значение начала периода по умолчанию включает- ся в период расчета итогов. Если параметр не задан, итоги рассчитываются с самой первой записи; ♦ «КонецПериода» — Дата, МоиентВреиени или Граница. Ис- пользуется для указания конца периода расчета итогов. Значение конца периода по умолчанию включается в период расчета итогов. Если параметр не задан, итоги рассчитываются по самую последнюю запись; ♦ «Периодичность» — конструкция языка запросов. Зада- ется одним из следующих вариантов: Период, Запись, Ре- гистратор, День, Неделя, Декада, Месяц, Квартал, Полугодие, Год. Используется для указания дополнительного раз- ворота итогов по периодичности. При указании значе- ния Период обороты представляются за весь период (с НачалоПериода по КонецПериода) без дополнительных разворотов. В остальных случаях — разворачивая по за- писям, регистраторам, неделям, декадам, месяцам, кварта- лам, полугодиям, годам соответственно. Значение по умолчанию — Период; ♦ «МетодДополнения» — конструкция языка запросов. Задается одним из следующих вариантов: Движения, Дви- жениями раницыПериода. Используется для указания вклю- чения граничных периодов в состав выдаваемых вирту- альной таблицей записей. Если выбирается вариант Движения, то граничные периоды не будут включаться (будут выданы записи только за те периоды, когда име- ли место движения). Если выбирается вариант Движе- нияИГраницыПериода, то граничные периоды будут вклю- чаться независимо от наличия или отсутствия движений в рамках интервала между НачалоПериода и КонецПерио- да. Значение по умолчанию: ДвиженияИГраницыПериода; ♦ «Условие» — конструкция языка запросов — условие. Строится по полям измерений, регистра накопления (или подчиненным им полям). Используется для огра- ничения состава исходных записей, по которым при по- строении виртуальной таблицы будут собираться ито- ги. Если параметр не указан, то для сбора итогов будут анализироваться все активные записи регистра. Виртуальная таблица остатков и оборотов не хранится в базе данных, а строится в момент обращения к ней. Для построения виртуальной таблицы всегда используются данные и таблицы итогов, и таблицы движений регистра (из базы данных). При этом учитываются значения пара-
метров виртуальной таблицы. Итоги ресурсов собирают- ся только по активным записям. Виртуальная таблица может строиться только по тем ре- гистрам, у которых использование итогов включено. При попытке выполнения запроса, в котором используется виртуальная таблица остатков для регистра накопления с отключенными итогами, выдается сообщение об ошибке. Сам алгоритм построения этой виртуальной таблицы включает в себя следующие этапы: ♦ получение остатков на начало заданного периода (так же, как это выполняется для построения виртуальной таблицы остатков); ♦ получение оборотов за заданный период с заданной пе- риодичностью (так же, как это выполняется для по- строения виртуальной таблицы оборотов); ♦ объединение полученных остатков и оборотов с учетом значения параметра МетодДополнения; ♦ досчет значений остатков для каждой записи. Если дополнительная периодичность не указана, то рас- чет всех данных производится в рамках одного запроса, включающего подзапросы, согласно разделам алгоритма. Подзапросы при этом примерно те же, что и для соответ- ствующих виртуальных таблиц получения остатков и по- лучения оборотов. В случае же использования дополнительной периодично- сти на каждом этапе алгоритма запросы выполняются, ре- зультаты запросов объединяются, полученная в резуль- тате объединения таблица записывается во временную таблицу базы данных, чтобы впоследствии быть исполь- зованной при выполнении основного запроса, в рамках которого была применена виртуальная таблица остатков и оборотов. Рассмотрим примеры использования виртуальной табли- цы остатков и оборотов для регистра ТоварыНаСкладах. Пусть таблица движений регистра ТоварыНаСкладах за- полнена так, как показано в табл. 8.65. Допустим, выполняется следующий запрос (листинг 8.68). Листинг 8.68. Пример получения остатков и оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Номенклатура. ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот, ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход, ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты АВТОУПОРЯДОЧИВАНИЕ Тогда результат выполнения приведенного запроса будет выглядеть следующим образом (таб. 8.66). Для получения информации с дополнительным разворо- том по временным периодам, например, по дням, когда были движения, можно применять следующий вариант написания запроса (листинг 8.69). Таблица 8.65. Таблица движений регистра накопления Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 10.07.2005 11:00:00 ПоступлениеТоваров №1 10.07.2005 11:00:00 1 Приход Истина Пульт PW Главный 1 10.07.2005 11:01:00 ПоступлениеТоваров №2 10.07.2005 11:00:00 1 Приход Истина Пульт VH Фили-2 10 13.08.2005 15:00:01 ПоступлениеТоваров №3 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 10 13.08.2005 15:00:01 ПоступлениеТоваров №3 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 17.08.2005 18:00:00 ПоступлениеТоваров №8 17.08.2005 18:00:00 1 Приход Истина Пульт PW Розничный 3 23.08.2005 15:30:45 ПоступлениеТоваров №4 23.08.2005 15:30:45 1 Приход Ложь Пульт VH Фили-2 5 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Расход Истина Пульт VH Главный 9 31.08.2005 13:00:00 ПоступлениеТоваров №5 31.08.2005 13:00:00 1 Приход Истина Пульт PW Фили-2 1 31.08.2005 14:00:00 ПоступлениеТоваров №6 31.08.2005 14:00:00 1 Приход Истина Пульт PW Фили-2 2 31.08.2005 15:59:00 Реализация №2 31.08.2005 15:59:00 1 Расход Истина Пульт PW Фили-2 1 31.08.2005 23:59:59 ПоступлениеТоваров №7 31.08.2005 23:59:59 1 Приход Истина Пульт PW Фили-2 2
Листинг 8.69. Пример получения остатков и оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Период, ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток. ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот. ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход, ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.0статкиИ0бороты( «НачалоПериода. «КонецПериода, День, Движения, ) КАК ТоварыНаСкладахОстаткиИОбороты АВТОУПОРЯДОЧИВАНИЕ Если при этом значения параметров установлены так, как показано в листинге 8.70, то в результате выпол- нения запроса будут получены данные, представленные в табл. 8.67. Листинг 8.70. Пример установки параметров запроса Запрос.УстановитьПараметрС"НачалоПериода", '20050801'): Запрос.УстановитьПараметрС "КонецПериода", КонецДняС'20050831')); Обратите внимание: значение поля Период соответствует началу каждого дня (дополнительная периодичность была именно День). Поскольку в параметрах виртуальной таблицы был ука- зан метод дополнения Движения, то в данном случае выход- ная таблица содержит записи по всем комбинациям зна- чений измерений, по которым в периоде с НачалоПериода по КонецПериода были движения. Поэтому в рассмотрен- ном примере в таблице результата не оказалось записей с комбинацией Пульт VH и Фили-2. Если же в выходной таблице результата должна быть ин- формация по остаткам номенклатурных позиций на скла- дах, несмотря на наличие или отсутствие движений внутри периода между НачалоПериода и КонецПериода, то вирту- альная таблица остатков и оборотов может быть построе- на следующим образом (листинг 8.71). Листинг 8.71. Пример получения остатков и оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Период, Тов арыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток. ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот, ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход, ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.0статкиИ0бороты( ^НачалоПериода, «КонецПериода. День. ) КАК ТоварыНаСкладахОстаткиИОбороты АВТОУПОРЯДОЧИВАНИЕ Таблица 8.66. Результат выполнения запроса Номенклатура Склад Количество- НачальныйОстаток Количество- КонечныйОстаток Количество- Оборот Количество- Приход Количество- Расход Пульт PW Главный 0 8 8 8 0 Пульт PW Розничный 0 3 3 3 0 Пульт PW Фили-2 0 4 4 5 1 Пульт VH Главный 0 1 1 10 9 Пульт VH Фили-2 0 10 10 10 0 Таблица 8.67. Результат выполнения запроса Период Номенклатура Склад Количество- Начальный- Остаток Количество- Конечный- Остаток Количество- Оборот Количество- Приход Количество- Расход 13.08.2005 00:00:00 Пульт PW Главный 1 8 7 7 0 17.08.2005 00:00:00 Пульт PW Розничный 0 3 3 3 0 31.08.2005 00:00:00 Пульт PW Фили-2 0 4 4 5 1 13.08.2005 00:00:00 Пульт VH Главный 0 10 10 10 0 27.08.2005 00:00:00 Пульт VH Главный 10 1 -9 0 9
Если значения параметров установлены так же (см. лис- тинг 8.70), то благодаря тому, что параметр МетодДополне- ния имеет по умолчанию значение ДвиженияИГраницыПериода, получается следующий результат (табл. 8.68). Для комбинаций измерений, по которым были начальные остатки на момент НачалоПериода, добавились записи, со- держащие значения этих остатков и в поле КоличествоНа- чальныйОстаток, и в поле КоличествоКонечныйОстаток, до за- писей, содержащих данные по движениям. Для комбинаций измерений, по которым были конечные остатки на момент КонецПериода, добавились записи, со- держащие значения этих остатков и в поле КоличествоНа- чальныйОстаток, и в поле «КоличествоКонечныйОстаток, по- сле записей, содержащих записи по движениям. В результате цель достигнута, то есть в таблицу результа- та запроса попадают записи так же и по тем комбинациям значений измерений, по которым не было движений во временном интервале построения виртуальной таблицы остатков и оборотов. Как «долго» система получает результат виртуальной таблицы остатков и оборотов? Исходя из приведенного выше описания алгоритма, мож- но сказать, что в общем случае скорость построения вирту- альной таблицы остатков и оборотов зависит от периода рассчитанных итогов (для расчета начальных остатков), и от количества записей движений регистра, попавших в требуемый период построения таблицы, а сильнее всего от дополнительной периодичности разворота результатов, указанной в параметрах виртуальной таблицы. От количе- Таблица 8.68. Результат выполнения запроса Период Номен- клатура Склад Количество- Начальный- Остаток Количество- Конечный- Остаток Количество- Оборот Количество- Приход Количество- Расход Остаток на границу «Начало- Периода» 01.08.2005 00:00:00 Пульт PW Главный 1 1 0 0 0 13.08.2005 00:00:00 Пульт PW Главный 1 8 7 7 0 Остаток на границу «Конец- Периода» 31.08.2005 00:00:00 Пульт PW Главный 8 8 0 0 0 17.08.2005 00:00:00 Пульт PW Розничный 0 3 3 3 0 Остаток на границу «Конец- Периода» 31.08.2005 00:00:00 Пульт PW Розничный 3 3 0 0 0 31.08.2005 00:00:00 Пульт PW Фили-2 0 4 4 5 1 Остаток на границу «Конец- Периода» 31.08.2005 00:00:00 Пульт PW Фили-2 4 4 0 0 0 13.08.2005 00:00:00 Пульт VH Главный 0 10 10 10 0 27.08.2005 00:00:00 Пульт VH Главный 10 1 -9 0 9 Остаток на границу «Конец- Периода» 31.08.2005 00:00:00 Пульт VH Главный 1 1 0 0 0 Остаток на границу «Начало- Периода» 01.08.2005 00:00:00 Пульт VH Фили-2 10 10 0 0 0 Остаток на границу «Конец- Периода» 31.08.2005 00:00:00 Пульт VH Фили-2 10 10 0 0 0
ства записей за другие периоды (например, за прошлые годы) скорость выполнения этой задачи не зависит. Для обеспечения максимальной скорости выполнения за- проса по этой виртуальной таблице также важно пра- вильное применение отборов по измерениям. Правила применения таких отборов описаны в разделе «Примене- ние отборов в запросах, использующих виртуальные таб- лицы регистров накопления», с. 230. Особенности использования периодов и моментов времени при получении остатков и оборотов По умолчанию при использовании виртуальной таблицы остатков и оборотов итоги по остаткам и оборотам рас- считываются включая граничные периоды (рис. 8.43). Поэтому все особенности использования параметров Нача- лоПериода и КонецПериода аналогичны виртуальной таблице оборотов (см. раздел «Особенности использования перио- дов и моментов времени при получении оборотов», с. 216). Расчет итогов по полям остатков при использовании виртуальной таблицы остатков и оборотов Отдельного рассмотрения заслуживает вопрос расчета итогов по полям остатков, поскольку с прикладной точки зрения не всегда они могут быть получены простым сум- мированием, а должны рассчитываться с привлечением специального алгоритма. Рис. 8.43. Получение остатков и оборотов включая границы периода Для задействования этого алгоритма система прежде все- го должна распознать необходимость специфичного рас- чета итогов по полям остатков. Например, для запроса, текст которого приведен в лис- тинге 8.72, итоги будут получены простым суммировани- ем данных соответствующих записей. Предположим, что таблица движений регистра Товары- НаСкладах заполнена так, как показано в табл. 8.69. В этом случае, если параметры запроса установлены так, как показано в листинге 8.73, результат выполнения за- проса будет иметь вид, представленный в табл. 8.70. Таблица 8.69. Таблица движений регистра накопления Период Регистратор Номер Строки Вид движения Активность Номенклатура Склад Количество 10.07.2005 11:00:00 ПоступлениеТоваров №1 10.07.2005 11:00:00 1 Приход Истина Пульт PW Главный 1 10.07.2005 11:01:00 ПоступлениеТоваров №2 10.07.2005 11:00.00 1 Приход Истина Пульт VH Фили-2 10 13.08.2005 15:00:01 ПоступлениеТоваров №3 13.08.2005 15:00:01 1 Приход Истина Пульт VH Главный 10 13.08.2005 15:00:01 ПоступлениеТоваров №3 13.08.2005 15:00:01 2 Приход Истина Пульт PW Главный 7 17.08.2005 18:00:00 ПоступлениеТоваров №8 17.08.2005 18:00:00 1 Приход Истина Пульт PW Розничный 3 23.08.2005 15:30:45 ПоступлениеТоваров №4 23.08.2005 15:30:45 1 Приход Ложь Пульт VH Фили-2 5 27.08.2005 12:30:45 Реализация №1 27.08.2005 12:30:45 1 Расход Истина Пульт VH Главный 9 31.08.2005 13:00:00 ПоступлениеТоваров №5 31.08.2005 13:00:00 1 Приход Истина Пульт PW Фили-2 1 31.08.2005 14:00:00 ПоступлениеТоваров №6 31.08.2005 14:00:00 1 Приход Истина Пульт PW Фили-2 2 31.08.2005 15:59:00 Реализация №2 31.08.2005 15:59:00 1 Расход Истина Пульт PW Фили-2 1 31.08.2005 23:59:59 ПоступлениеТоваров №7 31.08.2005 23:59:59 1 Приход Истина Пульт PW Фили-2 2
Листинг 8.72. Пример получения остатков и оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот КАК КоличествоОборот, ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход, ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.0статкиИ0бороты( &НачалоПериода. &КонецПериода. Движения, ) КАК ТоварыНаСкладахОстаткиИОбороты ИТОГИ СУММА(КоличествоНачальныйОстаток), СУММА(КоличествоКонечныйОстаток), СУММА(КоличествоОборот), СУММА(КоличествоПриход). СУММА(КоличествоРасход) ПО Номенклатура АВТОУПОРЯДОЧИВАНИЕ Листинг 8.73. Пример установки параметров запроса Запрос.УстановитьПараметрС"НачалоПериода", '20050801'); Запрос.УстановитьПараметрС"КонецПериода". КонецДняС'20050831')): Теперь изменим текст запроса так, как показано в лис- тинге 8.74. Листинг 8.74. Пример получения остатков и оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура. ТоварыНаСкладахОстаткиИОбороты.Период КАК Период. ТоварыНаСкладахОстаткиИОбороты.Склад. ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот КАК КоличествоОборот, ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход, ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты( ^НачалоПериода, ^КонецПериода. День. ДвиженияИГ раницыПериода, ) КАК ТоварыНаСкладахОстаткиИОбороты ИТОГИ СУММА(КоличествоНачальныйОстаток), СУММА(КоличествоКонечныйОстаток), СУММА(КоличествоОборот), СУММА(КоличествоПриход), СУММА(КоличествоРасход) ПО Номенклатура АВТОУПОРЯДОЧИВАНИЕ В этом случае при расчете итогов остатков система будет действовать по следующему алгоритму: ♦ исходные записи временной промежуточной таблицы (записанной в базе данных в процессе выполнения ал- горитма построения виртуальной таблицы остатков и оборотов) упорядочиваются по полям первого уровня (в нашем случае — Номенклатура и Склад), далее — хро- нологически; ♦ при обходе упорядоченных записей: первые записи по каждой комбинации полей первого уровня используются для суммирования начального остатка; последние записи по каждой комбинации полей пер- вого уровня используются для суммирования конеч- ного остатка. Если использовать тот же вариант установки значений параметров виртуальной таблицы остатков и оборотов (см. листинг 8.73), то таблица результата будет выглядеть уже по-другому (табл. 8.71). Серым фоном отмечены те поля, которые были просум- мированы при получении итогов полей остатков по но- менклатуре. Аналогичным образом система поступила бы, если бы группировок итогов было больше. Главное, что они нахо- дятся до группировки итогов Период. В случае же если среди итогов есть группировка Период (листинг 8.75), алгоритм расчета полей остатков еще бо- лее сложный. Таблица 8.70. Результат выполнения запроса Номенклатура Склад Количество- НачальныйОстаток Количество- КонечныйОстаток Количество- Оборот Количество- Приход Количество- Расход Пульт PW 1 15 14 15 1 Пульт PW Главный 1 8 7 7 0 Пульт PW Розничный 0 3 3 3 0 Пульт PW Фили-2 0 4 4 5 1 Пульт VH 0 1 1 10 9 Пульт VH Главный 0 1 1 10 9
Таблица 8.71. Результат выполнения запроса Номенклатура Склад Период Количество- Начальный- Остаток Количество- Конечный- Остаток Количество- Оборот Количество- Приход Количество- Расход Пульт PW 1 15 14 15 1 Пульт PW Главный 01.08.2005 00:00:00 1 1 0 0 0 Пульт PW Главный 13.08.2005 00:00:00 1 8 7 7 0 Пульт PW Главный 31.08.2005 00:00:00 8 8 0 0 0 Пульт PW Розничный 17.08.2005 00:00:00 0 3 3 3 0 Пульт PW Розничный 31.08.2005 00:00:00 3 3 0 0 0 Пульт PW Фили-2 31.08.2005 00:00:00 0 4 4 5 1 Пульт PW Фили-2 31.08.2005 00:00:00 4 4 0 0 0 Пульт VH 10 И 1 10 9 Пульт VH Главный 13.08.2005 00:00:00 0 10 10 10 0 Пульт VH Главный 27.08.2005 00:00:00 10 1 -9 0 9 Пульт VH Главный 31.08.2005 00:00:00 1 1 0 0 0 Пульт VH Фили-2 01.08.2005 00:00:00 10 10 0 0 0 Пульт VH Фили-2 31.08.2005 00:00:00 10 10 0 0 0 Листинг 8.75. Пример получения остатков и оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Период КАК Период, ТоварыНаСкладахОстаткиИОбороты.Склад. ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот КАК КоличествоОборот, ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход, ТоварыНаСкладахОстаткиИОбороты. КоличествоРасход КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах. 0статкиИ0бороты( ^НачалоПериода, ^КонецПериода. День, ДвиженияИГ раницыПериода, ) КАК ТоварыНаСкладахОстаткиИОбороты ИТОГИ СУММА(КоличествоНачальныйОстаток), СУММА(КоличествоКонечныйОстаток), СУММА(КоличествоОборот), СУММА(КоличествоПриход), СУММА(КоличествоРасход) ПО Номенклатура. Период АВТОУПОРЯДОЧИВАНИЕ Для приведенного примера при расчете полей остатков будут выполняться следующие действия: ♦ расчет итогов для группировки (группировок) перед группировкой Период (в нашем примере это расчет для группировки Номенклатура) выполняется по тому же ал- горитму, что и в предыдущем примере; ♦ расчет итогов для группировки Период: исходные записи временной промежуточной табли- цы остатков и оборотов (записанной в базе данных в процессе выполнения алгоритма построения вир- туальной таблицы остатков и оборотов) упорядочи- ваются по полям, использованным в группировках выше (в нашем случае это группировка Номенклату- ра), затем хронологически (по полю Период), да- лее — по оставшимся полям первого уровня (в на- шем случае Склад);
внутри группировки первого уровня (Номенклатура), для каждого значения группировки Период рассчиты- ваются значения полей остатков, посредством обходов записей и суммирования значений нужных полей: о для начального остатка: обход всех записей, у кото- рых дата больше или равна значению даты группи- ровки Период, начиная от этой даты (то есть «вниз»). При обходе выполняется суммирование значений поля НачальныйОстаток для записей, содержащих раз- личные (ранее не встреченные в процессе обхода) комбинации значений полей первого уровня (в на- шем примере Номенклатура и Склад); о для конечного остатка: обход всех записей, у кото- рых дата меньше или равна значению даты группи- ровки Период, начиная от этой даты (то есть «вверх»). При обходе выполняется суммирование значений поля КонечныйОстаток для записей, содержащих раз- личные (ранее не встреченные в процессе обхода) комбинации значений полей первого уровня (в на- шем примере Номенклатура и Склад). Для наглядности работы алгоритма расчета итогов остат- ков группировки Период рассмотрим фрагмент заполне- ния таблицы результата. Пусть заполнение регистра бу- дет тем же, что рассматривали раньше (см. табл. 8.66), с теми же значениями параметров НачалоПериода и Конец- Периода (см. листинг 8.73). Расчет промежуточных итогов остатков товара Пулы PW для значения периода 17.08.2005 00:00:00 будет произведен по следующей схеме (табл. 8.72). Серым фоном отмечены те поля, которые были просум- мированы при получении итогов. В целом таблица результата запроса будет выглядеть сле- дующим образом (табл. 8.73). Обратите внимание: «особыми» алгоритмами были рас- считаны только поля остатков, поля же оборотов рассчи- тываются простым суммированием в рамках требуемых группировок. Для более сложных случаев, когда среди группировочных полей итогов есть и предшествующие полю Период и на- ходящиеся после него, алгоритм расчета итогов включает в себя следующие этапы: ♦ расчет итогов для группировок, предшествующих груп- пировке Период; ♦ расчет итогов для группировки Период; ♦ расчет итогов для группировок после группировки Пе- риод. Производится как для обычных полей, то есть простым суммированием. Хотелось бы еще раз подчеркнуть, что в любом случае при- менение этих «особых» алгоритмов происходит уже после того, как виртуальная таблица остатков и оборотов была получена и сохранена во временной таблице базы данных. Рассмотрим еще ряд особенностей различных вариантов использования полей остатков, когда система будет при- менять еще более сложные алгоритмы. Получение итогов по одному полю остатков Для того чтобы запрос мог рассчитать итоги по полям ос- татка, необходимо, чтобы в запросе получались оба значе- ния остатка за период (начальный и конечный). В случае если в запросе получается только один остаток и по нему ведется расчет итога, программа неявно добавит в запрос получение данных из информационной базы поле парно- го остатка. Например, в случае выполнения запроса, представленно- го в листинге 8.76, будет неявно добавлено поле Товары- НаСкладахОстаткиИОбороты. КоличествоКонечныйОстаток, по- тому что иначе возникли бы сложности с расчетом итогов последних периодов, если в них не было движений. Таблица 8.72. Результат расчета промежуточных итогов Номенклатура Период Склад КоличествоНачальный- Остаток КоличествоКонечный- Остаток Упорядоченные записи из временной таблицы остатков и оборотов Пульт PW 01.08.2005 00:00:00 Главный 1 1 Пульт PW 13.08.2005 00:00:00 Главный 1 8 Рассчитываемая запись итога по периоду Пульт PW 17.08.2005 00:00:00 8 И Упорядоченные записи из временной таблицы остатков и оборотов Пульт PW 17.08.2005 00:00:00 Розничный 0 3 Пульт PW 31.08.2005 00:00:00 Главный 8 8 Пульт PW 31.08.2005 00:00:00 Розничный 3 3 Пульт PW 31.08.2005 00:00:00 Фили-2 0 4 Пульт PW 31.08.2005 00:00:00 Фили-2 4 4
Таблица 8.73. Результат выполнения запроса Номенклатура Период Склад Количество- Начальный- Остаток Количество- Конечный- Остаток Количество- Оборот Количество- Приход Количество- Расход Итоги по номенклатурной позиции Пульт PW 1 15 14 15 1 Итоги по периоду «День» Пульт PW 01.08.2005 00:00:00 1 1 0 0 0 Итоги по граничному значению «НачалоПериода» Пульт PW 01.08.2005 00:00:00 Главный 1 1 0 0 0 Итоги по периоду «День» Пульт PW 13.08.2005 00:00:00 1 8 7 7 0 Пульт PW 13.08.2005 00:00:00 Главный 1 8 7 7 0 Итоги по периоду «День» Пульт PW 17.08.2005 00:00:00 8 11 3 3 0 Пульт PW 17.08.2005 00:00:00 Рознич- ный 0 3 3 3 0 Итоги по периоду «День» Пульт PW 31.08.2005 00:00:00 11 15 4 5 1 Итоги по граничному значению «КонецПериода» Пульт PW 31.08.2005 00:00:00 Главный 8 8 0 0 0 Итоги по граничному значению «КонецПериода» Пульт PW 31.08.2005 00:00:00 Рознич- ный 3 3 0 0 0 Пульт PW 31.08.2005 00:00:00 Фили-2 0 4 4 5 1 Итоги по граничному значению «КонецПериода» Пульт PW 31.08.2005 00:00:00 Фили-2 4 4 0 0 0 Итоги по номенклатурной позиции Пульт VH 10 И 1 10 9 Итоги по периоду «День» Пульт VH 01.08.2005 00:00:00 10 10 0 0 0 Итоги по граничному значению «НачалоПериода» Пульт VH 01.08.2005 00:00:00 Фили-2 10 10 0 0 0 Итоги по периоду «День» Пульт VH 13.08.2005 00:00:00 10 20 10 10 0 Пульт VH 13.08.2005 00:00:00 Главный 0 10 10 10 0 Итоги по периоду «День» Пульт VH 27.08.2005 00:00:00 20 И -9 0 0 Пульт VH 27.08.2005 00:00:00 Главный 10 1 -9 0 9 Итоги по периоду «День» Пульт VH 31.08.2005 00:00:00 И И 0 0 0 Итоги по граничному значению «КонецПериода» Пульт VH 31.08.2005 00:00:00 Главный 1 1 0 0 0 Итоги по граничному значению «КонецПериода» Пульт VH 31.08.2005 00:00:00 Фили-2 10 10 0 0 0
Листинг 8.76. Пример получения остатков и оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Период КАК Период, ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот КАК КоличествоОборот, Т оварыНаСкладахОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход, ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.0статкиИ0бороты( &НачалоПериода, &КонецПериода, День. ДвиженияИГ раницыПериода, ) КАК ТоварыНаСкладахОстаткиИОбороты ИТОГИ СУММА(КоличествоНачальныйОстаток), СУММА(КоличествоОборот), СУММА(КоличествоПриход), СУММА(КоличествоРасход) ПО Номенклатура, Период АВТОУПОРЯДОЧИВАНИЕ Аналогичным образом система поступает и в ситуации, ко- гда поле-остаток используется в выражении (листинг 8.77). Листинг 8.77. Пример получения остатков и оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Период КАК Период. ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток * ТоварыНаСкладахОстаткиИОбороты.Номенклатура. ЗакупочнаяЦена КАК СуммаКонечныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот * ТоварыНаСкладахОстаткиИОбороты.Номенклатура. ЗакупочнаяЦена КАК СуммаОборот. ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход * ТоварыНаСкладахОстаткиИОбороты.Номенклатура. ЗакупочнаяЦена КАК СуммаПриход, ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход * Т оварыНаСкладахОстаткиИОбороты.Номенклатура. ЗакупочнаяЦена КАК СуммаРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОборотыГ &НачалоПериода, &КонецПериода, День, ДвиженияИГ раницыПериода, ) КАК ТоварыНаСкладахОстаткиИОбороты ИТОГИ СУММА(СуммаКонечныйОстаток). СУММА(СуммаОборот), СУММА(СуммаПриход), СУММА(СуммаРасход) ПО Номенклатура, Период АВТОУПОРЯДОЧИВАНИЕ В этом случае будет неявно добавлено поле ТоварыНаСкла- дахОстаткиИОбороты.КоличествоНачальныйОстаток * Товары- НаСкладахОстаткиИОбороты.Номенклатура.ЗакупочнаяЦена. Получение итогов по регистратору или номеру строки Поле Период записей, подчиненных одному регистратору, в общем случае может иметь неодинаковые значения. По- этому для определения момента времени, начиная с кото- рого запись влияет на рассчитываемые итоги, сначала учитывается значение поля Период записи, потом Регист- ратор, а потом — НомерСтроки. В результате, из-за того что регистратор, по сути, являет- ся уточнением периода, при расчете итогов по регистра- тору необходимо иметь в виду, что получать итоги по ре- гистратору можно только внутри группировки Период. Если получить итоги по регистратору до получения ито- гов по периоду, они могут оказаться некорректными! Аналогично, итоги по номеру строки можно получать только внутри группировки по периоду и регистратору. Получение итогов остатков в комбинации с другими полями В ситуациях, когда выходные поля запроса получаются посредством выражения, содержащего начальный или ко- нечный остаток, действия системы аналогичны. В этом случае запрос будет манипулировать значениями, вычис- ленными согласно описанным правилам. То есть для поля, представленного в листинге 8.78, значения будут в «ЗакупочнаяЦена» раз больше. Листинг 8.78. Поле выборки запроса ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток * ТоварыНаСкладахОстаткиИОбороты.Номенклатура. ЗакупочнаяЦена КАК СуммаКонечныйОстаток. Но если в составе выражения используется более одного поля начального или конечного остатка, то итоги по та- ким полям получаются уже простым суммированием. Рассмотрим запрос, представленный в листинге 8.79. Если установить параметры запроса так, как показано в листинге 8.80, то результат выполнения запроса будет выглядеть так, как показано в табл. 8.74. Листинг 8.79. Пример получения остатков и оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Период КАК Период, ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток, ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток - ТоварыНаСкладахОстаткиИОбороты. КоличествоНачальныйОстаток КАК Разница ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток * ТоварыНаСкладахОстаткиИОбороты. КоличествоНачальныйОстаток КАК Произведение
из РегистрНакопления.ТоварыНаСкладах.ОстаткиИОборотыС &НачалоПериода, &КонецПериода. День. ДвиженияИГ раницыПериода. ) КАК ТоварыНаСкладахОстаткиИОбороты ИТОГИ СУММА(КоличествоНачальныйОстаток), СУММА(КоличествоКонечныйОстаток), СУММА(Разница), СУММА(Произведение) ПО Номенклатура, Период АВТОУПОРЯДОЧИВАНИЕ Листинг 8.80 Установка параметров запроса Запрос.УстановитьПараметрГ"НачалоПериода", '20050801'): Запрос.УстановитьПараметрС"КонецПериода", КонецДняГ'20050831')); Таблица 8.74. Результат выполнения запроса Номенклатура Период Склад Количество- НачальныйОстаток Количество- КонечныйОстаток Разница Произведение Пульт PW 1 15 И 98 Пульт PW 01.08.2005 00:00:00 1 1 0 1 Пульт PW 01.08.2005 00:00:00 Главный 1 1 0 1 Пульт PW 13.08.2005 00:00:00 1 8 7 8 Пульт PW 13.08.2005 00:00:00 Главный 1 8 7 8 Пульт PW 17.08.2005 00:00:00 8 И 3 0 Пульт PW 17.08.2005 00:00:00 Розничный 0 3 3 0 Пульт PW 31.08.2005 00:00:00 И 15 4 89 Пульт PW 31.08.2005 00:00:00 Главный 8 8 0 64 Пульт PW 31.08.2005 00:00:00 Розничный 3 3 0 9 Пульт PW 31.08.2005 00:00:00 Фили-2 0 4 4 0 Пульт PW 31.08.2005 00:00:00 Фили-2 4 4 0 16 Пульт VH 10 И 1 211 * Пульт VH 01.08.2005 00:00:00 10 10 0 100 Пульт VH 01.08.2005 00:00:00 Фили-2 10 10 0 100 Пульт VH 13.08.2005 00:00:00 10 20 10 0 Пульт VH 13.08.2005 00:00:00 Главный 0 10 10 0 Пульт VH 27.08.2005 00:00:00 20 И -9 10 Пульт VH 27.08.2005 00:00:00 Главный 10 1 -9 10 Пульт VH 31.08.2005 00:00:00 11 И 0 101 Пульт VH 31.08.2005 00:00:00 Главный 1 1 0 1 Пульт VH 31.08.2005 00:00:00 Фили-2 10 10 0 100
Использование соединений с таблицей остатков и оборотов В случае применения конструкции ИТОГИ ПО для запросов, включающих в себя соединения виртуальной таблицы ос- татков и оборотов с другими таблицами (например, с ос- новной таблицей регистра), необходимо учитывать влияние наличия всех возможных комбинаций значений полей связанных таблиц (удовлетворяющих условиям соедине- ния) на вышеописанные алгоритмы расчета полей итогов. Иначе легко получить «удивительные» с прикладной точки зрения результаты запросов. Например, рассмотрим запрос, текст которого представ- лен в листинге 8.81. Листинг 8.81. Пример получения остатков и оборотов регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток, Т ов арыНаСкладахОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход, ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход, Т оварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток, ТоварыНаСкладах.ВидОперации КАК ВидОперации ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах ПО ТоварыНаСкладахОстаткиИОбороты.Номенклатура = ТоварыНаСкладах.Номенклатура ИТОГИ СУММА(КоличествоНачальныйОстаток), СУММА(КоличествоПриход), СУММА(КоличествоРасход). СУММА(КоличествоКонечныйОстаток) ПО Номенклатура, ВидОперации В результате данные по остаткам и оборотам каждой но- менклатурной позиции могут быть завышены в несколь- ко раз, или даже десятков тысяч раз, в зависимости от того, сколько записей с этой номенклатурной позицией присутствует в таблице движений регистра и как они упорядочатся по хронологии внутри вышестоящих груп- пировок. Применение отборов в запросах, использующих виртуальные таблицы регистров накопления Для обеспечения максимальной скорости выполнения за- просов важно правильно применять условия отборов. Например, для получения остатков по отдельной номенк- латурной позиции текст запроса может выглядеть так, как показано в листинге 8.82, или так, как показано в лис- тинге 8.83. Листинг 8.82. Пример использования отбора в виртуальной таблице ВЫБРАТЬ ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстатки.Склад КАК Склад. ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки! &Период, Номенклатура = &НоменклатураОтбора ) КАК ТоварыНаСкладахОстатки Листинг 8.83. Пример неэффективного запроса, использующего виртуальную таблицу остатков ВЫБРАТЬ ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстатки.Склад КАК Склад, ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК ТоварыНаСкладахОстатки ГДЕ ТоварыНаСкладахОстатки.Номенклатура = &НоменклатураОтбора По сравнению с первым, второй вариант является неэф- фективным по скорости исполнения, поскольку сначала по всем номенклатурным позициям будут проведены не- обходимые расчеты и получена виртуальная таблица ос- татков, а отбор будет использован уже после. Условия построения виртуальной таблицы могут реали- зовываться не только по равенству значений измерений, но и по вхождению их в массив или список значений (листинг 8.84). Листинг 8.84. Пример получения остатков регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстатки.Склад КАК Склад, ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки! &Период, Номенклатура В !&МассивНоменклатурныхПозиций) ) КАК ТоварыНаСкладахОстатки Также может использоваться условие вхождения в таб- лицу результата вложенного запроса. Например, если при проведении документа РеализацияТоваров требуется получить данные о количестве товара в самом документе и в остатках регистра ТоварыНаСкладах на момент проведе- ния документа, то, для быстрого выполнения этой опера- ции, виртуальную таблицу остатков лучше строить толь- ко по тем номенклатурным позициям и тому складу, которые указаны в документе (листинг 8.85).
Кроме того, условие построения виртуальной таблицы может быть по значениям полей, подчиненных полям из- мерений (листинг 8.86). Листинг 8.85. Пример получения остатков регистра накопления ВЫБРАТЬ ТаблицаДокунента.Ноненклатура, СУММА(ТаблицаДокунента.Количество) КАК Количество, ТоварыНаСкладахОстатки.КоличествоОстаток, СУММАСТаблицаДокумента.Сунна) КАК Сунна ИЗ Документ. РеализацияТоваров.Состав КАК ТаблицаДокунента ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки( &Монент. Ноненклатура В (ВЫБРАТЬ РАЗЛИЧНЫЕ РеализацияТоваровТовары.Ноненклатура ИЗ Докунент.РеализацияТоваров. Состав КАК РеализацияТоваровТовары ГДЕ РеализацияТоваровТовары.Ссылка = &ТекущийДокунент И Склад = &Склад)) КАК ТоварыНаСкладахОстатки ПО ТаблицаДокунента.Ноненклатура = ТоварыНаСкладахОстатки.Ноненклатура ГДЕ ТаблицаДокунента.Ссылка = &ТекущийДокунент СГРУППИРОВАТЬ ПО ТаблицаДокунента.Ноненклатура, ТоварыНаСкладахОстатки.КоличествоОстаток Листинг 8.86. Пример получения остатков регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстатки.Ноненклатура КАК Ноненклатура, ТоварыНаСкладахОстатки.Склад КАК Склад, ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки( &Период, Ноненклатура.ЗакупочнаяЦена > БПороговаяЦена ) КАК ТоварыНаСкладахОстатки Однако необходимо учитывать, что подобные операции «разыменования» реализуются за счет неявных дополни- тельных соединений с соответствующими таблицами. В данном примере в момент построения виртуальной таб- лицы выполняется левое соединение с таблицей справоч- ника. Наибольшего эффекта увеличения скорости построения виртуальных таблиц за счет применения параметра усло- вия можно добиться в том случае, если условия наклады- ваются на первые измерения, потом вторые и так далее. В принципе, сам порядок описания условий не важен, ва- жен порядок измерений, на которые эти условия накла- дываются. Тогда система сможет эффективно применять индексы при выполнении запроса. В вышеописанных примерах, если не применять условие отбора по первому измерению Номенклатура, а применить условие отбора по измерению Склад (листинг 8.87), то для получения данных таблицы итогов система сможет при- менить индекс Период + Номенклатура + Склад, а из таблицы движений регистра данные будут взяты при помощи ин- декса Период + Регистратор + НомерСтроки. То есть произойдет отбор всех записей соответствующего перио- да из таблиц регистра. А уже просматривая эти записи, система сможет отсечь из рассмотрений записи по ненуж- ным складам. Поскольку для регистра накопления обыч- ной является ситуация, когда количество записей движе- ний на порядки больше количества записей итогов, то для повышения скорости построения виртуальной табли- цы «бороться» прежде всего нужно с движениями по «лишним» складам. Листинг 8.87. Пример получения остатков регистра накопления ВЫБРАТЬ ТоварыНаСкладахОстатки.Ноненклатура КАК Ноненклатура, ТоварыНаСкладахОстатки.Склад КАК Склад, ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиС &Период, Склад = ЯСкладОтбора ) КАК ТоварыНаСкладахОстатки Поэтому изначально, описывая данные регистра как объекта конфигурации можно указать индексирование измерения Склад. Тогда система сможет использовать данные не только индекса Период + Регистратор + Номер- Строки, но и индекса Склад + Период + Регистратор + Номер- Строки. Необходимо заметить, что порядок применения или не- применения тех или иных индексных таблиц в каждом конкретном случае исполнения конкретного запроса бе- рут на себя механизмы СУБД, отвечающие за доступ к информации. Однако оптимальный порядок следования измерений в структуре регистра и индексирование полей регистра помогают СУБД чаще принимать верные с точ- ки зрения эффективности решения. Когда следует использовать запрос вместо объектной модели обращения при получении данных регистров накопления В случаях простейших обращений к информации базы данных удобство и быстродействие использования таб- личной и объектной модели чтения одинаковы. Дело в том, что как запрос, написанный на языке системы «1С:Предприятие», так и использование соответствую- щего метода реализуются платформой посредством «пе- ревода» этих обращений в язык запросов СУБД, зачас- тую совершенно (или почти) одинаковых. Исключение составляют ситуации использования меха- низма обращения к динамическим данным. Посредством этого механизма чтение информации осуществляется не полностью в момент обращения, а блоками. Более под- робно использование данного механизма описано ниже,
в разделе «Работа с регистрами при отображении дина- мических данных», с. 233. В данном же разделе обращается внимание на задачи, ко- торые можно решить эффективно только посредством за- просов. К ним относятся: ♦ гибкое применение отборов и группировок; ♦ соединение с информацией других объектов; ♦ применение блокировок считываемых данных; ♦ применение разграничения доступа на уровне запи- сей. В случае применения методов Остатки О и ОборотыО воз- можно применение отборов для измерений на равенство неким значениям. Более сложные отборы необходимо реализовать с помощью установки значений параметров соответствующих виртуальных таблиц запросов. Это относится, например, к условию вхождения значений измерений в определенную группу; условию не равен- ства некому значению; условию превышения некого значения (например, если измерение имеет тип Дата); условию равенства двум значениям (логическое «или») и т. д. В случае необходимости соединения данных несколь- ких объектов применение запросов также является бо- лее эффективным. Например, задачу контроля остатка для каждой номенклатурной позиции при проведении документа реализации товаров, можно решить как с ис- пользованием запроса, так и с использованием объект- ной модели. Если рассматривать запрос, использующий левое соеди- нение (листинг 8.88), то результатом его работы будет таблица, содержащая колонки КоличествоВДокументе и Ко- личествоВОстаткеРегистра. В данном случае виртуальная таблица остатков будет по- строена только по нужным товарным позициям (указан- ным в табличной части Состав проводимого документа), далее полученный результат соединен с записями таб- личной части проводимого документа. Результирующая таблица будет сгруппирована на случай упоминания од- них и тех же товарных позиций в документе более одного раза. Все эти операции будут выполнены в рамках одного запроса обращения к данным базы данных. При использовании объектной модели необходимо будет выгрузить табличную часть Состав документа в таблицу значений. Затем свернуть полученную таблицу значений по колонке Номенклатура (на случай неоднократного упо- минания одного и того же товара в табличной части). По- сле этого в цикле перебора строк полученной таблицы значений обращаться к данным регистра методом ОстаткиО, применяя отбор по значению конкретной номенклатур- ной позиции. Неэффективность данного подхода прояв- ляется в многократных обращениях к таблицам регистра в базе данных. Модификация использования объектной модели чтения для решения данной задачи, когда метод ОстаткиО полу- чается не в цикле перебора строк, а до него, также неэф- фективна, поскольку тогда для функциональности алго- ритма придется получать остатки по всем (а не по нужным) номенклатурным позициям, а в цикле перебора товаров документа искать нужные строки в таблице зна- чений остатков. Листинг 8.88. Пример получения остатков регистра накопления с помощью запроса ВЫБРАТЬ ТаблицаДокумента.Номенклатура, СУММАСТаблицаДокумента.Количество) КАК КоличествоВДокументе, ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоВОстаткеРегистра ИЗ Документ.РеализацияТоваров.Состав КАК ТаблицаДокумента ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки( , Номенклатура В (ВЫБРАТЬ РАЗЛИЧНЫЕ РеализацияТоваровТовары. Номенклатура ИЗ Документ.РеализацияТоваров.Состав КАК РеализацияТоваровТовары ГДЕ РеализацияТоваровТовары.Ссылка = &ТекущийДокумент И Склад = &Склад)) КАК ТоварыНаСкладахОстатки ПО ТаблицаДокумента.Номенклатура = ТоварыНаСкладахОстатки. Номенклатура ГДЕ ТаблицаДокумента.Ссылка = &ТекущийДокумент СГРУППИРОВАТЬ ПО ТаблицаДокумента.Номенклатура, ТоварыНаСкладахОстатки.КоличествоОстаток Использование же в данной ситуации запроса позволяет получать данные из таблиц регистра только по нужным значениям измерений, причем в рамках одного обраще- ния к базе данных. В случае отработки задач конкурентного использования ресурсов запрос также предпочтительнее. Например, при использовании клиент-серверного режима работы про- граммы для обработки проведения документа необхо- димо получать текущие остатки регистра. Но эти остатки (по нужным значениям измерений) гарантировано не должны изменяться такими же документами, проводи- мыми параллельно, вплоть до окончания транзакции. То- гда при чтении данных регистра запросом можно приме- нить конструкцию ДЛЯ ИЗМЕНЕНИЯ. На нужные записи будут наложены блокировки обновления, обеспечивающие вы- полнение задачи. Соответствующий пример можно найти в разделе «Блокировка записей регистров», с. 237. Также запросы позволяют использовать, при необходи- мости, один из двух режимов получения данных из полей базы данных: ♦ с использованием конструкции РАЗРЕШЕННЫЕ; ♦ с использованием конструкции ВСЕ. В первом случае в таблице результата запроса будут об- работаны только те записи, что разрешены при использо- вании ограничений доступа на уровне записей. Неразре- шенные записи будут проигнорированы. Объектная же техника обращения к информации базы данных выполня- ется только в режиме ВСЕ.
Отдельные вопросы использования регистров накопления Работа с регистрами при отображении динамических данных Объект РегистрНакопленияСписок.<имя> Для обеспечения динамического просмотра записей реги- стра в табличном поле предназначен объект РегистрНакоп- ленияСписок.<иня>. Он осуществляет считывание данных из информационной базы блоками, в процессе навигации пользователя в табличном поле. Это уменьшает время за- грузки списка и объем отводимой для него памяти, что позволяет комфортно работать даже с очень большими списками. Например, не возникает задержек при откры- тии формы (считывается только нужный блок, а не весь список), или при переходе в конец списка (система не обязана считывать все данные регистра, будет считан блок только с нужными) и т. д. Объект РегистрНакопленияСписок.<имя> позволяет управлять составом считываемых полей (колонок), отборами и сор- тировкой. При этом и элемент управления ТабличноеПоле управляет набором полей, считываемых из базы данных. Считыва- ются только следующие поля таблицы базы данных: ♦ связанные с соответствующими видимыми колонками табличного поля; ♦ поля, по которым выполняется упорядочивание; ♦ поля, используемые табличным полем для отображе- ния картинки. То есть в составе объекта РегистрНакопленияСписок.<иня> всегда будут присутствовать колонки: ♦ Регистратор; ♦ Активность; ♦ ВидДвижения (для регистра накопления остатков). Остальные колонки будут присутствовать, только если соответствующие им колонки табличного поля видимы. Настройка видимости колонок может осуществляться не только в режиме конфигуратор, но и пользователем. Это можно реализовать посредством команды Настройка списка.., вызываемой через контекстное меню или через меню ко- мандной панели в форме списка регистра (рис. 8.44). После установки видимости/невидимости колонок таб- личное поле установит новый набор колонок в связанный с ним динамический список. В результате невидимые ко- лонки (за исключением вышеназванных «всегда присут- ствующих») будут удалены из списка. То есть система не будет считывать эти данные из базы данных. Логика про- ста — если не нужно показывать, то не нужно и считы- вать, чтобы еще больше сократить время считывания. Но иногда возникают задачи, когда может оказаться не- обходимым, чтобы объект РегистрНакопленияСписок.<иня> содержал некоторые колонки, даже если колонки в таб- личном поле, им соответствующие, невидимы. Например, при отображении данных регистра накопле- ния ТоварыНаСкладах для некой последующей обработки нужно, чтобы вне зависимости от видимости в табличном поле колонки, содержащей значения реквизита ВидОпера- ции, соответствующая колонка присутствовала в колон- ках списка РегистрНакопленияСписок.ТоварыНаСкладах. Гг Список Товары на складах Действиям (•**] gj Ke 10 01 2002 12 00 01 If Бдхгалгерир 77F. Реализация. □ X Настройка списка Колонки I Прочее____________ t 1 Стандартная настройка ОК | [ Отмена | Применить | Справка- Рис. 8.44. Форма настройки списка регистра накопления Для решения данной задачи можно в обработчике собы- тия ПриОткрытии формы списка регистра проверить нали- чие данной колонки и в случае отсутствия ее добавить (листинг 8.89). Листинг 8.89. Обработчик события ПриОткрытии Процедура ПриОткрытииО Если РегистрНакопленияСписок.Колонки.НайтиСВидОперациии") = Неопределено Тогда РегистрНакопленияСписок.Колонки.Добавить("ВидОперации", Ложь); КонецЕсли; КонецПроцедуры При добавлении колонки свойству АвтоУдаление колонки списка устанавливается значение Ложь. В результате, при удалении колонки ВидОперации из табличного поля, свя- занная с ней колонка списка регистра удаляться не будет. В случае если такая колонка может быть видна пользова- телю, задача решается еще проще. Разработчик может в палитре свойств колонок табличного поля установить свойство Видимость и сбросить свойство ИзненятьВидиность. Сортировки и отборы, которые автоматически пред- ставляет к использованию система при работе с отобра- жением динамических данных регистра, реализованы с точки зрения обеспечения эффективности по скорости отображения. Дело в том, что для эффективной работы система использует индексы тех таблиц, содержимое которых отображается. В случае если пользователь (при «помощи» разработчика) будет использовать сор-
тировку, не соответствующую ни одному из индексов, механизм динамического просмотра не задействуется. И система будет вынуждена считывать сразу все дан- ные, которые потенциально могут быть отображены в списке (разумеется, согласно условиям отбора, если они будут наложены). Поэтому единственный вариант оптимального упорядо- чивания, предоставляемый системой и видимый пользо- вателю, — по полю Период (рис. 8.45). Отбор и сортировка Рис. 8.45. Форма настройки отбора и сортировки Данное упорядочивание дополняется системой по полям Регистратор и НомерСтроки. Необходимо заметить, что в поле Регистратор содержатся ссылки. Поэтому дополнительное упорядочивание будет по ссылкам на регистраторы. Если же разработчик установит программно сортировку по полю Регистратор либо предоставит возможность такой сортировки пользователю, то данный вариант сортиров- ки будет уже неоптимальным, система будет вынуждена упорядочивать по регистраторам в порядке их дат. В ре- зультате механизм динамического просмотра задейство- ван не будет. Подробно это описано в разделе «Порядок», с. 61. Работа с итогами при отображении динамических данных При работе с отображением динамических данных ино- гда возникает задача отображения и итогов регистров по значениям измерений, взятых из этих динамических дан- ных. Например, при отображении списка справочника Номенк- латура необходимо отображать остатки по этим номенкла- турным позициям в отдельной колонке списка. К решению подобных задач надо подходить предельно осторожно. Если расчет остатков будет происходить в рамках обра- ботчика события ПриВыводеСтроки, то получится, что систе- ма будет обращаться к базе данных каждый раз при выво- де отдельной строки. Это нельзя назвать оптимальным по скорости. Оптимально будет использование обработчика другого события ПриПолученииДанных. Данное событие касается всех видимых строк табличного поля. Параметром об- работчика события является коллекция объектов типа ОфорнлениеСтроки. То есть в обработчике события ПриПо- лученииДанных можно изменять любые элементы оформ- ления строк: шрифт, цвета и т. д., включая текст ячеек строк. Например, в составе табличного поля СправочникСписок формы списка справочника Номенклатура создадим ко- лонку с именем Остаток (рис. 8.46). В обработчике события ПриПолученииДанных табличного по- ля СправочникСписок разместим следующий код (лис- тинг 8.90). Листинг 8.90. Обработчик события ПриПолученииДанных Процедура СправочникСписокПриПолученииДанныхОленент. ОфорнленияСтрок) ОфорнлениеСтрокиПоНоненклатуре = Новый Соответствие: ОтображаемыеТовары = Новый Массив: Для каждого ОфорнлениеСтроки из ОфорнленияСтрок Цикл Товар = ОфорнлениеСтроки.ДанныеСтроки.Ссылка; // Заполнить пассив отображаемых номенклатурных позиций Отображаемые!ов ары.Доба вить(Товар); // Заполнить соответствие товара и оформления строки ОфорнлениеСтрокиПоНоненклатуре.Вставить(Товар, ОфорнлениеСтроки); КонецЦикла; // Сформировать запрос для получения остатков ЗапросОстатка = Новый Запрос; ЗапросОстатка.Текст = "ВЫБРАТЬ Справочник Номенклатура Гиперссылка О Чаюгъзоваие Автоотметка незаполненного Q Рис. 8.46. Добавление колонки в табличное поле
ТоварыНаСкладахОстатки.Номенклатура, ТоварыНаСкладахОстатки.КоличествоОстаток ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки( Номенклатура В ((^Номенклатура)) КАК ТоварыНаСкладахОстатки"; ЗапросОстатка.УстановитьПараметрС"Номенклатура", ОтображаемыеТовары); Выборка = ЗапросОстатка.ВыполнитьО.ВыбратьО: Пока Выборка.Следующий() Цикл // Вывести остаток в строку, найденную в соответствии // по номенклатуре из запроса ОформлениеСтрокиПоНоиенклатуре. Получить(Выборка.Номенклатура). Ячейки. Остаток. Значение = Выборка. КоличествоОстаток; КонецЦикла; КонецПроцедуры Краткий комментарий: сначала готовим массив номенк- латурных позиций, отображаемых на текущий момент в табличном поле, для последующего отбора по ним остат- ков. Параллельно готовим соответствие ссылок на эти но- менклатурные позиции объектам ОфорнлениеСтроки, в кото- рых эти товары упоминались. Далее формируем запрос по остаткам товаров с применением соответствующего отбора. В цикле перебора выборки результата запроса ус- танавливаем значения полей колонки Остаток для соот- ветствующих строк. Важно помнить, что в некоторых случаях обработчик со- бытия ПриПолученииДанных может вызываться табличным полем более одного раза при обновлении. Например, если текущая строка табличного поля находится в середине видимой области, и кроме того, в составе некоторой груп- пы, то при обновлении обработчик события ПриПолучении- Данных будет вызван трижды. Первый раз — для группы строк, определяющей иерархию активной строки; второй раз — начиная от текущей строки до верхней видимой; третий раз — для группы строк, начиная от текущей — до нижней видимой (рис. 8.47). Текущая строка входит в коллекцию “от текущей до верхней" * Справочник Номенклатура _ С X Рис. 8.47. Вызов обработчика события ПриПолученииДанных Такое поведение табличного поля связано с тем, что при обновлении табличное поле пытается сохранить позицию текущей строки в видимой области. Хотелось бы все же отметить, что в решении задач авто- матического отображения остатков в отдельной колонке динамического списка быстродействие системы сильно зависит от сложности алгоритма расчета. Ведь, например, при прокрутке списка пользователем система вынуждена будет слишком часто обращаться к базе данных для рас- чета остатков появляющихся полей. Если быстродействие получается неприемлемым, тогда надо рассматривать другие варианты отображения остат- ков, то есть изменять условия задачи. Например, нужно отображать остатки в отдельном поле в форме только для текущей строки табличного поля при нажатии на кнопку. Как еще один вариант решения, можно применять эле- менты механизма динамического просмотра данных, но с дополнительной функциональностью получения остат- ков. Пример такого решения приведен в демонстраци- онной конфигурации «Хранение информации и учет движения средств», которая находится на прилагаемом компакт-диске. Это обработка ПодборНоменклатуры. Форма обработки включает в себя два табличных поля: ДеревоНоменклатуры и ТаблицаПодбора. Поле ДеревоНомен- клатуры отображает группы справочника Номенклатура (только группы). При выборе пользователем группы в этом табличном поле в обработчике события заполняется таблица, отображаемая в ТаблицеПодбора (рис. 8.48). Форма обработки Подбор номенкгвгура * ’ X ДействАЯ’ (?) Рис. 8.48. Форма Подбор номенклатуры Состав обработки ПодборНоменкгвтуры = Макеты Для реализации данной функциональности использует- ся обработчик события Выбор табличного поля ДеревоНо- менклатуры. В процедуре сначала запросом собираются данные об ос- татках номенклатуры, входящей в выбранную группу, на нужном складе. Далее таблица, отображаемая нижним табличным полем, сначала очищается, потом заполняется необходимой информацией, полученной выборкой из ре- зультата запроса (листинг 8.91). Листинг 8.91. Обработчик события Выбор Процедура ДеревоНоненклатураВыборОленент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка) И Выбрать товары группы с остатками Запрос = Новый Запрос; Запрос.Текст = "
ВЫБРАТЬ Товары.Код. Товары.Ссылка КАК Номенклатура, ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток ИЗ Справочник.Номенклатура КАК Товары ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки( Номенклатура В (ВЫБРАТЬ Номенклатура.Ссылка ИЗ Справочник.Номенклатура КАК Номенклатура ГДЕ Номенклатура. Родитель = ((Родитель И Склад = &Склад)) КАК ТоварыНаСкладахОстатки ПО Товары.Ссылка = ТоварыНаСкладахОстатки.Номенклатура ГДЕ Товары. Родитель = ((Родитель И (НЕ Товары.ЭтоГруппа)"; // Установить в качестве параметра выбранную группу Запрос.УстановитьПарамегрСРодитель", ВыбраннаяСтрока); Запрос.УстановитьПараметрССклад", Склад): Результат = Запрос. ВыполнитьО: // Очистить таблицу подбора НоменклатураДляПодбора.Очистит ь О; // Заполнить таблицу подбора Выборка = Результат. Выбрать О; Пока Выборка.СледующийО Цикл НоваяСтрока = НоменклатураДляПодбора.ДобавитьО; НоваяСтрока. Код = Выборка. Код; НоваяСтрока.Номенклатура = Выборка.Номенклатура: НоваяСтрока.Остаток = Выборка.Остаток; КонецЦикла; КонецПроцедуры Теперь независимо от действий пользователя (например, использование полосы прокрутки), пока не будет перевы- брана группа в верхнем табличном поле, никаких обраще- ний к базе данных происходить не будет. В данном примере намеренно не используется механизм динамического отображения данных. Однако обеспечива- ется достаточно комфортная работа пользователя. Получение остатков при проведении документов При решении бизнес-задач зачастую возникают вопросы конкурентного управления ресурсами автоматизируемо- го предприятия. Сам учет ресурсов, как правило, ведется посредством регистров. Поэтому рассмотрим классиче- скую задачу и пути ее решения. Пользователи оформляют и проводят документы Заказ- Покупателя. Данный документ связан с двумя регистрами: Резервы Номенклатуры и ТоварыНаСкладах. При проведении данного документа необходимо отло- жить товар в резерв (выполнить движения по регистру РезервыНоменклатуры), но перед этим выполнить кон- троль возможности проведения данной операции. Отложить товар в резерв можно только в том случае, если его хватает, то есть если достаточно свободного (не заре- зервированного другими) остатка (рис. 8.49). Рис. 8.49. Контроль наличия товара Кроме того, контроль остатка нужно проводить не только при оперативном проведении. Иначе пользователи «по- нарезервируют» задним числом столько, сколько компа- ния вовек не продаст. А если заставить все заказы прово- дить только оперативно, то первый, кто возражает против такого решения — начальник отдела продаж. Зачастую выправление ситуаций коллизий остро конкурирующих заказов он разрешает, именно управляя хронологией за- казов. Мол, «вон тот заказ — поставим на вчера, а Ива- нов — пусть следующей поставки ждет...» Таким образом, при реализации алгоритма проведения документа необходимо будет читать данные остатков ре- гистров накопления. Пример реализации данного алгоритма проведения реа- лизован в модуле документа «ЗаказПокупателя» демон- страционной конфигурации «Хранение информации и учет движения средств», которая находится на прилагае- мом компакт-диске (листинг 8.92). Листинг 8.92. Обработчик события ОбработкаПроведения Процедура ОбработкаПроведения(Отказ, Режим) Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ ЗаказПокупателяСостав.Номенклатура, СУММА(ЗаказПокупателяСостав.Количество) КАК Количество, ЕСТЬМОЕКТоварыНаСкладахОстатки.КоличествоОстаток, 0) КАК Остаток, ЕСТЬШЕКРезервыНоменклатурыОстатки.КоличествоОстаток, 0) КАК Резерв ИЗ Документ.ЗаказПокупателя.Состав КАК ЗаказПокупателяСостав ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки( ((Момент, Номенклатура В (ВЫБРАТЬ РАЗЛИЧНЫЕ ЗаказПокупателяСостав.Номенклатура ИЗ Документ.ЗаказПокупателя.Состав КАК ЗаказПокупателяСостав ГДЕ ЗаказПокупателяСостав.Ссылка = («Ссылка)) КАК ТоварыНаСкладахОстатки ПО ЗаказПокупателяСостав.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.РезервыНоиенклатуры.Остатки( &Момент, Номенклатура В (ВЫБРАТЬ РАЗЛИЧНЫЕ ЗаказПокупателяСостав.Ноненклатура ИЗ Документ.ЗаказПокупателя.Состав КАК ЗаказПокупателяСостав ГДЕ ЗаказПокупателяСостав.Ссылка = &Ссылка)) КАК РезервыНоменклатурыОстатки ПО ЗаказПокупателяСостав.Номенклатура = РезервыНоменклатурыОстатки.Номенклатура ГДЕ ЗаказПокупателяСостав.Ссылка = &Ссылка СГРУППИРОВАТЬ ПО ЗаказПокупателяСостав.Номенклатура, РезервыНоменклатурыОстатки.КоличествоОстаток, ТоварыНаСкладахОстатки.КоличествоОстаток ДЛЯ ИЗМЕНЕНИЯ РегистрНакопления.РезервыНоиенклатуры.Остатки; Запрос.УстановитьПараметрС“Ссылка", Ссылка): Запрос.УстановитьПараметрС'Момент”, МоментВремениО); Результат = Запрос.Выполнить(): Выборка = Результат.ВыбратьО: Пока Выборка.Следующий() Цикл // Выполнить контроль остатка Нехватка = Выборка.Количество - (Выборка.Остаток - Выборка.Резерв); Если Нехватка > 0 Тогда Сообщить("Нехватка товара " + СокрЛП(Выборка.Номенклатура) + " + Нехватка): СообщитьСЗаказ покупателя " + Номер + " от " + Дата + " не проводится!"); Отказ = Истина: КонецЕсли; Если Не Отказ Тогда // Сформировать движения Движение = Движения.РезервыНоиенклатуры.ДобавитьО; Движение.ВидДвижения = ВидДвиженияНакопления.Приход: Движение.Период = Дата; Движение.Номенклатура = Выборка.Номенклатура; Движение.Количество = Выборка.Количество; КонецЕсли; КонецЦикла; КонецПроцедуры Краткий комментарий: сначала запросом выбираются все необходимые для проведения документа данные. Запрос реализован левым соединением данных табличной части проводимого документа с данными виртуальных таблиц остатков из регистров ТоварыНаСкладах и РезервыНоменк- латуры. Виртуальные таблицы остатков получены на момент вре- мени данного документа, с применением отбора только по тем номенклатурным позициям, которые входят в со- став проводимого документа. Сам момент времени доку- мента при установке параметра запроса получен методом объекта документа МоментВремени(). Поскольку может иметь место ситуация, когда данные по неким номенклатурным позициям в регистре отсутству- ют, то для выходных полей запроса применена функция преобразования возможных Null значений в числовое значение 0. Это сделано для того, что бы впоследствии выполнять арифметические действия с данными резуль- тата запроса без опасений, что те окажутся непригодны- ми для подобных действий. Полученная в результате соединения таблица сгруппиро- вана по номенклатуре и данным, полученным из регист- ров, с суммированием данных поля Количество документа. Это сделано для обеспечения корректности последующе- го контроля остатков даже в случае «дублей строк», то есть когда одна и та же номенклатурная позиция встреча- ется несколько раз в составе документа. Для полученного результата запроса открывается цикл перебора выборки. Внутри цикла для каждой строки вы- борки производится контроль остатка посредством вы- числения нехватки. В случае положительного значения нехватки параметр Отказ процедуры обработчика события получает значение Истина, что приведет к откату транзак- ции записи документа с проведением. В случае отсутствия отказа в проведении формируются движения по регистру РезервыНоиенклатуры. Блокировка записей регистров Отдельного рассмотрения в вышеописанном алгоритме требует применение конструкции ДЛЯ ИЗМЕНЕНИЯ в тексте запроса. При выполнении запроса система получает данные об ос- татках, резервах и количестве документа. Дальнейший контроль остатков производится, опираясь на данные ре- зультата запроса. Если обработка проведения выполняется быстро, то ве- роятность того, что параллельно с проведением нашего документа какие-то другие процессы (например, проведе- ние другого документа) попытаются тоже зарезервиро- вать некоторое количество товаров — низка. Но если, по разным причинам, длительность транзакции записи документа с проведением все же «продолжитель- на» по времени, то такая вероятность возрастает. Из-за этого возрастает вероятность взаимных блокировок. Дело в том, что процесс проведения документа выполня- ется в транзакции. При этом на используемые таблицы базы данных накладываются транзакционные блокиров- ки. Если же некие процессы начинают записывать ин- формацию в таблицы базы данных, вероятность кон- фликта блокировок возрастает. Блокировка записи не совместима с блокировкой, которая накладывается при чтении в транзакции. Поэтому может оказаться ситуация, когда при проведении одного заказа не может закончить- ся запись в регистр РезервыНоиенклатуры по причине, что на часть этого набора записей наложена транзакционная блокировка проведения другого заказа. А другой заказ не может завершить свое проведение по причине, что часть записей заблокирована первым. Как можно предотвратить подобные ситуации средствами, предоставляемыми платформой «ЮПредприятие 8.0»? В файловом варианте работы системы параллельное про- ведение документов или параллельное проведение доку- мента изменение данных регистра в принципе невоз- можны. Дело в том, что при выполнении транзакции,
в которую входит проведение документа, для считывания и записи данных системой автоматически применяются блокировки на уровне таблиц базы данных. В результате один из процессов успеет заблокировать таблицы доку- мента и регистров а второй будет вынужден подождать освобождения ресурсов, и только потом станет выпол- няться (рис. 8.50). Рис. 8.50. Блокировки при проведении в файловом варианте работы В клиент-серверном варианте для максимального быстро- действия программы при использовании ее большим чис- лом пользователей, обеспечивается параллельность рабо- ты пользователей. Это реализуется за счет применения блокировок не на уровне таблиц базы данных, а на уровне записей таблиц и диапазонов записей таблиц регистров. Для того чтобы в нашем алгоритме проведения еще на этапе выполнения запроса, то есть на этапе чтения дан- ных из регистров, наложить блокировку на записи по нужным номенклатурным позициям (по которым потом будут изменяться данные), применяется конструкция ДЛЯ ИЗМЕНЕНИЯ. В тексте запроса данная конструкция применяется для виртуальной таблицы остатков регистра РезервыНомен- клатуры. При исполнении данной инструкции система заблокирует данные от чтения другими транзакциями, которые тоже пытаются установить блокировку обновле- ния или записи, удовлетворяющие условию отбора при построении виртуальной таблицы. Рассмотрим этот мо- мент более подробно. Процессы, просто обращающиеся для чтения информа- ции таблиц базы данных, блокировкой обновления оста- навливаться не будут. Но если некий процесс при чтении данных на какую-то из уже заблокированных записей по- пытается тоже наложить блокировку, ему придется подо- ждать освобождения ресурсов. То есть окончания первой транзакции, за которым последует снятие первой блоки- ровки. Именно это и произойдет при проведении второго документа, поскольку алгоритм проведения документов абсолютно идентичен (рис. 8.51). В результате в рассмотренном нами примере проведение второго документа будет вынуждено дождаться оконча- ния проведения первого документа еще до выполнения запроса. Это снижает вероятность взаимных блокировок двух «параллельно проводимых» документов. Рис. 8.51. Блокировки при проведении в клиент-серверном варианте работы В случае же если, например, два заказа при проведении попытаются провести контроль остатков и дальнейшее формирование движений по разному номенклатурному составу, параллельная блокировка обновления для раз- ных записей регистра возможна. То есть процессы друг другу мешать не будут, если диапазоны блокируемых за- писей «не пересекаются» (рис. 8.52). Рис. 8.52. Блокировки при проведении документов с разной номенклатурой Итак, мы рассмотрели, как в системе «1С:Предприятие 8.0» применением механизма блокировок можно обеспечить параллельность работы пользователей. Однако разработчику необходимо иметь в виду, что сами блокировки в таблицах базы данных выполняются все же не средствами системы «1С:Предприятия», а средствами СУБД. Поэтому на применение блокировок в каждом
Таблица 8.75. Таблица движений регистра накопления остатков Период Регистратор Вид движения Номенклатура Количество 13.08.2005 15:00:01 ПоступлениеТоваров №1 13.08.2005 15:00:01 Приход Пульт VX 10 23.08.2005 12:30:45 РеализацияТоваров №1 23.08.2005 12:30:45 Расход Пульт VX 7 23.08.2005 12:30:45 РеализацияТоваров №2 23.08.2005 12:30:45 Расход Пульт VX 2 конкретном случае могут влиять механизмы оптимиза- ции работы СУБД. Например, анализируя диапазоны за- писей таблицы движений регистра, подлежащие блоки- рованию, СУБД может принять решение, что «дешевле» с точки зрения быстродействия будет заблокировать всю таблицу целиком. И вместо параллельного проведения документов в результате получим последовательное. Вероятность таких ситуаций тем выше, чем меньше запи- сей в таблицах. Более того, если на момент чтения с бло- кировкой обновления в таблице почему-то записей вооб- ще не будет, система опять же заблокирует всю таблицу целиком. То есть начав проводить самый первый доку- мент в базе, никак не получится параллельно провести второй. Даже если в нем будут указаны совсем другие но- менклатурные позиции. Поэтому реальную эффективность применения конст- рукции ДЛЯ ИЗМЕНЕНИЯ можно оценивать только при работе с «большими» объемами данных, а не на тестовых приме- рах «в два-три документа». Более подробно же о приме- нении блокировок можно узнать в главе «Уровни изоля- ции транзакций», с. 76. Чтение данных регистра остатков при неоперативном проведении Кроме блокировок, хотелось бы еще обратить внимание на вопрос «на какой временной момент нужно получать данные регистров при проведении документа». Для решения этого вопроса, прежде всего, важно определить, используется ли для ведения учета механизм оперативного проведения. Си- туация, когда механизм используется, приводит к тому, что при получении информации остатков из регистров достаточ- но получать данные актуальных итогов, что сильно повыша- ет быстродействие этой операции. То есть можно применять виртуальные таблицы получения остатков без указания зна- чения параметра Период. Подобный пример приведен в де- монстрационной конфигурации «Хранение информации и учет движения средств», которая находится на прилагаемом компакт-диске, при проведении документа РеализацияТова- ров. Также этот пример описан в разделе «Использование механизма оперативного проведения», с. 152. В приведенном выше алгоритме (см. листинг 8.92) реали- зована ситуация, когда по каким-то причинам не исполь- зуется механизм оперативного проведения документа. Тогда для обеспечения корректности контрольных опера- ций при проведении документов нужно будет получать не актуальные данные регистров остатков, а данные на момент времени документа посредством использования соответствующего значения для параметров виртуальных таблиц. Хочется подчеркнуть, что не на дату документа, а именно на момент времени. Например, возможна такая ситуация. В таблице движе- ний регистра остатков есть три записи (табл. 8.75). Проводится очередной документ Заказ товаров №1, в нем указана следующая информация (табл. 8.76). Поскольку оперативное проведение не используется, то дата документа вполне может иметь значение точно такое же, как и у предыдущего документа. Таблица 8.76. Данные документа Заказ товаров ЗаказПокупателя Номер: №1 Дата: 23.08.2005 12:30:45 Номенклатура Количество Пульт VX 3 В результате если остатки регистра будут посчитаны на значение Дата, то получим, что на складе 10 пультов (то есть документ ЗаказПокупателя можно провести, хотя это не так). Поэтому данные остатков нужно брать на момент време- ни проводимого документа (рис. 8.53). Рис 8.53. Получение остатков на момент времени документа Однако необходимо иметь в виду, что управлять положе- нием документов внутри одной секунды возможности нет, то есть не факт, что новый документ займет на вре- менной оси положение после уже введенных с той же да- той документов. Но при применении получения данных на момент времени, по крайней мере, есть уверенность в однозначном порядке расположения документов на вре- менной оси с точки зрения чтения информации регист- ров при проведении документов. Поэтому все же возможные коллизии в результате неопе- ративного проведения документов можно разрешать за счет перепроведения документов, в частности с помощью последовательностей документов. Более подробно это опи- сано в разделе «Последовательности документов», с. 166.
Глава 9. Реализация задач бухгалтерского учета Введение Эта глава нашей книги посвящена задачам бухгалтерско- го учета и возможностям системы ЮПредприятие 8.0 для их решения. Говорят, что правильно поставленная за- дача — наполовину решенная задача. Мы считаем, что ут- верждение это недалеко от истины, но уделить достаточ- ное внимание вопросам теории бухгалтерского учета не позволяет формат нашей книги. Тем не менее мы будем стараться, где это возможно, разъяснять основные поня- тия и методы предметной области, задачи которой будем решать. Все примеры, рассмотренные в этой главе, содер- жатся в демонстрационной конфигурации «Бухгалтерский учет», которая находится на прилагаемом компакт-диске. Основная задача любой учетной системы — управление и контроль за работой объекта учета. Задача бухгалтер- ского учета — учет операций хозяйственной деятельности всего предприятия в целом. Цель учета — контроль за фи- нансово-хозяйственной деятельностью и управление всем предприятием посредством замкнутой системы по- казателей. Далее при рассмотрении внутреннего устройства регист- ра бухгалтерии (основного объекта, предназначенного для реализации задач бухгалтерского учета) мы будем проводить сравнение с другим объектом — регистром на- копления. Эти объекты весьма похожи, но предназначены и оптимизированы для решения разных задач, поэтому умение выделить задачи бухгалтерского учета и задачи оперативного учета позволит значительного оптимизиро- вать работу конфигурации. Диаграмма взаимодействия объектов Схему взаимодействия объектов системы 1С:Предпри- ятие при реализации задачи бухгалтерского учета можно представить, как на рис. 9.1. Рассмотрим объекты, участвующие в схеме, и начнем это делать с плана счетов. Бухгалтерский учет ведется на счетах, каждый из кото- рых предназначен для группировки однородных хозяйст- венных операций. Все счета, используемые для ведения учета на предприятии, объединяются в план счетов. Сче- та — это основной разрез учета. Все остальные разрезы (аналитический учет, измерения) являются вспомога- тельными и необязательными. Для хранения бухгалтерских проводок по счетам исполь- зуется объект конфигурации Регистр бухгалтерии. Самый простой регистр бухгалтерии, предназначенный для веде- ния бухгалтерского синтетического учета, может содер- жать всего один ресурс (для учета средств в валюте учета, в которой будет составляться вся отчетность и формиро- ваться баланс) и более ничего. Такой регистр бухгалте- рии позволит анализировать остатки и обороты по сче- там, а также и обороты между счетами. Для получения оборотов между счетами регистр должен поддерживать схему учета с поддержкой корреспонденций, при которой каждая запись обязательно включает два счета: дебетуе- мый и кредитуемый. Дополнительными разрезами при ведении учета являют- ся аналитические разрезы (аналитический учет) и изме- рения регистра бухгалтерии (с помощью которых воз- можно реализовать многовалютный учет, консолидиро- ванный учет и др.). Аналитический учет описывается в системе ЮПред- приятие 8.0 с помощью понятий Вид субконто и Суб- конто. Под видом субконто подразумевается группа однородных объектов аналитического учета (список контрагентов, номенклатуры, статей и др.). Субконто — это один объект из этого множества (объект аналитиче- ского учета, например: контрагент, карточка товара, статья затрат и др.). Для реализации аналитического учета используется «связ- ка» объектов План видов характеристик, План счетов, Регистр бухгалтерии. План видов характеристик, использующийся для ведения аналитического учета на выбранном плане сче- тов, выбирается в соответствующем свойстве плана счетов. Виды характеристик «привязываются» к счетам плана сче- тов, требующим ведения аналитического учета. Результат этих действий — изменяющиеся таблицы регистра бухгал- терии, которые позволят хранить остатки и обороты не только по счетам, но и по счетам в разрезе субконто. Чтобы понять, как используется план видов характери- стик, можно «разложить» название этого объекта («план» и «видов характеристик»). Получается два уровня «вло- женности»: план, представляющий собой совокупность видов субконто, каждый из которых хранит информацию о типе характеристик, каждая из которых является объек- том аналитики, то есть субконто. Характеристика — это один экземпляр вида характеристик, так же как субконто
это один экземпляр вида субконто. Характеристика не является самостоятельным объектом конфигурации. Для ведения аналитического учета, как правило, используются элементы справочников, значения перечисления, ссылки на документы. Виды характеристик, как правило, имеют ссы- лочный тип данных (хотя возможны и другие варианты). Рис. 9.1. Схема взаимодействия объектов Решение задач консолидированного, многовалютного учета, единого для всех счетов аналитического учета и не- которые другие осуществляется с использованием изме- рений регистра бухгалтерии, которые, как правило, при- нимают значения ссылочных типов данных. Каждая запись (проводка) регистра бухгалтерии подчи- нена какому-то регистратору (документу) и, как правило, им же создана. При проектировании реквизитного соста- ва документов, которые должны формировать записи в регистр бухгалтерии, как правило, используются ссылоч- ные типы данных. Документ при проектировании задачи бухгалтерского учета это, прежде всего, средство форми- рования движений в регистр бухгалтерии. А движения эти, как уже было сказано выше, содержат субконто и из- мерения, которые и заполняются обычно значениями ре- квизитов документа. Каждый документ имеет свойство Движения, представ- ляющее собой коллекцию наборов записей тех регист- ров, регистратором для которых он является. Схема про- ведения документа по регистрам унифицирована для всех регистров (регистры сведений, накопления, расче- тов, бухгалтерии) и включает запись измененных (при проведении, напрямую, используя набор записей «руч- ной операции», или другим способом) наборов записей в регистр при записи интерактивной документа или про- граммно. Регистр бухгалтерии с точки зрения традиционной (бу- мажной) бухгалтерии можно рассматривать как собра- ние форм бухгалтерского учета, включающее в себя как формы для хронологической (проводки), так и для сис- тематической (итоги по счетам, по субконто, обороты между счетами) записи. Кроме записи и хранения бух- галтерских проводок и итогов по счетам, регистр бух- галтерии предоставляет ряд методов и таблиц для вы- полнения запросов. И те и другие предназначены для удобного и оптимального получения остатков и оборо- тов по счетам и аналитикам. Так как основным методом извлечения данных в системе является запрос, то имен- но таблицы (в первую очередь, виртуальные) использу- ются в большинстве случаев для построения бухгалтер- ской отчетности, являющейся главным результатом бухгалтерского учета. План счетов и его основные свойства План счетов — центральное место любой конфигурации для ведения бухгалтерского учета. Бухгалтерский учет ведется на счетах, все счета, входящие в один баланс, объ- единяются в один план счетов. По свой сути, план сче- тов — это справочник счетов. Рассмотрим пример несложного бухгалтерского учета на небольшом предприятии. Каждое предприятие обладает каким-то имуществом (активами) и обязательствами (пас- сивами). Пусть у нашего предприятия будут активы: ♦ наличные деньги в кассе; ♦ деньги, которые нам должны наши покупатели за по- ставленные им товары; ♦ сами товары, которые мы приготовили для продажи; ♦ прочие материальные ценности для собственных нужд. Все эти активы «взялись не откуда-то», а были получены нашим предприятием или от инвестора (хозяина, вла- дельца, которому принадлежит наше предприятие) или от сторонних по отношению к предприятию организаций и физических лиц (например, поставщиков). Таким обра- зом, пассивы нашего предприятия складываются из обя- зательств перед хозяином, сторонними контрагентами и собственными сотрудниками, которые работают на на- шем предприятии. Итак, наши пассивы: ♦ задолженность перед сотрудниками; ♦ задолженность перед поставщиками; ♦ задолженность перед владельцем.
Таким образом, мы имеем два ряда счетов, которые «вы- текают» из баланса нашего предприятия1. Так как активы не могли взяться из «ниоткуда» и не могут исчезнуть в «никуда», то сумма всех активов в денежном выражении будет равна сумме всех обязательств в том же денежном выражении. В нашем учете нас интересуют и остатки, и обороты по каждому виду активов и обязательств. Поэтому для каж- дого из них мы заведем отдельный счет в плане счетов. По своей сути каждый счет — это один (или несколько) учетный регистр (форма). От количества и назначения счетов будет зависеть весь учетный процесс, поэтому пе- репроектирование плана счетов почти всегда связано с существенными изменениями конфигурации. Группи- ровка этих счетов, их порядок в плане счетов во многом зависит от традиций, стандартов и просто предпочтений бухгалтера. Если речь идет о регламентированном уче- те, то эти свойства плана счетов описываются в законе и стандартах. В нашем случае мы создадим план счетов сами, и он будет включать следующие счета (табл. 9.1). Таблица 9.1. Состав плана счетов Код Имя Назначение 1 Активы Группа счетов, объединяет все активы нашего предприятия 1.1 Касса Наличные деньги 1.2 Покупатели Деньги, которые нам должны наши покупатели за поставленные им товары 1.3 Товары Товары, которые мы приготовили для продажи 1.4 Материалы Прочие материальные ценности для собственных нужд 2 Обязательства Объединяет все обязательства перед контрагентами и сотрудниками 2.1 Сотрудники Задолженность перед сотрудниками 2.2 Поставщики Задолженность перед поставщиками 3 Капитал Задолженность перед владельцем План счетов — объект конфигурации, который позволяет описать состав счетов, используемый для ведения учета на предприятии и их свойства. Рассмотрим план счетов для ведения нашего бухгалтерского учета. Закладка Основные (рис. 9.2) позволяет назначить имя, синоним и комментарий для плана счетов. Надо заме- тить, что планов счетов в одной конфигурации может быть несколько. Для целей регламентированного учета это не требуется, но встречаются задачи управленческого учета, требующие ведения учета по разным стандартам или ведения не только бухгалтерского учета, который фиксирует свершившиеся факты, но бюджетного учета, который учитывает планируемые операции. Рис. 9.2. Основные свойства плана счетов Рис. 9.3. Данные плана счетов Закладка Данные (рис. 9.3), кроме таких свойство, как Ре- квизиты и Табличные части, назначение которых — хранение дополнительной информации о счете, содержит следую- щие свойства (табл. 9.2). Закладка Нумерация (рис. 9.4) позволяет определить пра- вила нумерации счетов в плане счетов и мало отличается от подобных закладок других объектов. 1 Для более полного понимания теории бухгалтерского учета можно рекомендовать труды д. э. н., профессора Я. В. Соколова, автора замечательных книг и не менее замечательных статей, многие из которых можно прочитать в издании «БУХ.1С».
Таблица 9.2. Свойства плана счетов Свойство Назначение Длина кода Максимальная длина кода счета, включая все его субсчета и знаки, используемые для отделения счета и субсчета Длина наименования Максимальная длина наименования счета Маска кода Свойство позволяет задать правила использования символов (цифровой, буквенно-цифровой код и т. д.) и иерархичность кода счета Автопорядок по коду Это свойство будет рассмотрено подробно ниже Длина порядка Максимальная длина дополнительного индексируемого поля, значение которого используется для сортировки счетов в форме списка плана счетов и запросах Основное представление Выбор основного представления счета в полях ввода документов, отчетов и др. Обычно счет принято отображать в виде кода, но в методических целях будем использовать наименование Признаки учета Дополнительное свойство счета, позволяющее определить необходимость ведения на выбранном счете дополнительного вида учета (например, валютного или количественного) Закладка Субконто (рис. 9.5) предназначена для описания общих правил ведения аналитического учета плана сче- тов. Здесь устанавливается, какой из планов видов харак- теристик будет использоваться для хранения списка видов субконто (свойство Виды субконто), максимально возможное количество параллельных (независимых) ви- дов субконто на любом счете плана счетов. Здесь же соз- даются дополнительные свойства субконто на счете - Признаки учета субконто, которые позволяют управлять не- обходимостью ведения того или иного вида учета для од- ного из видов субконто выбранного счета. Рис. 9.4. Нумерация плана счетов Закладка Формы (рис. 9.6), кроме настройки форм, позво- ляет настроить способы редактирования счета и выбора его в диалогах в поле выбора. Здесь же указывается, по каким полям будет осуществляться ввод по строке в диа- логах выбора (при наборе с клавиатуры кода счета или его наименования система будет осуществлять поиск сче- та в плане счетов). Закладки до Прочее пропустим. План счетов ОсновнойПланСчетов Основные Данные Нумерация ► Субконто Формы Макеты Подсистемы Ввод на основании Права Интерфейсы Обмен данными Прочее _ П X | Действия ~ I <Назад~| | Далее?| Закрыть | j Справка t План видов характермст Предопределенные виды характеристик _ О X И План видов характеристик ВидыСубконто _ П X Код |00001 00002 00004 00003 00005 Контрагенты Номенклатура Склады_______ Сотрудники Статьи Наименование Тип Контрагенты Номенклатура Склады_______ Сотрудники Статьи СправочьикСсылка Контрагенты СправочникСсылка. Номенклатура СправочьикСсылка. Склады______ СправочкыкСсылкаСотрудниси СправочьикСсылка. Статьи Рис. 9.5. Субконто плана счетов
Рис. 9.6. Формы плана счетов План счетов ОсновнойПланСчетов _ П X Основные Данные Нумерация Субконто Формы Макеты Подсистемы В вдв на основании Права Интерфейсы Обмен данными ► Прочее Прси/Tpcac.iptwc | Справочная 1 нформация] Включать в сод вржание справки I I | Действия *] | <Назад j Далее> f Закрыть 11 СлраекГ План счетов ОсновнойПланСчетов: Предопределенные счета _ О X Действия •» <1 В- Активы Наименование s- Касса |.Покупатели !.Товарь !.Материалы ^-Обязательства j—Сотрудники —Поставщики - Капитал Активы 11 Касса___________ 12 Покупатели 1 3 Т свары ______ 1 4 Материалы 2 Обязательства 21 Сотрудники 2.2 Поставщики 3 Капитал Забт Порядок Активный________1 Активный________1.1 Активный ______ 1 2 Активный________1 3 Активный________1 4 Пассивный _____ 2 Пассивный_______2.1 Пассивный______2. 2 Пассивный 3 Рис. 9.7. Прочие свойства плана счетов Закладка Прочее (рис. 9.7) — последняя по порядку, но не по значимости, кроме ввода справочной информации предназначена для изменения модуля объекта, списка предопределенных счетов и справочной информации о плане счетов. А теперь рассмотрим подробнее основные из перечислен- ных свойств и их использование при решении задач бух- галтерского учета. Коды счетов Использование кодов плана счетов во многом определя- ется стандартами, в соответствии с которыми ведется бухгалтерский учет. Это может быть «Закон о бухгалтер- ском учета» (если решается задача регламентированного учета), GAAP или другие зарубежные стандарты (при ре- шении задачи получения бухгалтерской отчетности в со- ответствии с МСФО), или внутренние стандарты пред- приятия (если необходимо ведение управленческого учета). Кроме кода, который в понимании бухгалтера «... и есть счет», необходимы и другие свойства. Эти свой- ства и состав счетов плана счетов позволяет определить в системе объект конфигурации План счетов. Код счета предназначен для идентификации счета поль- зователем и, как правило, используется как основное представление объекта. Именно код счета обычно вводит пользователь при заполнении бухгалтерской проводки, код счета выводится в качестве измерений (строк и коло- нок) бухгалтерских отчетов. Свойство Длина кода позволя- ет задать максимальную длину кода, которой будет огра- ничено описание кодов для счетов выбранного плана счетов. Максимально возможно значение этого свойства составляет 50 символов. При описании максимальной длины кода счета необходимо учитывать возможную иерархичность плана счетов. Для счетов одного плана счетов можно установить (и обыч- но устанавливается) контроль уникальности кода, кото- рый может контролировать серии кодов или во всем справочнике, или в пределах подчинения владельцу. Ос- новное отличие от справочника здесь заключается в том, что код счета включает в себя коды всех его родителей. Поэтому при установке уникальности в пределах подчи- нения владельцу мы можем добавить к счету с кодом 02 субсчет с кодом 01.1, ведь там такого еще нет. Свойство Наименование счета и его длина не требует с на- шей точки зрения отдельного описания, так как не отли- чается по свому назначению от аналогичного свойства объектов Справочник и План видов характеристик. Так же как и в перечисленных объектах, это свойство предназначено для хранения вводимого пользователем наименования элемента плана счетов (счета). Свойство Маска кода заслуживает отдельного и более под- робного описания. Это свойство предназначено для огра- ничения использования символов в коде счета и задания иерархической структуры плана счетов. Система позво- ляет описывать как линейные, так и иерархические пла- ны счетов. Каждый план счетов может включать неогра- ниченное число счетов первого уровня, неограниченное число субсчетов к каждому счету первого уровня и т. д. Первая задача, ограничение использование символов, ре- шается с помощью использования при заполнении маски кода счета символов, описание которых можно найти в документации, например, в описании метода Маска().
В строке маски допустимо использование следующих специальных символов: ♦ ! — любой введенный символ преобразуется в верхний регистр; ♦ 9 — допустимо ввести произвольный символ цифры; ♦ # — допустимо ввести произвольный символ цифры, или — (знак минус), или + (знак плюс), или пробел; ♦ N — допустимо ввести любые алфавитно-цифровые символы (буквы или цифры); ♦ U — допустимо ввести любые алфавитно-цифровые символы (буквы или цифры) и любой введенный сим- вол преобразуется в верхний регистр; ♦ X (латинского алфавита) — допустимо ввести произ- вольный символ; ♦ @ — допустимо ввести любые алфавитно-цифровые символы (буквы или цифры) в верхнем регистре или пробел и др. Таким образом, если мы зададим маску кода счета ##, в план счетов можно будет вводить счета с кодами, со- стоящими только из цифр, знаком минуса, плюса и про- бела. Кроме того, максимальное количество кодов счетов становится равным 99 (счет с кодом 100 содержит уже три символа, что не разрешается выбранной маской). Вторая задача, задание иерархической структуры планы счетов (или, точнее, кодов счетов, потому что иерархия кодов и иерархия счетов может отличаться, и об этом пойдет речь ниже), решается за счет использования сим- волов-разделителей в составе маски кода счета. Раздели- телем может выступать любой символ, не перечисленный в описании специальных символов маски. Для отделения счета верхнего уровня от субсчета, как правило, исполь- зуется «.» (символ точка). Таким образом, если мы счита- ем, что нам будет достаточно плана счетов с двумя уров- нями вложенности (счет — субсчет), нам будет достаточно задать маску кода счета ##.##, что соответст- вует длине кода счета, которую мы выбрали ранее (5 сим- волов — два знака счет, два знака субсчет и точка-разде- литель между ними). Отдельно следует остановиться на использовании симво- ла @ в описании маски кода счета. Использование этого специального символа не только позволяет вводить «лю- бые алфавитно-цифровые символы (буквы или цифры) в верхнем регистре или пробел», как уже было отмечено выше, но и влияет на хранение кода в базе и отображение его в диалогах ввода. При использовании символа @ в маске кода счета группа знаков кода, для которой использованы символы @, при сохранении кода в базу данных упаковывается — из него вырезаются пробелы. Рассмотрим на примере нашего плана счетов, для которого мы установили в свойствах маску кода счета @@.@@, соответствующую максималь- ной длине кода счета 5 символов. Проиллюстрируем ра- боту маски, содержащей символы @, на примере ввода счета с кодом 1.1 (табл. 9.3 и 9.4). Таким образом, вводится код «1 .1» (единица, пробел, точка, единица), а в базе данных сохраняется 1.1. При ре- дактировании счета в плане счетов код счета распаковы- вается до вида, подходящего под маску. При записи опять упаковывается. Таблица 9.3. Маска кода с использованием символа @ Номера символов 1 2 3 4 5 Маска @ @ @ @ Вводится 1 Пробел 1 Пробел Хранится 1 1 Нет Нет Символов 3 Таблица 9.4. Маска кода без использования символа @ (используется #) Номера символов 1 2 3 4 5 Маска # # # # Вводится 1 Пробел 1 Пробел Хранится 1 Пробел 1 Пробел Символов 5 При работе пользователя с диалогами форм, содержащи- ми ссылки на счет плана счетов, ввод по подстроке осу- ществляется по «упакованному» коду. В нашем случае пользователь должен будет набрать с клавиатуры 1.1 (без пробелов, то есть не дополняя код до вида маски). Упорядочивание счетов в плане счетов План счетов, как и объекты Справочник и План видов харак- теристик, по умолчанию сортируется в формах списка и упорядочивается (автоупорядочивание) в запросах по основному представлению. Но, во-первых, есть вероят- ность, что основным представлением будет выбрано на- именование (в целях управленческого учета это возмож- но), а упорядочить необходимо по коду. А во-вторых, код, особенно при использовании в маске кода счета символов @, позволяющих упаковывать код счета, может не подхо- дить для сортировки. Рассмотрим это на примере первой группы счетов плана счетов, который мы начали делать. Пользователь ввел счета со следующими кодами (табл. 9.5). Таблица 9.5. Счета, введенные пользователем Коды по порядку их ввода (как должно быть) Счета, отсортированные по коду 1.1 1.1 1.2 1.10 1.3 1.11 1.N 1.2 1.10 1.3 1.11 1.N
Возможное решение проблемы неверной сортировки сче- тов — использование лидирующих нулей или пробелов, при кодировании счетов в плане счетов (табл. 9.6). Таблица 9.6. Использование лидирующих нулей в коде счета Коды по порядку их ввода (как должно быть) Счета, отсортированные по коду 01.01 01.01 01.02 01.02 01.03 01.03 01.0N 01.0N 01.10 01.10 01.11 01.11 Альтернативный вариант решения проблемы сортиров- ки — воспользоваться свойством счета Порядок. Это поле с автоматическим индексированием с упорядочиванием, предназначенное для хранения значения, по которому бу- дут выполняться упорядочивание счетов в форме списке и результатах запроса. В отличие от кода, который для хранения в базе данных может упаковываться, порядок хранится в базе в неизменном виде. Порядок становится доступным для использования, если длина его больше нуля. При этом программа не разрешит записать в базу данных счет с пустым порядком. Зададим длину порядка в нашем плане счетов (5 символов), поря- док зададим произвольный (рис. 9.8). На картинке видно, что счет Капитал с кодом 3 занял пер- вое место (порядок 01), а счет Активы переместился вниз. Если в маске кода счета используются только символы @ и символы-разделители, то для счетов, вводимых в пользова- тельском режиме, поле Порядок можно сформировать авто- матически. Для этого в модуле формы счета или в модуле объекта (закладка Прочее кнопка Модуль объекта) необходимо разместить процедуру — обработчик события (листинг 9.1). Метод ПолучитьПорядокКодаО развернет упакованный код и дополнит его «лидирующими пробелами», что позволит упорядочить план счетов правильно без использования в коде счета лидирующих нулей (табл. 9.7). Листинг 9.1. Пример автоматического формирования порядка счета Процедура ПередЗаписью(Отказ) Порядок = ПолучитьПорядокКодаО; КонецПроцедуры Таблица 9.7. Пример использования метода ПолучитьПорядокКодаО Номера символов 1 2 3 4 5 Вводим код счета 1 Пробел 1 Пробел Маска кода счета @ @ @ @ Хранится в базе данных 1 1 Нет нет Получить- ПорядокКодаО Пробел 1 Пробел 1 После выполнения записи всех счетов в пользователь- ском режиме и установки сортировки по полю Порядок план счетов приобретет следующий вид (рис. 9.9). Мы видим, что Новый счет с кодом 1.11 занял свое «закон- ное» место — последним в группе Активы. Тем не менее остается возможность отсортировать план счетов по коду, и, кроме того, при вводе предопределенного счета поле порядок автоматически не заполняется. Для автоматического заполнения поля Порядок кодом, до- полненным лидирующими пробелами при вводе предо- пределенного счета и для подмены сортировки по коду, сортировкой по порядку используется свойство счета Автопорядок по коду. После его установки, во-первых, при вводе предопределенного счета в момент перехода с поля Код (Tab или Enter) при незаполненном порядке счета он будет заполняться по описанным выше правилам (как при использовании метода ПолучитьПорядокКодаО). А во-вторых, Код ’ |Н««лвное»мв Порядок эядок * 1 Активы 09 01 1.1 Касса 08 ъ 2.2 Поставщики 02 1 т 1.11 Новый счет 10 L 2.1 Сотрудники 03 Т, 1.2 Покупатели 07 L 2 Обязательства 04 | т. 1.3 Т овары 06 Ъ 1.4 Материалы 05 т. 1.4 Материалы 05 1.3 Товары ОБ т» 2 Обязательства 04 1.2 Покупатели 07 | Т. 2.1 Сотрудники 03 1.1 Касса 08 т. 2.2 Поставщики 02 ъ 1 Активы 09 3 Капитал 01 — т 1.11 Новый счет 10 Рис. 9.8. Сравнение сортировки по коду и по порядку
Код Порядок ' т, 1 Активы 1 т, 1.1 Касса 1 1 ъ 1.2 Покупатели 1.2 I» 1.3 Т овары 1.3 L 1.4 Материалы _ 1 4 т 1.11 Новый счет 1 11- Т Обязательства 2 т, 2.1 Сотрудники 2 1 L 2.2 Поставщики 2.2 Та 3 Капитал 3 Рис. 9.9. Сравнение сортировки по порядку и по коду Код ’ Н энмеяядоагм П орядок т« 1 Активы 1 т# 1.1 Касса 1 1 т 1.11 Новый счет 1.11 L 1.2 11окупатели I 2 L 1.3 Т овары 1 3 Ь 1.4 Материалы 1.4 Т. 2 Обязательства 2 т< 2.1 Сотрудники 2.1 т. 2.2 Поставщики 2.2 т» 3 Капитал 3 Код ’ 'наименование Порядок Код Наименование Ч Порядок т" " Активы 1 Т, 1 Активы Г L 1.1 Касса 1.1 Т. 1.1 Касса 1.1 Ъ 1.2 Покупатели 1.2 ь 1.2 Покупатели 1.2 L 1.3 Т овары 1 3 ь 1.3 Т овары 1.3 L 1.4 Материалы 1 4 Т, и Материалы JL4 Т 1.11 111 т 1.11 111 I L 2 Обязательства 2 т, 2 Обязательства 2 Т* 2.1 Сотрудники 2.1 т» 2.1 Сотрудники 2.1 т« 2.2 Поставщики 2 2 Т« 2.2 Поставщики 2.2 L 3 Капитал 3 3 Капитал 3 Рис. 9.10. Сравнение сортировки по коду и по порядку в формах списка и запросах при указании сортировки по полю Код она будет автоматически заменяться на сорти- ровку по полю Порядок, то есть получить порядок кодов будет невозможно (рис. 9.10). Две приведенные картинки отличаются между собой ко- лонкой, по которой выполняется сортировка. Левый спи- сок отсортирован по полю Порядок, правый — по полю Код, но сортировка на обоих выполняется по полю Поря- док, что можно увидеть по положению счета 1.11, кото- рый ранее, при сортировке по полю Код всегда занимал место после счета с кодом 1.1. Подобная же сортировка (по полю Порядок) будет выполняться и в запросах при указании в предложении УПОРЯДОЧИТЬ ПО в качестве поля сортировки Код (листинг 9.2). Листинг 9.2. Сортировка по полю Код в тексте запроса УПОРЯДОЧИТЬ ПО Код Иерархичность плана счетов Как уже было замечено выше, объект План счетов позволя- ет создавать иерархические планы счетов. Наш план сче- тов имеет два уровня вложенности: счета первого уровня Активы, Обязательства и Капитал и несколько субсчетов к счетам Активы и Обязательства. Платформа позволяет соз- давать неограниченное число счетов и уровней вложен- ности. Это свойство плана счетов позволяет детализировать учет, однако детализация эта будет иерархической и не позволит организовать фасетное (параллельное) деление итогов. Например, не удастся организовать учет товаров на складах с возможностью автоматического получения итогов по складу, по товару и по товару на складе. То есть иерархическая организация плана счетов не может в пол- ной степени обеспечить ведение аналитического учета. Для ведения аналитического учета предназначены поня- тия Вид субконто и Субконто, о которых пойдет речь в разделе «Основы организации аналитического учета», с. 251. «Бесконечная иерархичность» плана счетов обеспечива- ется благодаря свойству Родитель счета. Это свойство мо- жет заполняться и для предопределенных счетов и для счетов, вводимых пользователем. Это свойство содержит ссылку на родительский счет. Рассмотрим свойство иерар- хичность на схеме (рис. 9.11). При необходимости иерархичность плана счетов всегда можно изменить, например, разделив счет Касса на два субсчета Рублевая касса и Валютная касса. При такой иерархичности счета первого уровня (в нашем случае: Активы и Обязательства), имеющие субсчета, не те- ряют возможности участвовать в проводках и выполнять те же функции, что и счета конечного уровня. И кроме того, они позволяют сгруппировать данные в отчетах, суммируя итоги со своих субсчетов. План счетов напоми- нает справочник, у которого установлено свойство Иерар- хия элементов.
| Счета fcy 1 Родитель: пустая ссылка как в базу были введены и проводки по счетам Активы и Обязательства, и проводки по их субсчетам. Активы Касса Родитель: Активы —►! Расчеты с покупателями | Родитель: Активы Обязательства Товары Родитель: Активы Материалы Родитель: Активы ] Родитель: пустая ссылка —Расчеты с сотрудниками | Родитель: Обязательства —Расчеты с поставщиками | Родитель: Обязательства Капитал Родитель: пустая ссылка Рис. 9.11. Иерархичность плана счетов Рис. 9.13. Отчет Оборотка Ввод проводок и формирование отчетов по счетам, содержащим подчиненные Подобная организация плана счетов позволяет перепро- ектировать подчинение счетов в плане счетов в процессе работы с программой. Счет, предназначенный изначаль- но для ведения по нему учета, однажды может стать груп- пой счетов, объединяющей в себе субсчета более низкого уровня. Рассмотрим пример на нашем плане счетов. Предположим, что до какого-то момента счета Активы и Обязательства не имели субсчетов и участвовали в провод- ках (рис. 9.12). Рис. 9.12. Документ Операция Далее было принято решение разбить счета Активы и Обя- зательства на субсчета и не использовать их в проводках в дальнейшем. Запрет использования в проводках можно реализовать, добавив в план счетов реквизит, принимаю- щий два значения: разрешить или запретить использо- вать в проводах, и проверять его значение при выборе счета в диалоге формы документа. Итак, решение было принято, были созданы субсчета и все дальнейшие про- водки вводились пользователем по субсчетам. На рис. 9.13 приведен фрагмент отчета, который показы- вает состояние остатков и оборотов по счетам после того, Мы видим, что в группах счетов Активы и Обязательства появились остатки и обороты по одноименным субсче- там. Подобных субсчетов нет в плане счетов. Так плат- форма интерпретирует в отчетах ситуацию, когда в ин- формационной базе присутствуют проводки по счетам, имеющим субсчета. Все проводки, сделанные по счету, имеющему субсчета, группируются системой и отобража- ются в отчете по «служебному» субсчету. При написании запросов к регистру бухгалтерии можно получить данные только по проводкам счета, имеющего субсчета (листинг 9.3). Листинг 9.3. Условие для получения данных по счету Счет = &Счет В приведенном примере &Счет — это параметр типа План- СчетовСсылка.<иня>, содержащий ссылку на счет, имеющий субсчета. Если необходимо получить в отчете данные по счету и всем его субсчетам, условие будет выглядеть иначе (листинг 9.4), при этом в итоги попадут и проводки по са- мому счету-группе. Листинг 9.4. Условие для получения данных по счету и всем субсчетам Счет В ИЕРАРХИИ(&Счет) Однако приведенный пример не является руководством к действию — если у счета есть подчиненные субсчета, то в проводках, как правило, участвуют они. А сам счет- группа предназначен для сбора итогов по всем своим суб- счетам. Приведенный пример лишь демонстрирует, что: ♦ система корректно отрабатывает ситуации, когда суще- ствуют движения и по счету, и по подчиненным ему субсчетам; ♦ всегда существует возможность «разбить» счет на суб- счета даже на этапе промышленной эксплуатации сис- темы без необходимости вносить изменения в проводки в закрытом отчетном периоде.
Свойства счета-родителя и подчиненных ему счетов Продолжая рассматривать иерархическую организацию плана счетов, обратим внимание на такую особенность, как возможные отличия свойств счета-родителя и подчи- ненных ему субсчетов. Это свойство плана счетов позво- ляет создать у активного счета пассивные субсчета или использовать на счете и его субсчетах различную анали- тику или задавать коды субсчетов без учета кода счета ро- дителя. Как можно использовать, например, различную аналитику на счете и его субсчетах? Это может иметь смысл, только если ранее использовавшийся счет был разбит на субсчета и на них потребовалась другая анали- тика или если один из субсчетов выбивается из общего правила (все субсчета имеют одну детализацию и счет- родитель ее же, а один субсчет — другую). Может ли на практике счет-родитель быть активным, а его субсчета активными и пассивными? Может! Напри- мер, счет Внеоборотные активы будет, несомненно, актив- ным (ведь это же активы!), а среди его субсчетов могут быть и активные (Первоначальная стоимость), и пассивные (Накопленная амортизация). Схожей особенностью обладает и код счета. Каждый счет в плане счетов нумеруется в соответствии с маской кода счета и включает в себя коды «предполагаемых» родите- лей. Подчеркнем слово «предполагаемых», дело в том, что при условии отсутствия уникальности или уникаль- ности кода по всему плану счетов для счета возможна смена родителя. Таким образом, счет с кодом 1.1, говоря- щим нам, что он располагается внутри группы счетов с кодом 1, на самом деле может оказаться в группе 3 или любой другой по усмотрению пользователя (рис. 9.14). В результате иерархичность счетов и иерархичность ко- дов счетов могут отличаться, что необходимо учитывать при написании кода, как в объектной модели, так и при написании запросов. Рассмотрим возможные ошибки на примере. Задача — сделать отчет Карточка, который позволит пользователю получить отбор всех проводок по одному счету. Восполь- зуемся в качестве источника данных для этого отчета виртуальной таблицей регистра бухгалтерии Движения- ССубконто. Таблица, которая должна получиться в резуль- тате выполнения отчета, показывает все проводки по сче- ту (или группе счетов). Отбор осуществляется по счету (или группе счетов) выбранному в диалоге пользовате- лем. Если выбранный пользователем счет участвует в проводке по дебету, сумму проводки необходимо ото- бразить в колонке СуммаДт, если по кредиту — СуммаКт (рис. 9.15). Рис. 9.15. Отчет Карточка При построении отчета по группе счетов проверку, при- надлежит ли выбранной группе дебетуемый или креди- туемый счет проводки, можно выполнить разными спосо- бами. Первый вариант кода (листинг 9.5) выполняет проверку при обработке результатов запроса. Листинг 9.5. Фрагмент отчета Карточка Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ ДвиженияССубконто.Период КАК Период, ДвиженияССубконто.Регистратор, ПРЕДСТАВЛЕНИЕ(ДвиженияССубконто.Регистратор), ДвиженияССубконто.СчетДт, ДвиженияССубконто.СчетКт, ДвиженияССубконто.Сумма ИЗ [РборотДт Рис. 9.14. Счет Касса 15 516,00 1 843,00 100,00 95,00 350,00 1 000,00 13,00 285,00 2,00 2,00 13 771,00 6 961,00 6 810,00
РегистрБухгалтерии.ОсновнойРегистрБухгалтерии. ДвиженияССубконто( &НачПериода, &КонПериода, Счет В ИЕРАРХИИ (&Счет)) КАК ДвиженияССубконто УПОРЯДОЧИТЬ ПО Период"; Запрос.УстановитьПараметр("КонПериода". КонПериода); Запрос.УстановитьПараметрСНачПериода", НачПериода); Запрос.УстановитьПараметр("Счет", Счет); Результат = Запрос.ВыполнитьО; КодКоррСчета = Счет.Код; ОборотДт = 0; ОборотКт = 0; ВыборкаДетали = Результат.ВыбратьО: Пока ВыборкаДетали.СледующийО Цикл Если Найти(ВыборкаДетали.СчетДт.Код. КодКоррСчета) > 0 Тогда ОбластьДетальныхЗаписей.Параметры.СуммаДт = ВыборкаДетали.Сумма; ОборотДт = ОборотДт + ВыборкаДетали.Сумма; КонецЕсли; Если Найти(ВыборкаДетали.СчетКт.Код, КодКоррСчета) > 0 Тогда ОбластьДетальныхЗаписей.Параметры.СуммаКт = ВыборкаДетали.Сумма; ОборотКт = ОборотКт + ВыборкаДетали.Сумма: КонецЕсли; КонецЦикла; Этот вариант проверяет вхождение кода счета дебета или кода счета кредита (метод НайтиО) в код счета, выбранно- го в диалоге. Не учитывается возможность несовпадения иерархии кодов и иерархии счетов. В случае несовпаде- ния иерархии кодов и счетов отчет будет сформирован неверно. Второй вариант (листинг 9.6) выполняет сравнение в за- просе, его и рекомендуется использовать. Листинг 9.6. Фрагмент отчета Карточка Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ДвиженияССубконто.Период КАК Период, ДвиженияССубконто.Регистратор, ПРЕДСТАВЛЕНИЕ(ДвиженияССубконто.Регистратор), ВЫБОР КОГДА ДвиженияССубконто.СчетДт В ИЕРАРХИИ (&Счет) ТОГДА ДвиженияССубконто.Сумма ИНАЧЕ 0 КОНЕЦ КАК СуммаДт, ВЫБОР КОГДА ДвиженияССубконто.СчетКт В ИЕРАРХИИ (&Счет) ТОГДА ДвиженияССубконто.Сумма ИНАЧЕ 0 КОНЕЦ КАК СуммаКт ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии. ДвиженияССубконто( &НачПериода. &КонПериода, Счет В ИЕРАРХИИ (&Счет)) КАК ДвиженияССубконто УПОРЯДОЧИТЬ ПО Период ИТОГИ СУММА(СуммаДт), СУММА(СуммаКт) ПО ОБЩИЕ"; Запрос.УстановитьПараметр("КонПериода". КонПериода); Запрос.УстановитьПараметр("НачПериода", НачПериода); Запрос.УстановитьПараметр("Счет", Счет); Результат = Запрос.ВыполнитьО; ВыборкаОбщийИтог = Результат.Выбрать( ОбходРезультатаЗапроса.ПоГруппировкам); ВыборкаОбщийИтог.СледующийО; И Общий итог ВыборкаДетали = ВыборкаОбщийИтог. Выбрать О; Пока ВыборкаДетали.СледующийО Цикл //... КонецЦикла; Это не означает, что нельзя проверить принадлежность группе при обходе результатов запроса. Можно. Но нуж- но проверять принадлежность родителю, а не «коду». Предопределенные и пользовательские счета План счетов может содержать счета, вводимые пользовате- лем, и счета, введенные на этапе конфигурирования. По- следние называются «предопределенными» и являются объектами конфигурации (имеют свое уникальное в рам- ках плана счетов имя). Надо отметить, что для плана счетов, в отличие, например, от справочника, который обладает такой же возможностью, ввод счетов в режиме конфигуратора является в большинстве случаев основным вариантом заполнения. План счетов, ну или, по крайней мере, его основа (счета первого уровня) создаются еще на этапе конфигурирования и во многом определяют логику учета. Ввод новых счетов (субсчетов) пользователем явля- ется скорее исключением, чем правилом. Свойства счета Предопределенные счета вводятся по кнопке Предопреде- ленные с закладки Прочие плана счетов. При вводе для предопределенного счета есть возможность задать сле- дующие свойства (табл. 9.8). Как мы видим, часть свойств, которые мы задаем на этапе конфигурирования, могут изменяться пользователем при работе в информационной базе. По сути, задавая такие поля, как Код, Родитель, Наименование, Порядок, мы лишь указываем начальные значения по умолчанию, пользова- тель сможет присвоить свой код, изменить наименование, переопределить родителя, установить новый порядок сортировки счетов. Особенности написания запросов Возможность изменения этих свойств необходимо учи- тывать при конфигурировании. Так, например, при напи- сании запроса для получения остатка по одному счету можно поступить следующим образом (листинг 9.7).
Таблица 9.8. Свойства счета Свойство Комментарий Может изменяться пользователем Имя Имя объекта Нет Родитель Счет-родитель Да Код Код счета в соответствии с маской Да Наименование Наименование счета Да Вид счета Активный, Пассивный, Активный/Пассивный определяет вариант подсчета остатков по счету Нет Забалансовый По счету не выполняется контроль двойной записи Нет Порядок Сортировка счетов в списке и запросах Да Признаки учета (сколько введено в плане счетов) Участие счета в том или ином виде учета Нет Виды субконто (не более чем определено в плане счетов) Детализация счета в аналитическом учете Нет Признаки учета субконто (сколько определено в плане счетов) Возможность отключить ведение того или иного вида учета для одного вида субконто на счете Нет Листинг 9.7. Пример получения остатка по счету Процедура ПолучитьОстаток(Кнопка) Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ Остатки.СуммаОстаток ИЗ РегистрБухг аптерии.ОсновнойРегистрБухг аптерии.Остат ки( Счет.Код = ""I.!'"', ) КАК Остатки": Остатки = Запрос.ВыполнитьО.ВыбратьО; Остатки.Следующий() ; Остаток = Остатки.СуммаОстаток; КонецПроцедуры В этой процедуре выполняется запрос, который получает из виртуальной таблицы регистра бухгалтерии РегистрБух- галтерии.ОсновнойРегистрБухгалтерии.Остатки остаток по сче- ту с кодом 1.1, который в нашем плане счетов называется Касса. Ну, или точнее, назывался на этапе конфигурирова- ния. Если пользователь изменит код счета, запрос или не будет выполнен, или будет выполнен не по тому счету. По- этому всегда имеет смысл при установке отборов по сче- там использовать или ссылку (полученную, например, пу- тем выбора в диалоге элемента из плана счетов), или неизменямое имя предопределенного счета (рис. 9.16). Рис. 9.16. Свойства предопределенного счета ВНИМАНИЕ Когда мы сказали о необходимости использовать имя для получения ссылки на предопределенный счет плана счетов, имелось в виду свойство счета Имя, а не наименование сче- та. Имя — свойство любого объекта метаданных конфигура- ции, в том числе и предопределенного счета плана счетов. Имя служит для однозначной идентификации счета в плане счетов конфигурации и, как следствие, может использо- ваться для получения ссылки на объект. Листинг 9.8. Пример получения остатка по счету Процедура ПолучитьОстаток(Кнопка) Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ Остатки.СуммаОстаток ИЗ РегистрБухгаптерии.ОсновнойРегистрБухгаптерии.Остатки( Счет = &Счет, j КАК Остатки"; Запрос.УстановитьПараметрС"Счет", ПланыСчетов. ОсновнойПланСчетов.Касса); Остатки = Запрос. ВыполнитьО. ВыбратьО ; Остатки.СледующийО; Остаток = Остатки.СуммаОстаток; КонецПроцедуры Основы организации аналитического учета Иерархический план счетов позволяет организовать де- тальный учет. И при желании можно организовать де- тальный аналитический учет, используя возможность ор- ганизации иерархического плана счетов и ввода новых субсчетов пользователем. Однако детализация эта будет иерархической. При такой организации аналитического
Рис. 9.17. План счетов Основной план счетов Т овары учета не представляется возможным получение итогов по нескольким параллельным срезам. Рассмотрим учет това- ров на складах. Предположим, в нашей организации есть несколько складов, на каждом из которых множество ви- дов номенклатурных позиций. Перед нами стоит задача обеспечить получение остатков и оборотов по каждому складу и товару в отдельности и сводно по всем. Задачу можно решить, используя субсчета счета Товары. Изменив длину кода счета (до 10 символов) и маску кода счета мы можем завести к счету учета товаров необходимое количество субсчетов (рис. 9.17). Подобная организация аналитического учета возможна, но имеет ряд существенных недостатков. Во-первых, план счетов будет расти (и расти существенно) по мере изме- нения номенклатуры товаров (добавления новых по- зиций, отказа от старых и появления неиспользуемых). Во-вторых, он будет расти нелинейно, так как одна и та же позиция номенклатуры может храниться на разных складах, таким образом, количество субсчетов на каждую позицию будет равняться количеству складов. И самое главное — не представляется возможности автоматиче- ски сгруппировать данные по одной позиции номенкла- туры, хранимой на разных складах. Организацию аналитического учета с использованием суб- счетов нельзя назвать неправильной. Это вполне возмож- ный вариант, который имеет свои ограничения (мы пере- числили их выше) и свои достоинства. К достоинствам можно отнести, например, интуитивную прозрачность учета для любого бухгалтера, который ранее не сталки- вался с учетом при помощи компьютерной программы, всю жизнь проработал в «бумажной бухгалтерии». Однако подавляющее большинство бухгалтеров предпо- читает бухгалтерские программы с большими возможно- стями в части ведения аналитического учета. Для описания возможностей системы при автоматизации задач анали- тического учета используются понятия Вид субконто и Субконто. Вид субконто — группа однородных объектов аналитического учета. Понятие вид субконто соответст- вует понятию бухгалтерского учета «аналитический счет». В демонстрационной конфигурации «Бухгалтерский учет», которая находится на прилагаемом компакт-диске, воз- можны следующие виды субконто: список контрагентов для ведения учета расчетов в разрезе контрагентов, но- менклатура товаров и список складов для учета товаров на складах, список статей затрат для учета затрат и дру- гие. Каждый элемент списка вида субконто представляет собой объект аналитического учета и называется Субкон- то. Ни субконто, ни вид субконто не имеют объектного представления в системе и существуют лишь как поня- тия, реализуемые с помощью других объектов. Виды суб- конто, как привило, бывают ссылочного типа и содержат в себе ссылку на справочник, документ или перечисле- ние, хотя возможны и другие варианты. Если видом суб- конто является справочник, то субконто — один элемент этого справочника. Сами по себе виды субконто не хра- нят никакой информации об остатках и оборотах по сче- там и являются, по сути, подключаемыми измерениями для счетов план счетов. Использование видов субконто для организации анали- тического учета можно представить в виде схемы на рис. 9.18. Левая часть схемы описывает наш иерархический план счетов. Каждый из счетов предназначен для ввода и хра- нения относительно укрупненной информации — остаток всех товаров на всех складах, долг всех покупателей, за- долженность перед всеми поставщиками и др. Вместо того чтобы развивать субсчета у названных счетов, мы от- крываем на них аналитический учет, используя виды суб- конто. Каждый счет на данной схеме можно рассматри- вать как учетный регистр, накапливающий остатки и обороты в денежном выражении. Виды субконто позво- ляют добавлять измерения в эти регистры и создают но- вые сущности. Так, например, один и тот же справочник Контрагенты может использоваться для организации ана- литического учета как на счете Расчеты с покупателями, так и на счете Расчеты с поставщиками. Анализируя остатки и обороты по счету Расчеты с покупателями в разрезе объек- тов аналитического учета (контрагентов), мы получим список наших покупателей и остатки (задолженность) и обороты (увеличение, погашение) по каждому из них.
Возможность системы привязать к одному счету несколь- ко самостоятельных видов субконто позволяет нам полу- чить фасетное (параллельное) деление: на одном складе могут быть разные товары, один и тот же товар может быть на разных складах, мы всегда можем получить оста- ток по складу, по товару и по товару на складе. —Кагитал Рис. 9.18. Использование видов субконто для организации аналитического учета План видов характеристик для создания списка видов субконто Для хранения списка видов субконто используется объ- ект План видов характеристик. Название объекта имеет два уровня «вложенности» («план» «видов характеристик»): план, представляющий собой совокупность видов суб- конто, каждый из которых хранит информацию о типе характеристик, каждая из которых является объектом аналитики, то есть субконто. Характеристика — это один экземпляр вида характеристик, так же как субконто — это один экземпляр вида субконто. Характеристика не явля- ется самостоятельным объектом конфигурации. Для ве- дения аналитического учета, как правило, используются элементы справочников, значения перечисления, ссыл- ки на документы, поэтому характеристика, как правило, имеет ссылочный тип данных (хотя возможны и другие варианты). Один план видов характеристик может ис- пользоваться для организации аналитического учета для нескольких планов счетов. Можно провести следующие параллели между понятиями системы и понятиями пред- метной области (табл. 9.9). Таблица 9.9. Соответствие понятий системы 1С:Предприятие и понятий предметной области Объект Понятие Планы видов характеристик Все виды субконто Вид характеристики Вид субконто Характеристика Субконто Начнем организацию аналитического учета с создания нового плана видов характеристик. Назовем его Виды суб- конто (рис. 9.19 и 9.20). Рис. 9.19. Основные свойства плана видов характеристик Рис. 9.20. Тип значения характеристик ПРИМЕЧАНИЕ Не рекомендуется включать в тип значения характеристик какие-либо типы кроме ссылочных. Это существенно повы- шает нагрузку на систему. В базе данных поле составного типа, включающего в себя только ссылочные типы данных, хранится в трех полях таблицы (фактический тип хранимого значения, номер таблицы, на которую ссылается значение, и идентификатор записи, на которую ссылается значение). При добавлении в составной тип данных примитивных ти- пов на каждый из них добавляется новое поле в базу дан- ных. Кроме увеличения объема базы данных, это имеет еще одну негативную сторону: система выполняет индекси- рование полей для хранения итогов по субконто таблиц ре- гистра бухгалтерии и количество полей в индексе ограни- чено в SQL-версии 16 полями, часть из которых уже заняты под счет, период, измерения. Более подробно эта тема рас- смотрена в разделе «Индексы таблиц итогов регистра бух- галтерии», с. 306. Так как в качестве объектов аналитики могут выступать данные разных объектов (разных справочников, как в на- шем случае, или справочников и документов и перечисле- ний и др.), то тип значения характеристик устанавливается составным. Фактически, в диалоге редактирования типа характеристик мы выбираем объекты конфигурации, ко- торые будут использоваться для ведения аналитического учета. Выбираем, какого типа мы (и пользователь) смо- жем создавать виды субконто. Надо отметить, что поле
диалога для выбора значения субконто в документах, от- четах и других механизмах будет иметь тип Характеристи- ка. Ви дыСубконто плана видов характеристик Виды субконто. А тип значения поля в базе данных будет составным и бу- дет включать все выбранные в типе значения характери- стик типы. Как и счета плана счетов, виды субконто могут создавать- ся как в режиме конфигуратора, так и в пользовательском режиме. Если мы не считаем необходимым предоставлять пользователю создавать собственные виды субконто, то настройку закладки Общая можно на этом закончить, пе- рейти на закладку Прочее и создать предопределенные виды характеристик (рис. 9.21). 1? План видов характерно™ ... Предопределенные виды характеристик «ОХ Действия- «g < tg " Склады Контрагенты 00001 Номенклатура 00002 00004 Наименование Тип Контрагенты Номенклатура Склады СправочникСсылка Контрагенты СправочникСсылка Номенклатура СправочникСсылка. Склады Н«» Сотрудники 00003 Сотрудники ;СправочнжСсылка.Сотрудники L-~— Статьи 00005 j Статьи Слрагчл—жЕсытаСтатьи Рис. 9.21. Предопределенные виды характеристик У пользователя все равно будет возможность создавать новые виды субконто, но только тех типов данных, кото- рые мы выбрали в качестве возможных типов значения характеристик. Например, он сможет создать еще один вид субконто Продавцы типа СправочникСсылка.Контрагенты, но физически эти «продавцы» будут «лежать» в справоч- нике Контрагенты. Маловероятно, что пользователю при- годится такая возможность. Скорее всего, он предпочел бы создать новый вид субконто, в котором может хранить какие-то новые объекты аналитики, для которых не пре- дусмотрено справочника в конфигурации. Для предоставления пользователю возможности созда- вать собственные виды субконто предусмотрен механизм дополнительных значений характеристик. Для этого соз- дается новый справочник в конфигурации, который мы назовем, например, Субконто. Потом включаем его в тип значения характеристик и получаем, таким образом, «местечко про запас», где пользователь сможет хранить собственные объекты аналитики. Теперь пользователь сможет создать сколько угодно видов субконто, имеющих тип этого справочника, но все его объ- екты аналитики будут лежать «вперемешку». Чтобы пре- доставить пользователю возможность создавать отдельные подмножества объектов аналитики, справочник Субконто необходимо сделать подчиненным к плану видов характе- ристик. Подчиненность справочника Субконто плану видов характеристик — обязательное условие функционирования механизма дополнительных характеристик (рис. 9.22). Тем самым мы предоставили пользователю создать сколь- ко угодно новых видов субконто. Физически все они бу- дут храниться в одном справочнике, но «перемешивать- ся» не будут, так как на каждый новый вид субконто в справочнике будет выделяться новое множество подчи- ненных ему элементов. А чтобы нумерация этих элемен- тов была также независимой, имеет смысл на закладке Нумерация объекта конфигурации Справочник Субконто ус- тановить переключатель Серии кодов в значение В пределах подчинения владельцу. Рис. 9.22. Владельцы справочника Субконто
Последний штрих — выбрать справочник Субконто в каче- стве дополнительных значений характеристик (рис. 9.23). Теперь вновь создаваемые пользователем виды субконто (виды характеристик) по умолчанию будут иметь тип значения СправочникСсылка.Субконто. ^Составной тип данных X типа данных ✓ Номенклатура Ред актиров зиме Контрагенты SSB Сотрудники Склады Валюты Статьи © -Efi-I Рис. 9.23. Дополнительные значения характеристик Более подробно про план видов характеристик можно прочитать в разделе «Хранение дополнительных характе- ристик произвольного типа. Использование плана видов характеристик», с. 131. Детализация счета плана счетов по видам субконто Теперь, когда созданы «аналитические счета» — виды субконто, чтобы они «заработали» и позволили вести аналитический учет на счетах, которые ранее были син- тетическими, необходимо «привязать» виды субконто к счетам плана счетов. Выполняется это в объекте План счетов. Начинаем на- стройку с закладки Субконто. На этой закладке в свойстве Виды субконто выбираем план видов характеристик, ко- торый хранит виды субконто для этого плана счетов (рис. 9.24). Закладка Субконто также позволяет определить макси- мальное количество субконто на счете. Это число парал- лельных аналитических срезов (видов субконто), которое можно будет выбрать для каждого счета. И число это в большинстве случаев определяется отчетными потребно- стями объекта автоматизации. На рисунке выбрано зна- чение 2, в типовом решении Бухгалтерия предприятия выбрано значение 3, максимально возможное поддержи- ваемое платформой значение 50. Выбор максимального количества субконто — важный этап в проектировании системы автоматизации бухгалтерского учета, и мы оста- новимся на нем отдельно ниже, в разделе «Принятие ре- шений при организации аналитического учета», с. 259. Пока же установка этого свойства привела к тому, что для каждого счета плана счетов было добавлено новое свойст- во — специализированная табличная часть Виды субконто. И содержать эта табличная часть в нашей конфигурации может максимум две строки. Подчеркнем: именно в на- шей конфигурации (где в свойствах плана счетов выбра- но значение максимального количества субконто равным двум) и именно для каждого счета (разные счета могут иметь различную детализацию) (рис. 9.25). Рис. 9.24. Субконто плана счетов Рис. 9.25. Виды субконто Каждая из строк табличной части содержит ссылку на вид характеристики плана видов характеристик выбранного в свойстве плана счетов Виды субконто и дополнительные свойства. Каждая строка табличной части ВидыСубконто содержит следующие поля: ВидСубконто, Предопределен- ное, ТолькоОбороты и признаки учета субконто. ВидСубконто — свойство типа ПланВидовХарактеристикСсыл- ка.<имя>, позволяющее получить доступ к свойствам вида характеристики плана видов характеристик. Это поле за- дает вид субконто, в разрезе которого будет вестись ана- литический учет. Кроме того, оно может быть использо- вано, например, при установке типов значений для реквизитов формы или для полей построителя отчета (листинг 9.9). В приведенном примере счет — переменная или поле вво- да типа ПланСчетовСсылка.<имя>. Цикл по видам субконто счета позволит узнать их типы, наименования, были они введены в конфигураторе (предопределенный вид суб- конто был добавлен на счет в режиме конфигуратора)
или добавлены пользователем, узнать признаки учета субконто. Листинг 9.9. Пример использования свойства ВидСубконто Для Каждого ВидСубконто Из Счет.ВидыСубконто Цикл Вид = ВидСубконто.ВидСубконто; ТипЗначения = Вид.ТипЗначения; Наименование = Вид.Наименование; ВведенВКонфигураторе = ВидСубконто.Предопределенное: Оборотный = ВидСубконто.ТолькоОбороты; Количественный = ВидСубконто.Количественный; КонецЦикла; Ввод в диалоге и хранение в базе данных объектов аналитического учета С тех пор как нами была добавлена возможность ведения аналитического учета, в нашей конфигурации должны будут произойти изменения. Теперь пользователю будет необходимо в диалогах форм отчетов, документов, а мо- жет быть и не только, выбирать объекты аналитики, соот- ветствующие выбранному уже в том же диалоге счету. А информационной базе придется сохранять этот сде- ланный пользователем выбор. Для хранения выбранного пользователем объекта аналитики в конфигурации пре- дусмотрен специальный тип данных Характеристика.<Имя>. Этот тип данных может быть назначен полю ввода в фор- ме и реквизиту объекта, хранимому в информационной базе. Этот тип данных является составным и включает в себя все типы данных, выбранные в свойстве Тип значения ха- рактеристик плана видов характеристик. Рассмотрим пер- вый пример, в котором пользователь должен в документе (или справочнике) выбрать сначала в первом поле ввода вид субконто, а затем в другом объект субконто выбран- ного ранее вида. Для этого добавим два реквизита: Вид- Субконто типа ПланВидовХарактеристикСсылка.ВидыСубконто и Субконто типа Характеристика.ВидыСубконто (рис. 9.26). Если этим ограничиться, то при выборе значения субкон- то в диалоге формы, пользователю сначала будет предла- гаться выбор типа из списка типов значений характери- стик Виды субконто. Следующая наша задача — ограничить выбор типа только типами выбранного пользователем вида субконто. Для этого в свойствах поля ввода Субконто необходимо уста- новить свойство Связь по типу в значение, указывающее на реквизит Виды субконто. Теперь если, например, пользова- телем выбран вид субконто Контрагенты (который в на- шей конфигурации имеет тип значения СправочникСсыл- ка. Контрагенты), то диалог выбора типа содержит только те типы значений, которые может принимать данный вид субконто. В большинстве случаев субконто имеет не составной тип данных. Поэтому нам кажется разумным совсем изба- виться от диалога выбора типа. Для этого создадим про- цедуру — обработчик события При изменении поля ввода ВидСубконто (листинг 9.10). Листинг 9.10. Обработчик события ПриИзменении поля ввода ВидСубконто Процедура ВидСубконтоПриИзменении(Злемент) ТипСубконто = ВидСубконто.ТипЗначения; ЭлементыФормы.Субконто.Выбират ьТип = (ТипСубконто.ТипыО .КоличествоО > 1); Субконто = ТипСубконто.ПривестиЗначение(Субконто): КонецПроцедуры Свойства: Реквизит Ц V ¥ X V Субконго Субконто Основные. Имя Синоним Индексировать [Не индексировать Тип данных: Т ип | Характеристика.В чаыСу бконто Свойства реквизитов документа Свойства элемента формы Рис. 9.26. Реквизиты Субконто и ВидСубконто
Прокомментируем процедуру. Все начинается с того, что мы получаем описание типов возможных для этого вида субконто. Описание может содержать несколько типов. Поэтому в следующей строке мы устанавливаем для элемента формы поля ввода Субконто флаг необхо- димости выбора типа. Выбор типа необходим только в том случае, если количество типов в описании более од- ного. Далее используется метод описания типов ПривестиЗначе- ние(). Метод в качестве параметра получает значение (в нашем случае значение реквизита Субконто), которое будет приводиться к типу описания. Далее метод выпол- няет проверку на соответствие значения описанию типов. Если значение соответствует, то метод возвращает его об- ратно (в реквизит Субконто), если нет — приводит к типу, данному в описании. В практике создания механизмов для ведения бухгалтер- ского учета чаще, однако, встречается другая ситуация, когда пользователь выбирает в диалоге формы счет и да- лее должен выбрать значения субконто того типа данных, который выбран для видов субконто этого счета. В таком случае в диалоге формы размещают поле ввода для рек- визита Счет (тип ПланСчетовСсылка.<иня>) и устанавливают связь между полем ввода для выбора значения субконто и счетом (минуя вид субконто, который становится не ну- жен). Создадим следующие реквизиты: Счет (тип ПланСчетов- Ссылка.ОсновнойПланСчетов), Субконто1 (тип Характеристика. ВидыСубконто) и Субконто2 (тип Характеристика.ВидыСубконто). В свойствах нашего плана счетов выбрано максимальное количество субконто равным двум, поэтому более двух значений субконто для одного счета выбирать не потре- буется. В диалоге формы разместим все реквизиты и ус- тановим свойства для полей ввода Субконто1 и Субконто2 (рис. 9.27). Из всего множества свойств нам интересно свойство Связь по типу, в котором в этот раз мы укажем реквизит Счет. Те- перь диалог выбора типа будет содержать только те типы значений, которые могут принимать виды субконто вы- бранного пользователем счета. Чтобы оставить только те типы (или один тип, если используется субконто не со- ставного типа), которые нужны для выбора первого вида субконто, необходимо установить значение свойства Вид субконто равным 1. Для поля ввода реквизита Субконто2 это свойство будет равным 2. Свойство поля ввода Вид субконто появляется после установки связи по типу с рек- визитом типа ПланСчетовСсылка.<иня> и позволяет указать порядковый номер вида субконто на счете, значение ко- торого должно выбираться в этом поле ввода. Следующая наша задача — «избавиться» от диалога вы- бора типа. Для этого напишем процедуру — обработчик события При изменении поля ввода Счет (листинг 9.11). Реквизиты документа Свойства элементов Форт* Порядковый номер субконго на счете Рис. 9.27. Размещение реквизитов в диалоге формы
Листинг 9.11. Обработчик события ПриИзменении поля ввода Счет Процедура СчетПриИзменении(Зленент) ЧислоСубконто = Счет.ВидыСубконто.КоличествоО; Для Сч = 1 По ЧислоСубконто Цикл ТипСубконто = Счет.ВидыСубконто[Сч - 1]. ВидСубконто.ТипЗначения; ЭлеиентыФормы["Субконто" + Сч].ТолькоПросмотр = Ложь; ЗлементыФормы["Субконто" + Сч].ВыбиратьТип = (ТипСубконто.ТипыО .КоличествоО > 1); Если ТипСубконто.ПривестиЗначениеС ДокументОбъект["Субконто" + Сч]) о ДокументОбъект["Субконто" + Сч] Тогда ДокументОбъект[”Субконто" + Сч] = ТипСубконто.ПривестиЗначениеС ДокументОбъект["Субконто" + Сч]); КонецЕсли; КонецЦикла; МаксКоличествоСубконто = Метаданные.ПланыСчетов.ОсновнойПланСчетов. МаксКоличествоСубконто: Для Сч = (ЧислоСубконто + 1) По МаксКоличествоСубконто Цикл Если Не ДокументОбъект["Субконто” + Сч] = Неопределено Тогда ДокументОбъект["Субконто" + Сч] = Неопределено; КонецЕсли: ЗлементыФормы["Субконто" + Сч].ТолькоПросмотр = Истина: КонецЦикла; КонецПроцедуры Прокомментируем текст этой процедуры. Процедура на- писана достаточно универсально и не зависит от настроек ведения аналитического учета плана счетов. Начинается ее выполнение с того, что мы узнаем число субконто, за- действованных для ведения аналитического учета на вы- бранном счете. В цикле по числу субконто на счете мы получаем описание типов субконто. Для этого обращаем- ся к табличной части счета ВидыСубконто и получаем из нее строку по индексу (индексация строк этой табличной части начинается с нуля). В конце процедуры в отдельном цикле по максимальное количество субконто на счете выбранного плана счетов мы установим для полей ввода субконто формы, которые не задействованы для текущего счета, свойство Только- Просмотр. При перевыборе счета это свойство для задейст- вованной аналитики нужно снять. Выбор типа из поля ввода субконто имеет смысл только для субконто составного типа (такие тоже могут быть). Мы определяем количество типов, входящих в описание типа, и если этот тип составной (более одного), устанав- ливаем флаг элемента формы ВыбиратьТип. Наша процедура расположена в модуле формы докумен- та. Основной реквизит этой формы ДокументОбъект. Мы стараемся писать процедуру универсально, поэтому пре- дусматриваем возможность ее вызова не только при из- менении счета, но и, например, при открытии формы. Чтобы не устанавливать флаг модифицированное™ при открытии формы, мы проверяем тип значения реквизита на соответствие типу субконто и приводим тип только в том случае, если тип реквизита отличается от типа описа- ния субконто. Так как выбранный счет может иметь количество субкон- то меньше, чем предусмотрено для плана счетов, то мы очищаем все незадействованные реквизиты документа и устанавливаем для полей ввода формы этих реквизитов свойство ТолькоПроснотр. Последний штрих в работе этого механизма — управле- ние видимостью полей ввода субконто и надписями для этих полей. Это связано с тем, что не на каждом счете ис- пользуются оба вида субконто, могут быть на счете, где задействован только один аналитический разрез или во- обще ни одного (листинг 9.12). Листинг 9.12. Процедура УстановитьВидимостьСубконто Процедура УстановитьВидимостьСубконтоО Для Ном = 1 по 2 Цикл Если (Нои <= Счет.ВидыСубконто.КоличествоО) И (НЕ Счет.ПустаяО) Тогда ЗлементыФормы[''НадписьСубконто"+Ном] .Заголовок = Строка(Счет.ВидыСубконто[Ном-1].ВидСубконто); ЗлементыФормы["НадписьСубконто"+Ном].Видимость = Истина; ЭлементыФормы["Субконто"+Ном].Видимость = Истина; Иначе ЭлементыФормы["НадписьСубконто"+Ном].Видимость = Ложь; ЗлементыФорны[''Субконто"+Ном]. Видимость = Ложь; КонецЕсли; КонецЦикла; КонецПроцедуры Вызов этой процедуры из обработчика события формы При открытии и обработчика события При изменении поля ввода Счет позволит скрыть неиспользуемые поля ввода субконто и надписи к ним, а для используемых полей на- значить заголовки надписей — имена видов субконто. Признаки учета субконто Признаки учета субконто будут рассмотрены нами под- робнее ниже при изучении регистра бухгалтерии в разде- ле «Свойство ресурса Признак учета субконто», с. 268. Пока же рассмотрим вкратце их предназначение и созда- ние. Признаки учета субконто дополняют специализиро- ванную табличную часть Виды субконто новыми свойства- ми типа Булево. Каждое свойство, связанное с ресурсом регистра бухгалтерии, позволяет управлять хранением остатков и оборотов выбранного ресурса для объектов субконто выбранного счета (рис. 9.28). Для плана счетов Основной план счетов предусмотрена воз- можность отключать для отдельных видов субконто веде- ние количественного и суммового учета. Так, например, если на счете товаров необходимо учитывать номенкла- турные позиции товаров в количественном выражении в разрезе складов, а в суммовом — по предприятию в целом (без учета складов), то настройка счета будет выглядеть, как на рис. 9.28). Свойство Только обороты схоже по своему назначению с признаками учета субконто. Оно ограничивает хране- ние итогов по субконто счета только хранением оборотов, исключая из таблиц итогов остатки. Это может быть не- обходимо в случае, когда остатки по субконто просто не имеют смысла.
План счетов ОсновнойПланСчетов _ □ X Мековиел ное количество субконто Виды субконго: ВидыСубконто Основные Данные Нумерация ► Субконго 1 | Справка"] Рис. 9.28. Признаки учета субконто Например, учет на счете денежных средств в разрезе статей, характеризующих виды поступлений и списаний средств. В таком учете остаток по статье не будет нести никакого экономического смысла. По одной статье мы получаем денежные средства, по другой — списываем. Результатом аналитического учета станут постоянно растущие и нико- гда не списываемые остатки по статьям, по одним из них — положительные, по другим — отрицательные. Рассмотрим программное заполнение субконто счета и их свойств. Следующий фрагмент кода (листинг 9.13) по- зволяет узнать, ведется ли на счете Товары учет в разрезе субконто Склады, и если нет, то добавить это субконто на счет, включив на нем признаки учета субконто суммовой и количественный. Листинг 9.13. Пример программного заполнения субконто и их свойств СчетТовары = ПланыСчетов.ОсновнойПланСчетов.Товары; ВидСубконтоСклады = ПланыВидовХарактеристик. ВидыСубконто.Склады; Если СчетТовары.ВидыСубконто.Найти(ВидСубконтоСклады, "ВидСубконто") = Неопределено Тогда СчетТоварыОбъект = СчетТовары.ПолучитьОбъектС); НовыйВид = СчетТоварыОбъект.ВидыСубконто.ДобавитьО; НовыйВид.ВидСубконто = ВидСубконтоСклады; НовыйВид. Суммовой = Истина; НовыйВид.Количественный = Истина: СчетТоварыОбъект.ЗаписатьО; КонецЕсли; ПРИМЕЧАНИЕ Комментируя это процедуру, необходимо уточнить, что до- бавление вида субконто на счет возможно только в том случае, если табличная часть получена как свойство объек- та Счет. Кроме того, надо учитывать, что проверка на пре- вышение максимального количества видов субконто для плана счетов будет выполняться только при записи счета. Принятие решений при организации аналитического учета От организации плана счетов и аналитического учета во многом зависит не только функциональность, но и произ- водительность конфигурации. Остановимся подробнее на наиболее важных моментах организации аналитического учета в конфигурации. Как правило, организация аналитического учета опреде- ляется отчетными потребностями руководства, органи- зационной структурой предприятия, необходимостью выполнения стандартов учета (международных, государ- ственных, внутрифирменных и т. д.). Рассмотрим пример организации учета товаров. Пользо- ватель изъявил желание вести учет товаров в разрезе но- менклатуры товаров. Желание разумное, ведь подобная организация аналитического учета позволит ему анали- зировать остатки и обороты по каждой номенклатурной позиции. Список товаров существенный и незакрытый (в него добавляются новые позиции, удаляются старые). Кроме кода и наименования номенклатуры необходимо хранить и другую дополнительную, но важную информа- цию. Ниже приводится таблица (табл. 9.10), позволяю- щая в данном конкретном случае принять решение об оп- тимальности использования механизма платформы. Таблица 9.10. Решение первое. Выбор: субсчета или субконто Критерий Учет на субсчетах Учет на субконто Количество позиций От единиц до десятков От десятков до бесконечности Список позиций учета закрыт Как правило — да Может и будет расширяться Параллельные срезы возможны Только иерархический учет Несколько параллельных срезов Достаточная информатив- ность Кода и наименования достаточно Есть дополни- тельные свойства Принимаем решение: вести учет на счете товаров в разре- зе субконто Номенклатура типа СправочникСсылка.<имя>. Следующее желание пользователя получать дополни- тельные группировки и отборы в отчетах по складам, что соответствует организационной структуре предприятия, и списывать товары методов FIFO. Дополнительно по- требуется группировка в отчете остатки товаров по годам
приобретения имеющихся на складе МПЗ и видам това- ров. По партиям и складам, основываясь на предыдущей таблице, принимаем решение о необходимости открытия новых видов субконто Партии и Склады на счете учета то- варов. По видам товаров и годам закупки МПЗ решение может быть проще (табл. 9.11). Таблица 9.11. Решение второе. Выбор: новый вид субконто или новое свойство старого Критерий Новый вид субконто Новое свойство субконто Можно ли однознач- но связать новый критерий отбора (группировки) с су- ществующим объек- том аналитического учета Связать невоз- можно, это па- раллельный срез Новый крите- рий вполне можно размес- тить как новое свойство суще- ствующего вида аналитики Принимаем решение: вид товара — это новый реквизит справочника Номенклатура, год можно получить из партии товара. Стало быть, добавления новых видов аналитики эти два критерия не потребовали. В результате пришли к выводу, что для получения затре- бованной информации потребуется ведение аналитиче- ского учета на счете товаров в разрезе трех независимых видов аналитик: номенклатура, склады и партии. Следующий вопрос: порядок следования аналитик. Более подробно об организации регистра бухгалтерии мы рас- скажем потом, пока же заметим, что физическая органи- зация таблиц позволяет наиболее быстро получать раз- вернутые отчеты по тем аналитическим срезам, которые находятся «ближе к счету» (табл. 9.12). Таблица 9.12. Решение третье. Выбор: порядок следования видов субконто Критерий Первый на счете Последний на счете По какому аналити- ческому срезу отче- ты чаще всего будут «разворачиваться», по какому реже Номенклатура Склады Принимаем решение: первый вид субконто на счете будет Номенклатура, второй Партии, третий Склады. Следующая наша задача — оценить возможность исполь- зования трех видов субконто на счете со стороны типово- го (или просто существующего) решения, которое мы адаптируем, и со стороны платформы. Любое типовое решение ориентировано, как правило, на фиксированное заданное максимальное количество суб- конто на счете. Так, например, конфигурация Бухгалте- рия предприятия содержит в себе набор документов, среди которых есть универсальные, и отчетов, предназначен- ных для работы с максимум тремя видами субконто на счете (три поля для выбора). Кроме того, важно оценить влияние изменившейся аналитики счета на работу суще- ствующих механизмов типового решения. Любое измене- ние аналитики счета, задействованного в автоматических учетных схемах, может привести к существенной пере- делке этих схем, даже если не превышено максимальное количество субконто, установленное в свойствах плана счетов. А если, к тому же, требуется увеличить максималь- ное количество субконто, предусмотренное в плане сче- тов типового решения и, как следствие, прописанное во всех универсальных механизмах, переделка коснется и их. Формальное ограничение со стороны платформы на макси- мальное количество субконто составляет 50 субконто на счете. Именно формальное, так как существует особенность сервера базы данных при построении индексов таблиц, о которой более подробно будет рассказано в разделе «Ин- дексы таблиц итогов регистра бухгалтерии», с. 306. Во мно- гих случаях при проектировании плана счетов имеет смысл обдумать возможность вынесения отдельных разделов уче- та из бухгалтерии в оперативный учет, который может быть реализован с помощью регистров накопления (о которых можно прочитать в главе 8 «Реализация задач учета движе- ния средств», с. 177). При принятии решения о необходи- мости вынесения раздела в оперативный учет имеет смысл учитывать критерии, перечисленные в табл. 9.13. Таблица 9.13. Решение четвертое. Выбор: оперативный или бухгалтерский учет Критерий Субконто бухгалтерии Измерения оперативного учета Максимальное коли- чество субконто, вы- бранное в плане счетов демонстраци- онной конфигурации Не более двух Нет ограниче- ния, может быть создан регистр с нужным количе- ством измерений Максимальное коли- чество субконто, с которыми эффек- тивно может рабо- тать платформа * * Количество объектов учета Десятки, сотни, тысячи ** Десятки и сотни тысяч ** Количество доку- ментов в день Единицы, десятки ** Десятки, сотни ** Измерение прими- тивного типа Настоятельно не рекоменду- ется В принципе, возможно Влияние на бухгал- терский баланс Необходимо Не рекоменду- ется * Не представляется возможным дать этот критерий в количест- венном выражении не увидев и не проанализировав задачу, кото- рую необходимо решить. Можно сказать лишь, что при решении одной и той же задачи автоматизации одного раздела учета нали- чия и движения средств, регистр накопления будет эффективнее регистра бухгалтерии. Это обусловлено универсальностью реги- стра бухгалтерии, платой за которую является эффективность. ** Количественные оценки очень приблизительны и неточны, и причина этого все та же: невозможно дать универсальные ре- комендации. Правильное решение должно быть результатом оценки каждой конкретной задачи, и осуществляется эта оценка на этапе технического проектирования задачи после детального изучения объекта автоматизации.
Отдельно можно выделить последний критерий: влияние на бухгалтерский баланс. Разделяя учет на бухгалтерский и оперативный, в качестве критерия можно использовать необходимость включения информациЬ с выбранной де- тализацией в сводные формы бухгалтерской отчетности (в первую очередь — бухгалтерский баланс). Приведем пример: в бухгалтерском балансе товары вхо- дят в раздел оборотные активы и отображаются там свер- нуто (без деления по номенклатуре, складам, партиям). Вывод: можно целиком вынести этот аналитический раз- рез в оперативный учет. Еще один пример: в бухгалтерском балансе задолжен- ность контрагентов (перед контрагентами) отображается развернуто по контрагентам. Значит, ведение учета по контрагентам должно выполнятся с помощью субконто плана счетов на регистре бухгалтерии, так как баланс должен строиться только на основании данных, введен- ных методом двойной записи. А если взаиморасчеты еще надо вести в разрезе договоров? Если развернутая инфор- мация по договорам или по срокам погашения задолжен- ности, которая хранится в договоре, используется в ба- лансе, значит? это субконто. А если нет — значит можно вынести учет по договорам в регистры накопления. Принимаем решение: в нашем случае учет МПЗ можно было бы «вынести» в оперативный учет. Отдельно следует рассмотреть возможность использо- вания небалансовых измерений регистра для ведения сквозного аналитического учета для всех (или большин- ства) счетов. Об этих возможностях платформы рассказа- но в разделе «Измерения регистра бухгалтерии», с. 269. Предназначение регистра бухгалтерии В разрезе чего ведется бухгалтерский учет? В разрезе сче- тов бухгалтерского учета, управление которыми осущест- вляется с использованием объекта План счетов. В разрезе объектов аналитического учета, управлять списком кото- рых позволяет объект План видов характеристик. Это как минимум. Возможны и другие разрезы. Где ведется бухгалтерский учет? Где хранятся проводки? Как эти проводки формировать и записывать? Как рас- считываются остатки и обороты по счетам и получаются бухгалтерские отчеты? На все эти вопросы отвечают свойства и методы объекта Регистр бухгалтерии. Но прежде чем приступить к их изучению, давайте договоримся, что будем иметь в виду под «бухгалтерским учетом». Можно приводить различные определения, которыми изобилуют учебники, но нам важно понять отличия этого вида учета от оперативного. У этих двух видов учета мно- го общего, оба вида учета предназначены для решения од- ной и той же задачи: накопления и анализа каких либо показателей в разрезе каких-либо измерений. Основные отличия заключаются в том, как это делается и для чего это делается. В первую очередь, «для чего». Задача оперативного учета — управление (часто опера- тивное, в реальном времени) одним (или несколькими, но не всеми) участком учета предприятия. Задача бухгал- терского учета — управление всей финансово-хозяйст- венной деятельностью предприятия. И решение этой задачи требует использования специфических методов, в первую очередь двойной записи на счетах, которая об- разует замкнутую систему показателей. Итак, приведем основные отличия двух этих видов учета (табл. 9.14) и ответим на вопрос, почему нельзя обойтись только механизмами оперативного учета. Из отличий в видах учета вытекают и отличия в механиз- мах платформы, их реализующих. Необходимость учета всего множества хозяйственных операций предприятия исключает возможность задать однажды состав и струк- туру учетных регистров и не изменять их в процессе ра- боты пользователя. В процессе работы возникают новые виды деятельности, новые хозяйственные операции и, как результат, новые учетные регистры, которые также должны попасть в баланс двойной записи. Причем воз- можность создавать эти новые учетные регистры предоставлена не только программисту, но и пользовате- лю программного продукта. Достигается эта возможность за счет добавления новых счетов в план счетов и опреде- ления для них аналитики, путем выбора вида субконто из списка существующих в конфигурации или добавления новых видов субконто в план видов характеристик. Таблица 9.14. Основные отличия оперативного и бухгалтерского видов учета Критерий Оперативный учет Бухгалтерский учет Охват деятельно- сти предприятия Один или не- сколько участков Вся хозяйствен- ная деятельность Измеритель Любой и зависит от участка В едином денежном выражении Обязательные разрезы учета Отсутствуют Счета бухгалтер- ского учета Показатели Независимые Взаимосвязанные Метод учета Произвольный Двойная запись По свой сути регистр бухгалтерии — это «регистр регист- ров», совокупность регистров. Один регистр бухгалтерии содержит в себе множество учетных регистров (счетов), каждый из которых может иметь независимую аналитику (субконто), в разрезе которой и будут отражаться учет- ные показатели. В целях контроля все учетные регистры (счета) связаны между собой правилом двойной записи, которое образует замкнутую систему показателей: невоз- можно изменить значение показателя одного учетного ре- гистра, не затронув другой, причем на ту же сумму. Счет бухгалтерского учета служит для указания, к какой области учета относится показатель, а набор субконто — измерения, в разрезе которых необходимо его учиты- вать.
Если рассматривать только синтетическую составляю- щую плана счетов, который мы реализовали в нашей кон- фигурации, и вести учет только в денежном выражении, можно интерпретировать наш план счетов в виде сово- купности регистров учета (регистров накопления). При этом каждый счет будет представлен в этой совокупности отдельным регистром учета. Дополнительно должен быть организован еще один регистр, задача которого — хранить обороты между счетами (разделами учета). Таблица Про- водки (обороты) будет создана только в том случае, если используется регистр бухгалтерии с поддержкой коррес- понденций (табл. 9.15). Таблица 9.15. Перечень регистров учета Регистр Измерения Ресурсы Касса Сумма Покупатели Сумма Товары Сумма Материалы Сумма Сотрудники Сумма Поставщики Сумма Капитал Сумма Проводки (обороты) СчетКт СчетКт Сумма Подобный набор регистров накопления позволит пол- ностью реализовать бухгалтерский синтетический учет (учет в денежном выражении в валюте учета на счетах бухгалтерского учета). Пользователь сможет анализиро- вать остатки и обороты по каждому разделу учета, а так- же обороты между счетами. Проводку, представленную в табл. 9.16, можно записать с помощью следующих движений в регистрах учета (табл. 9.17). Таблица 9.16. Пример проводки Дебет Кредит Сумма Касса Капитал 100 Таблица 9.17. Набор движений регистров учета Раздел учета Вид движения Измерения Сумма Касса Приход 100 Капитал Расход 100 Проводки Касса Капитал 100 Полностью план счетов нашей конфигурации можно пред- ставить следующим образом (табл. 9.18 и 9.19). Подобный набор учетных регистров полностью повторит функциональность регистра бухгалтерии, за исключени- ем контроля двойной записи и возможности создания но- вых учетных регистров (счетов) с произвольным набором дополнительных измерений (видов субконто) пользова- телем. Таблица 9.18. Перечень измерений и дополнительных измерений регистров учета Регистр Измерения Дополнительные измерения Касса Органи- зация Валюта Касса (об) Органи- зация Валюта Статьи Покупатели Органи- зация Контр- агенты Товары Органи- зация Номенк- латура Склады Материалы Органи- зация Номенк- латура Сотрудники Органи- зация Сотруд- ники Поставщики Органи- зация Контр- агенты Капитал Органи- зация Проводки (об) Органи- зация Валюта СчетКт СчетКт Таблица 9.19. Перечень ресурсов регистров учета Регистр Ресурсы Касса Сумма Вал сумма Касса (об) Сумма Вал сумма Покупатели Сумма Товары Сумма Количество Материалы Сумма Количество Сотрудники Сумма Поставщики Сумма Капитал Сумма Проводки (об) Сумма Количество Вал сумма Балансовое измерение регистра бухгалтерии Организация позволяет разделить учет на всех участках учета по орга- низациям. Измерение Валюта включено только для счета Касса. Счет Касса потребовал создания двух регистров: од- ного для хранения остатков по счету в целом и еще одно- го для хранения оборотов по статьям (субконто Статьи имеет свойство Только обороты). Приведенная нами в каче- стве примера проводка (Дебет Касса — Кредит Капитал, см. табл. 9.16) теперь может быть интерпретирована таки- ми движениями в регистры учета (табл. 9.20). Подобное «раздвоение» одного счета учета на два (или более) учетных регистра применяется каждый раз, когда используются признаки учета субконто. Если предста- вить, что на счете Товары мы решим для вида субконто Склады снять признак ведения суммового учета (это мо- жет потребоваться для выполнения правила учетной по- литики: расчет себестоимости должен выполняться по
Таблица 9.20. Набор движений регистров учета Раздел учета Вид движения Измерения Ресурсы Касса Приход Организация Валюта 100 руб Ю у.е Касса (об) Организация Валюта Статья 100 руб Ю у.е Капитал Расход Организация 100 руб Проводки (об) Организация Валюта 100 руб Ю у.е Таблица 9.21. Пример учетных регистров для счета Товары Регистр Измерения Дополнительные измерения Ресурсы Товары Организация Номенклатура Сумма Товары Организация Номенклатура Склады Количество номенклатурному номеру без учета складов), то один счет Товары будет представлен в нашей модели двумя учетными регистрами (табл. 9.21). Подобная организация регистров позволит получать ко- личественные остатки каждого номенклатурного номера на каждом складе и суммовые остатки номенклатуры по предприятию в целом. Суммовые остатки и обороты по складу не ведутся. Рассмотренные нам свойства регистра бухгалтерии «на- кладывают отпечаток» на проектирование всей конфигу- рации. Многообразие хозяйственных операций и возмож- ность расширения пользователем состава регистров учета и/или их измерений потребовало обязательное включение в конфигурации документов-регистраторов типа «ручная операция», которые позволяют непосредственно редакти- ровать движения регистра бухгалтерии, используя в про- водках любые счета и аналитику. Кроме универсальных документов-регистраторов, потребуется учитывать осо- бенности регистра бухгалтерии и в других документах, многие из которых должны предоставлять возможность выбора счета (одного или обоих) и/или аналитики. Необходимость анализировать остатки и обороты по новым учетным регистрам и по всем учетным регистрам, включая новые, привело к необходимости разработки в типовом ре- шении универсальной отчетности. Эти отчеты, с одной сто- роны, являются универсальными и позволяют анализиро- вать движения по любым счетам. С другой — сами формы отчетов устоялись за четыреста лет использования двойной записи и не могут быть произвольными по содержанию и расположению строк и колонок отчета: это оборотки, шах- матки, ведомости, ордера, карточки и другие. Анализ таблицы, в которой мы выполнили реализацию нашего плана счетов с использованием регистров накоп- ления, хорошо демонстрирует некоторую «неоптималь- ность»: слишком много «пустых» ячеек... Под измерение Валюта резервируется место и для тех учетных регистров, где валютный учет не ведется. Сделано это для того, что- бы пользователь мог в любой момент сам добавить новый учетный регистр и включить на нем валютный учет. Или же включить валютный учет на любом из предопределен- ных счетов (изменив настройки этого счета в конфигура- торе). Та же ситуация и с ресурсами. Ресурсы Валютная сумма и Количество задействованы не на всех счетах, а ме- сто под них резервируется в любом случае и с той же це- лью, что и для измерения Валюта. Для справедливости надо заметить, что наша таблица не- правильно передает способ хранения дополнительных измерений (субконто) в регистре бухгалтерии. Субконто хранятся иначе, в другой таблице (более подробно о фи- зическом строении регистра рассказано в разделе «Реаль- ные таблицы», с, 280) и хранятся компактно — пустых ячеек там нет. Но в любом случае, платой за универсальность регистра бухгалтерии является некоторое снижение производи- тельности по сравнению с регистрами накопления. По- этому при проектировании задачи бухгалтерского учета очень важно выявить и выделить в оперативный учет те разделы учета, которые требуют хранения и обработки значительного объема информации, особенно информа- ции разнородной (ресурсы) и с большой детализацией (измерения). Если довести эту задачу почти до абсурда, то идеальной организацией бухгалтерского учета можно считать ведение синтетического (на счетах и субсчетах) учета в денежном выражении с незначительной детализа- цией по видам субконто, остатки по которым требуются для формирования баланса. А все остальные виды учета (многовалютный, количественный, подробный аналити- ческий) реализовать, используя механизмы оперативного учета. Вывод: основной результат бухгалтерского учета — баланс, и все что на него не влияет, может быть вынесено в оперативный учет. Выше нами был рассмотрен лишь один раздел науки об управлении предприятием — учет на предприятии, в ко- тором мы выделили подвиды учета оперативный и бух- галтерский (хочется надеяться, что выделили оптималь- но). Однако управление предприятием в целом намного шире и кроме учета свершившихся фактов (чем и занима- ется учет) включает в себя планирование, анализ и мно- гое другое. В этих разделах общей задачей управления также есть место методам бухгалтерского учета и, как следствие, механизмам бухгалтерского учета системы 1 С:Предприятие 8.0. Как заключение, можно сделать вывод, что любая задача, цель которой получение взаимосвязанной системы пока- зателей в виде баланса (в широком смысле этого слова: баланса средств и их источников, баланса оборотов и т. д.), может быть эффективно решена с использованием реги- стра бухгалтерии. Пример: получение прогнозного балан- са в финансовом планировании, получение баланса-нетто в бухгалтерском управленческом учете и т. д.
Объект Регистр бухгалтерии Этот раздел будет посвящен свойствам и методам объек- та Регистр бухгалтерии. Причем, преимущественно, тем ме- тодам, которые позволяют записывать данные в регистр. Методы объекта, предназначенные для чтения данных об остатках и оборотах по счетам, будут рассмотрены нами в разделе «Методы менеджера регистра бухгалтерии», с. 301, посвященным таблицам регистра бухгалтерии и извлечению данных из них. Основные свойства регистра бухгалтерии Создание объекта Регистр бухгалтерии начинается с запол- нения его основных свойств (рис. 9.29). Рис. 9.29. Основные свойства регистра бухгалтерии На закладке Основные выбирается план счетов и признак поддержки корреспонденций. Как планов счетов, так и регистров бухгалтерии может быть несколько, но один регистр бухгалтерии содержит проводки только между счетами одного плана счетов. В то же время на одном пла- не счетов могут основываться два и более регистров бух- галтерии. Пример подобного использования: в разрезе счетов одного и того же плана счетов ведется учет свершившихся хозяйст- венных операций (один регистр бухгалтерии) и планируе- мых операций (бюджетных транзакций в другом регистре бухгалтерии). Наличие между ними единого связующего звена — плана счетов — позволит получить отчеты для план-фактного анализа, а различная структура регистров по- зволит вести каждый вид учета удобно и эффективно. Сравнивая объекты Регистр накопления (или понятие «учет- ный регистр») и Регистр бухгалтерии, можно сказать, что в са- мом простом случае регистр бухгалтерии — это регистр, ко- торый позволяет учитывать значение какого-то (или каких- то, но как минимум одного — сумма в валюте учета) ресурса в разрезе двух «предопределенных» измерений Счет дебета и Счет кредита (или Счет и Вид движения для регистра без под- держки корреспонденций). Это скорее образное сравнение, чем демонстрация физического строения таблиц регистра, однако, по нашему мнению, вполне имеет право на жизнь. Для того чтобы получить самый простой бухгалтерский учет (синтетический: на счетах и субсчетах в денежном выражении в валюте учета), достаточно выбрать в регист- ре бухгалтерии план счетов, установить (или снять) при- знак поддержки корреспонденции и ввести в регистр один-единственный ресурс — сумма, например, в котором и будет храниться сумма проводки. В этом случае провод- ка будет выглядеть так, как показано на рис. 9.30. Регистр бухгалтерии с поддержкой корреспонденции № Дебет Кредит Сумма 1 Касса Капитал 100.00 Рис. 9.30. Реализация принципа двойной записи в регистре бухгалтерии В случае если регистр поддерживает корреспонденцию, то есть реализует привычную для России схему учета, ка- ждая проводка включает два корреспондирующих счета (счет дебета и счет кредита) и ресурс Сумма. При такой ар- хитектуре регистра пользователю будут доступны для анализа остатки и обороты по каждому счету и обороты между счетами. Учетная схема без поддержки корреспонденций может считаться более гибкой и в большей степени удовлетво- ряющей отражению экономической сути хозяйствен- ных операций (хотя бы по тому, что не приходится «ук- ладывать» каждую операцию в «прокрустово ложе» корреспонденций счетов, разбивая движения на кор- респондирующие пары счетов), однако отсутствие кор- респонденции исключает возможность анализа оборо- тов между счетами (табл. 9.22). Таблица 9.22. Отличия учетных схем с поддержкой корреспонденции и без поддержки корреспонденции Критерий Поддержка корреспонденции Включена Выключена Контроль двойной записи В рамках проводки В рамках набора дви- жений регистратора Анализ остатков по счету Да Да Анализ оборотов по счету Да Да Анализ оборотов между счетами Да Нет
ПРИМЕЧАНИЕ Обращаем внимание, что отсутствие поддержки коррес- понденций не означает отсутствие контроля двойной запи- си. В случае, когда корреспонденция поддерживается, кон- троль двойной записи осуществляется в рамках каждой проводки. Если же поддержки корреспонденции нет — в рамках набора записей регистра, принадлежащему одно- му регистратору (рис. 9.31). Контроль двойной записи осуществляется для балансо- вых счетов, балансовых измерений и балансовых ресур- сов. Для регистра без поддержки корреспонденции кон- троль двойной записи осуществляется для балансового ресурса по балансовому измерению (всем сочетаниям ба- лансовых измерений, если их несколько) в рамках набора записей одного регистратора. Регистр бухгалтерии с поддержкой корреспонденции № Дебет Кредит Сумма 1 Касса Капитал 70.00 2 Касса Обяза- тельства 30 00 Регистр бухгаптерии без поддержки корреспонденции № Счет Вид движения Сумма 1 Касса Дебет 100.00 2 Капитал Кредит 70.00 3 Обяза- тельства Кредит 30.00 Рис. 9.31. Контроль двойной записи Данные регистра бухгалтерии Задача любого регистра — учет значений некоторых по- казателей (ресурсов) в разрезе некоторых измерений (счета проводки, измерения регистра и дополнительные измерения регистра — субконто), с возможностью оста- вить дополнительную информацию о каждой записи ре- гистра (реквизиты). Закладка Данные регистра бухгалте- рии позволяет определить все перечисленные свойства (рис. 9.33). Рассказывая о контроле двойной записи, нельзя не расска- зать о свойстве ресурсов и измерений регистра бухгалтерии Балансовый. В процессе настройки регистра бухгалтерии нами был добавлен новый ресурс сумма с установленным свойством Балансовый. Этим же свойством обладают, как видно на рис. 9.32, и измерения регистра. Счета балансо- выми являются по-умолчанию, есть возможность объ- явить их забалансовыми. Рис. 9.33. Данные регистра бухгалтерии Далее мы подробно рассмотрим свойства Измерения и Ре- сурсы регистра бухгалтерии. Реквизиты регистра, с нашей точки зрения, столь подробного описания не требуют. Ре- квизит характеризует лишь запись регистра бухгалтерии и, по сути, является дополнительной информацией, кото- рую можно к этой записи прикрепить (рис. 9.34). Рис. 9.34. Реквизит Содержание Рис. 9.32. Свойство Балансовый По значению реквизита можно получить отбор движе- ний, но нельзя получить остаток или оборот по счету или суб конто. Типичный вариант использования реквизита регистра — содержание проводки, куда пользователь смо- жет написать краткий комментарий к сделанной им про- водке. Надо предостеречь от использования большого числа реквизитов или реквизитов значительной длины.
Несмотря на то что таблицы итогов регистра не вклю- чают в себя реквизиты, таблицы первичных движений будут резервировать под них место и, как результат, уве- личивать объем базы данных. Лучше оставлять всю до- полнительную информацию в документе-регистраторе, который сделал это движение, чем в самом движении. Ресурсы регистра бухгалтерии Если единственным обязательным разрезом ведения бух- галтерского учета являются счета и субсчета, то единст- венное значение, которое в этом разрезе нужно учитывать, это сумма в валюте учета (или валюте составления балан- са, можно сказать и так). Для регламентированного учета этой валютой является национальная валюта. Другими словами, для ведения регламентированного бухгалтер- ского учета достаточно добавить в регистр бухгалтерии один ресурс, который обычно называют Сумма, в который будут записываться значения, выраженные в рублях. Если речь идет об автоматизации нерегламентированного учета, то ничто не мешает в качестве валюты учета вы- брать любую другую. Например, в качестве валюты управленческого учета стараются выбрать наиболее ус- тойчивую валюту или валюту той страны, в которой рас- положены основные деловые партнеры (учредители, ин- весторы). В РФ управленческий учет чаще всего ведется в долларах США и, с недавних пор, в Евро. Рассматривая свойства первого ресурса, который был до- бавлен нами для ведения бухгалтерского учета, следует остановиться на его свойствах. Ресурс регистра бухгалтерии может иметь только число- вой тип, длиной и точностью его мы можем управлять. Свойство ресурса Балансовый Свойство Балансовый влияет на структуру регистра бух- галтерии. Основная цель бухгалтерского учета — баланс. Основывается баланс на методе двойной записи, в соот- ветствии с которым при движении в учете каждое учиты- ваемое значение (в данном случае сумма в валюте учета) должно «проходить» по двум сторонам проводки: по де- бету и по кредиту. При установке свойства Балансовый платформа создаст в регистре бухгалтерии с поддержкой корреспонденции одно новое свойство Сумма. Таким об- разом, заполняя сумму проводки, пользователь указывает и сумму, на которую изменяется дебетуемый счет провод- ки, и ту (ее же) на которую изменяется кредитуемый. Каждый ресурс регистра бухгалтерии создает новый вид учета. Первый созданный нами ресурс «создал» в регистре «учет в денежном выражении в валюте учета». Добавляя новые ресурсы, мы можем увеличить функциональность нашей «бухгалтерии», расширив виды учета, которые можно здесь вести. Например, в случае необходимости ведения учета натуральных показателей в регистр бухгал- терии будет добавлен новый ресурс Количество. Добавляя новый ресурс, задумаемся о смысле этого учета. На отдельных счетах материальных ценностей пользова- тель хочет видеть остатки и обороты по этим счетам не только в стоимостном, но и в натуральном выражении. Само собой разумеется, что контролировать баланс двой- ной записи по этому ресурсу смысла не имеет: во-первых, он будет задействован не для всех счетов (какой экономи- ческий смысл ресурс Количество будет иметь для счета учета наличных денег Касса? Что будет в нем учитывать- ся? Монеты, бумажки, и что будет получаться в итоге от сложения монет и бумажек?). А во-вторых, в этом ресур- се, возможно, будут учитываться движения в различных единицах измерения (учитываться в количественном вы- ражении будут материальные ценности, которые в про- грамме представлены объектами аналитического учета, а они могут храниться в различных единицах измерения). Вывод: баланс не нужен. Значит, ресурс будет небалансо- вым. Небалансовые ресурсы предназначены для ведения вспо- могательных видов учета, которые, по большому счету, можно было бы вообще в бухгалтерии не вести, а вести, например, в отдельных учетных регистрах оперативного учета. Но если уж мы поставили перед собой задачу все виды учета вести в регистре бухгалтерии, инструменты для этого платформа нам предоставляет (рис. 9.35). Рис. 9.35. Ресурс Количество Причем предоставляет возможность не только их создать, но обеспечить пользователя возможностью добавлять но- вые учетные регистры, включая на них различные виды учета (универсальность регистра бухгалтерии!), напри- мер, количественный. Экономический смысл количественного учета, рассмот- ренный нами выше, предполагает, что пользователь дол- жен иметь возможность для каждого счета проводки (и дебетуемого, и кредитуемого) указать свое значение ресурса Количество. При использовании регистра бухгалте- рии без поддержки корреспонденций, в котором дебетуе- мые и кредитуемые счета располагаются в разных запи- сях, в регистр будет добавлено новое поле Количество. Единственным отличием, которого от поля Сумма будет отсутствие контроля двойной записи. То есть при записи набора движений в базу данных платформа разрешит за- писать набор, если итог по ресурсу Количество дебетуе- мых записей не будет равен итогу по этой же графе кре- дитуемых. В регистре бухгалтерии с поддержкой корреспонденции каждая запись включает сразу два счета, положение кото- рых в проводке (дебетуется или кредитуется) и определя- ет вид движения по счету. Чтобы предоставить возмож- ность независимого заполнения ресурса для каждой из сторон проводки, платформа добавляет на каждый неба- лансовый ресурс два поля регистра бухгалтерии, отли- чающиеся постфиксами (Дт и Кт), подсказывающими, к какому счету проводки поле относятся. В данном слу- чае будут добавлены поля КоличествоДт и КоличествоКт.
Надо заметить, что дополнительные виды учета можно создавать, добавляя не только небалансовые ресурсы ре- гистра бухгалтерии, но и балансовые. Примером исполь- зования в регистре бухгалтерии более одного балансового ресурса может служить трехвалютный учет. При таком виде учета предприятие, входя в состав холдинга, вынуж- дено готовить отчетность в двух валютах учета, которы- ми, например, могут быть национальная (для РФ — руб- ли) и валюта учета холдинга (если руководство холдинга европейское, видимо, эта валюта — Евро). Первое решение, которое приходит в голову — это просто взять всю бухгалтерскую отчетность и пересчитать значе- ние каждого ее показателя по курсу на сдачу отчетности. Однако на такое решение могут возникнуть замечания со стороны руководства холдинга — ведь в течение отчетно- го периода соотношения курсов национальной валюты и валюты холдинга менялись, и, как результат, необходимо пересчитывать не итоговые показатели отчетности, а сум- му каждой проводки по историческому курсу (то есть по курсу на дату проводки). Пересчитывать и результат где- то хранить, чтобы можно было быстро получить отчет- ность. Можно было бы пересчитывать каждый раз, а не хранить, но пересчета по историческому курсу будут тре- бовать не только обороты за период, но и входящие остат- ки, то есть считать каждый раз нужно будет с самого на- чала. Поэтому проще в регистр бухгалтерии добавить еще один балансовый ресурс, который, скорее всего, не будет дос- тупен пользователю для заполнения и изменения, а будет рассчитываться при записи набора движений в регистр. И при составлении отчетности нам останется лишь обра- титься к показателям остатков и оборотов по новому виду учета. Свойство ресурса Признак учета Как уже было замечено выше, количественный учет (поч- ти, как и любой другой дополнительный вид учета) имеет смысл не для всех счетов. Таким образом, может возник- нуть необходимость в инструменте, который позволит за- претить заполнять ресурс для тех счетов, по которым ве- дение его не имеет смысла. Это позволит сэкономить время пользователя и исключит ошибки в учете. Решени- ем этой задачи занимается механизм признаков учета. Признаки учета вводятся в плане счетов на закладке Дан- ные. Они всегда имеют тип Булево и, по сути, являются новыми свойствами (специальными реквизитами) счета плана счетов. Количество (и «качество») признаков учета в общем случае должно соответствовать количеству заба- лансовых ресурсов регистра бухгалтерии. Так, например, в случае если в нашей бухгалтерии ведут- ся только два вида учета — Суммовой и Количественный, причем суммовой ведется по всем счетам (по нему со- ставляется баланс), то необходимо создать один признак учета Количественный (рис. 9.36). Признак учета Количественный, созданный на закладке Данные объекта План счетов, позволит отметить (и нам — предопределенные, и пользователю, те которые он ввел в план счетов самостоятельно) счета, требующие ведения количественного учета. Пока это просто новая «галочка», новое свойство счета. П лан счетов 0 сновнойП ланСчето., Основные ► Данные Нумерация Субконто Формы Макеты Подсистемы Ввод на основании Права Интерфейсы Обмен данными Прочее Длина кеда Длина, наименования Маска । кеда Автопорядок Длина по коду порядка в!: Основное представлен 5 В виде кода В виде наименования - С X г аягерим ОсиовнойРегистрБухгалгермм □ 5^ Признаки учета Валютный JMM Рис. 9.36. Признак учета Количественный В Измерения r-t-*. Организация "••• ♦ Валюта EJ- _ Ресурсы — g Сумма — g ВалютнаяСумма СуммаХолдинга ЙК Реквизиты ..Содержание _ а х 13 j [~~Далее> Закрыть Справка t
Чтобы это свойство «заработало», необходимо пометить ресурс регистра бухгалтерии, который зависит от этого признака учета. Для этого предназначено свойство ресур- са регистра бухгалтерии Признак учета. Теперь заполнение ресурса количества возможно только в том случае, если в проводке участвует счет, отмеченный флагом Количественный, и только по той стороне провод- ки регистра с поддержкой корреспонденций, в которой этот счет участвует (рис. 9.37). Рис. 9.37. Использование признака учета Свойство ресурса Признак учета субконто Создавая аналитический учет в нашей конфигурации, мы предусматривали возможность, что отдельные виды уче- та (количественный, валютный), которые задаются в кон- фигурации ресурсами регистра бухгалтерии, включаются на счетах опционально с помощью признаков учета сче- тов. Устанавливая такой признак учета, мы (или пользо- ватель для пользовательских счетов) тем самым предо- ставляем возможность заполнять тот или иной ресурс и в дальнейшем получать остатки и обороты этого ресурса. В случае когда на счете ведется аналитический учет (один или несколько видов субконто), может возникнуть необходимость отключить для одного из видов субконто ведение одного из видов учета. Классическим примером может служить учет материально-производственных за- пасов на складах. Обычно запасы учитываются по цене приобретения. При списании запасов со склада оценка производится по одной из принятых в учете методик (по стоимости приобретения каждого объекта, один из вари- антов расчета средний, FIFO, LIFO). При этом если один и тот же номенклатурный номер хранится на разных складах, то при списании с любого из них стоимость спи- сания надо рассчитать по предприятию в целом. Можно проиллюстрировать учет графически. Рассмот- рим ситуацию, когда предприятие закупает один и тот же вид материально-производственных запасов (МПЗ) по разным ценам. Выполним расчет средней стоимости от- дельно по каждому складу и по предприятию в целом (рис. 9.38). Мы видим, что «средняя», рассчитанная по предприятию в целом (по номенклатурному номеру) и по складу отли- чаются. При расчете стоимости по складу для правильно- го ведения учета необходимо хранить информацию о сум- мовых и количественных (признак учета Количественный) остатках каждого вида МПЗ (аналитический разрез по субконто Номенклатура) на каждом складе (субконто Склады). При расчете стоимости по предприятию учетная схема (признак учета, аналитика) остается без измене- ний: нам по-прежнему необходимо видеть остатки и сум- мовые и количественные по номенклатуре. И по-прежнему нужны остатки по складу... но только количественные (что- бы оценить, хватает ли номенклатуры). Если при расчете себестоимости «по предприятию в целом» оставить суммо- вой учет по складам, то в результате на них после списания всего количества будут оставаться отрицательные и поло- жительные остатки на разницу между суммой оприходо- ванных на склад МПЗ и списанных по средней стоимости. Рис. 9.38. Пример расчета средней себестоимости Учет наличия и движения средств с необходимой степе- нью детализации в целях расчета стоимости при списа- нии и получении оперативной отчетности об остатках и оборотах во многих случаях имело бы смысл вынести в отдельную подсистему оперативного учета. Однако в дан- ном случае, руководствуясь особенностями учета пред- приятия, мы приняли решение реализовать его в регистре бухгалтерии, где предусмотрена возможность отключе- ния отдельных видов учета с отдельных видов субконто на выбранных счетах. Рассмотрим текущую организацию аналитического учета на примере счета учета товаров (табл. 9.23). Таблица 9.23. Учетный регистр Товары Регистр Изме- рения Дополнительные измерения Ресурсы Товары Органи- зация Номенк- Склады латура Сумма Коли- чество Счет товаров ведется как все счета в разрезе балансового измерения Организация и двух видов субконто Номенклатура и Склады. На счете ведется суммовой и количественный учет. Наша задача сводится к тому, чтобы превратить один учетный регистр Товары в два учетных регистра (табл. 9.24).
Таблица 9.24. Ведение количественного учета на счете Товары Регистр Изме- рения Дополнительные измерения Ресурсы Товары Органи- зация Номенк- латура Сумма Товары Органи- зация Номенк- латура Склады Коли- чество Первый из них должен хранить остатки и обороты в сум- мовом выражении в разрезе номенклатуры. Второй дол- жен хранить количественные показатели для каждого номенклатурного номера на каждом складе. Задача реша- ется с помощью признака учета субконто. Задача признака учета субконто — отключить ведение од- ного из видов учета на одном виде субконто одного счета. Признаки учета субконто создаются на закладке Субконто (рис. 9.39). В общем случае, количество признаков учета субконто должно быть меньше или равно количеству ресурсов ре- гистра бухгалтерии. Меньше — потому что не все виды учета, ведущиеся в ресурсах регистра, есть необходи- мость отключать. Чтобы предоставить себе и пользова- телю возможность отключать два вида учета (в нашем случае: суммовой и количественный), для отдельных, субконто необходимо создать два признака учета суб- конто. Для решения нашего примера (расчет стоимости по предприятию в целом) нам было бы достаточно одно- го признака учета субконто Суммовой, который бы позво- лил нам отключить ведение суммового учета с субконто Склады. Каждый признак учета, созданный в объекте План счетов, необходимо «привязать» к ресурсу регистра бухгалте- рии — к тому самому, учетом в котором он будет управ- лять. Когда каждый признак учета «знает» свой вид уче- та, можно перейти к настройке счетов. Каждый признак учета субконто дополнит специальную табличную часть Виды субконто новым свойством (колонкой), которое по- зволит управлять ведением учета. Именно такая настройка счета Товары (см. рис. 9.39) по- зволит решить поставленную задачу только количествен- ного учета товаров на складах. Измерения регистра бухгалтерии Все измерения регистра бухгалтерии можно условно раз- делить на собственно измерения (которым и посвящен этот раздел и которые создаются на закладке Данные свойств регистра бухгалтерии), дополнительные измере- ния (виды субконто) и обязательные измерения (встро- енные, предопределенные, разделы учета — ни одно из этих понятий не является «штатным» описанием меха- низма, но позволяет понять суть явления), которыми для регистра бухгалтерии с поддержкой корреспонденции яв- ляются Счет дебета и Счет кредита, а для регистра без под- держки корреспонденции Счет и Виддвижения (рис. 9.40). Задачи, которые решаются с помощью измерений регист- ра бухгалтерии, как и сами измерения из ветки Измерения закладки Данные регистра бухгалтерии, можно разделить на две группы: ведение раздельных балансов и получение сводной отчетности (балансовые измерения) и разделе- ние отдельных (или всех, но встречается это реже) разде- лов учета по какому-то признаку. Рис. 9.39. Признаки учета субконто
Регистр бухгалтерии 0еиовнойРегистрБдхгаптерии Основные 5 > Данные Регистраторы Формы Макеты Подсистемы Права Интерфейсы Обмен данными [ ДЦ -и» Организация--- - и* Валюта Ресурсы Сумма Количе Ст8о Валют аяСумма Сумма! (одоинга Й-g Реквизить Соаер) ание Б- _ □ X [ Действия •» <Наздц Далез> Закрыть | Спрайт Рис. 9.40. Измерения регистра бухгалтерии Свойство ’Балансовый" измерения регистра бухгалтерии Свойство измерения Балансовый Балансовые измерения делят весь учет (все разделы уче- та) на самостоятельные балансы. Баланс, как известно, — замкнутая система показателей. Поэтому если в процессе конфигурирования было добавлено балансовое измере- ния Организация, значит, по каждой организации (в дан- ном случае список организаций ведется в справочнике Организации) программой будет составлен свой баланс. Это значит, что у каждой организации будут свои активы (касса, расчетные счета, склады и др.), свои обязательства (перед сотрудниками, перед поставщиками) и свой собст- венный капитал. Именно так и никак иначе! Наличие балансового измерения в регистре бухгалтерии совершенно исключает возможность, например, перемес- тить товары с одной организации в другую. По каждой организации ведется свой баланс. А значит, для решения задачи перемещения товаров нужно в одной организации их списать (на какой-нибудь счет расчетов с той, другой организацией), а в другой организации их оприходовать (со счета учета расчетов с первой организацией). Баланс обособленного подразделения 2 Внутрихозяйственные расчеты Аналитика: Подразделение 1 Товары Дт Кт Дт Кт 100.00 Получены товары 100.00 Сводный баланс предприятия Внутрихозяйственные Внутрихозяйственные расчеты. Аналитика: расчеты. Аналитика: Подразделение 2 Подразделение 1 Дт Кт Дт Кт 100.00 100.00 100.00 Закрытие счета расчетов Рис. 9.41. Расчеты с обособленными подразделениями
К слову надо заметить, что в хозрасчетном учете РФ та- кой счет имеет код 79 и называется Внутрихозяйственные расчеты и предназначен для расчетов с обособленными, выделенными на отдельный баланс подразделениями. Схема проводок изображена на рис. 9.41. Мы видим, что закроется счет расчетов только в балансе всего предприятия, как правило, по результатам работы за год, по отдельным же значениям разделителя задол- женность будет оставаться. Эта учетная схема всего лишь один из вариантов ведения учета и была приведена не как руководство к действию, а как демонстрация всей серьезности шага добавления ба- лансового измерения в регистр бухгалтерии. Балансовое измерение добавляет новое поле во все таб- лицы регистра бухгалтерии. При записи набора движе- ний в регистр осуществляется контроль двойной записи по каждому значению (сочетанию значений, если балан- совых измерений несколько) балансового измерения. Небалансовое измерение по своей сути напоминает суб- конто. Так же как и субконто, оно «делит» не все разделы учета на самостоятельные балансы, а лишь некоторые (как правило), или все разделы учета, но баланса по нему полу- чить нельзя. Для регистра без поддержки корреспонден- ции добавляется два поля — по одному на каждую сторону проводки, например ВалютаДт и Вал юта Кт. Для регистра без поддержки поле добавляется одно, но при записи набора движений в регистр контроля двойной записи по каждому значению такого измерения не осуществляется. Небалансовое измерение можно сравнить в субконто, ко- торое в обязательном порядке прикрепили ко всем счетам. Хотя хранение в физических таблицах регистра, которые будут рассмотрены ниже, у них различное, но функцио- нально механизмы небалансовых измерений и субконто похожи (табл. 9.25). Таким образом, можно предложить использование неба- лансового измерения вместо субконто, в том случае, если данный признак аналитики используется на всех (или на подавляющем большинстве) счетов. Более того, можно считать использование в этом случае измерения более оп- тимальным, чем субконто, что связано с типом данных. Приведем пример: организации необходимо вести учет почти всех разделов учета в разрезе источников финанси- рования. Для решения этой задачи можно воспользовать- ся или добавлением субсчетов к нужным (почти всем) счетам, или добавлением на них нового вида субконто, или добавлением в регистр нового небалансового измере- ния. У каждого решения есть свои плюсы и минусы (табл. 9.26). Свойство измерения Признак учета Еще один вариант использования небалансовых изме- рений — добавление нового вида учета, требующего не только учета нового показателя (ресурса), но ведение нового разреза для этого и других (сумма, например) ресурсов. Даже если этот новый вид учета используется далеко не на всех счетах, а место под новое измерение Таблица 9.25. Сравнение небалансовых измерений и субконто Критерий Небалансовое измерение Субконто Компактность хранения в базе Поле резервируется даже для счетов, где измерение не используется Резервируется только в том случае, если субконто на счете используется Тип данных Любой, чаще просто ссылка на справочник Всегда составной, причем состав опреде- ляется для плана видов характеристик Возможность включить/отключить для конкретного счета Да, с помощью признаков учета Да, при подключении вида субконто на счет Всегда на своем месте Да Может быть любым по порядку на счете, и для пользовательских счетов порядок мо- жет быть задан произвольно пользователем Таблица 9.26. Сравнение субсчетов, субконто и небалансовых измерений Решение Плюсы Минусы Субсчета Может потребовать незначительного измерения типового решения, если оно с самого начала пре- дусматривало возможность расширения субсчетов второго или третьего уровня Сложность получения отчетности по одному ис- точнику финансирования и сложность ведения учета из-за значительного числа счетов в плане счетов Субконто Может потребовать незначительного изменения типового решения, если уложиться в максималь- ное число субконто для плана счетов Может потребовать значительных изменений, если все субконто для отдельных счетов уже за- няты и надо увеличивать максимальное число субконто. Увеличение максимального числа субконто может негативно повлиять на производительность Небалансовое измерение Позволит разделить учет оптимально, чем в слу- чае субконто и удобно подготавливать отчетность, как по значению измерения, так и сводно Потребует значительных изменений типового решения
будет все равно резервироваться для всех счетов, ис- пользование механизма небалансовых измерений оп- равдано необходимостью создать универсальный меха- низм, который сможет использовать и пользователь системы. Примером такого использования может служить валют- ный (многовалютый, мультивалютный) учет. Суть учета состоит в том, что для отдельных (не всех) счетов необхо- димо учитывать не только показатели в валюте учета (ре- сурс Сумма), но и в иностранных валютах. Если бы ино- странная валюта была одна, этот вид учета ничем не отличался бы от учета количественного, который мы рас- смотрели в разделе, посвященном признакам учета ресур- са регистра бухгалтерии. Но валют может быть много, и по каждой из них мы хотим видеть остатки и обороты, как в валюте, так и валюте учета. Другими словами, нам необходим разрез по валютам. Развивая тему количественного учета и доводя его до абсурда, можно предложить схожее решение для задачи количественного учета в разрезе единиц измерения. В этом случае к небалансовому ресурсу Количество нам пришлось бы добавить небалансовое измерение Едини- ца измерения и связать их признаком учета, чтобы поль- зователь мог одним щелчком мыши включить новый вид учета на счете. Подчеркнем еще раз — это именно пример абсурдного использования регистра бухгалте- рии. Для решения задач наличия и движения средств с целью управления ими (а не предприятием в целом, как в нашем случае) существуют механизмы оперативного учета. Возвращаясь к задаче ведения валютного учета, который, как правило, является обязанностью бухгалтерии, заме- тим, что кроме справочника Валюты нам потребуется еще один связанный с ним объект — периодический регистр сведений Курсы валют. Регистр будет иметь измерение Ва- люта типа ссылка на справочник Валюты и ресурс Курс типа Число. А если требуется вести учет в валютах с очень маленькими значениями курса, то два ресурса Курс и Кратность, и для получения эквивалента в валюте учета валютную сумму нужно будет сначала умножить на курс, а затем разделить на кратность. Какие изменения коснутся механизмов бухгалтерии? Во- первых, необходимо добавить новый признак учета в пла- не счетов Валютный (рис. 9.42). Он позволит отметить те счета, которые требуют ведения валютного учета. Рис. 9.42. Признак учета Валютный
Во-вторых, добавить новый ресурс регистра бухгалте- рии Валютная сумма, где будет храниться сумма в ва- люте. И в-третьих, добавить новое небалансовое измерение ре- гистра бухгалтерии Валюта — ссылка на элемент справоч- ника Валюты, по которому будет «разделен» учет отмечен- ного признаком счета. Схему взаимодействия объектов можно изобразить графически (рис. 9.43). Результат: по включению одно- го флага в настройках счета для этого счета становятся доступными для заполнения новый ресурс и новое из- мерение. Рис. 9.43. Схема взаимодействия объектов Запись движений в регистр бухгалтерии Регистр бухгалтерии подчинен регистратору, и движения в регистр можно сделать, только указав в движении ссыл- ку на документ-регистратор. Регистратором может яв- ляться любой документ системы. Выбрать документ как регистратор можно или на закладке Регистраторы регистра бухгалтерии (рис. 9.44), или на закладке Движения доку- мента (рис. 9.45). Рис. 9.44. Регистраторы регистра бухгалтерии Рис. 9.45. Движения документа По сути, на этих закладках разных объектов отображает- ся одна и та же информация. Движение в регистр может быть сделано разными способами (мы рассмотрим ниже), но без ссылки на документ-регистратор сделать движение невозможно (рис. 9.46). Рис. 9.46. Движения документа Документ, во-первых, требуется как «ссылка», которая будет прописана в одно из полей регистра бухгалтерии, а во-вторых, документ обладает коллекцией наборов за- писей Движения, которая используется для записи движе- ний в регистры. Коллекция Движения содержит в себе на- боры записей регистров, по которым документ может делать движения. Коллекция содержит столько элемен- тов, для скольких регистров документ является регистра- тором. В приведенном примере коллекция Движения документа Операция содержит всего один элемент Основной Регистр- Бухгалтерии, это набор записей регистра бухгалтерии Ос- новной регистр бухгалтерии. Каждый набор записей может содержать сколько угодно записей одного регистра, под- чиненных документу-регистратору. Изменять набор записей регистра из коллекции Движения можно как из документа, так и из любого другого про- граммного модуля, как интерактивно, так и программно. В любом случае набор записей регистра позволит прочи- тать из базы данных существующий набор записей, изме-
нить его и записать в базу данных одной транзакцией. Можно предложить следующие основные варианты из- менения наборов записей регистра. Интерактивно: ручная операция Одно из отличий бухгалтерского учета от оперативного состоит в том, что он охватывает все предприятие в це- лом. Поэтому автоматизировать все операции, алгорит- мизировав формирование проводок документами факти- чески невозможно. Все равно останутся операции (коррес- понденции счетов), про которые забыли. Поэтому, как правило, при автоматизации бухгалтерского учета авто- матизируется формирование проводок документами толь- ко для регулярно встречающихся операций, а для осталь- ных создается документ Операция, который позволяет пользователю, по сути, редактировать регистр бухгалте- рии «вручную», вводя любые проводки. Документ нам нужен, во-первых, как ссылка, которая бу- дет прописана в поле Регистратор регистра бухгалтерии, а во-вторых, мы задействуем его свойство Движения, содер- жащее набор записей регистра бухгалтерии, который мы хотим разрешить изменять пользователю. Создадим новый документ. В свойствах этого документа на закладке движения мы устанавливаем свойства, как на рис. 9.47. Документ не будет проводиться (Проведение: запретить), это означает, что при записи документа в базу данных не будет выполняться алгоритм проведения документа, рас- положенный в обработчике события модуля объекта Об- работка проведения. Документ будет являться регистратором для регистра бухгалтерии. Установка этого свойства привела к тому, что в коллекции Движения появился набор записей регист- ра бухгалтерии, который позволит изменять регистр бух- галтерии. Заполнять этот набор записей проводками можно разными способами. Поставленная нами задача создания документа Операция предполагает, что набор за- писей будет заполняться пользователем интерактивно, то есть в форме документа. Создавая форму документа, мы размещаем в диалоге формы табличное поле, связанное с данными Движения. ОсновнойРегистрБухгалтерии. Помощник размещения дан- ных, вызванный для табличного поля, позволит добавить в него колонки, соответствующие свойствам регистра бухгалтерии. Часть свойств мы разместим в диалоге формы, часть бу- дем заполнять программно, часть предоставим заполнять платформе. Рассмотрим все свойства нашего регистра подробнее. ♦ Регистратор — ссылка на документ, в нашем случае на документ Операция. Поле составного типа данных, ко- личество типов зависят от того, сколько документов Размещение данных Рис. 9.47. Движения документа Операция
могут являться регистраторами для регистра. Платфор- ма не разрешит сделать движение в регистр «по друго- му регистратору». Поэтому свойство не имеет смысл включать в диалог формы и заполнять программно при проведении или записи регистра, платформа сама запи- шет в него документ-регистратор. ♦ НомерСтроки — номер записи, нумерация начинается с 1. ♦ Активность — свойство записи должно быть одинаковым для всех записей одного регистратора, в противном слу- чае, платформа не разрешит записать набор в регистр. Записи с установленным свойством отражаются в таб- лицах итогах и включаются в виртуальные таблицы ре- гистра бухгалтерии. «Не активные» записи существуют только в таблицах первичных движений и не влияют на бухгалтерскую отчетность. ♦ Период — содержит дату периода, в итоги которого долж- на попасть проводка. Поле не может быть пустым и должно быть обязательно заполнено или интерактивно или программно при записи набора в регистр. Периоды разных записей даже одного набора могут отличаться. Период записи может отличаться от даты докумен- та регистратора. В регламентированном бухгалтерском учете возможность документа записывать проводки да- той, отличной от даты документа, редко находит свое применение, однако можно предположить, что в других разделах учета, таких как управленческий учет и бюд- жетирование, использующих механизмы бухгалтерско- го учета для получения баланса, свойство может приго- диться. ♦ СчетДт, СчетКт — ссылки на счет, который выбран в свой- ствах регистра. Наличие двух счетов в проводке обу- словлено свойством Корреспонденция. ♦ СубконтоДт1, СубконтоДт2, СубконтоКт1, СубконтоКт2 — в свой- ствах плана счетов установлено максимальное количе- ство субконто равным 2, поля составного типа данных, который определен в свойствах плана видов характери- стик, выбранном в плане счетов. ♦ Организация — балансовое измерение регистра, в нашем случае предназначенное для получения отчетности в разрезе самостоятельных организаций (юридических лиц или обособленных подразделений, выделенных на отдельный баланс). Измерение является свойством ка- ждого движения, но в нашем случае мы будем исходить из предположения, что каждая операция в бухгалтер- ском учете должна быть подкреплена первичным доку- ментом и на нем должна быть печать. Причем печать одной организации. Поэтому принимаем решение за- полнять поле Организация одним значением (из шапки документа) для всех записей и делать это программно. ♦ ВалютаДт, ВалютаКт — небалансовое измерение регистра бухгалтерии породило два поля в регистре (для дебето- вой и для кредитовой стороны проводки). ♦ Сунна — балансовый ресурс, един для обоих сторон про- водки. ♦ КоличествоДт, КоличествоКт, ВалютнаяСуннаДт, ВалютнаяСун- маКт — небалансовые ресурсы, свой для каждой стороны проводки. ♦ Содержание — реквизит регистра. Для выбора организации в шапке документа был введен реквизит документа Организация. Записать организацию и дату документа в соответствующие поля записи регистра бухгалтерии позволит обработчик события Перед записью формы или объекта документа. Мы воспользуемся собы- тием объекта, чтобы обрабатывать не только интерактив- ную, но и программную запись документа (листинг 9.14). Листинг 9.14. Обработчик события ПередЗаписью Процедура ПередЗаписьюСОтказ, РежинЗаписи, РежимПроведения) Для каждого Проводка Из Движения. ОсновнойРегистрБухгалтерии Цикл Проводка.Период = Дата; Проводка.Организация = Организация КонецЦикла; КонецПроцедуры Пример заполненного документа Операция представлен на рис. 9.48. Рис. 9.48. Документ Операция Активность Активность — свойство записи регистра, влияющее на от- ражение этой записи в таблицах итогов регистра. Актив- ные записи находят свое отражение в итогах и, как след- ствие, попадают в отчеты, неактивные — нет. Физической организации таблиц регистра посвящен отдельный раз- дел нашей главы, пока же можно заметить, что все таблицы регистра бухгалтерии разделяются на таблицы первич- ных движений (собственно проводки и значения субкон- то этих проводок) и таблицы итогов, которые хранят ин- формацию об остатках и оборотах на счетах и субконто сгруппировано по месяцам. Физические таблицы могут быть использованы разработчиком для написания запро- сов, но используются как источник данных редко. Табли- цы итогов как источники данных запроса недоступны и являются (вместе с таблицами первичных движений) ис- точниками данных при создании платформой виртуаль- ных таблиц регистра бухгалтерии. Именно они и служат источниками данных для большинства отчетов. Вирту- альные таблицы включают (как правило) только актив- ные записи. Таким образом, активность — это свойство записи, позво- ляющее пользователю системы проанализировать «...а что было бы, если этой проводки не было бы...». Проводка с выключенной активностью не удаляется из базы данных. Если сравнивать удаление движения и отключение ак- тивности этого движения, то разница будет заметна в первую очередь на документах, которые формируют дви- жения автоматически при проведении. Сделав такой доку- мент непроведенным, удалив все движения, пользователь, конечно, сможет проанализировать данные отчетов «без
этого документа». Но включение этого документа обрат- но в учет потребует его перепроведения, при котором движения будут сформированы заново и новые... то есть существует вероятность, что повторное исполнение алго- ритма проведения в возможно изменившихся условиях приведет к формированию других движений. Если же воспользоваться свойством Активность, то по- вторное включение документа в учет не потребует его пе- репроведения. Старые проводки не были удалены, они просто были исключены из итогов. При включении ак- тивности в итоги будут включены те же проводки, кото- рые были выключены, а не новые. Листинг 9.15 содержит процедуру, которая может быть расположена в модуле формы документа, и позволяет управлять активностью записей регистра. Листинг 9.15. Пример процедуры, переключающей активность записей Процедура ВключитьВыключитьПроводки(Кнопка) Проводки = Движения.ОсновнойРегистрБухгалтерии; КоличествоПроводок = Проводки.КоличествоО: Если КоличествоПроводок > 0 Тогда Проводки.УстановитьАктивность(НЕ Проводки[0].Активность); КонецЕсли; КонецПроцедуры Процедура получает активность первой записи из набора (с индексом 0), инвертирует ее (НЕ) и устанавливает полу- ченную в результате активность для всего набора. Рассмотрим еще один вариант использования этого свой- ства движения на примере документа Операция. Операция не хранит в себе движения, а лишь объединяет их одним регистратором, которым и является. Документ не про- водится (не выполняет алгоритм проведения документа) и поэтому не может быть снят с проведения. При уста- новке на документ пометки на удаление записи в регист- ре остаются неизмененными, то есть даже удаленная опе- рация продолжает участвовать в учете. Поставим задачу — удаленная операция не должна участвовать в учете, не должна попадать в отчеты. Но должна быть возможность, сняв пометку на удаление, вернуть ее в учет. Для этого воспользуемся свойством Активность движения регистра. При установке пометки удаления документа бу- дем снимать активность записей, при снятии пометки на удаление — восстанавливать активность записей (лис- тинг 9.16). Листинг 9.16. Управление активностью записей при установке/снятии пометки удаления документа Процедура ПередЗаписью(0тказ. РежимЗаписи, РежимПроведения) Проводки = Движения.ОсновнойРегистрБухгалтерии; НужноСчитатьНабор = (НЕ Ссылка.Пустая() И НЕ Проводки.МодифицированностьО И НЕ Проводки.Выбран()); Если НужноСчитатьНабор Тогда Проводки. ПрочитатьО; КонецЕсли: КоличествоПроводок = Проводки.КоличествоО: Если КоличествоПроводок > 0 Тогда ТекущаяАктивностьПроводок = Проводки[0].Активность; НужнаяАктивностьПроводок = НЕ ПометкаУдаления: Если ТекущаяАктивностьПроводок о НужнаяАктивностьПроводок Тогда Проводки.УстановитьАктивность( НужнаяАктивностьПроводок); КонецЕсли; КонецЕсли; КонецПроцедуры Прокомментируем работу процедуры. Обработчик собы- тия Перед записью объекта документа выполняется перед каждой записью документа. Отметка о проведении доку- мента является свойством документа. После изменения этого свойства платформа производит запись документа в базу. Процедура получает на переменную Проводки на- бор записей регистра документа. Запись движений в ре- гистр осуществляется в разных ситуациях. Это может быть интерактивная запись нового документа пользо- вателем, запись измененного документа пользователем, удаление или снятие пометки удаления документа. Документ в момент открытия формы считывает набор за- писей из регистра бухгалтерии. Если форму не открывали, а установка пометки удаления осуществляется без откры- тия формы, необходимо прочитать из информационной базы набор записей регистра. Необходимость считывать набор из регистра определяется совпадением трех усло- вий: ♦ этот документ не новый, если он новый, то набор запи- сей документа еще не записан в базу, а находится в до- кументе; ♦ набор записей регистра не был изменен, если он был из- менен, то считывание его из базы затрет изменения пользователя; ♦ набор еще не считывался из базы данных, что позволя- ет узнать метод ВыбранО. Если все три условия присутствуют, считываем из реги- стра набор записей и выполняем действия с ним. Прове- рив количество движений в наборе записей, мы получаем текущую активность движений набора записей по первой записи и устанавливаем нужную активность для набора записей. Программно, при проведении документа Формирование и запись проводок в момент проведения документа можно считать основным вариантом измене- ния регистра бухгалтерии. В отличие от документа Опера- ция, запись проводок при проведении позволяет описать сложный алгоритм формирования проводок, вычисление сумм и обусловленное заполнение других свойств запи- сей и используется для автоматизации ввода часто встре- чающихся в практике учета операций. В этом случае заполнение набора записей регистра осу- ществляется в обработчике события проведения доку- мента Обработка проведения. Несложный алгоритм прове- дения, использующий при заполнении свойств движений преимущественно значения реквизитов документа, можно разработать с использованием конструктора движений.
@ Документ ПриходнаяНаклааная Основные Данные Нумерация ► Движения Послвйоепте.^пхтж Журналы Формы Макеты Подсистемы Ввод на основании Права Интерфейсы Обмен данными Прочее I Конструктор движений Действия » < Назад Далее> Закрыть Справка □ X ОсновнойРегистрБухгалтерии 'О® Бюджет Проведение: Разрешить Оперативное проведение: Запретить * Удаление движений Удалять движ § Документ ПрнходнаяНак ладная Основные Данные Нумерация Движения Последовательности Журналы ► Формы Макеты Подсистемы Ввод на основании Права Интерфейсы Обмен данными Прочее Основные Формы--------------------- Списка х Q Выбора '|Дх Доку мента Ф орма ДокуменГ- ] х: Q Ввод по строке Номер J^]x t * t Действия •] i <Наэад Далее>~~~] |__________Закрыть”] £ Справка______ Рис. 9.49. Данные документа ПриходнаяНакладная _ П х Рассмотрим его работу на примере документа Приходная- Накладная. Документ предназначен для ввода проводок закупки товаров у поставщика. В шапке документа поль- зователь сможет выбрать организацию (из справочника Организации), поставщика (из справочника Контрагенты) и склад (из справочника Склады). В табличной части будут выбираться товары (из справочника Номенклату- ра), вводиться цена покупки, количество и сумма товара (рис. 9.49). Форма документа включает все перечислен- ные реквизиты. Конструктор движений документа Алгоритм проведения такого документа может быть пол- ностью сформирован конструктором движений докумен- та, вызываемым по кнопке Конструктор движений с заклад- ки Движения свойств документа (рис. 9.50). Рис. 9.50. Конструктор движений регистров
Результатом работы конструктора (убраны только ком- ментарии) будет процедура в модуле объекта (лис- тинг 9.17). Листинг 9.17. Процедура ОбработкаПроведения Процедура 06работкаПроведения(0тказ, Режим) Для Каждого ТекСтрокаТовары Из Товары Цикл // регистр ОсновнойРегистрБухгалтерии Движение = Движения.ОсновнойРегистрБухгалтерии. ДобавитьО; Движение.СчетДт = ПланыСчетов.ОсновнойПланСчетов. Товары: Движение.СчетКт = ПланыСчетов.ОсновнойПланСчетов. Поставщики: Движение.Период = Дата; Движение.Организация = Организация; Движение.Сумма = ТекСтрокаТовары.Сумма: Движение.КоличествоДт = ТекСтрокаТовары.Количество: Движение.Содержание = "Покупка товара"; Движение.СубконтоДт[ПланыВидовХарактеристик. ВидыСубконто.Номенклатура] = ТекСтрокаТовары.Номенклатура; Движение.СубконтоДт[ПланыВидовХарактеристик. ВидыСубконто.Склады] = Склад: Движение.СубконтоКт[ПланыВидовХарактеристик. ВидыСубконто. Контрагенты] = Поставщик; КонецЦикла; // записываем движения регистров Движения.ОсновнойРегистрБухгалтерии.Записать(); КонецПроцедуры В цикле по табличной части Товары в набор записей реги- стра бухгалтерии, расположенный в коллекции движе- ний, добавляется новое движение. Далее заполняются свойства записи регистра. После завершения цикла про- изводится запись движений в базу данных. В этот типо- вой алгоритм, сформированный конструктором, можно было бы внести изменения. Возможен альтернативный вариант синтаксиса при за- полнении субконто проводки. Используемый конструк- тором — универсальный и больше подходит в документах, где счет выбирается в диалоге пользователем (лис- тинг 9.18). Листинг 9.18. Пример установки значения субконто Движение.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконто. Контрагенты] = Поставщик; В этой строке обращение к элементу коллекции субконто кредита проводки производится с использованием опера- тора «[ ]», в который в качестве параметра необходимо передать ссылку на вид характеристик. В нашем случае ссылки на элементы плана счетов получаются по неизме- няемым именам счетов и поэтому можно было бы ис- пользовать упрощенный синтаксис (листинг 9.19). Листинг 9.19. Пример установки значения субконто Движение.СубконтоКт.Контрагенты = Поставщик; Метод набора записей ЗаписатьО не является обязатель- ным и даже желательным. После записи документа плат- форма осуществит автоматическую запись всех изменен- ных наборов записей, хранящихся в свойстве Движения. Этой автоматической записью мы воспользовались, на- пример, в предыдущем примере — документ Операция. Принудительная запись движений в регистр, вызванная методом ЗаписатьО, в нашем случае не приведет к повтор- ной записи движений в регистр, так как на момент про- верки необходимости автоматической записи набор уже не будет изменен. Дополнительным плюсом автоматиче- ской записи можно считать строго одинаковый порядок записи наборов в базу данных, следовательно, блокиров- ка таблиц также происходит всегда в одинаковом поряд- ке. Подробнее об этом можно прочитать в разделе «Еди- ный порядок доступа к ресурсам», с. 725. Оперативное и неоперативное проведение Оперативность — это свойство документа, используемое в первую очередь при решении задач оперативного учета в реальном времени. Бухгалтерия редко работает в реальном времени. Как правило, бухгалтер работает со свершивши- мися событиями, обрабатывая первичные документы за отчетный период. Поэтому свойство документа Оператив- ное проведение обычно при решении задач бухгалтерского учета устанавливают в значение Запретить. Тем не менее, практика автоматизации учета малых предприятий пока- зывает частое использование механизмов бухгалтерского учета для решения задач учета оперативного, поэтому мы кратко рассмотрим это свойство и возможности его ис- пользования. Подробнее об оперативном учете можно про- читать в разделе «Оперативный учет. Описание задач, ре- шаемых регистрами накопления», с. 177. Установленное свойство Оперативное проведение позво- лит контролировать ввод документов задним числом и запретить ввод документов будущей датой. При по- пытке ввода будущей датой пользователю будет выда- но предупреждение и отказано в проведении документа (рис. 9.51). 1 С: Пред приятие X Дета оперативно документа больше текущей. Документ не может быть проведен Рис. 9.51. Предупреждение о невозможности оперативного проведения При вводе документа задним числом пользователю пред- ложат провести документ в неоперативном режиме (рис. 9.52). Рис. 9.52. Выбор неоперативного проведения При перепроведении существующего документа пользо- вателю будет задан дополнительный вопрос о необходи- мости оперативного или неоперативного проведений до- кумента (рис. 9.53).
Рис. 9.53. Выбор режима проведения Пользователь может или согласиться с необходимостью провести документ оперативно. И тогда дата и время до- кумента будут изменены на текущие. Или отказаться от оперативного проведения, и тогда документ будет запи- сан в базу с существующей датой и временем. В любом случае на второй параметр процедуры Обработка проведения будет передано значение системного перечис- ления РежинПроведенияДокумента Оперативный или Неоперативный, которое и может анализировать разработчик конфигура- ции с целью принятия решения о способе проведения до- кумента. Основная задача, которую может помочь решить разде- ление проведения документа на оперативное и неопера- тивное, — это сокращение времени на проведение доку- мента, в случае, если документы вводятся в реальном времени и в правильной (реальной, соответствующей событиям в реальной жизни) хронологической последо- вательности. Время на проведение документа всегда яв- ляется критичным фактором в оценке удобства эксплуа- тации системы. Особенно если в ней работает большое число пользователей и особенно если они работают в ре- альном времени. Рассматриваемая нами в качестве примера приходная на- кладная навряд ли может улучшить свою работу, ведь всю необходимую для проведения информацию она со- держит в себе и не обращается к другим объектам базы данных. А вот, например, расходная накладная, списывая товар, обязательно должна проверить его наличие по дан- ным учетных регистров (в нашем случае, счета товары ре- гистра бухгалтерии), рассчитать себестоимость и многое другое. В большинстве случаев извлечение данных из базы выполняется с помощью запроса (исключение может составлять лишь получение одного значения, тогда до- пускается использование метода объекта). Физическая организация таблиц регистра бухгалтерии (более подроб- но об этом пойдет речь ниже) позволяет наиболее быстро выполнить запрос к актуальным итогам. Актуальные ито- ги хранятся в регистре и пересчитываются при любом движении в регистре. Но в каком случае мы можем воспользоваться этими актуальными итогами? Тогда и только тогда, когда уве- рены, что, во-первых, не вводились документы будущей датой и, во-вторых, документ вводится с текущим вре- менем и, стало быть, надо «снимать» актуальные итоги. В случае же если документ вводится задним числом, для оценки возможности его проведения, расчета остат- ков и себестоимости обязательно нужно получить не актуальные итоги, а итоги на момент времени доку- мента. Таким образом, если стоит задача учета документов в ре- альном времени и большинство документов вводятся в правильной хронологической последовательности, опе- ративное проведение может существенно сократить вре- мя на проведение и улучшить работу пользователей. Автоматическое удаление движений Свойство документа Удаление движений устанавливается на закладке Движения и может принимать два значения: Уда- лять движения автоматически или Не удалять движения автома- тически. Автоматическое удаление движений выполняется плат- формой при повторном проведении документа перед за- писью новых движений, а также при удалении и отмене проведения документа. Режим автоматического удале- ния является основным. Отключение этого режима имеет смысл, прежде всего, при решении задач оперативного учета в реальном времени. Один из вариантов использования документа с отклю- ченным автоматическим удалением движений — построч- ное проведение документа. При решении задачи автома- тизации учета продавцов товаров в реальном времени это свойство может быть актуально. Представим себе ситуа- цию, что два менеджера продают один и тот же товар, ко- личество которого ограничено. Пока первый из них, удо- стоверившись в наличии товара на складе по данным регистра, проводит свой документ с установленным свой- ством Автоматическое удаление движений, второй менеджер за те мгновения, когда старые движения уже удалены, а новые еще не записаны, успевает провести свой доку- мент. Научившись на горьком опыте, первый менеджер начина- ет нажимать на кнопку Провести после добавления каж- дой строки документа. Но при проведении каждый раз удаляются все ранее сформированные записи в регистре и формируются новые. И между этими двумя событиями все равно остается временной лаг, достаточный для спи- сания товара вторым менеджером. Решение этой проблемы — построчное проведение доку- мента первым менеджером, при котором запись по новой строке добавляется в регистр без удаления всех ранее сде- ланных. В этом случае контроль удаления записей при прове- дении документа в целом, отмене проведения и удале- нии документа лежит на программисте, разрабатываю- щем этот документ. Мы рассмотрели эти темы поверхностно по одной и той же причине: бухгалтерский учет почти никогда не требу- ет работы пользователей в реальном времени. Программно без проведения документа Документ может иметь движения в регистре и не будучи проведенным. Для записи движений в регистр можно ис- пользовать или свойство документа Движения, содержащее коллекцию наборов записей, или набор записей регистра бухгалтерии. Этот вариант формирования движений в регистр нельзя считать основным. Его можно рекомендовать для офф- лайнового проведения документа, когда в реальном вре-
мени документ проводится в оперативном учете, а отра- жение операции в бухгалтерском выполняется в конце отчетного периода. В этом случае можно предложить один из следующих вариантов (листинг 9.20). Листинг 9.20. Пример записи движений документа Приходные = Документы.ПриходнаяНакладная.ВыбратьО; Пока Приходные.Следующий) Цикл ПриходнаяОбъект = Приходные.ПолучитьОбъектО; Проводки = ПриходнаяОбъект.Движения. ОсновнойРегистрБухгалтерии; НоваяПроводка = Проводки.ДобавитьО; НоваяПроводка.Период - ПриходнаяОбъект.Дата; НоваяПроводка.Организация = ПриходнаяОбъект.Организация; НоваяПроводка.СчетДт = ПланыСчетов.ОсновнойПланСчетов. Товары; НоваяПроводка.СчетКт = ПланыСчетов.ОсновнойПланСчетов. Поставщики; НоваяПроводка.Сумма = ПриходнаяОбъект.Всего: Проводки.Записать(Ложь); КонецЦикла; Предложенный выше код может располагаться в любой обработке. Программный код получает из базы данных выборку документов и для каждого из них, создавая объ- ект документа, выполняет заполнение набора записей движениями и запись его в регистр добавлением к тем за- писям, которые уже существуют в регистре. В приведен- ном примере для записи движений в регистр использует- ся свойство документа Движения. Можно не использовать его, а воспользоваться набором записей регистра бухгалтерии. Следующий фрагмент кода выполняет ту же задачу, но с использованием объ- екта РегистрБухгалтерииНаборЗаписей.ОсновнойРегистрБухгал- терии (листинг 9.21). Листинг 9.21. Пример записи движений документа Приходные = Документы.ПриходнаяНакладная.ВыбратьО; Проводки = РегистрыБухгалтерии.ОсновнойРегистрБухгалтерии. СоздатьНаборЗаписейО; Пока Приходные.Следующий() Цикл ПриходнаяСсылка = Приходные.Ссылка; Проводки.Отбор.Регистратор.Установить(ПриходнаяСсылка); НоваяПроводка = Проводки.Добавить(); НоваяПроводка.Период = ПриходнаяСсылка.Дата; НоваяПроводка.Организация = ПриходнаяСсылка.Организация; НоваяПроводка.СчетДт = ПланыСчетов.ОсновнойПланСчетов. Товары; НоваяПроводка.СчетКт = ПланыСчетов.ОсновнойПланСчетов. Поставщики; НоваяПроводка.Сумма = ПриходнаяСсылка.Всего; Проводки.Записать(Ложь); КонецЦикла; При использовании набора записей регистра от докумен- та нам нужна ссылка, чтобы по ней установить отбор в на- боре записей. Затем, используя методы набора записей регистра, мы добавляем нужную запись в набор записей и записываем его с добавлением. Оба варианта кода предусматривают возможность непро- веденного документа иметь движения. Необходимо, од- нако, учитывать, что повторное проведение документа штатным способом (интерактивно из формы или про- граммно методом документа Записать(РежимЗаписиДокумен- та.Проведение)) не будет учитывать наличие добавленной нами записи. Так, например, если в свойствах документа установлено свойство автоматического удаления движе- ния, будет удалено и дополнительное, сделанное обработ- кой движение. А при формировании движений из проце- дуры Обработка проведения не будет добавлено движение, описанное в обработке. Чтение данных регистра бухгалтерии Для чтения данных регистра бухгалтерии в системе 1С:Предприятие 8.0 предусмотрены методы объекта Ре- гистр бухгалтерии и набор таблиц, используемых запросом как источники данных. Основным способом извлечения данных в системе является запрос. Мы полагаем, что это утверждение актуально и для регистра бухгалтерии, по- этому начнем изучение подходов к извлечению данных об остатках и оборотах на счетах с изучения таблиц реги- стра — источников данных запроса. Методы объекта, ко- торые можно считать вспомогательным механизмом, бу- дут рассмотрены позднее. Таблицы регистра бухгалтерии Регистр бухгалтерии — сложный объект, представленный в табличной модели данных рядом таблиц (рис. 9.54). Все таблицы регистра бухгалтерии можно разделить на две группы: реальные и виртуальные. Реальные таблицы предоставляют доступ посредствам запроса к физически существующим в информационной базе таблицам. У ре- гистра бухгалтерии таких таблиц две: основная таблица и таблица значений субконто, которая создается в инфор- мационной базе после добавления в конфигурацию меха- низмов аналитического учета. Реальные таблицы Имя основной таблицы регистра бухгалтерии содержит имя регистра, и для использования ее в качестве источни- ка данных в нашем случае необходимо написать следую- щее предложение (листинг 9.22). Листинг 9.22. Обращение к таблице записей регистра бухгалтерии ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии Основная таблица регистра бухгалтерии с поддержкой корреспонденции содержит следующие поля (табл. 9.27).
Рис. 9.54. Таблицы запросов регистра бухгалтерии Основная таблица регистра бухгалтерии без поддерж- ки корреспонденции отличается отсутствием корреспон- денции счетов и отсутствием деления измерений на ба- лансовые и небалансовые, которые в таблице регистра с поддержкой корреспонденции были представлены двумя полями — свое для дебета, и свое для кредита. Основная таблица хранит проводки (движения регистра бухгалтерии) без данных аналитического учета. Для хра- нения данных аналитического учета предназначена вто- рая реальная таблица регистра бухгалтерии — таблица значений субконто. Эта таблица не содержит числовых характеристик и навряд ли может использоваться само- стоятельно. В таблице хранится информация о виде и значении каждого субконто проводки. Для получения полной информации о проводке (включая данные анали- тического учета) система соединяет данные таблицы за- писей и таблицы значений субконто по периоду, регист- ратору и виду движения. Субконто платформой хранятся компактно, и количество полей этой таблицы не зависит от количества субконто на счете. Чем больше субконто описано в проводке, тем больше записей будет содержать таблица значений субконто. Одной проводке из основной таблицы может соответствовать несколько записей таб- лицы значений субконто. Обращение к таблице значений субконто в нашем случае будет выглядеть так (лис- тинг 9.23). Таблица значений субконто регистра бухгалтерии содер- жит следующие поля (табл. 9.28). Таблица 9.27. Поля основной таблицы регистра бухгалтерии Поле Тип Комментарий Период Дата Дата движения Регистратор ДокументСсылка.<иня> Документ движения МоментВремени МонентВренени Момент времени документа НомерСтроки Число Номер движения в наборе записей Активность Булево Участвует ли запись в таблицах итогов СчетДт ПланыСчетовСсылка.«иня» Дебетуемый счет СчетКт ПланыСчетовСсылка.«иня» Кредитуемый счет «Измерение» Определяется типом измерения Балансовое измерение регистра бухгалтерии «Измерение»Дт Определяется типом измерения Небалансовое измерение регистра бухгалтерии создает два поля в регистре «Измерение»Кт Определяется типом измерения «Ресурс» Число Балансовый ресурс регистра бухгалтерии «Ресурс»Дт Число Небалансовый ресурс регистра бухгалтерии создает два поля в регистре «Реквизит» Определяется типом реквизита Характеристика движения регистра Таблица 9.28. Поля таблицы значений субконто Поле Тип Комментарий Период Дата Дата движения Регистратор ДокументСсылка.«имя» Документ движения Моментвремени Моментвремени Момент времени документа НомерСтроки Число Номер движения в наборе записей ВидДвижения ВидДвиженияБухгалтерии Дебет или Кредит ВидСубконто ПланВидовХарактеристикСсылка.«имя» Вид субконто Значение Характеристика.«имя» Значение субконто
Листинг 9.23. Обращение к таблице значений субконто ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Субконто В регистре без поддержки корреспонденции отсутствует поле ВидДвижения. Виртуальные таблицы Реальные таблицы регистра бухгалтерии малопригодны для формирования большинства бухгалтерских отчетов и являются скорее вспомогательным механизмом. Для по- строения отчетов и анализа данных в большинстве случаев используются виртуальные таблицы. Эти таблицы не хра- нятся в информационной базе и создаются системой при обращении к ним. По своей сути это вложенные запросы. Запросы выполняются системой к физическим таблицам регистра бухгалтерии, о которых мы расскажем ниже. Виртуальные таблицы параметризированы: обращаясь к ним, мы можем передать в качестве параметров условия выполнения запроса. Виртуальные таблицы узкоспециа- лизованы и предназначены для решения конкретных за- дач, поэтому проще изучать их исходя из задач, которые с их помощью можно решить. Таблица остатков Для получения остатков по счетам в разрезе субконто и измерений используется таблица остатков. Эта таблица позволит решить такие задачи, как получение количест- венных и суммовых остатков материально-производ- ственных запасов при их списании, определение остат- ка задолженности для выполнения зачета аванса, расчет амортизации и курсовых разниц и многие другие, где тре- буется узнать остаток какого-либо ресурса по счету, суб- конто или измерению, свернутый или развернутый. Таб- лица не отличается для регистра с поддержкой и без поддержки корреспонденции. Использование таблицы остатков в качестве источника запроса представлено в листинге 9.24. Листинг 9.24. Обращение к таблице Остатки ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки После имени таблицы в круглых скобках могут (и в боль- шинстве случаев — будут) указываться параметры, за- дающие условия отбора данных из физических таблиц информационной базы. Рассмотрим поля виртуальной таблицы остатков. ♦ Счет — это поле имеет тип ПланСчетовСсылка.<иня>. Поле позволяет получить остатки, сгруппированные по сче- там. ♦ Субконто<М> — это поле имеет тип Характеристика.<иия>. Количество полей Субконто зависит от максимального количества субконто на счете плана счетов. Поле позво- ляет получить остатки, сгруппированные по значениям субконто. ♦ <Изнерение> — тип этого поля задается при создании из- мерения регистра. Количество полей зависит от коли- чества измерений, объявленных в регистре бухгалте- рии. На поле не влияет свойство измерения Балансовый. Поле позволяет получить остатки, сгруппированные по измерениям регистра. ♦ <РесуроОстаток — это поле имеет тип Число. Абсолют- ный остаток (как он хранится в физических таблицах информационной базы) без учета вида счета — дебе- товый остаток показывается положительным числом, кредитовый — отрицательным числом. ♦ <Ресурс>ОстатокДт — это поле имеет тип Число. Дебето- вый остаток с учетом вида счета. Если счет пассивный, значение этого поля всегда равно нулю. Если счет ак- тивный, значение поля равно значению поля Остаток. Если счет активно-пассивный, значение поля равно значению поля Остаток, если Остаток больше или равен нулю. Если Остаток меньше нуля, значит — ноль. ♦ <Ресурс>ОстатокКт — это поле имеет тип Число. Кредито- вый остаток с учетом вида счета. Если счет активный, значение этого поля всегда равно нулю. Если счет пас- сивный, равно «- Остаток». Если счет активно-пассив- ный, значение поля равно нулю, если значение поля Ос- таток больше или равно нулю. Если значение поля Остаток меньше нуля, значение этого поля равно «- Ос- таток». ♦ <Ресурс>Развернутый0статокДт — это поле имеет тип Чис- ло. Развернутый дебетовый остаток. Имеет смысл толь- ко при использовании в запросе итогов. Для детальной записи значение этого поля равно значению поля Оста- токДт. Для итоговой — сумме дебетовых остатков всех детальных записей. ♦ <Ресурс>Развернутый0статокКт — это поле имеет тип Чис- ло. Развернутый кредитовый остаток. Имеет смысл только при использовании в запросе итогов. Для де- тальной записи значение этого поля равно значению поля ОстатокКт. Для итоговой записи равно сумме кре- дитовых остатков всех детальных записей. В физических таблицах регистра хранится абсолютный остаток (поле <Ресурс>Остаток), все остальные рассчиты- ваются при формировании системой виртуальной табли- цы остатков. Алгоритм расчета полей ОстатокДт и Оста- токКт можно представить в виде схемы (рис. 9.55). Рис. 9.55. Алгоритм расчета полей ОстатокДт и ОстатокКт При обращении к полям ОстатокДт или ОстатокКт система в первую очередь проверяет наличие в запросе группи- ровки (или отбора) по счету. Если такой разрез в запросе
есть и этот счет один, вычисление полей зависит от вида счета. В случае если используемый в запросе счет актив- ный, система отображает в поле ОстатокДт значение поля Остаток, кредитовый остаток для активного счета всегда равен нулю. Если используемый в запросе счет пассив- ный, значение поля ОстатокКт будет равно значению поля Остаток с обратным знаком («Остаток»), дебетовый оста- ток для пассивного счета всегда равен нулю. При расчете полей остатков активно-пассивного счета система дополнительно будет анализировать знак остат- ка. Если поле Остаток содержит положительное число, остаток будет интерпретирован системой как ОстатокДт, если отрицательное — как ОстатокКт. В случае если в запросе нет разреза по счету или в качест- ве условия используется отбор по списку счетов, то поля ОстатокДт и ОстатокКт рассчитываются по правилам актив- но-пассивного счета. Алгоритм формирования развернутых остатков счета мы рассмотрим более подробно ниже. Параметры виртуальной таблицы остатков позволяют за- дать условие отбора данных из информационной базы. Параметры следует задавать строго в порядке их опи- сания. ♦ Период — имеет тип значения Дата, МоментВремени или Гра- ница. На этот момент будут рассчитаны остатки вирту- альной таблицей. Если параметр не задан, будут полу- чены актуальные остатки, включающие движения последнего проведенного документа. Физическая орга- низация таблиц позволяет максимально быстро полу- чить остатки за месяц (на начало следующего месяца) и актуальные остатки. ♦ Счет — содержит конструкцию языка запросов. Позво- ляет установить фильтр по счету или счетам. Как пра- вило, содержит следующие условия: Счет = (В ИЕРАРХИИ, В) &Счет. ♦ Субконто — имеет тип ПланВидовХарактеристикСсылка.<иия> или содержит массив значений типа ПланВидовХарактери- стикСсылка.<имя>. В этот параметр таблицы можно пере- дать ссылку на вид субконто для получения отбора по этому виду или массив видов для установки отбора и упорядочивания видов субконто в результате запроса. ♦ Условие — содержит конструкцию языка запросов. По- зволяет устанавливать отбор данных виртуальной таб- лицей по значениям субконто и измерений регистра бухгалтерии. Рассмотрим примеры построения запросов к таблице ос- татков регистра бухгалтерии. При необходимости получить количественный остаток конкретного товара со счета товаров можно использовать следующий код (листинг 9.25). Листинг 9.25. Пример получения остатка товара ВЫБРАТЬ Остатки.КоличествоОстаток ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки( &Момент, Счет = &СчетТоваров, Организация = (^Организация И Субконто! = ^Номенклатура) КАК Остатки В приведенном тексте запроса используются параметры ♦ Момент — Дата, МоментВремени или Граница на которую не- обходимо получить остаток. ♦ СчетТоваров — ПланСчетовСсылка.<имя>. Ссылку для пре- допределенного счета можно получить по имени, на- пример: СчетТоваров = ПланыСчетов.ОсновнойПланСчетов.То- вары. ♦ Организация — ссылка на элемент справочника Организа- ции, который используется как измерение регистра. ♦ Номенклатура — ссылка на элемент справочника Номенк- латура, который используется на счете товаров как пер- вый вид субконто. Результат запроса будет содержать одну строку в одном поле: абсолютный остаток по ресурсу регистра Количест- во. Следующий запрос позволяет отобрать остатки по всем счетам, по которым ведется валютный учет, и в разрезе валют проанализировать остатки в валюте сделки и в ва- люте учета (листинг 9.26). Листинг 9.26. Пример получения остатков регистра бухгалтерии ВЫБРАТЬ Остатки.Счет, Остатки.Валюта, Остатки.ВалютнаяСуммаОстаток, Остатки.СумиаОстаток ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки( Счет.Валютный = ИСТИНА, j КАК Остатки В результате выполнения этого запроса будет получена, например, следующая таблица (табл. 9.29). Таблица 9.29. Результат выполнения запроса Счет Валюта Валютная- СуммаОстаток СуммаОстаток Касса Рубль 100 100 Касса Доллар 100 2850 Касса Евро 100 3500 Новый счет Доллар 10 285 Таблица оборотов Для получения оборотов по счету, по счету в разрезе суб- конто и измерений и оборотов счета с корреспондирую- щими счетами (как дебетуемыми, так и кредитуемыми) используется таблица оборотов. Таблица присутствует как у регистра с поддержкой, так и без поддержки коррес- понденции, хотя и с небольшими отличиями. Таблица оборотов может быть использована при решении задач получения оборотных показателей таких отчетов, как анализ счета/субконто/по датам и др., журнальный ор- дер, ведомость по счету. Использование таблицы оборотов в качестве источника запроса представлено в листинге 9.27. Листинг 9.27. Обращение к таблице Обороты ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Обороты
После имени таблицы в круглых скобках могут (и в боль- шинстве случаев — будут) указываться параметры, за- дающие условия отбора данных из физических таблиц информационной базы. Рассмотрим поля виртуальной таблицы оборотов. ♦ Счет — это поле имеет тип ПланСчетовСсылка.<иня>. Поле позволяет получить обороты выбранного счета. ♦ КорСчет — это поле имеет тип ПланСчетовСсылка.<иня>. Поле позволяет получить обороты выбранного счета, указанного в параметре Счет с выбранным корреспонди- рующим счетом. ♦ СубконтскМ» — это поле имеет тип Характеристика.<иня>. Количество полей Субконто зависит от максимального количества субконто на счете плана счетов. Поле позво- ляет получить обороты, сгруппированные по значени- ям субконто. ♦ КорСубконто<М> — это поле имеет тип Характерно™ - ка.<иня>. Количество полей КорСубконто зависит от мак- симального количества субконто на счете плана счетов. Поле позволяет получить обороты, сгруппированные по значениям субконто корреспондирующего счета. ♦ «Измерение* — тип поля задается при создании измере- ния регистра. Количество полей зависит от количества измерений, объявленных в регистре бухгалтерии. Поле существует как для балансовых, так и для небалансо- вых измерений. ♦ <Измерение*Кор — тип поля задается при создании из- мерения регистра. Количество полей зависит от коли- чества измерений, объявленных в регистре бухгалтерии. Поле создается только для небалансовых измерений. ♦ Период — тип Дата, Регистратор — тип ДокунентСсылка, НомерСтроки — тип Число. Поля создаются в том слу- чае, если в параметрах виртуальной таблицы задана пе- риодичность и она отличается от значения Период. ♦ <Ресурс*Оборот — это поле имеет тип Число. Разница оборотов выбранного счета (дебетовый оборот минус кредитовый оборот). ♦ <Ресурс>ОборотДт — это поле имеет тип Число. Дебето- вый оборот счета. ♦ <Ресурс*ОборотКт — это поле имеет тип Число. Кредито- вый оборот счета. ♦ <Ресурс>КорОборот — это поле имеет тип Число. Содер- жит разницу оборотов (кор оборот дебета — минус кор оборот кредита) для небалансового ресурса корреспон- дирующего счета. ♦ <Ресурс>КорОборотДт — это поле имеет тип Число. Дебе- товый оборот для небалансового ресурса корреспонди- рующего счета. ♦ <Ресурс*КорОборотКт — это поле имеет тип Число. Креди- товый оборот для небалансового ресурса корреспонди- рующего счета. Параметры виртуальной таблицы оборотов позволяют задать условие отбора данных из информационной базы. Параметры следует задавать строго в порядке их описания. ♦ НачалоПериода, КонецПериода — имеет тип Дата, МонентВрене- ни или Граница. Период времени, за который будут полу- чены обороты. ♦ Периодичность — содержит конструкцию языка запросов. Позволяет задать дополнительную группировку дан- ных по стандартным периодам. Возможные значения: Период, Год, Полугодие, Квартал, Месяц, Декада, Неделя, День, Регистратор, Запись. Если периодичность не задана или задана как Период, дополнительной группировки не вы- полняется. ♦ Счет — содержит конструкцию языка запросов. Позво- ляет установить фильтр по счету или счетам. Как пра- вило, содержит следующие условия: Счет = (В ИЕРАРХИИ, В) &Счет. ♦ Субконто — имеет тип ПланВидовХарактеристикСсылка.<иня> или содержит массив значений типа ПланВидовХарактери- стикСсылка.<иня>. В этот параметр таблицы можно пере- дать ссылку на вид субконто для получения отбора по этому виду или массив видов для установки отбора и упорядочивания видов субконто в результате запроса. ♦ Условие — содержит конструкцию языка запросов. По- зволяет устанавливать отбор данных виртуальной таб- лицей по значениям субконто и измерений регистра бухгалтерии. ♦ КорСчет — содержит конструкцию языка запросов. По- зволяет установить фильтр по корреспондирующему счету или счетам. Как правило, содержит следующие условия: КорСчет = (В ИЕРАРХИИ, В) &КорСчет. ♦ КорСубконто — имеет тип ПланВидовХарактеристикСсылка. <иня> или содержит массив значений типа ПланВидов- ХарактеристикСсылка.<иня>. В этот параметр таблицы можно передать ссылку на вид субконто для получения отбора по этому виду или массив видов для установки отбора и упорядочивания видов субконто в результате запроса. Рассмотрим примеры построения запросов к таблице обо- ротов регистра бухгалтерии. Все запросы обращаются к итогам за весь период, который есть в регистре (не указы- ваются параметры начало и конец периода). Во всех за- просах в качестве параметра передается условие по счету, где СчетТоваров — ссылка на счет «Товары плана счетов». Запрос, который покажет, сколько было куплено и списа- но товаров разных видов в количественном выражении, представлен в листинге 9.28. Листинг 9.28. Пример использования таблицы Обороты ВЫБРАТЬ Обороты.Субконто!, Обороты.КоличествоОборотДт, Обороты.КоличествоОборотКт ИЗ РегистрБухгалтерии. ОсновнойРегистрБухгалтерии. ОборотыС Счет = &СчетТоваров. j КАК Обороты Результат такого запроса представлен в табл. 9.30. Таблица показывает, какие из товаров в каком количест- ве были оприходованы (КоличествоОборотДт) и списаны (КоличествоОборотКт). Если требуется узнать с какого корреспондирующего сче- та (субконто корреспондирующего счета) были получены те или иные товары, необходимо воспользоваться полями таблицы оборотов КорСчет и КорСубконто (листинг 9.29).
Таблица 9.30. Результат запроса Субконто! КоличествоОборотДт КоличествоОборотКт Комплект 1 Паркер 15 10 Школьная 10 Цветной 3 не будет равен кредитовому обороту счета кредита провод- ки. Как пример можно привести комплектацию (рис. 9.56). 3 Операция Операция 9 от 24.12.2005 0 00.00 Действия» 4. л- s* Перейти» ? Включить выключить проводки Номер: 9 Дата: Действия» Ц t 4 Но... Ак.. Счет Дт СубконгоДт! Счет Кт -ОХ t2412.2005 00(13: Организация Альфа Листинг 9.29. Пример использования таблицы Обороты ВЫБРАТЬ Обороты.Субконто!, Обороты.КорСчет, Обороты.КорСубконто!, Обороты.КоличествоОборотДт ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Обороты( Счет = &СчетТоваров, ) КАК Обороты Результат запроса представлен в табл. 9.31. Таблица демонстрирует, какой именно товар (Субконто1) с какого корреспондирующего счета был получен (Кор- Счет), от какого контрагента (первое субконто корреспон- дирующего счета) и в каком количестве был получен. Как мы видим, большинство товаров было получено со счета Поставщики, от разных контрагентов. Однако есть и такие, которые были получены со счета Сотрудники и счета Това- ры. Именно эта корреспонденция может нас заинтересо- вать. Количество является небалансовым ресурсом регистра бухгалтерии. Регистр, который мы рассматриваем, под- держивает корреспонденцию, поэтому для каждого неба- лансового ресурса создается два поля в таблице записей регистра бухгалтерии. Таким образом, допускается ситуа- ция, когда корреспондируют два счета, поддерживающих вид учета, ведущийся в небаласовом ресурсе (в нашем случае — количество). При этом будут иметь различные обороты. То есть дебетовый оборот счета дебета проводки СубконтоКт1 >/ Доверы [Комплект [Товары ~Ь1аркер Рис. 9.56. Комплектация Содержание__________ _____________100,00! U К Записать Закрыть В приведенном примере дебетуется счет Товары с анали- тикой Комплект и кредитуется счет Товары с другой анали- тикой. При этом ресурс сумма балансирует (балансовый ресурс регистра бухгалтерии), а количество дебета и кре- дита отличаются: было списано 10 «Паркеров» и оприхо- дован один «Комплект». Воспользовавшись полем ОборотДт виртуальной таблицы оборотов, мы сможем проанализировать, сколько Ком- плектов было оприходовано на счет Товары в количествен- ном (КоличествоОборотДт) и в суммовом выражении (Сум- маОборотДт). Для балансового ресурса этой информации более чем достаточно. Ресурс небалансовый, как мы убе- дились, может быть заполнен и для основного и для кор- респондирующего счета проводки и заполнен незави- симо. Если потребуется проанализировать из какого количест- ва авторучек Паркер было собрано какое количество Ком- плектов, нам пригодится поле с постфиксом КорОборот. Напишем запрос, в котором установим для виртуальной таблицы оборотов, фильтр по полям Счет и КорСчет и по- лучим, таким образом, в качестве итогов обороты по всем проводкам, где корреспондировали между собой счет То- вары и счет Товары (листинг 9.30). Результат запроса приведен в табл. 9.32. Аналогичное назначение имеет поле виртуальной табли- цы оборотов <Измерение>Кор, которое позволит сгруппи- ровать или отобрать данные, например, по валюте коррес- пондирующего счета. Таблица 9.31. Результат запроса Субконто! КорСчет КорСубконто! КоличествоОборотДт Комплект Товары Паркер 1 Паркер Поставщики СтройТоргВсе 10 Паркер Поставщики Дисконт центр 5 Школьная Сотрудники Иванов 5 Школьная Поставщики Дисконт центр 5 Цветной Поставщики МонтажДоставка 3 Таблица 9.32. Результат запроса Субконто! КоличествоОборотДт КорСубконто! КоличествоКорОборотДт Комплект 1 Паркер 10
Листинг 9.30. Пример использования таблицы Обороты ВЫБРАТЬ Обороты.Субконто1, Обороты.КоличествоОборотДт, Обороты.КорСубконто1, Обороты.КоличествоКорОборотДт ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.ОборотыС Счет = &СчетТоваров, КорСчет = &СчетТоваров, ) КАК Обороты Таблица оборотов регистра без поддержки корреспонден- ции отличается отсутствием в ней полей, содержащих слово Кор. Таблица остатков и оборотов Основное предназначение таблицы остатков и оборо- тов — формирование оборотно-сальдовых ведомостей, отчетов, где для каждой строки необходимо показать ос- таток на начало периода, обороты за период и остаток на конец периода. Надо сразу заметить, что функционально таблица остатков и оборотов не является соединением таблицы остатков с таблицей оборотов (табл. 9.33). Таблица 9.33. Сравнение функциональности таблиц регистра бухгалтерии Функциональность Соединение табли- цы остатков и таб- лицы оборотов Таблица остатков и оборотов Получить остатки Да Да Обороты по счету (субконто, измере- нию счета) Да Да Обороты счета с кор- респондирующими (счетами, субконто, измерениями) Да Нет Как видно из таблицы, таблица остатков и оборотов по- зволяет получить обороты по счету аналогично таблице оборотов, однако не предоставляет возможности ана- лизировать обороты с корреспондирующими счетами, субконто, измерениями. По этой причине, например, не представляется возможным использовать ее для получе- ния отчета Анализ счета. Использование таблицы в качестве источника запроса потребует следующего обращения (листинг 9.31). Листинг 9.31. Обращение к таблице остатков и оборотов ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии. ОстаткиИОбороты Рассмотрим поля виртуальной таблицы остатков и обо- ротов: ♦ Счет — это поле имеет тип ПланыСчетовСсылка. <иия>. Поле содержит счет, для которого получены остатки и обороты; ♦ Субконто<М> — тип этого поля определяется типом суб- конто. Количество таких полей зависит от максималь- ного количества субконто на счете плана счетов. Поле позволяет получить остатки и обороты, сгруппирован- ные по значениям субконто; ♦ -«Измерение» — тип этого поля определяется типом из- мерения регистра накопления. Количество таких полей зависит от количества измерений, объявленных в реги- стре бухгалтерии. Поле существует как для балансо- вых, так и для небалансовых измерений. ♦ Период, Регистратор, НомерСтроки — эти поля имеют тип со- ответственно Дата, ДокументСсылка.<иня> и Число. Поля соз- даются в том случае, если в параметрах виртуальной таб- лицы задана периодичность, и она отличается от Период; ♦ <Ресурс»Оборот,<Ресурс>ОборотДт,<Ресурс»ОборотКт — эти поля имеют тип Число. Поля аналогичны полям таблицы оборотов, подробнее можно прочитать в разделе «Табли- ца оборотов», с. 283; ♦ <Ресурс»НачальныйОстаток, <Ресурс»НачальныйОстатокДт, РесуроНачальныйОстатокКт, <Ресурс»НачальныйРазверну- тыйОстатокДт, <Ресурс»НачальныйРазвернутый0статокКт — эти поля имею тип Число. Поля аналогичны полям таб- лицы остатков (подробнее можно прочитать в разделе «Таблица остатков», с. 282), рассчитываются на дату начала интервала, указанного в параметре таблицы ос- татков и оборотов НачалоПериода; ♦ <Ресурс»КонечныйОстаток, <Ресурс»КонечныйОстатокДт, <Ресурс»КонечныйОстатокКт, <Ресурс»КонечныйРазверну- тыйОстатокДт, <Ресурс»КонечныйРазвернутый0статокКт — эти поля имею тип Число. Поля аналогичны полям таб- лицы остатков (подробнее можно прочитать в разделе «Таблица остатков», с. 282), рассчитываются на дату начала интервала, указанного в параметре таблицы ос- татков и оборотов КонецПериода. Параметры виртуальной таблицы остатков и оборотов позволяют задать условие отбора данных из информаци- онной базы. Параметры следует задавать строго в поряд- ке их описания: ♦ НачалоПериода, КонецПериода — эти параметры имеют тип соответственно — Дата, МоиентВренени и Граница. Период времени, за который будут получены обороты; ♦ Периодичность — этот параметр содержит конструкцию языка запросов. Позволяет задать дополнительную груп- пировку данных по стандартным периодам. Возможные значения: Период, Год, Полугодие, Квартал, Месяц, Декада, Не- деля, День, Регистратор или Запись. Если периодичность не задана или задана как Период, то дополнительной груп- пировки не выполняется; ♦ МетодДополнения — этот параметр содержит конструкцию языка запросов. Возможны два значения: Движения или ДвиженияИГраницыПериода. Управляет включением в отчет периодов, не имеющих оборотов, но имеющих остатки; ♦ УсловиеСчета — этот параметр содержит конструкцию языка запросов. Позволяет установить фильтр по счету или счетам. Как правило, содержит следующие усло- вия: Счет = (В ИЕРАРХИИ. В) &Счет. ♦ Субконто — этот параметр имеет тип ПланВидовХарактери- стикСсылка.<иня> или может содержать массив значений типа ПланВидовХарактеристикСсылка.<иня>. В этот параметр таблицы можно передать ссылку на вид субконто для получения отбора по этому виду или массив видов для
установки отбора и упорядочивания видов субконто в результате запроса ♦ Условие — этот параметр содержит конструкцию языка запросов. Позволяет устанавливать отбор данных вир- туальной таблицей по значениям субконто и измерений регистра бухгалтерии. Примером использования таблицы может быть отчет «Оборотно-сальдовая ведомость», текст которого приве- ден в листинге 9.32. Листинг 9.32. Пример отчета Оборотно-сальдовая ведомость ВЫБРАТЬ ОстаткиИОбороты.Счет КАК Счет, ПРЕДСТАВЛЕНИЕ(ОстаткиИОбороты.Счет), ОстаткиИОбороты.СуммаНачальныйОстатокДт КАК НачОстДт, ОстаткиИОбороты.СумнаНачальныйОсгатокКт КАК НачОстКт, ОстаткиИОбороты.СумнаОборотДт КАК ОборотДт, ОстаткиИОбороты.СуммаОборотКт КАК ОборотКт, ОстаткиИОбороты.СуммаКонечныйОстатокДт КАК КонОстДт, ОстаткиИОбороты.СуммаКонечныйОстатокКт КАК КонОстКт ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии. 0статкиИ0бороты( &НачПериода, &КонПериода, j КАК ОстаткиИОбороты УПОРЯДОЧИТЬ ПО ОстаткиИОбороты.Счет.Код ИТОГИ СУММА(НачОстДт), СУММА(НачОстКт), СУММА(ОборотДт), СУММА(ОборотКт), СУММА(КонОстатокДт), СУММА(КонОстКт) ПО Счет ИЕРАРХИЯ В результате выполнения этого запроса будут получены данные, представленные в табл. 9.34. Другой пример использования таблицы остатков и обо- ротов — получение детальных аналитических отчетов схожей структуры, то есть содержащих колонки «Оста- ток на начало периода», «Обороты за период», «Остаток на конец периода». Пример такого отчета — оборотно- сальдовая ведомость по счету товаров (листинг 9.33). Листинг 9.33. Пример отчета оборотно-сальдовая ведомость по счету товаров ВЫБРАТЬ ОстаткиИОбороты.Субконто1 КАК Товар, ОстаткиИОбороты.КоличествоНачальныйОстаток КАК НачОст, ОстаткиИОбороты.КоличествоОборотДт КАК Приход, ОстаткиИОбороты.КоличествоОборотКт КАК Расход, ОстаткиИОбороты.КоличествоКонечныйОстаток КАК КонОст ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии. ОстаткиИОбороты! &НачПериода, &КонПериода, Счет = БСчетТоваров, ) КАК ОстаткиИОбороты В данном случае запрос выполняется к таблице остатков и оборотов с фильтром за интервал дат и только по одно- му счету — счету учета товаров, на котором в качестве первого субконто используется Номенклатура товаров. Ре- зультатом запроса будет таблица, демонстрирующая ко- личественные остатки и обороты каждой позиции но- менклатуры (табл. 9.35). Таблица 9.34. Результат выполнения запроса Счет НачОстДт НачОстКт ОборотДт ОборотКт КонОстДт КонОстКт Активы 1481 1126 355 Активы 100 100 Касса 1016 10 1006 Покупатели 15 16 -1 Товары 350 100 250 Материалы 1000 -1000 Обязательства 12 352 340 Обязательства 100 100 Сотрудники 2 50 48 Поставщики 10 202 192 Капитал 15 15 Таблица 9.35. Результат выполнения запроса Товар НачОст Приход Расход КонОст Комплект 1 1 Паркер 15 10 5 Школьная 10 10 Цветной 3 3
ВНИМАНИЕ Не нужно считать таблицу остатков и оборотов «панацеей» и использовать для построения всех отчетов. Таблица уни- версальна и содержит поля, необходимые во многих отче- тах. Однако платой за универсальность всегда является производительность. Использование таблицы имеет смысл только в случаях, когда в одной группировке отчета требу- ется получение и остатков на начало, и оборотов и остатков на конец периода. Если требуются только остатки или толь- ко обороты или все три составляющие, но в разных группи- ровках строках отчета, стоит задуматься о возможности на- писания нескольких запросов к таблице остатков и таблице оборотов. Таблица движений с субконто Для получения отборов проводок используется таблица движений с субконто. Таблица включает в себя все поля основной таблицы и таблицы значений субконто и полу- чается их соединением, поэтому таблица отличается для регистра с поддержкой и без поддержки корреспонден- ции. Таблицу можно использовать для решения задач форми- рования отчетов «Карточка счета/субконто», «Отчет по проводкам». Таблица является виртуальной, но получа- ется соединением двух реальных таблиц (основная таб- лица и таблица значений субконто), поэтому одна из от- личительных особенностей этой таблицы состоит в том, что в нее попадают неактивные записи. Другая отличи- тельная особенность таблицы — несовпадение полей таб- лицы, которые можно использовать для группировки данных и полей, на которые можно ставить условие в параметре виртуальной таблицы. Таблица движений с субконто регистра с поддержкой корреспонденций содер- жит следующие поля (табл. 9.36). Виртуальная таблица движений с субконто имеет сле- дующие параметры: ♦ НачалоПериода, КонецПериода — эти параметры имеют тип Дата, МоиентВренени или Граница. Период времени, за кото- рый будут отобраны проводки; ♦ Условие — этот параметр содержит конструкцию языка запросов. Конструкция позволяет установить условие на любое поле виртуальной таблицы. Ниже приводится два рисунка, демонстрирующие поля виртуальной таблицы «Движения с субконто» демонст- рационной конфигурации «Бухгалтерский учет», которая находится на прилагаемом компакт-диске. Рисунок 9.57 показывает поля таблицы, доступные для группировки. Рисунок 9.58 — поля таблицы, доступные для установки на них условия в параметре Условие. Видно, что перечень полей, на которые можно устанавливать условия, существенно шире. Если для включения в отчет нам доступны только физически существующие поля, полу- ченные виртуальной таблицей из реальных таблиц первич- ных движений, то для выполнения отборов доступны также и виртуальные поля, такие как Счет (без указания стороны проводки), Субконто, ВидСубконто, КорСчет, <Ресурс>Кор. Пример запроса, использующий таблицу движений с суб- конто, приводится в разделе «Свойства счета-родителя и подчиненных ему счетов», с. 249. Таблица 9.36. Название таблицы Поле Тип Комментарий Период Дата Дата движения Регистратор ДокументСсылка.«имя» Документ движения МоментВремени МоментВремени Момент времени документа НомерСтроки Число Номер движения в наборе записей Активность Булево Участвует ли запись в таблицах итогов СчетДт ПланСчетовСсылка.«имя» Дебетуемый счет СчетКт ПланСчетовСсылка.«имя» Кредитуемый счет «Измерение» Определяется типом измерения регистра бухгалтерии Балансовое измерение регистра бухгалтерии «Измерен ие»Дт Небалансовое измерение регистра бухгалтерии создает два поля в регистре «Измерение»Кт «Ресурс» Число Балансовый ресурс регистра бухгалтерии «Ресурс»Дт Небалансовый ресурс регистра бухгалтерии создает два поля в регистре «Ресурс»Кт «Реквизит» Определяется типом реквизита регистра бухгалтерии Характеристика движения регистра ВидСубконтоДт«М> ПланВидовХарактеристикСсылка.«имя» Количество полей зависит от настройки плана счетов ВидСубконтоКт«М» СубконтоДт«Ь1» Определяется типом субконто Количество полей зависит от настройки плана счетов СубконтоКт«Ь1>
Период Е — Регистратор —— НомерСтроки | -- Активность Е — СчетДт Е— СубконтоДт! В — ВидСубконтоДт! В — СубконтоДт? В - ВодСубконгоДт? СчетКт В — СубконтоКт1 В-— ВиаСубконтоКт! (] — СубконтоКт? В — ВцдСубконтоКт? В-1— Организация B-U В а люта Дт В -t— ВалютаКт — g Сумма .| КоличествоДт •--g КоличествоКт — g ВалютнаяСуммаДт - | ВалютнаяСуммаКт --•g СуммаХоддинга —— Содержание .— МоментВремени Рис. 9.57. Поля, доступные для группировки В t— Валюта В- L. В а люта Дт 0-L ВалютаКор В L. ВалютаКт ...g ВалютнаяСумма g ВалютнаяСуммаДт g ВалютнаяСуммаКор ...| ВалютнаяСуммаКт □ — ВцдКорСубконто! В — ВидКорСубконто2 В-•— ВидСубконто! В — ВцдСубконто2 В-— ВидСубконтоДт! В — ВидСубконтоДт? В * ВидСубконтоКт! В— ВидСубконтоКт? ...g Количество -•g КоличествоДт ...g КоличествоКор ....g КоличествоКт Е-— КорСубконто! ф — КорСубконто2 Е — КорСчет МоментВремени J...— НомерСтроки Ё -1— Организация ...— Период Ё™- Регистратор ...— Содержание В — Субконто! Ё — Субконто2 Ё СубконтоДт! Ё”— СубконтоДт? В — СубконтоКт! В- — СубконтоКт? .g Сумма ...g СуммаХоддинга В — Счет В — СчетДт Ё-— СчетКт Рис. 9.58. Поля, доступные для использования в параметре Условие Таблица оборотов Дт Кт Таблица оборотов Дт Кт предназначена для получения оборотов между корреспондирующими счетами. Таблица присутствует только у регистра с поддержкой корреспон- денции и позволяет узнать оборот в дебет счета с кредита счета (субконто, измерения). Если рассматривать таблицу с точки зрения ее возможного использования при разра- ботке отчетов, то вероятнее всего это будут отчеты «Шах- матный баланс (шахматка)» и «Сводные проводки». Ос- новное отличие таблицы оборотов Дт Кт от таблицы оборотов состоит в том, что таблица оборотов Дт Кт позво- ляет анализировать обороты между счетами, где заранее известно, какой счет дебетуется, а какой кредитуется. В то время как таблица оборотов, кроме того, что позволяет анализировать обороты по счету (без указания второго), позволяет анализировать обороты между счетом и корсче- том. При этом одним обращением к таблице можно полу- чить как дебетовые, так и кредитовые корреспонденции. Рассмотрим поля этой виртуальной таблицы (табл. 9.37). Виртуальная таблица оборотов Дт Кт использует следую- щие параметры: ♦ НачалоПериода, КонецПериода — эти параметры имеют тип Дата, Момент времени или Граница. Период времени, за ко- торый будут отобраны обороты; ♦ Периодичность — этот параметр содержит конструкцию языка запросов. Позволяет задать дополнительную груп- пировку данных по стандартным периодам. Возможные значения: Период, Год, Полугодие, Квартал, Месяц, Декада, Не- деля, День, Регистратор, Запись. Если периодичность не за- дана или задана как Период, то дополнительной группи- ровки не выполняется; ♦ УсловиеСчетаДт — этот параметр содержит конструкцию языка запросов. Отбор по дебетуемому счету, как пра- вило, содержит следующие условия: СчетДт = (В ИЕРАРХИИ, В) &СчетДт. ♦ СубконтоДт — этот параметр имеет тип ПланВидовХаракте- ристикСсылка.<иня> или содержит массив значений типа ПланВидовХарактеристикСсылка.<иня>. В этот параметр таб- лицы можно передать ссылку на вид субконто для по- лучения отбора по этому виду для дебетовых оборотов или массив видов для установки отбора и упорядочива- ния видов субконто в результате запроса; Таблица 9.37. Поля виртуальной таблицы оборотов Дт Кт Поле Тип Комментарий Период Регистратор НомерСтроки Дата ДокументСсылка.<иня> Число Поля существуют в таблице, только если значение параметра Периодичность задано и отличается от Период СчетДт ПланыСчетовСсылка.<имя> Дебетуемый счет СчетКт Кредитуемый счет «Измерение» Определяется типом измерения регистра бухгалтерии Балансовое измерение регистра бухгалтерии <Измерение»Дт <Измерение»Кт Небалансовое измерение регистра бухгалтерии создает два поля в таблице СубконтоДт«Ь1> СубконтоКкМ» Определяется типом субконто Количество полей зависит от настройки плана счетов «РесуроОборот Число Оборот балансового ресурса регистра бухгалтерии «РесуроОборотДт «РесуроОборотКт Число Обороты небалансового ресурса регистра бухгалтерии
♦ УсловиеСчетаКт — этот параметр содержит конструкцию языка запросов. Отбор по дебетуемому счету, как пра- вило, содержит следующие условия: СчетКт = (В ИЕРАРХИИ. В) &СчетКт; ♦ СубконтоКт — этот параметр имеет тип ПланВидовХаракте- ристикСсылка. <иня> или содержит массив значений типа ПланВидовХарактеристикСсылка.<иня>. В этот параметр таб- лицы можно передать ссылку на вид субконто для получения отбора по этому виду для кредитовых обо- ротов или массив видов для установки отбора и упоря- дочивания видов субконто в результате запроса; ♦ Условие — этот параметр содержит конструкцию языка запросов. Конструкция позволяет установить условие на субконто и измерения. Примером отчета, который может быть построен с ис- пользованием таблицы оборотов Дт Кт, может послужить отчет «Сводные проводки», показывающий сводные обо- роты между дебетуемыми и кредитуемыми счетами. Простейший запрос, который позволяет получить этот отчет, приводится в листинге 9.34. Листинг 9.34. Пример отчета Сводные проводки ВЫБРАТЬ ОборотыДтКт.СчетДт. ОборотыДтКт.СчетКт, ОборотыДтКт.СумнаОборот ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.ОборотыДтКт КАК ОборотыДтКт В результате выполнения этого запроса будет получен следующий результат (табл. 9.38). Таблица 9.38. Результат выполнения запроса СчетДт СчетКт СуммаОборот Сотрудники Поставщики 2 Активы Обязательства 100 Покупатели Капитал 15 Покупатели Материалы 1000 Товары Сотрудники 50 Товары Товары 100 Товары Поставщики 200 Касса Капитал 6450 Новый счет Капитал 285 Разницу между таблицей оборотов и таблицей оборотов Дт Кт может показать следующий пример. Решим задачу: необходимо получить оборот между счетами, свидетель- ствующий об объеме выручки, полученной в кассу от по- купателей. Другими словами нам необходимо получить обороты за период в дебет счета Касса с кредита счета По- купатели в разрезе контрагентов (субконто Контрагенты привязано к счету Покупатели плана счетов). Во всех при- веденных ниже запросах используются следующие пара- метры (табл. 9.39). Таблица 9.39. Параметры запросов Параметр запроса Тип Значение НачПериода Дата Начало интервала отбора итогов КонПериода Дата Конец интервала отбора итогов Счет Кассы ПланыСчетов- Ссылка.<имя> Счет Касса СчетПокупателей ПланыСчетов- Ссылка.<имя> Счет Покупатели Решим эту задачу, используя таблицу оборотов Дт Кт (листинг 9.35). В результате выполнения этого запроса будут получены следующие данные (табл. 9.40). Листинг 9.35. Пример запроса, использующего таблицу оборотов Дт Кт ВЫБРАТЬ ОборотыДтКт.СубконтоКт1 КАК Покупатель, ОборотыДтКт.СумнаОборот КАК Выручка ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.ОборотыДтКт! &НачПериода, &КонПериода, СчетДт = &СчетКассы, СчетКт = &СчетПокупателей, j КАК ОборотыДтКт ИТОГИ СУММА(Выручка) ПО ОБЩИЕ Таблица 9.40. Результат выполнения запроса Покупатель Выручка СтройТоргВсе 200 МонтажДоставка 150 Дисконт центр 100 Итог 450 Эта же таблица отчета может быть получена с помощью таблицы оборотов следующим способом (листинг 9.36). В приведенном примере выполняет запрос с отбором по счетам Касса (основной счет) и Покупатели (корреспонди- рующий счет, надо сразу отметить, что можно и наоборот: основным счетом запроса сделать счет Покупатели, а кор- респондирующим — счет Касса). При этом данные группи- руются по первому субконто корреспондирующего счета Отчетом анализируются дебетовый оборот (дебетовый относительно основного счета запроса, то есть относи- тельно счета Касса, то есть оборот в дебет счета Касса). Теперь усложним задачу. Необходимо узнать не только, сколько было получено денег от покупателей в кассу за
выбранный период, но и сумму возвращенных покупате- лям средств и разницу между выручкой и возвратами. Листинг 9.36. Пример запроса, использующего таблицу оборотов ВЫБРАТЬ Обороты.КорСубконто! КАК Покупатель. Обороты-. СуннаОборотДт КАК Выручка ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.ОборотыС &НачПериода. &КонПериода, Счет = ЬСчетКассы, КорСчет = &СчетПокупателей. ) КАК Обороты ИТОГИ СУММА(Выручка) ПО ОБЩИЕ Для получения прямой и обратной корреспонденции в од- ном запросе с использованием в качестве источника дан- ных таблицы остатков и оборотов придется обратиться к источнику дважды: для получения оборота в дебет счета Касса с кредита Покупатели и в дебет Покупатели с кредита счета Касса. В отличие от этого варианта, с помощью таблицы оборо- тов эта же задача может быть решена с однократным об- ращением к таблице (листинг 9.37). Результат выполнения запроса приведен в табл. 9.41. Таблица 9.41. Результат выполнения запроса Покупатель Выручка Возвраты Результат СтройТоргВсе 200 200 МонтажДоставка 150 150 Дисконт центр 100 80 20 Итог 450 80 370 Листинг 9.37. Пример запроса, использующего таблицу оборотов ВЫБРАТЬ Обороты.КорСубконто1 КАК Покупатель, Обороты.СуннаОборотДт КАК Выручка, Обороты.СуниаОборотКт КАК Возвраты, Обороты.СуннаОборотДт - Обороты.СуннаОборотКт КАК Результат ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.ОборотыС &НачПериода, &КонПериода, Счет = &СчетКассы, ИТОГИ СУММАСВыручка). СУММАСВозвраты), СУММАСРезультат) ПО ОБЩИЕ КорСчет = &СчетПокупателей, ) КАК Обороты Общие приемы работы с виртуальными таблицами Все рассмотренные виртуальные таблицы имеют ряд об- щих параметров, полей и просто подходов, которые не имеет смысла описывать для каждой таблицы. Для начала сгруппируем параметры, которые использу- ются в виртуальных таблицах (табл. 9.42). Поля, используемые в виртуальных таблицах регистра бухгалтерии, представлены в табл. 9.43. Теперь перейдем к рассмотрению отдельных полей и па- раметров таблиц. Таблица 9.42. Параметры виртуальных таблиц регистра бухгалтерии Параметр Таблица оборотов Таблица оборотов Дт Кт Таблица остатков Таблица остатков и оборотов Таблица движений с субконто Период, НачалоПериода, КонецПериода Да Да Да Да Да Условие Да Да Да Да Да УсловиеСчета, УсловиеКорСчета, УсловиеСчетаДт, УсловиеСчетаКт Да Да Да Да Субконто, КорСубконто, СубконтоДт, СубконтоКт Да Да Да Да Периодичность Да Да Да МетодД ополнения Да
Таблица 9.43. Поля виртуальных таблиц регистра бухгалтерии Параметр Таблица оборотов Таблица оборо- тов Дт Кт Таблица остатков Таблица остат- ков и оборотов Таблица движе- ний с субконто Счет Да Да Да КорСчет Да Счет Дт/Кт Да Да <Измерение> Да Да Да Да Да <Измерение>Кор Да < Измерение>Д т/Кт Да Да Субконто<К> Да Да Да КорСубконто<Ь1> Да СубконтоДт<Ь1>/Кт<Ь1> Да Да Период Да* Да* Да* Да Регистратор Да* Да* Да* Да НомерСтроки Да* Да* Да* Да МоментВремени Да Активность Да <Реквизит> Да ВидСубконтоДт<Ы>/Кт<Ы> Да <Ресурс> Да <Ресурс> Дт/Кт Да <Ресурс>Остаток Да Да** <Ресурс>ОстатокДт/Кт Да Да** <Ресурс>РазвернутыйОстатокДт/Кт Да Да** <Рес урООборот Да Да Да <Ресурс>ОборотДт/Кт Да Да Да <Ресурс>КорОборот Да <Ресурс>КорОборотДт/Кт Да * Поля присутствуют в таблице при установленном значении параметра Периодичность; поле НомерСтроки доступно, если периодич- ность равна Запись; поле Регистратор доступно, если периодичность равна Запись или Регистратор. **И таблице присутствуют поля для получения остатков на начало и конец периода, заданного в параметрах таблицы. Параметр Субконто: отбор и упорядочивание по виду субконто В этом разделе пойдет речь о параметрах виртуальных таблиц (остатков, оборотов, оборотов Дт Кт остатков и обо- ротов) типа ПланыВидовХарактерстикСсылка.<иня>. В разных таблицах он называется по-разному (табл. 9.44). Таблица 9.44. Параметры различных таблиц Таблица Имя параметра Оборотов Субконто, КорСубконто Оборотов Дт Кт СубконтоДт, СубконтоКт Остатков Субконто Остатков и оборотов Субконто Все перечисленные параметры могут принимать значе- ния ПланыВидовХарактеристикСсылка.<имя> или содержать массив, состоящий из значений указанного типа дан- ных. Назначение этих параметров для всех таблиц схоже. Рас- смотрим возможные варианты использования этих пара- метров на примере таблицы остатков. Начнем с того, что это не субконто, в том смысле слова, который мы обычно вкладываем в него. В этом параметре можно передать не значение субконто, а значение вида субконто или массив видов субконто. К слову надо заметить, что для отбора по значению суб конто используется другой параметр вирту- альных таблиц. Для всех таблиц он называется Условие. В нем же можно устанавливать отбор по измерению реги- стра.
Какое же назначение у параметра Субконто? Их, как мини- мум, два: ♦ отбор итогов по виду субконто; ♦ упорядочивание субконто в результате запроса (в осо- бенности если запрос выполняется по нескольким сче- там). Рассмотрим подробнее каждый из перечисленных вари- антов. Задача отбора по виду субконто может быть сформули- рована следующим образом: необходимо получить отчет по остаткам товарно-материальных запасов. При этом од- ной строке отчете нужно показать сумму стоимостных ос- татков одного вида номенклатуры со всех счетов учета материальных ценностей. Такая постановка вопроса, ра- зумеется, возможна только при условии, что на всех сче- тах учета материальных ценностей в качестве аналитики используется один и тот же вид субконто. Применительно к демонстрационной конфигурации «Бух- галтерский учет», которая находится на прилагаемом ком- пакт-диске, можно уточнить задачу. В конфигурации два счета учета материальных ценностей, это Товары и Материа- лы. На обоих счетах первым субконто привязан вид суб- конто Номенклатура типа СправочникСсылка.Номенклатура. Для получения отчета, приведенного ниже, потребуется напи- сать следующий код (листинг 9.38). Листинг 9.38. Пример получения остатков регистра бухгалтерии Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ Остатки.Субконто! КАК Товар. Остатки.СуннаОстаток КАК Остаток ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки! ВДата. ^ВидСубконто) КАК Остатки ИТОГИ СУММА(Остаток) ПО ОБЩИЕ"; Запрос. УстановитьПаранетр( "ВидСубконто", ПланыВидовХарактеристик. ВидыСубконто. Номенклатура); Запрос.УстановитьПараметрС'Дата", Дата); В параметр ВидСубконто запроса передается ссылка на вид характеристик Номенклатура. Результатом подобного за- проса может быть таблица, представленная в табл. 9.45. Таблица 9.45. Результат выполнения запроса Товар Остаток Итог 1250 Комплект 100 Паркер 1050 Школьная 75 Цветной 25 В колонке остаток будет отображаться сумма остатков со счетов Товары и Материалы, так как только на этих счетах нашей конфигурации используется субконто Номенклату- ра. При желании в запрос можно добавить и отбор по списку счетов. При необходимости разделить отчет по счетам (Товары и Материалы) запрос может быть видоизменен (лис- тинг 9.39). Листинг 9.39. Пример получения остатков регистра бухгалтерии Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ Остатки.Субконто! КАК Товар. Остатки.Счет, Остатки.СуннаОстаток КАК Остаток ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.ОстаткиС ВДата, ^ВидСубконто) КАК Остатки ИТОГИ СУММА(Остаток) ПО ОБЩИЕ, Товар”; Запрос.УстановитьПараметр!"ВидСубконто”, ПланыВидовХарактеристик.ВидыСубконто. Номенклатура): Запрос.УстановитьПараметрС'Дата", Дата): В запрос было добавлено еще одно группировочное поле Счет, а по субконто был подведен итог. Результатом за- проса будет таблица, позволяющая увидеть не только итоговый остаток по виду номенклатуры в целом по всем счетам, но и по каждому в отдельности (табл. 9.46). Таблица 9.46. Результат выполнения запроса Товар Счет Остаток Итог 1250 Комплект 100 Товары 100 Паркер 1050 Товары 50 Материалы 1000 Школьная 75 Товары 75 Цветной 25 Товары 25 При необходимости отчету можно придать «шахматный» вид, переведя вторую группировку (счета) в колонки от- чета. Если мы еще усложним задачу, то нам может понадобить- ся второе назначение параметра Субконто. Представим, что аналитика счетов Товары и Материалы настроена следую- щим образом (табл. 9.47). Задача остается той же: получить в одной строке отчета остаток с двух счетов, причем строками отчета должны быть номенклатурные позиции. Если при подобной на-
стройке плана счетов мы выполним запрос без указания параметра Субконто, но с отбором по списку счетов в пара- метре таблицы УсловиеСчета (листинг 9.40), то результат выполнения этого запроса будет таким, как показано в табл. 9.48. Таблица 9.47. Аналитика счетов Товары и Материалы Код Счет Субконто! Субконто2 1.3 Товары Номенклатура Склады 1.4 Материалы Склады Номенклатура Листинг 9.40. Пример получения остатков регистра бухгалтерии Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ Остатки.Субконто1 КАК Товар. Остатки.СуннаОстаток КАК Остаток ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки( &Дата. Счет В С&СчетТоваров, «СчетМатериалов)) КАК Остатки ИТОГИ СУММА(Остаток) ПО ОБЩИЕ"; Запрос.УстановитьПараметрС"Дата", Дата); Запрос.УстановитьПаранетрС'СчетТоваров", ПланыСчетов. ОсновнойПланСчетов.Товары); Запрос.УстановитьПараметрС"СчетМатериалов", ПланыСчетов. ОсновнойПланСчетов.Материалы); Таблица 9.48. Результат выполнения запроса Товар Остаток Итог 1250 Комплект 100 Паркер 50 Школьная 75 Цветной 25 Филиал 1000 Обратите внимание на последнюю строку отчета «Фили- ал = 1000». Она говорит нам, во-первых, о том, что на складе Филиал есть остаток материалов на 1000, а во-вто- рых, что этот самый Филиал (субконто Склады) является первым субконто счета, которые мы и анализируем на- шим запросом. Если добавить в виртуальную таблицу ре- гистра, источник запроса, параметр Субконто и передать туда ссылку на вид субконто Номенклатура, ситуация бу- дет исправлена (листинг 9.41). Листинг 9.41. Пример получения остатков регистра бухгалтерии Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ | Остатки.Субконто! КАК Товар, Остатки.СуннаОстаток КАК Остаток |ИЗ | РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки! «Дата, Счет В (ЬСчетТоваров, «СчетМатериалов), «ВидыСубконто) КАК Остатки |ИТОГИ СУММА(Остаток) |П0 ОБЩИЕ"; Запрос.УстановитьПараметрС"Дата”, Дата); Запрос.УстановитьПараметрССчетТоваров", ПланыСчетов.ОсновнойПланСчетов.Товары); Запрос.УстановитьПараметрС"СчетМатериалов", ПланыСчетов.ОсновнойПланСчетов.Материалы); Запрос.УстановитьПараметрС"ВидыСубконто", ПланыВидовХарактеристик. ВидыСубконто.Номенклатура); Продолжим усложнять задачу. Предположим, нужно вклю- чить в отчет две группировки по субконто: сначала поль- зователь хочет увидеть итоги по номенклатуре, а потом детализацию по складам, на каком сколько числится. Ре- шение будет напоминать ранее сделанное решение для группировки по счетам, проблема только в настройке плана счетов: субконто Номенклатура прикреплено первым на счет товаров и вторым на счет материалов. А обраща- емся мы к ним в запросе именно по номеру (Субконто!, Субконто2). Чтобы добиться в результате запроса нужно- го порядка следования субконто на счетах (без изменения настройки плана счетов), необходимо воспользоваться все тем же параметром Субконто (листинг 9.42). Листинг 9.42. Пример получения остатков регистра бухгалтерии Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ОсновнойРегистрБухгалтерииОстатки.Субконто! КАК Товар, 0сновнойРегистрБухгалтерии0статки.Субконто2 КАК Склад, ОсновнойРегистрБухгалтерииОстатки. СуннаОстаток КАК СуннаОстаток ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки! «Дата, Счет В (&СчетТоваров, «СчетМатериалов), «ВидыСубконто, ) КАК ОсновнойРегистрБухгалтерииОстатки ИТОГИ СУММАССунмаОстаток) ПО ОБЩИЕ, Товар, Склад"; Запрос.УстановитьПараметрС"Дата", Дата): Запрос.УстановитьПараметрС"СчетТоваров", ПланыСчетов.ОсновнойПланСчетов. Товары); Запрос.УстановитьПараметрС"СчетМатериалов", ПланыСчетов.ОсновнойПланСчетов. Материалы); нВидыСубконто = Новый Массив; нВидыСубконто.Добавить(ПланыВидовХарактеристик. ВидыСубконто.Номенклатура): нВидыСубконто.Добавить(ПланыВидовХарактеристик. ВидыСубконто.Склады): Запрос.УстановитьПараметрС"ВидыСубконто", нВидыСубконто): Результатом выполнения этого запроса будет следующая таблица (табл. 9.49).
Таблица 9.49. Результат выполнения запроса Товар Склад СуммаОстаток Итог 1250 Комплект 100 Офис 100 Паркер 1050 Офис -50 Филиал 1100 Школьная 75 Офис 75 Цветной 25 Офис 10 Филиал 15 Таким образом, нам удалось «расставить субконто по местам»: первым субконто в нашем запросе является Но- менклатура, вторым — Склады. Причем если мы хотим из- менить последовательность группировок в запросе (сна- чала группировать по складам, потом внутри склада — по номенклатурным позициям), нам достаточно изменить порядок следования элементов массива, который переда- ется в параметр виртуальной таблицы Субконто. Параметры Период, НачалоПериода и КонецПериода Все виртуальные таблицы регистра позволяют устанав- ливать отбор итогов или на момент времени, или за пери- од. Для установки такого отбора итогов можно использо- вать значения типа Дата, МонентВренени или Граница. Использование в запросе параметра типа МонентВренени в большинстве случаев ограничивается обработками про- ведения документов, когда важно получить итоги с точ- ностью «до ссылки». Этот объект, предназначенный для получения и хранения момента времени для объекта в базе данных, можно считать самым точным указанием для отбора итогов. Таблица 9.50. Проводки Период Счет дебета Счет кредита Сумма Текущий остаток Остаток 31.12.2005 10,00 01.01.200 6 12:00:00 Касса Поку- патели 10,00 20,00 01.01.200 6 23:59:59 Касса Поку- патели 10,00 30,00 Остаток 01.01.2006 30,00 02.01.200 6 0:00:00 Касса Поку- патели 10,00 40,00 02.01.200 6 12:00:00 Касса Поку- патели 10,00 50,00 Остаток 02.01.2006 50,00 Рассмотрим использование этих объектов в параметре Пе- риод виртуальной таблицы остатков. Исходная ситуация будет описана нами в виде журнала проводок. Было сде- лано несколько проводок разными датами по счету Касса. Мы рассматриваем период за январь 2006 года. Входя- щий остаток составил 10 рублей и было сделано четыре проводки за первое и второе января по 10 рублей каждая. Исходящий остаток 50 рублей (табл. 9.50). Для анализа остатка мы воспользуемся следующим не- сложным запросом (листинг 9.43). Листинг 9.43. Пример получения остатков регистра бухгалтерии Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ Остатки.СуммаОстаток ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.ОстаткиС ЬМонент, Счет = &Счет. ) КАК Остатки"; Запрос.УстановитьПараметрС’Монент", Монент): Запрос.УстановитьПараметрС"Счет", ПланыСчетов. ОсновнойПланСчетов.Касса): Результат = Запрос. ВыполнитьО; Остатки = Результат.ВыбратьО; Остатки.Следующи й О: Остаток = Остатки.СуммаОстаток; Запрос будет получать остаток по счету Касса на тот мо- мент времени, который будет передан ему в качестве па- раметра. А передавать мы туда будем разные значения. Наша задача — получить остаток на счете Касса, который там сформировался к концу 1 января (или, другими сло- вами, к началу дня 2 января). Вариант первый (листинг 9.44). Листинг 9.44. Первый вариант установки параметра запроса Монент = Дата(2006, 1, 1); Полученный результат представлен в табл. 9.51. Таблица 9.51. Полученный результат и комментарий Момент равен Остаток равен Комментарий 01.01.06 0:00:00 10,00 Не было учтено время, получили остаток на начало дня Вариант второй (листинг 9.45). Листинг 9.45. Второй вариант установки параметра запроса Дата = Дата(2006, 1, 1); Монент = КонецДня(Дата); Полученный результат представлен в табл. 9.52. Таблица 9.52. Полученный результат и комментарий Момент равен Остаток равен Комментарий 01.01.06 23:59:59 20,00 Получили остаток на конец дня, но в остатки не попала последняя проводка, сделанная в 23:59:59
ВНИМАНИЕ В бухгалтерском учете проводка в 23:59:59 не редкость. Для счета Касса такая проводка маловероятна, но все счета, по которым выполняются регламентные операции, попада- ют «в группу риска», ведь, например, «закрытие месяца» наверняка будет выполнено именно последним докумен- том в этой дате. Вариант третий (листинг 9.46). Листинг 9.46. Третий вариант установки параметра запроса Дата = Дата(2006. 1, 1); ОдинДень = 60 * 60 * 24; Момент = НачалоДня(Дата + ОдинДень): Полученный результат представлен в табл. 9.53. Таблица 9.53. Полученный результат и комментарий Момент равен Остаток равен Комментарий 02.01.06 0:00:00 30,00 Правильно! Вариант четвертый (листинг 9.47). Листинг 9.47. Четвертый вариант установки параметра запроса Дата = Дата(2006, 1, 1); КонДня = КонецДня(Дата); Момент = Новый Граница(КонДня, ВидГраницы.Включая): Полученный результат представлен в табл. 9.54. Таблица 9.54. Полученный результат и комментарий Момент равен Остаток равен Комментарий Граница 30,00 Правильно! Подведем итоги (табл. 9.55). Итак, правильные результаты были получены в третьем и четвертом вариантах. Для получения правильного ос- татка на конец периода, включающего все операции, не- обходимо или получать остатки на начало следующего периода, или использовать объект Граница. Теперь рассмотрим этот же пример для таблицы оборо- тов (табл. 9.56). Ниже приведен запрос, который будет анализировать обороты (листинг 9.48). Листинг 9.48. Пример получения оборотов регистра бухгалтерии Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ Обороты.СуммаОборот ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.ОборотыС &НачПериода, &КонПериода, Счет = &Счет, ) КАК Обороты"; Запрос.УстановитьПараметрС"НачПериода", НачПериода); Запрос.УстановитьПараметрС"КонПериода", КонПериода); Запрос.УстановитьПараметрС"Счет', ПланыСчетов.ОсновнойПланСчетов.Касса); Результат = Запрос.ВыполнитьО; Если Результат.ПустойС) Тогда Возврат 0; КонецЕсли; Обороты = Результат.ВыбратьО: Обороты.Следующий С): Оборот = Обороты.СуммаОборот; Запрос получает обороты по счету Касса, за период с Нач- Периода по КонПериода. Таблица 9.55. Сводная таблица полученных результатов № Метод Момент Остаток Комментарий 1 01.01.06 0:00:00 10,00 Не было учтено время, получили остаток на начало дня 2 Конец текущего дня 01.01.06 23:59:59 20,00 Получили остаток на конец дня, но в остатки не попала последняя проводка, сделанная в 23:59:59 3 Начало следующего дня 02.01.06 0:00:00 30,00 Правильно! 4 Граница (включая) Граница 30,00 Правильно! Таблица 9.56. Проводки Период Счет дебета Счет кредита Сумма 01.01.2006 12:00:00 Касса Покупатели 10,00 01.01.2006 23:59:59 Касса Покупатели 10,00 Оборот за 01.01.2006 20,00 02.01.2006 0:00:00 Касса Покупатели 10,00 02.01.2006 12:00:00 Касса Покупатели 10,00 Оборот за 02.01.2006 20,00
С оборотами все проще. Нам достаточно использовать функции НачалоДняО и КонецДняО, чтобы получить все обороты за указанный интервал, включая указанные дни (листинг 9.49). Листинг 9.49. Пример установки начала и конца периода при получении оборотов Дата = Дата(2006, 1, 1): НачПериода = НачалоДня(Дата); КонПериода = КонецДня(Дата); Результатом работы функции будет значение 20, соответ- ствующее обороту за первое января 2006 года. Таблица остатков и оборотов рассчитывает исходящий остаток на основании входящего и оборотов (более под- робно о работе виртуальных таблиц с данными информа- ционной базы рассказано в разделе «Построение вирту- альных таблиц регистра бухгалтерии», с. 309), поэтому «особенного внимания» к себе не требует. Для получения корректных остатков и оборотов за 1 января 2006 года достаточно передать в качестве параметров даты (начало и конец дня). Параметры виртуальной таблицы не являются обязатель- ными. В случае если момент или период отбора итогов не будет указан, результат запроса вернет актуальные итоги. Более подробно об этом рассказано в разделе «Механизм актуальных итогов», с. 309, пока же упомянем лишь, что в таблицах итогов регистра бухгалтерии хранятся итоги не только рассчитанные по месяцам, но и актуальные с уче- том последнего проведенного документа. Периодичность «оборотных» таблиц Таблица оборотов, таблица оборотов и остатков и табли- ца оборотов Дт Кт содержат параметр Периодичность. Этот параметр позволяет задать дополнительную группировку данных таблицей: по стандартным периодам. Параметр может принимать одно из значений (табл. 9.57). Таблица 9.57. Значения, которые может принимать параметр Периодичность Период Комментарий Период или пусто Дополнительная группировка данных не выполняется Год Все проводки за год Квартал Все проводки за квартал Месяц Все проводки за календарный месяц Декада Все проводки за декаду Неделя Все проводки за неделю День Все проводки за день Регистратор Все проводки одного документа (регистратора) группируются Запись Движение регистра Значение по умолчанию, если параметр не заполнен — Период. При установке в параметре Периодичность виртуальной таблицы значения, отличного от Период, в таблице появля- ются новые поля, по которым можно сгруппировать данные. Покажем это на примере таблицы остатков и обо- ротов Дт Кт регистра бухгалтерии демонстрационной конфигурации «Бухгалтерский учет», которая находится на прилагаемом компакт-диске. Колонки таблицы — зна- чения параметра Периодичность. В таблице перечислены поля, добавляемые к тем, которые существуют «по умол- чанию» (когда значение параметра Периодичность равно Период) (табл. 9.58). Таблица 9.58. Поля, добавляемые в виртуальную таблицу остатков Дт Кт Период День и более Регистратор Запись Период Период Регистратор Период Регистратор НомерСтроки Как мы видим, по мере того как мы задаем большую дета- лизацию в параметре таблицы, появляются новые поля таблицы. В случае если периодичность равна День или больше (День — Год), появляется возможность группиро- вать данные по периодам. Поле Период будет содержать дату начала периода. Например, если выбрана периодич- ность Год, то все обороты за 2005 год будут сгруппирова- ны в период 01.01.2005 00:00:00, если выбрана периодич- ность Месяц, то в таблице появятся первые числа всех месяцев, за которые были обороты. Если периодичность равна Регистратор, то кроме периода появляется возможность получить доступ к документу, сделавшему движения в регистре. Если периодичность равна Запись, мы получаем доступ к еще одному полю таб- лицы — НомерСтроки, номеру записи в наборе. Запрос, приведенный ниже, позволит получить как отчет «Сводные проводки», так и «самые что ни на есть деталь- ные» проводки (листинг 9.50). Листинг 9.50. Пример отчета Сводные проводки Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ ОборотыДтКт.Период КАК Период. ОборотыДтКт.СчетДт, ОборотыДтКт.СчетКт, ОборотыДтКт.СуммаОборот ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.ОборотыДтКтС &НачПериода, &КонПериода. " + Периодичность + ”, СчетДт В ИЕРАРХИИ (&СчетДт), СчетКт В ИЕРАРХИИ (&СчетКт). ) КАК Обороть|ДтКт УПОРЯДОЧИТЬ ПО Период"; Запрос.УстановитьПараметрС"КонПериода", КонПериода); Запрос.УстановитьПараметрС"НачПериода". НачПериода): Запрос.УстановитьПараметрС"СчетДт", СчетДт): Запрос.УстановитьПараметрС'СчетКт", СчетКт); В запрос передаются четыре параметра (интервал дат, ус- ловие по счету дебета и кредита) и сам текст запроса фор-
мируется динамически и зависит от значения перемен- ной Периодичность. Переменная Периодичность имеет тип Строка и может принимать одно из значений конструкции запросов от Год до Запись. Выполнен запрос с отбором по корреспонденции счетов дебет Касса и кредит Капитал. При периодичности запроса Год поле Период будет содер- жать дату начала года. Как мы видим на рисунке внизу, часть проводок сделаны в 2005 году (не первого января или, точнее, не только первого января) на сумму 450, а часть — в 2006 году на сумму 40 (рис. 9.59). ОстаткиИОбороты! &НачПериода, &КонПериода, " + Периодичность + ", ' + Метод + ", Счет В ИЕРАРХИИ(&Счет) ) КАК ОстаткиИОбороты УПОРЯДОЧИТЬ ПО Период"; Запрос.УстановитьПараметрС’КонПериода". КонПериода); Запрос.УстановитьПаранетрСНачПериода". НачПериода); Запрос.УстановитьПараметрС"Счет", Счет); | Период | СчетДт | СчетКт | СумнаОборот | 01 01 2005 0:00:00 Касса Покупатели 450,00 01.01.2006 0:00:00 Касса Покупатели 40,00 Рис. 9.59. Результат отчета при периодичности Год Если периодичность сделать равной Запись, каждая стро- ка отчета будет отображать свою проводку, ее дату и вре- мя (рис. 9.60). |Период |СчетДт [СчетКт ) СумнаОборот 30.12.20050:00:00 Касса Покупатели 100,00 3012.2005 0:00:00 Касса Покупатели 150,00 3012.2005 0:00.00 Касса Покупатели 200,00 01.01.2006 1 2:00:00 Касса Покупатели 10,00 01.01.2006 23:59:59 Касса Покупатели 10,00 02.01.2006 0:00:00 Касса Покупатели 10,00 02.01 2006 12:00:00 Касса Покупатели 10,00 Рис. 9.60. Результат отчета при периодичности Запись В результате более детального отчета выяснится, напри- мер, что 40 рублей первого отчета состояли из четырех проводок по 10 рублей каждая, сделанных первого и вто- рого января 2006 года. Таким же образом устроена таблица оборотов. А вот таб- лица остатков и оборотов имеет свою особенность. Как видно из приведенных выше отчетов, в запрос попадают только те периоды, которые содержали обороты, соответ- ствующие отборам, установленным в других параметрах таблицы. В нашем случае были фильтры на счет дебета и счет кредита, но в отчет попали только те периоды, где обороты между выбранными счетами были. Иначе гово- ря, в первый отчет не попал 1999 год, потому что в нем не было никаких проводок, а во второй отчет не попало третье января по той же причине. Таблица остатков и оборотов позволяет в одной группи- ровке запроса получить и остатки (входящие и исходя- щие) и обороты. Поэтому в таблице присутствует еще один параметр, позволяющий управлять, будут ли вклю- чены в результат отчета периоды, которые имели оборо- ты или еще и границы интервала, если на эти даты были остатки. Параметр МетодДополнения может принимать два значения: ДвиженияИГраницыПериода (по умолчанию) и Дви- жения. Рассмотрим отличия на примере запроса, приве- денного ниже (листинг 9.51). Листинг 9.51. Пример получения остатков и оборотов регистра бухгалтерии Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ОстаткиИОбороты.Период КАК Период, ОстаткиИОбороты.СуниаНачальныйОстаток КАК НачОст. ОстаткиИОбороты.СумнаОборотДт КАК ОборотДт, ОстаткиИОбороты.СунпаОборотКт КАК ОборотКт, ОстаткиИОбороты.СунмаКонечныйОстаток КАК КонОст ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии. В запрос передаются параметры: счет, по которому будет выполняться отбор итогов, и интервал дат. Кроме того, сам текст запроса формируется динамически. Перемен- ная Периодичность может принимать одно из значений от Год до Запись, а переменная Метод принимает значение или Движения, или ДвиженияИГраницыПериода. Исходные данные: существуют проводки по счету Касса, сделанные 30 декабря 2005, 01 и 02 января 2006 года. Запрос выполняется по счету Касса за интервал дат с 31.12.2005 по 31.12.2006 год с периодичностью День. Ре- зультат выполнения запроса показан на рис. 9.61. | Период |НачОст {ОборотДт [ОборотКт | КонОст | 31.12.2005 0:00:00 10,00 10,00 01.01.2006 0:00:00 10,00 20,00 30,00 02 01.2006 0:00:00 30,00 20,00 50,00 31 12.2006 0:00:00 50,00 50,00 Рис. 9.61. Результат выполнения запроса Если бы параметр МетодДополнения принимал значение Дви- женияИГраницыПериода, то в отчет были бы включены дата начала интервала отбора итогов (31.12.05, так как на эту дату был входящий остаток), и дата конца интервала (31.12.2006, по той же причине) (рис. 9.62). IПериод |НачОст | ОборотДт I ОборотКт {КонОст I 01 01 2006 0:00:00 10,00 20,00 30,00 02.01.2006 0:00:00 30,00 20,00 50,00 Рис. 9.62. Результат выполнения запроса В случае если бы параметр МетодДополнения принимал зна- чения Движения, в отчет попали только те даты, за которые были обороты по счету Касса. ВНИМАНИЕ Наличие в таблице остатков и оборотов наиболее часто встречающихся показателей (остатки на начало и конец ин- тервала и обороты) и возможность формирования ее с пе- риодичностью до проводки включительно не должны при- водить к ее использованию для решения любых задач. Таблица остатков и оборотов является виртуальной, то есть она не хранится в базе данных и формируется системой при обращении к ней. Формирование таблицы может включать в себя выполнение до трех запросов. По каждому периоду (мы рассматриваем сейчас использование табли- цы с заполненным параметром Периодичность) будут рас- считаны и обороты, и входящие остатки, и исходящие ос- татки. Если поставленная задача не требует получения всех этих показателей по каждой группировке (строке) отчета (например, отчет «Карточка счета»), то использование таб- лицы можно считать неоптимальным и стоит обдумать воз- можность использования для решения другой таблицы (например, таблицы движений с субконто) для получения отбора проводок, и таблицы остатков для получения остат- ков на начало периода.
Развернутые остатки Мы знаем, что все счета бухгалтерского учета делятся на активные, пассивные и активно-пассивные (в стандартах учета, принятых в РФ). Активные счета предназначены для группировки операций о движении средств (имуще- ства, активов) предприятия. Остатки по активным счетам всегда дебетовые и показывают, каким имуществом обла- дает предприятие. Пассивные счета предназначены для группировки операций об изменении источников средств (пассивов) организации. Остатки по пассивным счетам всегда кредитовые и демонстрируют, откуда было полу- чено имущество предприятия. Самые простые примеры активных счетов — счета учета денежных средств (касса, банк) и материальных запасов (товары, материалы). При- мер пассивных счетов — капитал собственника (то есть задолженность перед хозяином предприятия) и расчеты с поставщиками. Таким образом, если на счете учитываются операции рас- четов с тем, кто должен нам (например, с покупателями за поставленный им товар), то такой счет является актив- ным (долг «нам» является нашим имуществом), и оста- ток по счету должен быть всегда дебетовым (дебиторская задолженность). Если на счете учитываются операции расчетов с тем, кому должны мы (например, с поставщи- ками за поставленный нам товар), то такой счет является пассивным (мы должны), и остаток будет всегда кредито- вым (кредиторская задолженность). Сложившаяся в РФ теория и практика учета предусмат- ривает и третий вид счетов: активно-пассивные. Это сче- та расчетов, на которых группируются операции с прочи- ми контрагентами, как внутренними (по отношению к предприятию), так и внешними. Такой прочий контр- агент, с которым могут совершаться самые разные опера- ции, может оказаться как дебитором, так и кредитором. Пример такого счета в хозрасчетной бухгалтерии ком- мерческой организации РФ — расчеты с прочими дебито- рами и кредиторами (счет 76). Рассмотрим несложный пример учета расчетов с прочи- ми контрагентами. В методических целях будем исполь- зовать для учета расчетов счет «Прочие контрагенты» (имя счета — Контрагенты). В методических целях мы со- кратим количество возможных операций по этому счету до двух: мы будем отдавать им деньги и получать от них деньги. В реальной практике учета есть вероятность, что среди прочих дебиторов и кредиторов окажутся контр- агенты, которым мы продаем товар, от которых мы по- лучаем внеоборотные активы и многие другие, но нам сейчас интересен учет остатков, и то, какие обороты сформировали эти остатки, — нам не принципиально. Итак, предположим, что у нас есть один Прочий контр- агент, которому мы выдали 10 рублей (табл. 9.59). Таблица 9.59. Первая проводка № СчетДт Аналитика СчетКт Аналитика Сумма Контр- агенты Иванов Касса 10 Кроме этого есть еще один контрагент, который решил 10 рублей дать нам (табл. 9.60). Таблица 9.60. Вторая проводка № СчетДт Аналитика СчетКт Аналитика Сумма Касса Контр- агенты Петров 10 Если на счете контрагенты не ведется аналитический учет, то, анализируя остаток по счету Контрагенты, можно прийти к выводу: никто никому ничего не должен (рис. 9.63), хотя контрагенты между собой о взаимозачете не догова- ривались. Касса Контрагенты Касса 10 руб 10 руб. 10 руб Оруб. 10 руб. Оруб. Рис. 9.63. Анализ счета Контрагенты Поэтому на счете Контрагенты будем вести учет в разрезе списка контрагентов. Тогда на каждого контрагента будет «открыт свой маленький» аналитический счет (рис. 9.64). Касса Иванов 10 руб 10 руб 10 руб Петров Касса 10 руб 10 руб 10 руб Рис. 9.64. Обороты по аналитическим счетам Теперь, когда мы открыли на счете Контрагенты аналити- ческий учет по контрагентам, мы, с одной стороны, мо- жем вести учет расчетов и анализировать задолженности по каждому контрагенту, что очень удобно. С другой сто- роны, мы получаем возможность видеть развернутый ос- таток по счету Контрагенты. Теперь у счета Контрагенты есть два типа остатков: свернутый (синтетический) оста- ток, который в нашем примере равен нулю, и разверну- тый (аналитический), который в нашем примере равен 10 руб. дебетовый остаток, и 10 руб. кредитовый остаток. Если свернутый (синтетический или просто остаток) у счета всегда один, зависит от типа счета (активный, пас- сивный или активно-пассивный) и рассчитывается систе- мой (и в теории бухгалтерского учета) по правилам, кото- рые мы рассматривали в разделе «Таблица остатков», с. 282, то развернутый остаток может быть и дебетовый, и кредитовый одновременно. В приведенном выше простом примере развернутый ос- таток счета соответствует оборотам счета, так как отсут- ствует входящий остаток. На самом деле они могут и на- верняка будут отличаться. Рассмотрим более сложную ситуацию. Добавим для счета Контрагенты входящие ос- татки. Иванов был нашим кредитором, и мы были ему должны 8 рублей. В текущем отчетом периоде мы запла-
тили ему 10 рублей. Переплатили 2 рубля, и теперь он наш дебитор (он нам должен 2 рубля) (рис. 9.65). Касса Иванов 8 руб Петров Зруб 10 руб 10 руб 2 руб 10 руб 7 руб Рис. 9.65. Остатки и обороты на аналитических счетах Петров наоборот был дебитором (был нам должен 3 руб- ля), в текущем отчетном периоде он сделал платеж на 10 рублей. Переплатил нам 7 рублей. Теперь мы ему должны 7 рублей. Мы видим, что при подсчете остатков по синтетическо- му счету Контрагенты, мы учитываем входящие (сверну- тое) сальдо (5 рублей) и обороты по счету в целом (рис. 9.66). Контрагенты (синтетический) Дт 5 руб. Кт 10 руб. 10 руб. 10 руб. 10 руб. 5 руб. Рис. 9.66. Синтетический счет Контрагенты При расчете развернутого сальдо по счету в разрезе ана- литики (рис. 9.67) мы: ♦ выполняем расчет по каждому объему аналитики; ♦ по каждому объекту аналитики получаем входящее (раз- вернутое) сальдо; ♦ по каждому объекту аналитики подсчитываем обороты; ♦ по каждому объекту аналитики рассчитываем исходя- щее сальдо; ♦ суммируем отдельно остатки по всем объектам анали- тики дебетовые и отдельно кредитовые; ♦ получаем развернутый дебетовый остаток и разверну- тый кредитовый остаток по счету. Контрагенты (аналитический) Дт 3 руб. 8 руб. Кт 2 руб 7 руб. Рис. 9.67. Аналитический счет Контрагенты Развернутый остаток не имеет смысл без критерия, по ко- торому он будет «разворачиваться». В практике учета чаще всего получают развернутые остатки счета с разво- ротом по аналитике этого счета. Хотя возможны и другие варианты, например, развернутые остатки счета-группы с разворотом по субсчетам. Наиболее часто развернутые остатки требуется получать именно по активно-пассивным счетам, счетам расчетов и, чаще всего, при составлении баланса. По стандартам уче- та расчеты при включении в баланс не должны «сворачи- ваться»: в активе баланса нужно показать полную сумму дебиторской задолженности, а в пассиве — кредиторской. Возвращаясь к нашему примеру, правильно: показать в активе баланса 2 рубля, а в пассиве 7 рублей. Неправиль- но: показать в пассиве 5 рублей. В системе «1С:Предприятие» для подсчета развернутых остатков используются специальные поля виртуальных таблиц. В таблице остатков это поля: ♦ <Ресурс>Развернутый0статокДт; ♦ <Ресурс>Развернутый0статокКт. В таблице остатков и оборотов такими полями являются следующие поля: ♦ <Ресурс>НачальныйРазвернутый0статокДт; ♦ <Ресурс>Конеч н ы й Развернуты йОстатокДт; ♦ <Ресурс>НачальныйРазвернутый0статокКт; ♦ <Ресурс>КонечныйРазвернутый0статокКт. Реализуем в конфигурации описанный выше пример уче- та на счете Контрагенты и напишем запрос для анализа развернутого остатка по счету. При решении задачи получения развернутых остатков всегда нужно исходить из формулы: Остаток по <Итог> развернутый по <ПоляДетальнойВыборки> Поля развернутых остатков, присутствующие в вирту- альных таблицах в детальной выборке запроса, полно- стью повторяют содержимое полей остатков (свернутых). Развернутые остатки имеют смысл только при наличии в запросе итогов. Построим несколько элементарных запросов к таблице остатков. Во все запросы будем передавать только один параметр Счет, который равен ссылке на счет Контрагенты. Первый запрос получит все остатки с отбором по счету (листинг 9.52). Листинг 9.52. Пример получения остатков регистра бухгалтерии ВЫБРАТЬ Остатки.Счет, Остатки.СумнаОстатокДт КАК СвернутыйДт, Остатки.СуммаОстатокКт КАК СвернутыйКт, Остатки.СумнаРазвернутыйОстатокДт КАК РазвернутыйДт, Остатки.СумнаРазвернутыйОстатокКт КАК РазвернутыйКт ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки! Счет = &Счет. ) КАК Остатки Результат этого запроса — одна строка. Свернутые и раз- вернутые остатки равны. Причина — мы не указали, по какому полю разворачивать (табл. 9.61). Изменим запрос, включим в поля выборки новое поле Субконто!, то есть контрагента (листинг 9.53).
Таблица 9.61. Результат выполнения запроса Счет СвернутыйДт СвернутыйКт РазвернутыйДт РазвернутыйКт Контрагенты 5 5 Таблица 9.62. Результат выполнения запроса Счет Контрагент СвернутыйДт СвернутыйКт РазвернутыйДт РазвернутыйКт Контрагенты Иванов 2 2 Контрагенты Петров 7 7 Таблица 9.63. Результат выполнения запроса Счет Контрагент СвернутыйДт СвернутыйКт РазвернутыйДт РазвернутыйКт Контрагенты 5 2 7 Иванов 2 2 Петров 7 7 Результатом запроса будет таблица из двух строк: счет повторяется, но остатки мы получили по каждому контр- агенту. Свернутые остатки и развернутые по-прежнему равны (табл. 9.62). Листинг 9.53. Пример получения остатков регистра бухгалтерии ВЫБРАТЬ Остатки.Счет, Остатки.Субконто! КАК Контрагент. Остатки.СуммаОстатокДт КАК СвернутыйДт. Остатки.СуммаОстатокКт КАК СвернутыйКт. Остатки.СуинаРазвернутыйОстатокДт КАК РазвернутыйДт, Остатки.СуммаРазвернутыйОстатокКт КАК РазвернутыйКт ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки( Счет = &Счет, j КАК Остатки Однако в этом запросе мы уже видим, что если подвести итоги по колонкам, мы получим тот самый развернутый остаток по счету, который нас и интересует. Давайте это сделаем. Подводим итоги по Счет, суммируя все числовые поля (листинг 9.54). Листинг 9.54. Пример получения остатков регистра бухгалтерии ВЫБРАТЬ Остатки.Счет КАК Счет. Остатки.Субконто! КАК Контрагент, Остатки.СуммаОстатокДт КАК СвернутыйДт. Остатки.СуммаОстатокКт КАК СвернутыйКт. Остатки.СуммаРазвернутыйОстатокДт КАК РазвернутыйДт. Остатки.СуммаРазвернутыйОстатокКт КАК РазвернутыйКт ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки( Счет = &Счет, ) КАК Остатки ИТОГИ СУММА(СвернутыйДт), СУММА(СвернутыйКт), СУММА(РазвернутыйДт), СУММА(Раз вернутыйКт) ПО Счет Результат выполнения этого запроса представлен в табл. 9.63. Мы получили свернутые и развернутые остатки по счету. При подведении итогов поля <РесуроОстатокДт и <Ресурс> ОстатокКт сворачиваются по правилам, которые определя- ет вид счета (активный, пассивный, активно-пассивный), а поля <Ресурс>Развернутый0статокДт и <РесуроРазверну- тыйОстатокКт суммируются раздельно: отдельно подво- дится итог по элементам выборки, имеющим дебетовый остаток, отдельно по элементам, имеющим кредитовый остаток. Можно ли было в нашем случае не включать в запрос поле Счет? Да, можно. Мы могли бы ограничиться вклю- чением в детальную выборку поля Субконто! и подвести общие итоги. Таким образом, итоги разворачиваются по всем полям детальной выборки (в нашем примере по двум: Счет и Суб ко нто 1) и рассчитываются по итоговому полю. Методы менеджера регистра бухгалтерии Основным способом чтения данных в системе является запрос, и это оправдано. Однако для извлечения данных может применяться и объектная техника. Менеджер ре- гистра бухгалтерии имеет три метода, позволяющих по- лучать остатки и обороты. Надо сразу же оговориться, что при обращении к этим методам система все равно вы- полнит запрос. Разница между использованием запроса к виртуальным таблицам регистра бухгалтерии и использо- вании методов объекта лишь в синтаксисе. У менеджера регистра бухгалтерии существует три мето- да извлечения остатков и оборотов: ♦ ОстаткиО; ♦ ОборотыО; ♦ ОборотыДтКтО.
Каждый из них по своему назначению и функционально- сти похож на одноименную виртуальную таблицу. Результат, возвращаемый этими методами, — таблица значений, содержащая затребованные при выполнении метода поля выборки. Такой же результат может быть по- лучен с помощью запроса и последующей выгрузки ре- зультата запроса в таблицу значений (листинг 9.55). Листинг 9.55. Выполнение запроса и выгрузка результата запроса в таблицу значений Таблица = Запрос.ВыполнитьО.ВыгрузитьО; Рассмотрим работу метода ОстаткиО. Задача — получить остаток одного товара на выбранную пользователем дату. Пользователь выбирает в диалоге формы следующие па- раметры: ♦ Дата; ♦ Организация; ♦ Товар. Решим сначала задачу с помощью запроса (листинг 9.56). Листинг 9.56. Получение остатков с помощью запроса Момент = Новый Граница(КонецДня(Дата), ВидГраницы.Включая); СчетТоваров = ПланыСчетов.ОсновнойПланСчетов.Товары; Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ Остатки.КоличествоОстатокДт ИЗ Per истрБухг алтерии.ОсновнойРег истрБухг алтерии.Остат ки( &Момент. Счет = &Счет, Субконто! = &Субконто1 И Организация = Организация) КАК Остатки": Запрос.УстановитьПараметрС"Момент", Момент); Запрос.УстановитьПараметрС"Счет", СчетТоваров); Запрос.УстановитьПараметрС“СубконтоГ, Товар); Запрос.УстановитьПараметрС'Организация". Организация); Результат = Запрос.ВыполнитьС): Остатки = Результат.ВыбратьО: Остатки.Следующий(); ОстатокТовара = Остатки.КоличествоОстатокДт; Эта же задача с помощью метода ОстаткиО менеджера ре- гистра бухгалтерии может быть решена следующим обра- зом (листинг 9.57). Листинг 9.57. Получение остатков с помощью метода ОстаткиО Момент = Новый Граница(КонецДняСДа1а). ВидГраницы.Включая); СчетТоваров = ПланыСчетов.ОсновнойПланСчетов.Товары; Регистр = PerистрыБухгалтерии.ОсновнойРегистрБухгалтерии; Отбор = Новый СтруктураС"Счет, Субконто1, Организация", СчетТоваров, Товар, Организация); ТаблицаРезультат = Регистр.ОстаткиСМомент. , Отбор. "" , "Количество"): ОстатокТовара = ТаблицаРезультат.ИтогС’КоличествоОстатокДт"); Сравним параметры виртуальной таблицы остатков регист- ра бухгалтерии и параметры метода ОстаткиО (табл. 9.64). Первый параметр метода — МонентВренени — по своему на- значению и использованию полностью идентичен перво- му параметру Период виртуальной таблицы остатков. Второй параметр — ВидыСубконто — позволяет установить отбор по виду субконто или упорядочить поля Субкон- to<N> запроса в точности, как параметр Субконто виртуаль- ной таблицы, более подробно о назначении параметра можно посмотреть в разделе «Параметр «Субконто»: от- бор и упорядочивание по виду субконто», с. 292. Таблица 9.64. Сравнение параметров таблицы остатков и метода ОстаткиО Метод ОстаткиО Запрос к виртуальной таблице остатков № Параметр № Параметр 1 Моментвремени 1 Период 2 ВидыСубконто 3 Субконто 3 Отбор 2 УсловиеСчета 4 Условие 4 Измерения Выбранные поля- измерения запроса 5 Ресурсы Выбранные поля-ресурсы запроса Третий параметр метода, Отбор, имеет тип Структура, клю- чи которого соответствуют полям, по которым можно вы- полнять отбор в виртуальной таблице (Счет, Субконто«М», «Измерение»), а значения элементов — значения, по кото- рым нужно установить отбор. Этот параметр объединяет в себе параметры второй (УсловиеСчета) и четвертой (Усло- вие) виртуальной таблицы. Четвертый (Измерения) и пятый (Ресурсы) параметры мето- да позволяют указать в виде строки несколько (через за- пятую) полей таблицы, которые будут включены в де- тальную выборку запроса. Как измерения могут быть указаны поля Счет, Субконто«М», «Измерение». В качестве ресурсов указываются имена ресурсов регистра бухгалте- рии. Ниже приводится пример использования параметров ме- тода ОстаткиО для получения таблицы остатков товаров (листинг 9.58). Листинг 9.58. Пример получения остатков регистра бухгалтерии Момент = Новый Граница(КонецДня(Дата), ВидГраницы.Включая); СчетТоваров = ПланыСчетов.ОсновнойПланСчетов.Товары; Регистр = РегистрыБухгалтерии.ОсновнойРегистрБухгалтерии: Отбор = Новый Структура("Счет, Организация" , СчетТоваров, Организация); ТаблицаРезультат = Регистр.ОстаткиСМомент, Отбор, ”Субконто1, Субконто2", "Количество, Сумма"); Результат исполнения кода приведен в табл. 9.65. Такой же результат может быть получен с помощью за- проса (листинг 9.59).
Таблица 9.65. Результат выполнения запроса Субконто! Субконто2 Количество ОстатокДт Количество ОстатокКт Сумма ОстатокДт Сумма ОстатокКт Комплект Офис 1 100 Паркер Офис -5 -50 Паркер Филиал 10 100 Школьная Офис 10 75 Цветной Офис 10 Цветной Филиал 3 15 Листинг 9.59. Пример получения остатков регистра бухгалтерии Момент = Новый Граница(КонецДня(Дата), ВидГраницы.Включая); СчетТоваров = ПланыСчетов.ОсновнойПланСчетов.Товары; Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ Остатки.Субконто1, Остатки.Субконто2, Остатки.КоличествоОстатокДт. Остатки.КоличествоОстатокКт, Остатки.СуммаОстатокДт, Остатки.СуммаОстатокКт |ИЗ | РегистрБухгалтерии.ОсновнойРегистрБухгалтерии.Остатки( &Момент, | Счет = &Счет. | Организация = Организация | ) КАК Остатки": Запрос.УстановитьПараметр("Момент", Момент): Запрос.УстановитьПараметрССчет", СчетТоваров); Запрос.УстановитьПараметрС"Организация". Организация); Результат = Запрос. ВыполнитьО; ТаблицаРезультат = Результат.ВыгрузитьО; Вопросы производительности регистра бухгалтерии Этот раздел посвящен внутреннему устройству объекта Регистр бухгалтерии и предназначен для более глубокого понимания работы системы и более оптимального напи- сания запросов к виртуальным таблицам регистра. Авторы не рекомендуют использовать знание физической орга- низации таблиц для непосредственного доступа к табли- цам. Все примеры и вопросы, рассмотренные в разделе, подразумевают использование системы 1С:Предприятие в клиент-серверном варианте работы, при котором ин- формационная база хранится в формате таблиц SQL Server. Физические таблицы регистра бухгалтерии Все физические таблицы регистра бухгалтерии можно разделить на две группы: таблицы первичных движений и таблицы итогов (рис. 9.68). Таблицы первичных движений доступны для выполне- ния запроса и поэтому знакомы нам, это основная табли- ца и таблица значений субконто. Эти две таблицы хранят полную информацию о проводке. Таблицы итогов скры- ты от прикладного разработчика и не могут выступать как источники запроса. И таблицы первичных движений, и таблицы итогов служат источниками данных для вир- туальных таблиц регистра, которые, по своей сути, явля- ются вложенными запросами. Таблицы первичных дви- жений рассмотрены в разделе «Реальные таблицы», с. 280, поэтому перейдем сразу к описанию таблиц итогов. Рис. 9.68. Физические таблицы регистра бухгалтерии Остатки и обороты по счетам Физическая таблица остатков и оборотов по счетам имеет следующую структуру (табл. 9.66). Рассмотрим подробнее поля этой таблицы (табл. 9.67).
Таблица 9.66. Структура таблицы остатков и оборотов по счетам Период Счет <Измерения> <Ресурсы> Остаток ОборотДт ОборотКт Таблица 9.67. Поля таблицы остатков и оборотов по счетам Поле Комментарий Период Итоги хранятся помесячно, поле содержит дату (первое число месяца) Счет Ссылка на счет плана счетов <Измерения> Количество полей зависит от измерений, которые созданы в регистре бухгалтерии <Ресурсы> Для каждого ресурса регистра бухгалтерии создается три поля таблицы итогов: Остаток, ОборотДт, ОборотКт Остаток Хранит абсолютный остаток (дебет-кредит) на начало месяца, за который рассчитаны итоги (то есть на конец прошлого месяца). При построении виртуальных таблиц служит основой для расчета полей ОстатокДт, ОстаткокКт, РазвернутыйОстатокДт, РазвернутыйОстатокКт и зависит от вида счета (активный, пассивный, активно-пассивный) ОборотДт Дебетовый оборот счета за рассчитанный месяц ОборотКт Кредитовый оборот счета за рассчитанный месяц Таблица хранит итоги по всем счетам. И при любом дви- жении в регистре бухгалтерии эта таблица обновляется. ВНИМАНИЕ Наличие этой таблицы, — одно из оснований, позволяю- щих утверждать, что регистры накопления более произво- дительны по сравнению с регистрами бухгалтерии. По свой сути регистр бухгалтерии это «регистр регистров», где каж- дый счет можно сравнить с регистром накопления. Однако таблица остатков и оборотов по счетам одна на все счета и изменяется при записи любого документа, делающего дви- жение по любым счетам. Таблицы остатков и оборотов по счетам и субконто Физические таблицы остатков и оборотов по счетам и субконто появляются, когда хотя бы на один счет плана счетов был добавлен хотя бы один вид субконто. Количе- ство таблиц соответствует максимальному количеству субконто, используемых на счетах. Структура таблиц на- поминает структуру физической таблицы остатков и обо- ротов по счетам. В случае если на счетах задействовано только два вида субконто, то будет создано две таблицы (табл. 9.68 и 9.69). Если мы увеличим максимальное количество субконто и добавим хотя бы на один счет третье субконто, в базу данных будет добавлена еще одна таблица (табл. 9.70). При записи движения в регистр изменяется только одна из этих таблиц (для регистра без поддержки корреспон- денций). Для регистра с поддержкой корреспонденций может потребоваться изменение двух таблиц (для счета дебета и счета кредита проводки, если на них различное количество субконто). Запись производится лишь в ту таблицу, количество суб- конто которой соответствует количеству субконто счета проводки. Таблица 9.68. Структура первой таблицы остатков и оборотов по счетам и субконто при использовании двух видов субконто Период Счет <Измерения> <Субконто> <Ресурсы> Субконто! Остаток ОборотДт ОборотКт Таблица 9.69. Структура второй таблицы остатков и оборотов по счетам и субконто при использовании двух видов субконто Период Счет <Измерения> <Субконто> <Ресурсы> Ск! Ск2 Остаток ОборотДт ОборотКт Таблица 9.70. Структура третьей таблицы остатков и оборотов по счетам и субконто при использовании трех видов субконто Период Счет <Измерения> <Субконто> <Ресурсы> Ск! Ск2 СкЗ Остаток ОборотДт ОборотКт
Таблица 9.71. Пример проводки № СчетДт Субконто 1 СчетКт Субконто 1 Сумма Субконто 2 Субконто 2 1 Поставщики Иванов Касса 10 Таблица 9.72. Пример проводки № СчетДт Субконто 1 СчетКт Субконто 1 Сумма Субконто 2 Субконто 2 2 Товары Авторучка Поставщики Иванов 10 Склад № 1 Например, пусть записывается проводка, представленная в табл. 9.71. В этом случае будет внесено изменение в одну из таблиц остатков и оборотов по счетам и субконто. В ту из них, где остатки и обороты учитываются в разрезе одного суб- конто. Теперь рассмотрим другую проводку (табл. 9.72). В этом случае будут изменены две таблицы: по счету По- ставщики будет сделана запись в таблицу, которая хранит итоги в разрезе Субконто1, по счету Товары будет сделана запись в таблицу, которая хранит итоги в разрезе Субконто 1 и Субконто 2. Кроме того, для двух проводок для каждого счета будут сделаны записи в физическую таблицу остатков и оборо- тов по счетам, рассмотренную нами в разделе «Остатки и обороты по счетам», с. 303. Обороты между счетами Для регистра с поддержкой корреспонденций создается физическая таблица для хранения оборотов в разре- зе корреспондирующих счетов (таблица оборотов между счетами) (табл. 9.73). Таблица хранит обороты между счетами без детализации по субконто. Поэтому для извлечения любых оборотов между субконто используются физические таблицы пер- вичных движений. Управление итогами Управление итогами регистра бухгалтерии осуществляется интерактивно с помощью диалога Управление итогами, вызы- ваемого по команде Операции ► Управление итогами (рис. 9.69). Расчет итогов можно выполнить программно, используя метод регистра бухгалтерии УстановитьПериодРассчитанных- ИтоговО (листинг 9.60). Листинг 9.60. Пример использования метода УстановитьПериодРассчитанныхИтоговО PerистрыБухгалтерии.ОсновнойРегистрБухгалтерии. УстановитьПериодРассчитанныхИтогов(Дата); В качестве параметра в метод передается дата месяца, за который необходимо выполнить расчет итогов. ВНИМАНИЕ Расчет итогов не является обязательным, но представляется нам очень желательным. Рассчитанные итоги влияют на скорость получения остатков и оборотов по счетам: при по- строении виртуальных таблиц система всегда, когда есть возможность, обращается к таблицам итогов. Если затре- бованных данных в таблицах итогов нет, система обраща- ется к таблицам первичных движений. Рассмотрим структуру физической таблицы остатков и обо- роты по счетам, соответствующей приведенному выше диалогу расчета итогов (итоги рассчитаны по 28.02.2006 года) (табл. 9.74). Таблица 9.73. Структура таблицы оборотов между счетами Период СчетДт СчетКт <Измерения> <Ресурсы> Оборот Рис 9.69. Диалог управления итогами
Таблица 9.74. Структура таблицы остатков и оборотов по счетам Период Счет <Измерения> <Ресурсы> 01.01.2006 00:00:00 <Счет> <Измерения> Остаток на начало января (на конец декабря 2005 года) Дебетовый оборот за январь 2006 года Кредитовый оборот за январь 2006 года 01.02.2006 00:00:00 <Счет> <Измерения> Остаток на начало февраля (конец января) 2006 года Дебетовый оборот за февраль 2006 года Кредитовый оборот за февраль 2006 года 01.11.3999 00:00:00 <Счет> «Измерения» Актуальный остаток с учетом всех движений регистра 0 0 Таким образом, каждая строка таблицы итогов регистра бухгалтерии, как указание месяца итогов, хранит дату на- чала месяца (01.01.2006 и 01.02.2006). Хранятся счет и из- мерения, и для каждого ресурса регистра бухгалтерии хранятся абсолютный остаток (дебетовый остаток минус кредитовый остаток) на начало рассчитанного месяца (то есть на конец прошлого месяца) и обороты за месяц. Дополнительно создается строка, маркированная перио- дом 01.11.3999, предназначенная для хранения актуаль- ных итогов регистра с учетом всех его записей. Получение данных из таблиц итогов рассмотрено в разде- ле «Виртуальные таблицы», с. 282. Индексы таблиц итогов регистра бухгалтерии Для ускорения поиска нужных записей в физических таблицах создаются индексы. Система создает индексы автоматически в соответствии со свойствами объектов. Нас интересует количество и состав полей в индексах, их зависимость от свойств объектов и их влияние на про- изводительность системы. Так как производительность подсистемы бухгалтерского учета во многом определяет- ся эффективностью хранения и получения данных из таблиц итогов регистра бухгалтерии, мы уделим им осо- бое внимание. В индекс таблиц итогов регистра бухгалте- рии входят следующие поля: Период + Счет + Измерение! + [Измерение?...] + ЗначениеСубконто1 + [ЗначениеСубконто2...] Индексы, создаваемые платформой для физических таб- лиц итогов регистра бухгалтерии, влияют на производи- тельность системы с двух сторон: влияние на скорость за- писи движений при проведении документа и влияние на скорость получения данных при обращении к итогам (табл. 9.75). Рассмотрим подробнее перечисленные критерии. Тип значения субконто и его влияние на количество индексов Количество индексов существенно зависит от типов по- лей, которые были использованы при создании измере- ний и/или субконто регистра. Рассмотрим несложный пример: в плане счетов установ- лено максимальное количество субконто равным «2». Ис- пользуются субконто примитивного типа данных (Дата и Строка). При использовании примитивных типов данных для ка- ждого включенного примитивного типа в составной тип данных значения субконто создается свое поле в инфор- мационной базе (рис. 9.70). Индекс будет создан на каждое сочетание полей (табл. 9.76). Таблица 9.75. Влияние индексов на производительность Критерий Влияние на производительность Запись Чтение Ограничение Коли- чество индексов Обновление индексов при записи движений. Чем больше индексов создано для таблиц регистра, тем дольше они будут обновляться в момент записи движений в таблицы регистра, что существенно увеличит время проведения документа Да Не более 128 индексов для таблицы Коли- чество полей в индексе Чем больше полей попало в индекс, тем точнее будет выполнен захват строк (диапазона строк) таблицы итогов, который надо обно- вить при записи движений в регистр Да Не более 16 полей в индексе Поля, не включенные в индекс, увеличат диапазон строк таблиц ито- гов на количество всех возможных комбинаций этих полей. Поиск нужных строк в этой выборке будет осуществляться перебором Да
Таблица 9.76. Создаваемые индексы Номер индекса Поля в индексе 1 ... + Субконто! (Дата) + Субконто2 (Дата) 2 ... + Субконто! (Дата) + Субконто2 (Строка) 3 ... + Субконто! (Строка) + Субконто2 (Дата) 4 ... + Субконто! (Строка) + Субконто2 (Строка) Несложно представить, к чему приведет увеличение мак- симального количества субконто до трех или включение еще одного примитивного типа данных (например, Буле- во) в состав составного типа данных значения субконто. Рис. 9.70. Поля записи СОВЕТ Категорически не рекомендуется включать в составной тип данных плана видов характеристик, используемого в каче- стве видов субконто, примитивные типы данных. Количество полей в индексе SQL Server имеет ограничение на количество полей в индексе, равное 16. Поиск по полям, участвующим в индексе, осуществляется системой быстро. В случае если есть поля, которые должны были бы участвовать в индексе (измерения, значения субконто), но не были включены в него по причине ограничения длины, систе- ма сможет быстро получить выборку, включающую в себя поля, участвующие в индексе и все сочетания полей в индекс не вошедших. Полученная выборка будет обра- батываться построчно с целью поиска нужной строки итогов. Рассмотрим это на примере физической таблицы остат- ков и оборотов по счетам и субконто регистра бухгалте- рии демонстрационной конфигурации «Бухгалтерский учет», которая находится на прилагаемом компакт-диске (рис. 9.71). Индекс будет включать следующие поля (табл. 9.77). Прокомментируем таблицу: для хранения значений типа Дата, ПланСчетовСсылка.<имя>, СправочникСсылка.<имя> система создает одно поле в таблице базы данных, и, следовательно, каждое из них занимает одно поле в ин- дексе. Й9 План видов характеристик ВидыСубконто ^►Основные Иерархия Данные Нумерация Формы Макеты Подсистемы Ввод на основании Права Интерфейсы Обмен данными Имя Синоним Комментарий: Тилзнач |ВцдьГсдбк Свойства объектов, влияющие на количество полей в индексе таблицы итогов регистра бухгалтерии актеристик. [ СправочникСсылка-Контрагенту.^ Дополнителыи гемннп уллгнгтрнттгикс |Субконто________________ t 1» L- Организация I— Валюта 5дрсв ' Сумм* Количестве ВалютнаяС^мма СуимаХолдинга □ В Реквизите Содержаниэ цхгалтермиО сновноиР егистрБухгалтерии »] | <На»вд ~~] | Далее> ] За<рьгь | | Справка Рис. 9.71. Свойства, влияющие на количество полей в индексе
Для описания субконто используется составной тип дан- ных. В демонстрационной конфигурации «Бухгалтер- ский учет», которая находится на прилагаемом компакт- диске, и в типовой конфигурации для описания составно- го типа данных, определяющего тип значения характери- стик ВидыСубконто, применяются только ссылочные типы данных. Для хранения одного значения составного типа данных (содержащего только ссылки) системой исполь- зуются три поля базы данных: фактический тип значе- ния, имя таблицы и идентификатор записи в этой табли- це. Если включить в составной тип данных примитивные, то кроме опасностей, описанных в разделе «Тип значения субконто и его влияние на количество индексов», с. 306, возникает еще одна: для хранения каждого примитивного типа данных (Число, Дата, Строка, Булево) в таблицу базы данных будет добавлено еще одно поле. Другими слова- ми, если добавить в составной тип данных все четыре примитивных типа, то для хранения одного значения суб- конто будет использоваться семь полей (из них три для ссылки). И как следствие, при той же максимальной дли- не индекса (16 полей) в него попадут только период, счет, измерение и первое субконто. Подробнее можно прочитать в разделе «Хранение значе- ний полей составного типа», с. 783. Продолжая рассматривать физическую таблицу остатков и оборотов по счетам и субконто регистра бухгалтерии демонстрационной конфигурации «Бухгалтерский учет», которая находится на прилагаемом компакт-диске, мы можем сделать вывод, что все десять полей помещаются в индексе. Мы можем увеличить максимальное количество субконто на счете, не рискуя потерять производитель- ность, до четырех. При таком максимальном количестве субконто мы как раз «укладываемся» в 16 полей индекса. Увеличение количества субконто в нашей конфигурации более чем до четырех приведет к тому, что последнее суб- конто не будет участвовать в индексе. Конфигурация с такой настройкой регистра бухгалтерии и аналитическо- го учета может и будет функционировать, но теряется производительность как при записи движений в регистр, так и при формировании отчетов. Рассмотрим особенности функционирования демонстра- ционной конфигурации «Бухгалтерский учет», которая находится на прилагаемом компакт-диске, в случае уве- личения максимального количества субконто на счете до пяти (табл. 9.78). Мы видим, что последнее субконто не включается в ин- декс таблицы. К чему это приведет? Давайте сравним работу таблицы итогов для демонстра- ционной конфигурации «Бухгалтерский учет», которая находится на прилагаемом компакт-диске, с максималь- ным количеством субконто равным четырем и пяти. Таблица 9.77. Поля, входящие в индекс № Поле Комментарий 1 Период Дата начала месяца периода итогов (Дата) 2 Счет Счет плана счетов (ПланСчетовСсылка.<имя>) 3 Организация Измерение регистра бухгалтерии Организация (СправочникСсылка.<имя>) 4 Валюта Измерение регистра бухгалтерии Валюта (СправочникСсылка.<имя>) 5 Субконто! Тип Фактический тип значения поля составного типа 6 Субконто! Таблица Тип ссылки 7 Субконто! Запись Значение ссылки 8 Субконто2 Тип Фактический тип значения поля составного типа 9 Субконто2 Таблица Тип ссылки 10 Субконто2 Запись Значение ссылки Таблица 9.78. Поля, входящие в индекс № поля Поле Комментарий 1 Период Обязательное поле 2 Счет Счет плана счетов (ПланСчетовСсылка.<имя>) 3 Организация Измерение регистра бухгалтерии Организация (СправочникСсылка.<имя>) 4 Валюта Измерение регистра бухгалтерии Валюта (СправочникСсылка.<имя>) 5, 6,7 Субконто! Три поля для хранения составного типа данных (только ссылки) 8, 9, 10 Субконто2 Три поля для хранения составного типа данных (только ссылки) И, 12, 13 СубконтоЗ Три поля для хранения составного типа данных (только ссылки) 14, 15, 16 Субконто4 Три поля для хранения составного типа данных (только ссылки) Субконто5 Три поля для хранения составного типа данных (только ссылки)
Итак, работа таблиц итогов, если все поля помещаются в индекс, представлена на рис. 9.72. ___________ Ищем итоги по: ___________________ СП 01 06 | Товары | АльФа [ USD | Тов! | Скл! |Парт1 | Сер? __________Индекс _________ — Период | Счёт | Орг-ция | Вал | Ск! | Ск2 | СкЗ | Ск4 Период Счет Орг-ция Вал. Ск! Ск2 СкЗ Ск4 0101 06 Товары 0101 06 Товары АльФа USD Тов! -»]01СП|В I Товары | Альфа | USD | Tosl | Скл1 | ПутТ | Сей~|~»| 100 00 | 50 00| ЭС.ОО| Остаток Оборотят Оборот кт 01.01 06 Поставит АльФа RUR Тов2 Скл2 01 0206 Касса Рис. 9.72. Получение итогов при четырех субконто При такой ситуации, когда система осуществляет поиск в таблице итогов, она обращается к индексу и получает точное указание на строку, которая хранит затребован- ные остатки и обороты. При увеличении количества субконто до пяти последний вид субконто не попадает в индекс, и работа системы из- меняется (рис. 9.73). Период Индекс __________________ Период | Счет | Орг-ция | Вал | Ск1 | Ск2 | СкЗ } Ск4 _______ Ищем итоги по, СП СП 06 | Товары | АльФа | USD | Тов1 | Скл! | Парт! J Сер! |~Вид!~ Осип» Орг-ция Вал. USD Альфа Тов! RUR Скл2 Альфа Тов2 Товары Товары Поставит. Касса Рис. 9.73. Получение итогов при 5-ти субконто СИСЛ 06 СП СП 06 0101 06 Товары АльФа USD Тов1 Скл! Парт! Сер! ВидИ 0101 06 Товары АльФа USD Toe! Скл! Парт! Сер! ВидО 0101 06 Товары АльФа USD Toe! Скл! Парт1 Сер! Вид! 0101 06 Товары АльФа USD Toe! Скл1 Парт1 Сер! Вид2 0101 06 Товары АльФа USD Toe! Скл1 Парт! Сер! ВидЗ 010106 СП 0206 70.00 25.00 3.00 1000.00 555.00 3300 10000 50.00 30.00 10.00 10.00 1500 30.00 200 50.00 На приведенной выше схеме видно, что в индексе участ- вуют только первые четыре субконто. Как результат, сис- тема при поиске итогов по затребованному набору полей получает не одну строку, а диапазон строк, содержащий строки со всеми хранимыми вариантами (в нашем приме- ре BnflN — ВидЗ). Далее поиск строки с нужным видом осуществляется перебором. Получение диапазона строк вместо одной строки итогов, во-первых, увеличит время формирования отчетов, в ко- торых требуется получить отбор по последнему (не вклю- ченному в индекс) виду субконто, а во-вторых, увеличит время записи и объем блокируемых транзакцией строк таблицы во время записи движений в регистр. Во время записи движений в регистр блокируются стро- ки таблицы итогов для внесения в них изменений. Если индекс охватывает все поля регистра, блокируется одна изменяемая и соседние (блокировка соседних строк связана с особенностями работы SQL) строки. Пока выполняется транзакция, другие пользователи не могут выполнять за- пись движений с таким же набором полей (Период + Счет + Измерение + Субконто). Если вместо одной строки итогов был получен диапазон строк, блокируется весь диапазон (плюс соседние стро- ки). Вероятность, что пользователи «столкнутся» при проведении документов увеличивается. СОВЕТ Если анализ поставленной задачи учета выявляет необхо- димость создания регистра, количество полей таблиц ито- гов которого больше, чем может включить в себя индекс, имеет смысл переосмыслить выбор объекта системы ЮПредприятие для решения этой задачи. Можно предпо- ложить, что решение ее с помощью регистров накопления будет рациональнее. Подходы к «отнесению» учетной за- дачи к бухгалтерскому или оперативному учету приводятся в разделе «Принятие решений при организации аналитиче- ского учета», с. 259. Если же постановка задачи исключает возможность решить ее с помощью объекта Регистр накоп- ления, следует располагать субконто с малой селективно- стью (обладающие малым количеством значений и редко используемые для отбора в отчетах) последними на счетах. Это сократит диапазон полученных по индексу строк и вре- мя на поиск в нем нужной строки. Построение виртуальных таблиц регистра бухгалтерии Как уже не раз говорилось, виртуальные таблицы регист- ра представляют собой запросы, которые собирают дан- ные из физических таблиц регистра бухгалтерии. Рас- смотрим правила построения виртуальных таблиц. Механизм актуальных итогов При описании физических таблиц итогов регистра мы упоминали, что итоги хранятся помесячно. Подобная ор- ганизация физических таблиц позволяет быстро полу- чать остатки на первое число месяца и обороты за кален- дарный месяц. Хранение итогов помесячно обосновано особенностью ведения учета: как правило, стандартными бухгалтерскими интервалами для составления отчетности являются месяц, квартал и месяц и квартал нарастающим итогом с начала года. Бухгалтерский учет «историчен» — как правило, обрабатываются документы, свидетельст- вующие об уже свершившихся фактах хозяйственной деятельности, после ввода всех документов за стандарт- ный бухгалтерский интервал формируется отчетность. Однако существуют и задачи учета в реальном времени. Тогда необходимо получать данные по еще незакрытому отчетному периоду, «на сейчас», то есть с учетом послед- ней записанной в информационную базу проводки. Для быстрого получения актуальных на текущий момент времени данных и предназначен механизм актуальных ито- гов. Рассмотрим несложный пример работы механизма для одного счета. В методических целях будем считать, что: ♦ ведется только синтетический учет (нет учета по суб- конто); ♦ только в валюте учета; ♦ без измерений; ♦ нет входящих остатков. Итак, были сделаны следующие проводки в таблице за- писей (табл. 9.79).
Таблица 9.79. Записи таблицы записей регистра бухгалтерии Период СчетДт СчетКт Сумма 01.01.2006 Касса Капитал 10 12.01.2006 Касса Покупатели 5 18.01.2006 Сотрудники Касса 3 05.02.2006 Касса Покупатели 8 13.02.2006 Поставщики Касса 6 20.02.2006 Касса Сотрудники 1 01.03.2006 Касса Покупатели 7 08.03.2006 Сотрудники Касса 9 16.03.2006 Касса Покупатели 4 01.04.2006 Касса Сотрудники 2 10.04.2006 Касса Покупатели 1 20.04.2006 Сотрудники Касса 2 Можно представить также этот журнал проводок в виде оборотной ведомости по счету касса в разрезе дней (табл. 9.80). Это пригодится нам в дальнейшем. О расчете итогов рассказывается в разделе «Управление итогами», с. 305. Результатом расчета итогов стали физи- ческая таблица остатков и оборотов по счетам и физиче- ская таблица оборотов между счетами за эти же два месяца, но в нашем примере мы не будем ее учитывать. Можно представить также этот журнал проводок в виде оборотной ведомости по счету касса в разрезе календар- ных месяцев (табл. 9.81). Итоги рассчитаны за январь и февраль. Ячейки, выделен- ные серым цветом, в физической таблице итогов не хра- нятся. Это остатки на конец месяца и еще не рассчитан- ные месяцы: пользователи уже начали вводить операции за апрель, однако и март и апрель еще не рассчитаны. Чтобы не использовать физические таблицы первичных движений каждый раз, когда требуется узнать последние (актуальные) итоги по счету с учетом всех движений (включая проводки за март и апрель), в физических таб- лицах итогов создается еще одна строка для хранения ак- туальных итогов. Поэтому на самом деле физическая таблица остатков и оборотов по счетам хранит не два (январь и февраль), а три «месяца» (январь, февраль, актуальные итоги) и вы- глядит следующим образом (табл. 9.82). На 01.11.3999 года хранятся актуальные итоги. Эти итоги учитываются все активные движения регистра. Дату 01.11.3999 можно увидеть, например, сформировав за- прос к виртуальной таблице остатков и оборотов без ука- зания интервала дат с периодичностью Месяц или более детально. Используя шкалу времени, можно представить хранение итогов в виде схемы, приведенной на рис. 9.74. Таблица 9.80. Представление журнала проводок в виде оборотной ведомости по счету Период СчетДт СчетКт Сумма Остаток на начало Оборот дг Оборот кт Остаток на конец 01.01.2006 Касса Капитал 10 0 10 0 10 12.01.2006 Касса Покупатели 5 10 5 0 15 18.01.2006 Сотрудники Касса 3 15 0 3 12 05.02.2006 Касса Покупатели 8 12 8 0 20 13.02.2006 Поставщики Касса 6 20 0 6 14 20.02.2006 Касса Сотрудники 1 14 1 0 15 01.03.2006 Касса Покупатели 7 15 7 0 22 08.03.2006 Сотрудники Касса 9 22 0 9 13 16.03.2006 Касса Покупатели 4 13 4 0 17 01.04.2006 Касса Сотрудники 2 17 2 0 19 10.04.2006 Касса Покупатели 1 19 1 0 20 20.04.2006 Сотрудники Касса 2 20 0 2 18 Таблица 9.81. Представление журнала проводок в виде оборотной ведомости по счету в разрезе месяцев Период Остаток на начало Оборот дт Оборот кт Остаток на конец Январь 2006 0 15 3 12 Февраль 2006 12 9 6 15 Март 2006 15 И 9 17 Апрель 2006 17 3 2 18
Таблица 9.82. Таблица остатков и оборотов по счетам Период Счет Остаток Оборот Дт Оборот Кт 01.01.2006 Касса 0 15 3 01.02.2006 Касса 12 9 6 01.11.3999 Касса 18 0 0 Проводки (первичные движения] Итоги рассчитаны по 28.02.2006 Рис. 9.74. Схема хранения итогов Пример формирования запроса без указания интервала дат был приведен не случайно. Именно в случае, если об- ращение к виртуальной таблице остатков производится без указания интервала дат, система обращается непо- средственно к строкам, где хранятся актуальные итоги. Актуальные итоги используются и при обращении к ито- гам на произвольную дату месяца, который не был рас- считан (на схеме — апрель). В нижней части схемы изображены различные варианты получения остатков и оборотов. Актуальному остатку со- ответствует элемент схемы «Остаток 5». Остальные эле- менты (варианты) будут рассмотрены ниже. В нашем примере, чтобы получить актуальный остаток по счету Касса, необходимо выполнить запрос к виртуальной таблице остатков без указания первого параметра табли- цы Момент. Или воспользоваться методом менеджера реги- стра бухгалтерии ОстаткиО, передав в качестве первого параметра метода значение Неопределено. Таблица остатков Источниками данных виртуальной таблицы остатков в базе данных являются физическая таблица остатков и оборотов по счетам, физическая таблица остатков и обо- ротов по счетам и субконто и, в ситуациях, когда физические таблицы итогов использовать невозможно, физическая таблица записей. Рассмотрим все возможные варианты работы виртуаль- ной таблицы остатков. В первую очередь рассмотрим ва- рианты выбора системой источника данных: физические таблицы итогов или физические таблицы первичных дви- жений. Критерием выбора в данном случае является мо- мент времени, на который затребован остаток. Вариант 1. При обращении к виртуальной таблице остат- ков указан момент времени, соответствующий началу ка- лендарного месяца, и этот месяц рассчитан. На приведенной схеме (рис. 9.74, вариант Остаток 1) это может быть начало января 2006 года (01.01.2006 0:00:00 или граница от конца дня 31.12.2005, включая последнюю секунду) или начало февраля 2006 года. В этом варианте система обращается к физической табли- це итогов и получает готовый остаток. Такой запрос бу- дет выполнен максимально быстро. Вариант 2. Требуется получить остаток на произвольный момент времени месяца. Важные замечания: этот месяц рассчитан и этот месяц не последний рассчитанный, то есть существует следующий рассчитанный месяц и, та- ким образом, есть остаток на конец того месяца, за произ- вольную дату которого нужно получить остаток. В нашем случае (рис. 9.74, вариант Остаток 2) это может быть лю- бая дата января (на рис. 9.74 — 15 января). Итоги рассчи- таны за февраль, то есть в физических таблицах итогов есть строка на 01.02.2006 с остатком на начало февраля (конец января). Система получит остаток на начало следующего месяца (начало февраля) из физической таблицы итогов и вы- чтет из него «проводки» с 15.01.2006 (включительно) по 31.01.2006 (включительно). Остаток на 15.01.2006 = Итоги остаток (01.02.2006) - Проводки (15.01.2006-31.01.2006) В нашем примере это будет: Остаток на 15.01.2006 = 12 руб. - (- 3 руб.) = 15 руб. Вариант 3. Требуется получить остаток на произвольный момент последнего рассчитанного месяца. В физических таблицах итогов нет следующей строки со следующим рассчитанным месяцем, где бы хранились остатки на конец выбранного нами. На рис. 9.101, вариант Остаток 3, это 15 февраля (итоги рассчитаны по февраль включи- тельно). Система получит итоги на начало февраля из физических таблиц итогов, далее из той же строки физической табли- цы итогов получит дебетовый и кредитовый оборот и, та- ким образом, сможет быстро получить остаток на конец февраля (начало марта). Получив этот остаток, она вы- чтет из него «проводки» с 15.02.2006 (включительно) по 28.02.2006 (включительно). Остаток на 15.02.2006 = Итоги остаток (01.02.2006) + Итоги дебетовый оборот (01.02.2006-28.02.2006) - Итоги кредитовый оборот (01.02.2006-28.02.2006) - Проводки (15.02.2006-28.02.2006) В нашем примере это будет: 12 руб. + 9 руб. - 6 руб. - 1 руб. = 14 руб.
Вариант 4. Требуется получить остаток на произвольный момент времени любого не рассчитанного месяца. В на- шем примере (рис. 9.74, вариант Остаток 4) это могут быть и 15 марта, и 15 апреля. В этом случае система воспользу- ется готовыми актуальными итогами и отнимет от них проводки за интервал дат с 15 марта (15 апреля) до по- следней записи. Остаток на 15.03.2006 = Итоги остаток (актуальный) - Проводки (15.03.2006 — последняя проводка) В нашем примере это будет: 18 руб. - (11 руб. - 7 руб.) = = 22 руб. Вариант 5. Требуется получить актуальный остаток. Мо- мент времени при обращении к виртуальной таблице не указывается, система получает актуальный остаток из физических таблиц итогов (рис. 9.74, вариант Остаток 5). Актуальный остаток = Итоги остаток (актуальный) В нашем примере это будет 18 руб. Если первым критерием, влияющим на выбор источника запроса для виртуальной таблицы (физическая таблица итогов или физическая таблица проводок), можно счи- тать момент времени, то вторым — были ли затребованы в отборах или списке выбранных полей субконто. Если аналитика встречалась, в качестве физической таблицы итогов (их может быть несколько, если запрос выполня- ется по нескольким счетам) будет использоваться физи- ческая таблица остатков и оборотов по счетам и субконто. Если требуются только синтетические остатки — физиче- ская таблица остатков и оборотов по счетам. Таблица оборотов В основе построения виртуальной таблицы оборотов ле- жит тот же принцип: если данные можно взять из физи- ческих таблиц итогов, используются они. Те, что из физи- ческих таблиц итогов взять нельзя — получаются из физических таблиц первичных движений. Рис. 9.75. Алгоритм использования физических таблиц при построении виртуальной таблицы оборотов Но у виртуальной таблицы оборотов есть и свои особен- ности. Если при обращении к виртуальной таблице пара- метр Периодичность установлен меньше месяца или ис- пользуются поля, содержащие в своем название «Кор», виртуальная таблица строится только на основании фи- зических таблиц первичных движений. Во всех остальных случаях обороты за календарные месяцы виртуальная таб- лица получает из физических таблиц итогов (рис. 9.75). Рассмотрим возможные варианты. Вариант 1. Затребован оборот за рассчитанный календар- ный месяц с 01.01.2006 по 31.01.2006 (рис. 9.74, вариант Оборот 1). Система обратится к строке физической таблицы итогов, маркированной периодом «01.01.2006» и получит дебето- вый или кредитовый оборот. Оборот за календарный месяц Январь = Итоги оборот дт/кт (01.01.2006-31.12.2006) В нашем примере это будет: оборот дт = 15 руб., оборот кт = 3 руб. Вариант 2. Требуется получить оборот с 20.12.2005 по 20.02.2006 (рис. 9.74, вариант Оборот 2). Система получит готовые обороты за январь, как в пре- дыдущем случае, а интервалы дат с 20.12.2005 по 01.01.2006 и с 01.02.2006 по 20.02.2006 рассчитает по дан- ным физической таблицы записей. Оборот за произвольный период (20.12.2005-20.02.2006 включительно) = Оборот дт = Итоги оборот дт (январь) + Проводки (20.12.2005-31.12.2005) + Проводки (01.02.2006-20.02.2006) В нашем примере это будет: Оборот дт = 15 руб. + 0 + 9 руб. = 24 руб. Вариант 3. Так же поступит система и в случае, если тре- буется получить оборот за период, в котором есть не рас- считанные интервалы (рис. 9.74, вариант Оборот 3). Рас- считанные, полностью включенные в период запроса календарные месяцы будут взяты из таблиц итогов, а ос- тавшиеся «куски» дат будут собраны системой по табли- цам проводок. Отдельно следует упомянуть про расчет полей с пост- фиксом Оборот. Поля виртуальной таблицы оборотов <имя>ОборотДт и <имя>ОборотКт рассчитываются таблицей «в один при- ход» — такие поля есть в физических таблицах итогов и достаточно одного «прохода» по физической таблице записей. Поля виртуальной таблицы <имя>0борот рассчитываются «в два прохода» — сначала рассчитывается дебетовый оборот, потом из него вычитается кредитовый оборот (рис. 9.76). Рис. 9.76. Алгоритм расчета полей оборотов
Остатки и обороты Рис. 9.77. Алгоритм формирования таблицы остатков и оборотов Таблица остатков и оборотов Формирование виртуальной таблицы остатков и оборотов можно представить в виде следующий схемы (рис. 9.77). Виртуальную таблицу остатков и оборотов система полу- чает в несколько проходов. Остатки на начало периода рассчитываются по той же схеме, по которой рассчитывается виртуальная таблица остатков. Обороты за период рассчитываются как виртуальная таб- лица оборотов с условием, что в ней не используются фильтры и группировки по <...>Кор полям. Далее система самостоятельно (не используя ресурсы SQL-сервера) подсчитывает остатки на конец периода. Если используется параметр Периодичность, то результаты запросов по остаткам на начало и оборотам помещаются во временную таблицу на сервер, к которой и выполняет- ся запрос для получения виртуальной таблицы остатков и оборотов. Таблица оборотов Дт Кт Построение виртуальной таблицы оборотов Дт Кт вы- полняется системой по алгоритму, напоминающему вир- туальную таблицу оборотов. Отличия есть, и они являют- ся следствием физической таблицы итогов (физическая таблица оборотов между счетами), которая может ис- пользоваться при построении виртуальной таблицы (рис. 9.78). При условии, что периодичность не меньше месяца (как и в виртуальной таблице оборотов) и в запросе не упоми- нается аналитика (физическая таблица оборотов между счетами не хранит информацию в разрезе субконто), ис- пользуется физическая таблица итогов, в противном слу- чае запрос выполняется к физическим таблицам первич- ных движений. Физическая таблица оборотов между счетами хранит ре- сурс Оборот, поэтому получение этого ресурса не требует двух проходов (как в виртуальной таблице оборотов). Рис. 9.78. Алгоритм построения таблицы оборотов Дт Кт Таблица движений с субконто Виртуальная таблица движений с субконто формируется системой с использованием только физических таблиц первичных движений, чем и обусловлена возможность получения этой виртуальной таблицей неактивных запи- сей (рис. 9.79). Рис. 9.79. Алгоритм формирования виртуальной таблицы движений с субконто
Зависимость производительности от настроек субконто счета Производительность системы при формировании вирту- альных таблиц зависит от многих факторов. Часть из них мы перечислили, описывая индексирование таблиц, часть — при описании конкретных виртуальных таблиц. Остались те, которые влияют на работу всех таблиц и ко- торые, мы считаем необходимыми учитывать при проек- тировании плана счетов и написании запросов. Во всех виртуальных таблицах отбор по полю Счет (СчетДт, СчетКт, КорСчет) вынесен в отдельное поле. Сдела- но это не случайно. При формировании таблицы система анализирует настройку видов субконто для каждого сче- та и выбирает соответствующую физическую таблицу итогов для получения остатков и оборотов. Например, если запрос выполняется сразу по трем сче- там, и на первом из них подключен один вид субконто (значение которого используется в запросе для фильтра или группировки), на втором два вида субконто (один из них тот же), а на третьем — три, источниками данных за- проса будут три физические таблицы остатков и оборотов по счетам и субконто регистра бухгалтерии (рис. 9.80). | Отбор по: | Субконто2 | Склад 1 ] Субконто2 Остаток Склад! 10 Склад 2 15 Склад 3 5 Запрос выполнится быстрее Субконто! Остаток Авторучка 10 Карандаш 1 Чернила 8 Запрос вьполнигся медленнее Рис. 9.81. Пример зависимости скорости выполнения запроса от «расположения» субконто Счет Субконто1 Субконто2 СубконтоЗ Покупатели Контрагенты Поставщики Контрагенты Договоры Прочие Контрагенты Договоры Виды Запрос по трем счетам с отбором (группировкой) по субконто ’Контрагенты" Остатки и обороты по счетами 1м2иЗ субкоиго Остатки и обороты по счетами 1и2 субконто Виртуальная таблица Также на производительность влияет и то, в каком поряд- ке привязаны на разные счета одни и те же виды субкон- то, если запрос выполняется сразу по нескольким счетам. Возможность упорядочить виды субконто в запросе, ис- пользуя параметр виртуальной таблицы Субконто, описана в разделе «Параметр «Субконто»: отбор и упорядочива- ние по виду субконто», с. 292. Если один и тот же субконто прикреплен к разным сче- там в различном порядке (на одном счете он первый, на другом второй), виртуальная таблица для сбора данных по этому субконто выполнит два подзапроса (рис. 9.82). Контрагент Иванов Петров_________ Сидоров Остаток_______ _________100.00 20000 300.00 Рис. 9.80. Пример использования физических таблиц Еще один вопрос, связанный аналитикой и производи- тельностью при работе виртуальных таблиц — это поря- док, в котором «прикреплены» субконто к счету. Наибо- лее быстро система сможет получить итоги по тем субконто, которые прикреплены к счету первыми. Можно порекомендовать располагать субконто на счете с учетом следующего правила: ♦ те из них, по которым наиболее часто нужно выполнять отбор, имеет смысл располагать «ближе к счету»; ♦ те, которые реже участвуют в отборе и чаще предназна- чены для группировки, имеет смысл поместить «в ко- нец» (рис. 9.81). Рис. 9.82. Схема формирования виртуальной таблицы
Глава 10. Реализация сложных периодических расчетов Введение Помимо задач оперативного и бухгалтерского учета плат- форма 1 С:Предприятие 8.0 предоставляет широкие воз- можности для создания решений, предполагающих вы- полнение сложных периодических расчетов. Наибольшее распространение механизмы периодических расчетов по- лучили в решениях по расчету заработной платы. Однако сфера применения этих возможностей платформы значи- тельно шире. Задачи сложных периодических расчетов имеют ряд осо- бенностей, отличающих их от задач оперативного и бух- галтерского учета. Эти виды учета отличаются как по предназначению, так и по основным методам, используе- мым для их реализации. Так, оперативный учет служит для непрерывного учета состояния и движения средств в различных аналитических разрезах. Реализация подоб- ных задач предполагает четкую привязку всех регистри- руемых событий к непрерывной оси времени (каждое со- бытие имеет так называемый момент времени, то есть точку на оси времени). Задачи бухгалтерского учета в це- лом схожи с оперативным учетом, но предполагают более сложную систему регистрации событий с возможностью использования корреспонденции счетов. Бухгалтерский учет также является по сути непрерывным. Отличительной особенностью периодических расчетов является отсутствие однозначной привязки событий к точке на оси времени. Регистрируемые события в этом виде учета имеют отношение не к моменту времени, а к периоду в целом. При этом периодом расчета может быть день, месяц, квартал или год в зависимости от спе- цифики решаемой задачи. Так, если для регистрации факта поступления товара важен точный момент его при- хода, то при начислении премии важен период расчета (например, месяц), в котором она была начислена. Еще одним отличием периодических расчетов является протяженность некоторых регистрируемых событий во времени. Например, при регистрации отпуска сотрудника указывается дата начала и дата окончания отпуска. В про- чих видах учета регистрация подобных записей невоз- можна. Таким образом, помимо задач расчета зарплаты, меха- низм периодических расчетов может быть использован и в других областях, предполагающих периодическую регистрацию протяженных во времени событий, напри- мер в задаче расчета аренды за помещения выставочного центра. Пример, который будет рассматриваться в рамках данной главы, приводится в демонстрационной конфигурации «Сложные периодические расчеты», которая находится на прилагаемом компакт-диске. В качестве примера вы- брана задача по расчету зарплаты как наиболее часто реа- лизуемая на практике. Технология реализации расчетных задач Основные понятия Вид расчета Одним из основных понятий механизма периодических расчетов является вид расчета. Любой расчет, выполняе- мый в системе, регистрируется с обязательным указанием вида расчета, под которым может пониматься как способ расчета данной записи, так и дополнительные свойства, характеризующие сущность именно этого расчета. На- пример, для целей расчета зарплаты различными видами расчета могут быть оклад, надбавка за вредность, оплата сверхурочных. В данном случае каждая из этих записей имеет свой алгоритм расчета, поэтому для каждого вида начисления сотрудникам вводится отдельный вид расче- та. Тем не менее оплата дежурства, например, может иметь тот же алгоритм расчета, что и оклад, но при этом это будет отдельный вид расчета, так как у него другой смысл. В общем случае список видов расчета, используе- мых в системе, зависит от специфики решаемой задачи. Расчетные инструменты платформы 1 С: Предприятия 8.0 устроены таким образом, что пользователь может само- стоятельно создавать и настраивать виды расчета, кото- рые ему необходимы для решения прикладной задачи, в режиме ЮПредприятие. Для организации системы взаимосвязанных видов расчета в платформе предусмот- рен объект конфигурации План видов расчета. План видов расчета определяет структуру хранения данных о видах расчета, используемых в прикладном решении для опре- деленных целей. Разработчик может создать в конфи- гурации несколько планов видов расчета для различных целей, в каждый из которых пользователь в режиме ЮПредприятие сможет внести неограниченное количе- ство видов расчета, а также настроить их взаимосвязь.
Принципы регистрации записей Все записи о расчетах регистрируются в системе в при- вязке к периоду расчета и конкретному виду расчета. Для хранения записей о расчетах в системе предусмотрен объ- ект метаданных Регистр расчета. Каждый регистр расчета имеет определенную периодичность (день, месяц, квар- тал или год) (рис. 10.1). В зависимости от периодичности записи в этом регистре имеют соответствующий период регистрации (подробнее о периоде регистрации ниже). Перзод ревждраыми Вндрасчета Сотрудник С)ми1 хнварв2005 Оклад Иванов 10И0 фехралв 2005 Оклад Иванов 8 700 карт 2005 Оклад Петрох 9000 Регистр расчета с периодичностью «квартал» Перюд регжтраинн Зкдрэегп Свтрулмнк Срама 1 партап2005 Оклад Иванов 32 000 II партах 2005 Оклад Иванов 27 000 II квартал 2005 Отпуск Иванов 3000 Рис. 10.1. Периодичность регистров расчета Все записи регистра расчета, помимо периода регистра- ции, содержат информацию о виде расчета, примененном в данной записи. В одном регистре расчета могут содер- жаться виды расчетов только из одного плана видов рас- четов. При этом регистров расчета, использующих один и тот же план видов расчета, может быть несколько. Напри- мер, виды расчета из плана видов расчета Начисления могут использоваться в двух разных регистрах Управленческие начисления и Регламентированные начисления (рис. 10.2). Рис. 10.2. Использование видов расчета в разных регистрах расчета В данном примере один и тот же план видов расчета На- числения используется как в регистре расчета Управленче- ские начисления для учета зарплаты работников в долла- рах для целей управленческого учета, так и в отдельном независимом регистре расчета Регламентированные начис- ления, предназначенном для учета начислений в рублях для целей регламентированного учета. Записи в регистрах расчета могут быть определенным об- разом взаимосвязаны между собой. Вид этой взаимосвязи определяется настройками используемых видов расчета. Взаимосвязь, установленная для видов расчета, действу- ет во всех регистрах, где эти виды расчета используются. Структура регистров расчета будет подробно рассмотре- на позднее. Период регистрации Все расчеты в системе фиксируются в привязке к перио- ду расчета, в котором они зарегистрированы. Этот период называется периодом регистрации расчета. В зависимо- сти от специфики задачи расчеты могут фиксироваться с периодичностью день, месяц, квартал и год. Период реги- страции всегда существует у любой записи о расчете. При этом запись не может быть зарегистрирована сразу в не- скольких периодах расчета. Например, при ведении ежемесячных периодических рас- четов привязка записей о расчетах периоду регистрации представлена на рис. 10.3. Период регистрации премии - март январь февраль март апрель Периодичность расчетов месяц Рис. 10.3. Привязка записей расчета к периоду регистрации В данном примере периодом регистрации оклада, начис- ленного в январе, будет являться месяц январь. Важно понимать, что периодом регистрации квартальной пре- мии будет тот месяц, в котором она начислена (в данном случае март), а не весь первый квартал. Период действия Записи о расчетах, зарегистрированные в системе, могут быть как протяженными во времени, так и нет. Напри- мер, командировка является протяженной во времени, так как для ее расчета важен период, в течение которого сотрудник находился в отъезде (рис. 10.4). В то же время, например, начисленный штраф не является протяжен- ным во времени, а относится в целом к периоду, в кото- ром он был начислен. Интервал, в течение которого длит- ся протяженная во времени запись, называется периодом действия этой записи. Штраф не имеет прсаолжигельности январь Рис. 10.4. Записи расчета, протяженные во времени Период действия представляет собой непрерывный ин- тервал времени, определяемый датой начала периода и датой его окончания. В приведенном примере периода
действия записи о командировке — это интервал с 8 по 24 февраля. Период действия одной записи регистра рас- чета может лежать только в рамках одного периода расче- тов. В случае если необходимо ввести расчет, который длится в рамках нескольких расчетных периодов, его не- обходимо разбить на несколько записей (рис. 10.5). Рис. 10.5. Ввод расчета, который длится в нескольких периодах Так, если установлена периодичность расчетов месяц, то нельзя ввести командировку с периодом действия с 10 ян- варя по 15 февраля, так как такой период не лежит в рам- ках одного месяца. Вместо этого вводятся две записи, у одной из которых период действия с 10 по 31 января, у другой — с 1 по 15 февраля. У протяженных во времени записей период действия мо- жет не принадлежать периоду регистрации и лежать как в прошлом, так и в будущем относительно периода регист- рации. Например, если работник болел в феврале, а оформлен- ный больничный лист принес только в марте, то оплата больничного будет начислена в марте, так как за февраль зарплата уже рассчитана (рис. 10.6). Оплата больничного I за февраль начислена Оплата больничного 10.02 22.02 Период регистрации . март I Период действия 10.02- 22.02 февраль март Рис 10.6. Период действия раньше периода регистрации Рис. 10.7. Период действия позже периода регистрации В этом случае периодом регистрации этой записи будет март, хотя расчет длился с 10 по 22 февраля. Обратный случай возможен, например, когда начисление за предстоящую в следующем месяце командировку про- изводится текущим месяцем (рис. 10.7). В этом случае периодом регистрации этого начисления будет февраль, а периодом действия — интервал с 9 по 25 марта. Вытесняющие расчеты и фактический период действия Протяженные во времени записи регистров расчета могут конкурировать между собой за период действия. Это оз- начает, что они не могут действовать одновременно. Та- кая конкуренция необходима, когда виды расчета явля- ются, по сути, взаимоисключающими. Например, виды расчета Оклад и Командировка не могут действовать в один и тот же момент, так как сотрудник не может одновременно работать на основном месте и находиться в командиров- ке. При вводе записи о командировке на определенный интервал времени система должна исключать действие оклада в этом интервале. Такие виды расчетов, которые исключают одновременное действие записей других ви- дов расчетов, называются вытесняющими (рис. 10.8). Рис. 10.8. Вытеснение по периоду действия В данном случае у записей о командировке и окладе воз- никает конкуренция за период действия в интервале с 10.03 по 15.03 (то есть в интервале действия командиров- ки). Как уже было отмечено, эти записи не могут действо- вать одновременно, поэтому в указанном интервале проис- ходит вытеснение оклада командировкой. Таким образом, вид расчета Командировка, по сути, является вытесняю- щим по отношению к виду расчета Оклад. Это означает, что записи с видом расчета Командировка будут вытеснять записи с видом расчета Оклад. При вытеснении одного расчета другим период действия вытесняемого расчета не изменяется. Результат вытесне- ния влияет на так называемый фактический период дей- ствия вытесняемого расчета. Под фактическим периодом действия записи понимается совокупность интервалов времени в рамках периода действия, на протяжении кото- рых расчет действует с учетом всех вытеснений. Если ни- каких вытеснений не происходило, фактический период действия совпадает с периодом действия (рис. 10.9). Таким образом, до вытеснений фактический период дей- ствия записи об окладе содержал только один интервал,
совпадающий с периодом действия. В результате вытес- нения период действия оклада не изменился, а конкурен- ция выразилась в разбиении фактического периода дей- ствия оклада на три интервала. До вытеснения ?' wv-r—-«чй пкмш денег внч После вытеснения Рис. 10.9. Фактический период действия ПРИМЕЧАНИЕ При формировании фактического периода действия при- нимаются во внимание также сторно-записи, о которых бу- дет сказано ниже. Поскольку конкуренция и вытеснение взаимоисключаю- щих записей происходит на интервалах пересечения пе- риодов действия, то фактический период действия таких расчетов никогда не будет пересекаться. Тем самым они никогда не будут действовать одновременно. Важно учитывать, что вытеснение срабатывает только при вводе вытесняющих расчетов текущим или будущим периодом. При вводе расчетов за предыдущий период («задним числом») механизм вытеснения не действует. Это связано с тем, что записи, введенные в систему рань- ше (то есть с меньшим периодом регистрации), имеют больший приоритет в конкуренции за период действия, чем более поздние записи (с большим периодом регист- рации), причем это не зависит от настройки списка вы- тесняющих расчетов (рис. 10.10). В данном случае больничный за февраль зарегистриро- ван в марте, то есть период регистрации больше периода действия. В такой ситуации вытеснения оклада не про- изойдет, так как запись об окладе имеет более ранний период регистрации, чем запись о больничном, поэтому механизм вытеснения не действует. В результате ввода такой записи фактический период действия больничного будет пустым, так как записи не могут действовать одно- временно, а вытеснения не происходит. Для того чтобы восстановить фактический период действия больнично- го, применяется механизм сторнирования, который будет описан позже. февраль Рис. 10.10. Записи ранних периодов не вытесняются Зависимость по базовому периоду В определенных случаях результат одного расчета может зависеть от результата других расчетов, введенных в сис- тему. Например, квартальная премия может зависеть от суммы начисленного за квартал заработка по окладу. В этом случае говорят, что оклад входит в базу расчета премии, а вид расчета Оклад является базовым по отноше- нию к виду расчета Квартальная премия. При этом один вид расчета может иметь несколько базовых видов расче- та, то есть зависеть одновременно от нескольких других расчетов. При расчете результата расчета по базе анали- зируется сумма базовых видов расчета за определенный период, который называется базовым периодом. Базовый период — это произвольный непрерывный интервал дат, который может покрывать несколько расчетных перио- дов. Например, при расчете оплачиваемого отпуска, как правило, производится расчет среднего заработка за 3 ме- сяца, предшествующих отпуску. Этот интервал и будет базовым периодом расчета отпуска (рис. 10.11). В приведенном примере виды расчетов Оклад и Надбавка являются базовыми по отношению к отпуску. Если на- числяется оплата отпуска за апрель, то базовым периодом этой записи будет интервал времени с 1 января по 31 мар- та (3 целых месяца, предшествующие отпуску). В этом случае в базу расчета отпуска войдут все базовые начис- ления, входящие в базовый период записи об отпуске. В данном случае база расчета отпуска составляет 33 000 руб- лей и состоит из суммы начислений по окладу за 3 месяца и начисленной в феврале надбавки. Исходя из этой базы будет производиться расчет начисления отпускных в со- ответствии с алгоритмом расчета. То есть расчетная база — это еще не результат расчета, а лишь исходные данные, которые участвуют в алгоритме расчета. В данном случае предположим, что отпускные рассчитываются как сред- нее арифметическое заработков за 3 предыдущих месяца. В этом случае расчет отпуска производится следующим образом: Результат расчета = База расчета/3 = 33 000/3 = 11 000. Расчет по базе может применяться ко всем видам расче- тов, независимо от того, являются они протяженными во времени или нет. Например, квартальная премия, кото- рая не имеет периода действия, может иметь базовый пе- риод (например, I квартал).
i январь февраль март апрель Отпуск Периса регистрации : апрель Периоддействия 05.04 - 22.04 Базовый период 01 01 • 31 03 Рис. 10.11. Базовый период Базовый период расчета премии апрель Рис. 10.12. Необходимость перерасчета при изменении базового вида расчета результат расчета премии необходимо пересчитать Ведущие расчеты и перерасчет Ведущими называют виды расчетов, при вводе или изме- нении которых необходимо перерасчитать результат уже существующих расчетов. Например, если работнику на- числена премия за март в размере 10% от заработка, то при вводе нового начисления в марте размер этой премии теряет актуальность. Премию необходимо пересчитать, чтобы учесть новое начисление (рис. 10.12). В данном случае премия изначально была рассчитана как 10% от суммы оклада. При вводе за март надбавки в раз- мере 3000 рублей, результат расчета премии становится неверным, так как не учитывает этой надбавки. Виды рас- четов Оклад и Надбавка являются ведущими по отно- шению к премии, так как влияют на ее расчет. В случае изменения этих расчетов или ввода новых результат пре- мии необходимо перерасчитать. Под понятием перерасчет понимается повторный рас- чет результата записи с учетом произошедших измене- ний. Система позволяет автоматически отслеживать изменения расчетов, которые могут повлечь перерасчет других записей, и формировать список расчетов, кото- рые необходимо перерасчитать. Для этого система при вводе расчета анализирует, по отношению к каким дру- гим видам расчета данный вид расчета является веду- щим. По сути, все виды расчета, являющиеся базовыми по от- ношению к данному виду расчета, должны быть одновре- менно и ведущими по отношению к нему. Это связано с тем, что если данный вид расчета использует результаты базовых расчетов, то при изменении этой базы запись не- обходимо перерасчитать. В указанном случае оклад и надбавка составляют базу расчета премии, поэтому ло- гично, что при их изменении нужно заново рассчитать премию. В то же время ведущими расчетами могут быть не только базовые. Ведущими могут быть также расчеты, влияющие на результат данного вида расчета косвенно. Например, вид расчета Невыход, который вытесняет оклад, косвенно влияет на расчет премии, так как при вводе невыхода мо- жет измениться сумма оклада. В этом случае Невыход является ведущим по отношению к премии. Такая же си- туация возникает при косвенной зависимости по базе (рис. 10.13). В данном случае командировка напрямую не входит в ба- зу расчета премии, но влияет на доплату за разъезды, которая, в свою очередь, входит в базу расчета премии. Таким образом, изменение суммы за командировку кос- венным образом повлияет на премию. И хотя сама пре- мия не рассчитывается на базе командировки, Коман- дировка будет ведущим видом расчета по отношению к премии.
Невыход вытеснение по парно* действия Ом. Мвмскостъ ПС базе Премия хммскоеть по базе мансмофть по базе Премия Сторно-запись, отменяет часть оклада и восстанавливает фактический период действия больничного ПрвМ4Я Базовые: Ведущие: Оклад Невыход Оклад ПрвМ4Я Базовые: Ведущие: Доплата Доплата за разъезды за разъезды Оклад февраль Рис. 10.14. Сторно-записи Рис. 10.13. Ведущие виды расчета Сторнирование Как уже отмечалось, записи с более поздним периодом регистрации ни при каких обстоятельствах не могут вытеснить по периоду действия записи с более ранним периодом регистрации. Больничный за февраль, вве- денный в марте, не изменит фактического периода дей- ствия февральского оклада. При этом указанные запи- си в силу настройки вытесняющих видов расчета не могут действовать одновременно, то есть их фактиче- ские периоды действия не должны пересекаться. В ре- зультате фактический период действия больничного будет пустым. Тем не менее эта ситуация должна быть как-то учтена, поскольку в этом случае работнику на- числен завышенный оклад за февраль. Для решения этой задачи необходимо: ♦ в текущем периоде регистрации отменить неправильно начисленную часть оклада; ♦ позволить больничному иметь непустой фактический период действия, чтобы правильное начисление могло вступить в силу. Эта задача решается вводом в систему корректирующих записей, которые называются сторно-записями. Процесс такой корректировки называется сторнированием. Как было отмечено выше, при формировании фактического периода действия записи учитывается наличие сторно- записей по конкурирующим видам расчета. Ввод в систе- му таких записей позволит больничному иметь непустой фактический период действия на интервале действия сторно-записи (рис. 10.14). В указанном примере изначально был начислен оклад в размере 10 000 рублей за февраль. В марте становится очевидным, что совершена ошибка, так как в середине ме- сяца сотрудник болел. Если просто ввести больничный за февраль с периодом регистрации март, он будет иметь пустой фактический период действия. Чтобы этого избе- жать, вводится сторно-запись по окладу, которая решает две задачи: ♦ отменяет начисление оклада за период болезни (за этот период сотруднику было ошибочно начислено 4000 руб- лей по окладу); ♦ позволяет больничному иметь непустой фактический период действия, в результате чего сотруднику начис- ляется 3000 рублей по больничному листу. В результате этих действий общий результат записей ста- новится верным. Важно понимать, что периодом регист- рации сторно-записи будет тот же месяц, которым введен больничный (в данном случае март). Иными словами, если в текущем периоде обнаружена ошибка и нужно внести изменения в предыдущий период, то соответст- вующая корректирующая запись будет зарегистрирована в текущем периоде. При этом вид расчета сторно-записи такой же, как и в ошибочно введенной записи прошлого периода (в данном случае Оклад). В этой связи стоит еще раз остановиться на принципах формирования фактического периода действия записей. В данном случае при определении фактического периода действия больничного учитывался не только период дей- ствия оклада, но и период действия сторно-записи. Таким образом, при формировании фактического периода дей- ствия учитывается наличие сторно-записей конкурирую- щих видов расчета. Этот механизм можно пояснить на следующем примере (рис. 10.15). Сторно-запись Больничный Период регистрации 7.03 15,03 22.03 март I Период ре гистрации апрель Рис. 10.15. Учет сторно-записей при формировании фактического периода действия В данном случае больничный, имеющий более поздний период регистрации, имел бы пустой фактический пери- од действия на интервале пересечения с периодом дейст- вия дежурства (с 07.03 по 22.03). Однако наличие сторно- записи позволяет больничному действовать параллельно с дежурством на интервале действия сторно-записи (с 07.03 по 15.03). При этом на интервале с 16.03 по 22.03 фактический период действия больничного будет по- прежнему прерываться, так как на этом интервале не дей- ствует сторно-запись по дежурству. Поэтому для того,
чтобы больничный мог занять весь свой период действия, сторно-запись должна быть введена с периодом действия 07.03-22.03, то есть на всем интервале пересечения периодов действия дежурства и больничного. Подробнее формирование таких сторно-записей рассмотрено в раз- деле «Сторнирование», с. 337. Планы видов расчета Назначение планов видов расчета Планы видов расчета представляют собой прикладные объекты конфигурации, предназначенные для описания структур данных, в которых хранятся однотипные виды расчета. Для создания и настройки этих объектов преду- смотрена отдельная ветка дерева конфигурации Планы ви- дов расчета (рис. 10.16). [• Планы счетов Планы ендов расчета Ё-^- ОсновныеНачисления 0-> ДополнительныеНачисления ЁУдержания нь Регистры сведений Рис. 10.16. Планы видов расчета Каждый план видов расчета определяет отдельную струк- туру данных, где пользователь в режиме «^Предпри- ятие» может создавать неограниченное число элементов (видов расчета). Созданные виды расчета пользователь впоследствии может изменять и удалять из базы данных. Кроме этого в режиме конфигурирования в плане видов расчета можно создать неограниченное количество пре- допределенных видов расчета. Эти виды расчета также будут доступны для использования в режиме «^Пред- приятие», но со следующими ограничениями: ♦ предопределенный вид расчета не может быть удален в режиме «1С:Предприятие»; ♦ в режиме «1С:Предприятие» не могут быть удалены и изменены некоторые свойства предопределенного вида расчета, заданные в режиме конфигурирования. Об этих свойствах будет подробнее сказано ниже. В конфигурации может быть создано неограниченное ко- личество планов видов расчета. Планы видов расчета мо- гут различаться между собой по свойствам или по назна- чению использования. В демонстрационной конфигурации «Сложные периоди- ческие расчеты», которая находится на прилагаемом ком- пакт-диске, присутствуют 3 плана видов расчета: ♦ ОсновныеНачисления — в этом плане видов расчета хра- нятся виды расчета, характеризующие начисления, ко- торые являются протяженными во времени, то есть имеют период действия; ♦ ДополнительныеНачисления — виды расчетов, хранящие- ся в этом плане видов расчета, отражают начисления, не являющиеся протяженными во времени; ♦ Удержания — в этом плане видов расчета хранятся виды расчетов, характеризующие удержания из зарплаты ра- ботников; Таким образом, планы видов расчета ОсновныеНачисления и ДополнительныеНачисления отличаются друг от друга по свойствам, а план видов расчета Удержания отличается еще и назначением использования. Свойства планов видов расчета При создании и настройке плана видов расчета разработ- чик может влиять на его свойства. Для каждого плана ви- дов расчета задается его Имя, по которому можно обра- щаться к этому объекту конфигурации, и Синоним, то есть название, которое будет использоваться в режиме «1С:Пред- приятие» (рис. 10.17). Рис. 10.17. Имя и синоним плана видов расчета При настройке необходимо указать длину кода и наиме- нования видов расчета, содержащихся в данном плане ви- дов расчета (рис. 10.18). Кроме этого указывается тип кода (строка или число) и основное представление видов расчета данного плана видов расчета для пользователя: в виде кода или в виде наименования. В зависимости от этой настройки, в режиме «1 С:Предприятие» будет ото- бражаться код или наименование вида расчета в полях, хранящих ссылку на этот вид расчета. Рис. 10.18. Код и наименование плана видов расчета Использование указанных выше свойств аналогично их роли при настройке справочников. Кроме этого, у плана видов расчета существуют специфические свойства, оп- ределяющие расчетные свойства соответствующих видов расчета. К таким свойствам относятся: Использует период действия. Если в плане видов расчета ус- тановлено свойство Использует период действия, то все виды расчета, хранящиеся в данном плане, будут рассматри- ваться как протяженные во времени (рис. 10.19). Для та- ких видов расчета применима настройка вытеснения по
периоду действия. Планы видов расчета, использующие период действия, можно использовать в регистрах расче- та с периодом действия (настройка регистров расчета бу- дет рассмотрена позже). по базовому периоду от оклада, принадлежащего плану видов расчета Основные начисления и премии за месяц, принадлежащей плану видов расчета Дополнительные на- числения (рис. 10.20). Рис. 10.19. Период действия и зависимость от базы Если свойство не установлено, все виды расчета данного плана видов расчета будут рассматриваться как непротя- женные во времени, для них нет смысла настраивать вы- теснение. Такие планы видов расчета не могут быть ис- пользованы в регистрах расчета с периодом действия. Зависимость от базы. Эта настройка определяет, будет ли в видах расчета данного плана видов расчета использо- ваться зависимость по базовому периоду. Если переклю- чатель установлен в положение Не зависит, то виды расче- та данного плана видов расчета не смогут зависеть по базовому периоду от других видов расчета. Установка переключателя в положение Зависит по периоду действия или Зависит по периоду регистрации позволит уста- навливать в видах расчета зависимость по базовому пе- риоду. Различие этих двух вариантов зависимости будет рассмотрено позже. При этом любой вид расчета данного плана видов расчета теоретически может зависеть по ба- зовому периоду от любых других видов расчета, в том числе из других планов видов расчета. Поэтому при на- стройке зависимости от базы необходимо указать, виды расчета каких планов видов расчета могут выступать как базовые для видов расчета данного плана. Рис. 10.20. Зависимость от видов расчета других планов видов расчета Например, в данном случае указано, что виды расчета из плана видов расчета Дополнительные начисления могут за- висеть от любых видов расчета этого же плана видов рас- чета, а также плана видов расчета Основные начисления. В частности, вид расчета Годовая премия может зависеть Структура планов видов расчета Структура плана видов расчета может существенно ме- няться в зависимости от его свойств. Общая структура плана видов расчета представлена на рис. 10.21. Рис. 10.21. Структура плана видов расчета Если свойство плана видов расчета Длина кода больше О, все виды расчетов этого плана видов расчета будут иметь предопределенный реквизит Код, тип кода будет установ- лен в зависимости от соответствующей настройки. Если свойство Длина наименования больше 0, то у всех видов рас- чета будет существовать предопределенный реквизит На- именования типа Строка. Если у плана видов расчета установлено свойство Исполь- зует период действия и одновременно установлена зави- симость от базы, у всех видов расчета данного плана ви- дов расчета будет доступен предопределенный реквизит ПериодДействияБазовый (Период действия является базовым пе- риодом) типа Булево. Установка этого свойства у вида рас- чета будет означать, что при использовании механизма зависимости по базовому периоду вместо базового перио- да записи с этим видом расчета будет использоваться фактический период действия записи. Для предопределенных видов расчета реквизиты Код, На- именование и ПериодДействияБазовый можно указывать в кон- фигураторе (рис. 10.22). При этом код и наименование предопределенных видов расчета пользователь сможет изменить в режиме «1 (^Пред- приятие», а признак Период действия является базовым пе- риодом будет доступен для изменения только в конфигу- раторе. Помимо указанных реквизитов разработчик может до- бавлять в план видов расчета произвольное количество других реквизитов любых типов. Для всех видов расчета, в том числе предопределенных, дополнительные рекви-
зиты могут редактироваться только в режиме «1С:Пред- приятие». Рис. 10.22. Создание предопределенного вида расчета Предопределен н ые табличные части У всех планов видов расчета независимо от настрой- ки существует предопределенная табличная часть Веду- щиеВидыРасчета. Эта табличная часть позволяет для любого вида расчета данного плана видов расчета указать список ведущих расчетов. При этом ведущие расчеты могут вы- бираться из всех планов видов расчета конфигурации независимо от их настройки. Например, для уже упоми- навшейся годовой премии ведущими могут быть виды расчета Оклад из основных и Премия за месяц из дополни- тельных начислений. У планов видов расчета, использующих период действия, существует также предопределенная табличная часть ВытесняющиеВидыРасчета, в которой для каждого вида расче- та задается список вытесняющих видов расчета. В качест- ве вытесняющих могут выступать только виды расчетов данного плана видов расчета. Если у плана видов расчета установлена зависимость от базы, в его структуре будет присутствовать еще одна пред- определенная табличная часть БазовыеВидыРасчета, в кото- рой для каждого вида расчета можно указать список базо- вых видов расчета. При этом в качестве базовых могут выступать только виды расчета тех планов видов расчета, которые отмечены в качестве базовых в свойствах данно- го плана видов расчета на закладке Расчет. Все 3 предопределенные табличные части имеют един- ственный предопределенный реквизит (колонку) — ВидРасчета. Состав реквизитов (колонок) предопреде- ленных табличных частей не может быть изменен. Для предопределенных видов расчета эти табличные части могут быть заполнены в режиме конфигурирования, но только видами расчета, также являющимися предопре- деленными. Эта настройка производится на соответст- вующих закладках формы предопределенного вида рас- чета (рис. 10.23). Чтобы добавить в одну из предопределенных табличных частей вид расчета, не являющийся предопределенным, необходимо перейти в режим «1С:Предприятие». Помимо предопределенных табличных частей разработ- чик может создать произвольное количество допол- нительных табличных частей с любым составом реквизи- тов (колонок). Редактирование таких табличных частей, в том числе для предопределенных видов расчета, доступ- но только в режиме «1С:Предприятие». Рис. 10.23. Настройка базовых, вытесняющих и ведущих видов расчета Проверки, выполняемые при записи вида расчета При записи вида расчета система производит ряд прове- рок на отсутствие конфликтов при заполнении свойств и предопределенных табличных частей. Проверки в предопределенных видах расчета Если вид расчета является предопределенным (введен в конфигураторе), то при записи объекта в режиме «1С:Предприятие» система будет выполнять следующие проверки: ♦ проверка изменения свойства ПометкаУдаления. Как уже отмечалось, пользователь в режиме «1С:Предприятие» не может интерактивно установить или снять пометку удаления с предопределенного вида расчета, эти изме- нения доступны только средствами встроенного языка. При попытке изменить это свойство интерактивно бу- дет выдано предупреждение «Пометка на удаление пред- определенного вида расчета»; ♦ проверка изменения свойства ПериодДействияБазовый. Для предопределенных видов расчета свойство Период дейст- вия является базовым периодом может быть изменено толь- ко из конфигуратора либо средствами встроенного язы- ка. При попытке изменить его интерактивно в режиме «1С:Предприятие» будет выдано предупреждение «Из- менены свойства предопределенного вида расчета»; ♦ проверка модификации предопределенных табличных частей. У предопределенного вида расчета в режиме «1С:Предприятие» не допускается модификация или удаление строк табличных частей ведущих, вытесняю- щих и базовых видов расчетов, заданных в конфигура- торе. Добавлять новые строки в эти таблицы в режиме «1С:Предприятие» можно. Проверки предопределенных табличных частей Во всех видах расчета (не только предопределенных) при записи производятся следующие системные проверки табличных частей ВедущиеВидыРасчета, БазовыеВидыРасчета и ВытесняющиеВидыРасчета: Проверка повторяющихся строк. В каждой из предопре- деленных табличных частей производится проверка дуб- лирующихся значений колонки ВидРасчета. Недопустимо, например, в список базовых видов расчета внести не- сколько раз один и тот же вид расчета. В этом случае бу-
Рис. 10.24. Проверка «зацикливания» вытесняющих видов расчета дет выдано предупреждение «Дублирование базовых ви- дов расчета». Проверка «зацикливания» вытесняющих видов расчета. В таблице ВытесняющиеВидыРасчета производится провер- ка отсутствия конфликтов при настройке вытеснения од- ного расчета другим. Если в списке вытесняющих указан вид расчета, который прямо или косвенно вытесняется текущим (записываемым) видом расчета, то механизм вытеснения по периоду действия не сможет сработать, так как не понятно, как будут конкурировать за период действия эти виды расчета. Например, если для оклада указан вытесняющий вид рас- чета Командировка, то при попытке указать оклад как вы- тесняющий в командировке возникнет ошибка «Вытес- няющий вид расчета вытесняется текущим!» (рис. 10.24). При этом проверяются табличные части вытесняющих видов расчета всех видов расчета данного плана видов расчета, так как текущий вид расчета может вытеснять за- данный как вытесняющий не напрямую, а опосредованно. Например, вытеснение видов расчета может быть на- строено так, как показано на рис. 10.25. Г Дежурство | I' Командировка I —tzzz_____________ Рис. 10.25. Проверка «зацикливания» вытесняющих видов расчета В данном случае система не позволит указать оклад в списке вытесняющих для командировки, так как сама командировка вытесняет оклад косвенно через вытесне- ние вида расчета Дежурство. Таким образом, проверка вы- полняется рекурсивно и будет выявлена сколь угодно длинная цепочка взаимного вытеснения. Проверка полноты списка вытесняющих видов расчета. При записи вида расчета система требует указания пол- ного списка вытесняющих расчетов. Это означает, что в списке должны присутствовать все виды расчета, вытес- няющие текущий не только напрямую, но и косвенно. Например, если в список вытесняющих для оклада вклю- чен вид расчета Дежурство, который, в свою очередь, вы- тесняется командировкой, то система потребует вклю- чить в список еще и командировку. В противном случае при записи элемента возникнет ошибка «Неполный спи- сок вытесняющих расчетов» (рис. 10.26). Вытесняющие виды расчета К ха Бояьжшый Вытесняющие виды расчета Рис. 10.26. Проверка полноты списка вытесняющих видов расчета Таким образом, все виды расчетов, вытесняющие теку- щий косвенно, необходимо также включить в табличную часть ВытесняющиеВидыРасчета. Проверка полноты списка ведущих расчетов. Табличная часть ВедущиеВидыРасчета проверяется по аналогичной схе- ме. В случае если в табличной части не указан вид расче- та, который является ведущим косвенно (через влияние на другой вид расчета), то система выдаст ошибку «Непол- ный список ведущих видов расчета». Так как ведущими могут быть виды расчета любого плана видов расчета, при проверке полноты списка будут анализироваться данные всех планов видов расчета конфигурации. Проверка правильного заполнения предопределенных таб- личных частей производится в момент записи вида расче- та. При этом запись вида расчета может быть иницииро- вана в следующих случаях: ♦ при интерактивной записи вида расчета в режиме «1 С .’Предприятие»; ♦ при записи вида расчета средствами встроенного языка (использование метода ЗаписатьО объекта ВидРасчета- Обьект); ♦ при реструктуризации базы данных после изменения конфигурации. Так как для предопределенных видов расчета возможно редактирование табличных частей в конфигураторе, при обновлении конфигурации базы данных должна производиться проверка табличных
частей всех видов расчета. При этом учитываются не только предопределенные строки этих таблиц, но и вве- денные в режиме «1С:Предприятие». Структура таблиц базы данных Для каждого плана видов расчета в системе хранится ос- новная таблица, а также отдельные таблицы на каждую табличную часть (как предопределенную, так и добавлен- ную разработчиком). Основная таблица содержит все виды расчета данного плана видов расчета с указанием предопределенных свойств, а также реквизитов, добав- ленных разработчиком. Основная таблица имеет структу- ру, представленную в табл. 10.1. Независимо от настройки плана видов расчета в основ- ной таблице будут присутствовать поля Ссылка, Предопре- деленный и ПометкаУдаления. Поле Ссылка хранит внутрен- ний уникальный идентификатор каждого вида расчета в базе данных. В полях Предопределенный и ПометкаУдале- ния, имеющих тип Булево, хранится информация о том, яв- ляется ли данный вид расчета предопределенным и поме- чен ли он на удаление. Поля Код и Наименование присутствуют в таблице в том случае, если в свойствах плана видов расчета для соответ- ствующих полей установлена ненулевая длина. Поле Пе- риодДействияБазовый присутствует в таблицах тех планов видов расчета, которые используют период действия и за- висят от базы. Кроме этого, в основной таблице могут присутствовать дополнительные поля любых типов для каждого реквизи- та, введенного разработчиком. Для каждой из предопределенных табличных частей в базе хранится отдельная таблица. Для всех предопре- деленных табличных частей структура таблицы одина- кова (на примере табличной части ВытесняющиеВидыРасчета) (табл. 10.2). Набор полей этих таблиц не зависит от настроек плана видов расчета и одинаков для всех предопределенных табличных частей. В поле Ссылка хранится ссылка на вид расчета (строку основной таблицы), которому данная строка табличной части принадлежит, то есть внутрен- ний идентификатор этого вида расчета (здесь условно обозначен как наименование со знаком *). Таким обра- зом, все строки этой таблицы со ссылкой на оклад пред- ставляют собой предопределенную табличную часть вида расчета Оклад. Строка табличной части не является ссы- лочным типом, поэтому собственной ссылки не имеет. Значение поля НомерСтроки формируется системой авто- матически как порядковый номер строки табличной час- ти в рамках данной ссылки. В рамках одного вида расчета (ссылки) номера строк таблицы уникальны. При помощи этого поля можно отличить одну строку табличной части от другой. Кроме этого, номер строки определяет порядок следования строк в табличной части. В поле ВидРасчета хранится ссылка на вид расчета (стро- ку основной таблицы), выбранный в табличной части. Например, в приведенном примере для вида расчета Оклад в качестве вытесняющих указаны виды расчета Больнич- ный, Дежурство и Командировка. Тип поля ВидРасчета для всех предопределенных табличных частей может быть разным. Для таблицы ВытесняющиеВидыРасчета — это ссыл- ка на текущий план видов расчета, ВедущиеВидыРасчета — составной тип, включающий ссылку на любой план видов расчета, БазовыеВиды Расчета — составной тип, определяе- мый настройками зависимости от базы текущего плана видов расчета. Поле Предопределенный хранит информацию о том, явля- ется ли данная строка табличной части заданной пред- определенно в конфигураторе. Таблица ВедущиеВидыРасчета формируется в базе данных для всех планов видов расчета, наличие таблиц для ос- тальных предопределенных табличных частей определя- ется настройками плана видов расчета, о которых было сказано выше. Таблица 10.1. Структура основной таблицы плана видов расчета Ссылка Код Наименование Предопре- деленный Пометка- Удаления ПериодДействия- Базовый Реквизит 1 ... Реквизит N ♦ 00001 Оклад ложь ЛОЖЬ ЛОЖЬ ♦ 00002 Командировка ложь ложь ложь * 00003 Сдельный ИСТИНА ложь ложь ♦ 00004 Больничный ложь ложь ложь Таблица 10.2. Таблица предопределенной табличной части ВытесняющиеВидыРасчета Ссылка НомерСтроки ВидРасчета Предопределенный ’Оклад 1 ’Больничный ЛОЖЬ ’Оклад 2 ’Дежурство ложь ’Оклад 3 ’Командировка ложь ’Дежурство 1 ’Командировка ложь
Таблицы для табличных частей плана видов расчета, вве- денных разработчиком, будут иметь структуру, показан- ную в табл. 10.3. Поля Ссылка и НомерСтроки будут присутствовать во всех таких таблицах и выполняют такие же функции, как и для предопределенных табличных частей. Кроме этого, для каждого реквизита табличной части, введенного раз- работчиком, в таблице будет предусмотрено соответст- вующее поле. Таблица 10.3. Таблица табличной части плана видов расчета Ссылка Номер- Строки Реквизит 1 ... Реквизит N ‘Оклад 1 ‘Оклад 2 ‘Дежурство 1 Регистры расчета Назначение регистров расчета Регистры расчета — это прикладные объекты конфигура- ции, предназначенные для периодической регистрации данных о произведенных расчетах для определенных це- лей. Регистров расчета может быть неограниченное коли- чество, для их создания и настройки предусмотрена от- дельная ветка дерева конфигурации (рис. 10.27). ’ •• (Trj) Регистры бухгалтерии Й- 1*5 Регистры расчета ОсновныеНачисленияРегл : E S ДополнительныеНачисленияРегл ; В-S УдержанияРегл Бизнес-процессы Рис. 10.27. Регистры расчета Помимо собственно регистрации записей регистры рас- чета обеспечивают правильное отображение взаимосвя- зей расчетов, о которых шла речь выше. Именно регистры расчета позволяют рассчитывать записи по базе, произво- дить вытеснение записей, формировать сторно-записи. Кроме этого, регистры расчета обеспечивают учет протя- женных во времени расчетов, хранят период действия и фактический период действия записей. Для расчетов, за- висящих от базового периода, регистр расчета также хра- нит данные о базовом периоде. Иными словами, хотя взаимозависимость видов расчета настраивается в планах видов расчета, расчетные механизмы платформы заложе- ны именно в регистры расчета. Свойства регистров расчета Настройка свойств регистра расчета определяет его спо- собность использовать описанные выше расчетные меха- низмы платформы (рис. 10.28). Основная задача регистра расчетов — периодическая ре- гистрация записей о расчетах. Поэтому главными свойст- вами регистра являются его периодичность, а также виды расчетов, которые в нем будут регистрироваться. Свойст- во Периодичность регистра расчетов определяет размер- ность периодов, для которых будет вестись учет в этом регистре. При настройке регистра доступны следующие виды периодичности: годовой, квартальный, месячный и дневной. Соответственно, записи в таком регистре будут фиксироваться в привязке к конкретному году, кварталу, месяцу или дню. Периодичность регистра определяет вид периода регистрации записей. Периодичность регистра зависит от задачи, которую он решает. Для целей расчета зарплаты, как правило, применяют регистры с периодич- ностью месяц. Рис. 10.28. Свойства регистра расчета В одном регистре расчета могут регистрироваться записи только с видами расчета из одного плана видов расчета. Используемый в данном регистре план видов расчета указывается в свойстве регистра План видов расчета. При этом регистров, использующих один план видов расчета, может быть несколько. Свойство Период действия определяет, можно ли будет в данном регистре учитывать записи, протяженные во времени. Установленное свойство Период действия позво- ляет для каждой записи хранить не только период регист- рации, но и период действия, отражающий протяжен- ность этой записи. Кроме этого, установка этого свойства означает, что в данном регистре будет задействован меха- низм вытеснения и будет формироваться фактический период действия записей. Для того чтобы учитывать про- тяженные во времени записи, в плане видов расчета, ис- пользуемом в данном регистре, должно быть установлено свойство Использует период действия.
Если свойство регистра расчета Период действия не уста- новлено, то регистрируемые записи не будут иметь периода действия и, соответственно, протяженности во времени. В таком регистре не будет использоваться меха- низм вытеснения. Тем не менее в регистре без периода действия может быть назначен план видов расчета, ис- пользующий период действия. Например, основные начисления, использующие период действия, могут регистрироваться как в регистре, где бу- дет происходить расчет зарплаты (в этом регистре период действия необходим для расчета), так и в регистре, где начисления учитываются для целей налогообложения (в этом регистре период действия не нужен) (рис. 10.29). Рис 10.29. Использование плана видов расчета разными регистрами расчета В данном случае один и тот же вид расчета из плана ви- дов расчета, использующего период действия, зарегист- рирован в двух разных регистрах, в одном из которых пе- риод действия учитывается, в другом — нет, так как в нем нет необходимости. Если в регистре будут учитываться записи, протяженные во времени, то необходимо настроить для данного регист- ра так называемый График. При расчете записей, являю- щихся протяженными во времени, часто значимость пе- риода действия этих записей не является равномерной, то есть отдельные его части имеют различную значимость. Например, если человек дежурил с 1 по 15 сентября, то этот интервал будет периодом действия этой записи. Од- нако в рамках этого периода не все дни могут являться одинаковыми. Например, человек работает различное ко- личество часов в разные дни, а в какие-то дни у него вы- ходные. Неравномерность значимости периода описыва- ется при помощи графика. График хранит определенное значение для каждой календарной даты года, соответст- венно, используя график, можно оценить значимость лю- бого периода (рис. 10.30). В приведенном примере график хранит количество рабо- чих часов в рамках каждого календарного дня. В данном случае количество часов и есть число, отражающее значи- мость каждого дня в периоде. Полные рабочие дни имеют значимость 8 (рабочих часов), сокращенные дни — 6, а выходные и праздничные дни имеют нулевую значи- мость. График в системе должен быть создан разработчиком самостоятельно как непериодический регистр сведений, у которого как минимум одно измерение типа Дата и как минимум один ресурс типа Число (рис. 10.31). Значение графика А 8 Б Дата графика Рис. 10.30. Неоднородность периода Регистры сведений ЙЛВ ГрафикиРаботы □ JL- Измерения | -- I— Дата □ Ресурсы L | Значение -в Реквизиты Формы Макеты Рис. 10.31. График регистра расчета Разработчик может создавать и более сложную структуру регистра, но указанные измерение и ресурс там должны присутствовать обязательно. Для того чтобы привязать график к регистру расчета, не- обходимо в поле График свойств регистра указать нужный регистр сведений. После этого в поле Значение графика нужно указать ресурс этого регистра сведений, который является значением графика. В поле Дата графика указы- вается измерение регистра, которое является датой гра- фика. Необходимость указания этих полей связана с тем, что в регистре может быть более одного измерения и бо- лее одного ресурса, поэтому поля даты и значения графи- ка должны быть указаны явно. Подробнее работа с графиками описана в разделе «На- стройка протяженных во времени расчетов», с. 332. Свойство регистра расчета Базовый период позволяет хра- нить в регистре базовый период записей и, соответст- венно, использовать механизм зависимости по базовому периоду. Только для записей регистров расчета с уста- новленным свойством Базовый период возможно получение значения базы. При этом свойство Базовый период уста- навливается независимо от свойства Зависимость от базы выбранного плана видов расчета. Даже если в плане видов расчета установлена зависимость от базы, в регист- ре свойство Базовый период может быть не установлено. В этом случае в данном регистре использование зависи- мости по базовому периоду будет недоступно. Структура регистров расчета В зависимости от настроек регистра расчетов его струк- тура будет различной. Общая схема структуры регистра расчета показана на рис. 10.32.
Рис. 10.32. Структура регистра расчета точно установить свойство Активность в значение Истина. Именно это происходит при снятии пометки на удале- ние с такого документа. ♦ Сторно — это признак типа Булево, который обознача- ет, является ли данная запись сторно-записью. Сторно- записи записываются в регистр со значением Истина в этом поле. Если у регистра установлено свойство Период действия, то в структуре появляются следующие предопределенные поля: ♦ ПериодДействияНачало — дата, обозначающая начало ин- тервала периода действия записи; ♦ ПериодДействияКонец — дата, обозначающая конец ин- тервала периода действия записи; ♦ ПериодДействия — дата, отражающая период регистра расчета, в котором действовала запись. Эта дата всегда имеет значение начала первого дня соответствующего периода (по аналогии с полем ПериодРегистрации). При- меры заполнения этих полей для регистров разной пе- риодичности приведены на рис. 10.33. Предопределенные поля Таким образом, в простейшем регистре расчета без пе- риода действия и базового периода всегда будут присут- ствовать следующие поля: ♦ Регистратор — ссылка на документ, который ввел запись в регистр. ♦ Период регистрации — период регистра расчета, к кото- рому относится данная запись. Размер периода опреде- ляется периодичностью регистра расчета. ♦ Вид расчета — ссылка на вид расчета, используемый в данной записи. ♦ Номер строки — порядковый номер записи в рамках данного регистратора. В рамках одного документа-ре- гистратора номер строк уникальный, таким образом, совокупность значений Регистратор и НомерСтроки по- зволяют идентифицировать конкретную запись реги- стра расчета. ♦ Активность — признак активности данной записи. За- пись влияет на учет только в том случае, если актив- ность установлена в значение Истина. Данное поле используется в документах прямой записи в регистр. В таких документах не хранятся данные, необходимые для формирования движений по регистру. Ввод запи- сей производится напрямую в регистр, через вывод на форму документа табличного поля с привязкой к набо- ру записей этого регистра. В демонстрационной конфи- гурации «Сложные периодические расчеты», которая находится на прилагаемом компакт-диске, таким до- кументом является РучнойВводНачислений. Типичным примером использования такого же принципа является документ Операция в решениях по бухгалтерскому уче- ту. При пометке на удаление такого документа нельзя удалять записи из регистра, так как их нельзя будет восстановить. Вместо этого у записей регистра расчета, введенных этим документом, свойство Активность уста- навливается в значение Ложь. При этом записи не удаля- ются из базы данных, но перестают влиять на учет. При необходимости снова задействовать эти записи доста- ПериодДействия 01.03.2005 00:00:00 Вид расчета ПериодДействия П-:•-ч.Дги-'нг ПериодДействия Начало Конец 16.03.2005 22.03.2005 ПериодДействия Начало 1В 03.2005 ПериодДействия Конец 2203.2005 Рис. 10.33. Пример заполнения полей ПериодДействияНачало, ПериодДействияКонец и ПериодДействия Таким образом, запись с одним и тем же интервалом пе- риода действия при записи в регистры разной периодич- ности будет иметь различное значение поля ПериодДей- ствия. Это будет начало месяца в случае помесячного расчета, начало квартала при поквартальном расчете и т. д. У регистров, для которых установлено свойство Базовый период, в структуре будут присутствовать следующие поля: ♦ БазовыйПериодНачало — дата начала интервала базового периода; ♦ БазовыйПериодКонец — дата окончания интервала базо- вого периода;
Поля, добавляемые при разработке Для каждого регистра расчета необходимо продумать структуру измерений, ресурсов и реквизитов, исходя из особенностей учетной задачи. Регистр расчета может и не иметь ни измерений, ни ресурсов, ни реквизитов. В этом случае в регистре можно вести периодический учет запи- сей с различными видами расчета без привязки к кон- кретным объектам (например, сотрудникам) и без сохра- нения числовых результатов расчетов (например, суммы начисления). При этом в регистре можно использовать период действия, будут работать механизмы вытеснения записей и перерасчетов, а также механизм зависимости по базовому периоду. При этом механизм зависимости по базовому периоду не позволит получить расчетную базу. Возможности регистра расчета в такой ситуации сильно ограничены, поэтому для решения прикладных задач, как правило, необходимо задать измерения, ресурсы и рекви- зиты регистра. Измерения регистров расчета Ввод измерений регистров расчета позволяет обозначить объект учета и расчета. При отсутствии измерений реги- стра расчетные механизмы действуют в рамках всех запи- сей. Например, в этом случае любая запись о больничном приведет к вытеснению всех записей об окладе, для кото- рых произойдет пересечение периодов действия. В ре- зультате добавления в регистр измерения ФизЛицо работа регистра изменится следующим образом: при вводе боль- ничного по сотруднику Иванов будут вытеснены только записи об окладе по сотруднику Иванов за соответствую- щий период действия. На рис. 10.34 представлен регистр без измерений, где ссылка на сотрудника хранится в рек- визите, а также регистр, где ссылка на сотрудника хра- нится в измерении ФизЛицо. Сплошными стрелками ука- зано вытеснение записей. Регистр расчета с измерением ФизЛицо ► №« । Г 01-032005 310320ОЬ~\ Оклад ’ i j 01032005 3t03200i ~j Оклад , | | 01032005 31032005 j Рис. 10.34. Использование измерений регистра расчета Такое же разделение произойдет и для механизма зависи- мости по базовому периоду. Так, при расчете месячной премии конкретного сотрудника в базу расчета можно бу- дет включить оклады только этого сотрудника за базовый период расчета. Измерения регистров расчета могут иметь произвольный тип. К формированию структуры измерений нужно под- ходить аккуратно, так как они имеют специфику, отлич- ную от, например, регистров накопления. Измерения ре- гистров расчета не связаны с получением аналитики в определенных разрезах. ВНИМАНИЕ Например, если необходимо учитывать все начисления в разрезе статей затрат, не нужно добавлять измерение СтатьяЗатрат! Это приведет к нарушению учета, так как, на- пример, оклад со статьей затрат Основная з\п в этом слу- чае не будет вытеснен командировкой со статьей затрат Ко- мандировочные, так как у этих записей разные значения измерений. Статья затрат в данном случае должна быть ре- квизитом регистра расчета. Свойство Базовое измерения регистра расчета Состав измерений регистра расчета имеет существенное значение при использовании механизма зависимости по базовому периоду. В разделе «Настройка зависимости по базовому периоду», с. 339, будут подробно рассмотрены методы получения базы для записи регистра расчета. При этом существует возможность получать базу с учетом значений определенных измерений регистра расчета. Это означает, что система при получении базы будет связы- вать таблицу регистра расчета вычисляемой записи с таб- лицами базовых регистров расчета, и в этих связях будет использоваться соединение по измерениям текущего ре- гистра. Например, при получении базы для премии систе- мой может быть выполнено следующее соединение таб- лиц (рис. 10.35). Г екущий регистр расчета "Дополнительные начисления" Лид расчета ФизЛицо Организация Результат Пре» win [ Яданоа Ромашка 0 Пре» win Петров [ ’fwawM j | О ~~ Пзвмми | [~ Хуэнакова Cnatcrpoi | . В~~ ,...' 1 Соединение таблиц по полям "ФизЛицо" и "Организация" ......... ... _________, Базовый регистр расчета "Основные начисления" Вш чета Чргвниэацмя Нвэдды 1млм Иланов ] [ РомаммгаП 9 200~~| Надбавка Иванов | [" Ромаака 200 Оклад р Лужыелова j СжцстроЛ В 900 ^ Рис. 10.35. Пример соединения таблиц при получении базы В данном случае таблица регистра расчета дополнитель- ных начислений будет соединена с таблицей регистра основных начислений для получения базы. При этом по- мимо соединения по измерениям будет присутствовать
соединение по периодам, но при изучении данного вопро- са мы его опускаем. На больших объемах данных такое соединение может вы- полняться достаточно долго. Для того чтобы ускорить выполнение такого запроса, необходимо создать индексы по полям, входящим в условие соединения, в данном слу- чае это измерения ФизЛицо и Организация. Если бы такое измерение было только одно, то эта проблема решалась бы установкой свойства Индексирование у соответствующе- го измерения, однако в данном случае необходим состав- ной индекс, включающий оба поля. Для оптимизации получения базы по двум и более изме- рениям предусмотрено свойство Базовое измерения реги- стра расчета. При установке этого свойства у измерений система создаст дополнительные индексы таблицы реги- стра расчета следующей структуры (табл. 10.4). Таблица 10.4. Дополнительные индексы таблицы регистра расчета Состав индекса Пояснение ПериодРегистрации + [ БазовоеИзмерение 1 ]+ [БазовоеИзмерение2]+... Если базовые измерения не заданы, то просто ПериодРегистрации [ БазовоеИзмерение 1 ]+ [БазовоеИзмерение2]+ ПериодРегистрации +... Если базовые измерения не заданы, то просто отсутствует ПериодДействия + [ БазовоеИзмерение 1 ]+ [БазовоеИзмерение2]+... Если базовые измерения не заданы, то просто ПериодДействия [БазовоеИзмерение1]+ [ БазовоеИзмерение2 ]+ ПериодДействия +... Если базовые измерения не заданы, то отсутствует При этом базовые измерения в индексе будут следовать в том порядке, в котором они заданы в конфигураторе. Такая структура индекса позволяет оптимизировать вы- полнение запросов на получение базы с соединением таб- лиц по набору измерений, которые отмечены как базовые. Поэтому для оптимизации работы решения следует отме- чать как базовые те измерения регистров расчета, кото- рые наиболее часто будут использованы при получении базы. Таким образом, свойство Базовое измерения регистра рас- чета не влияет на логику работы конфигурации, а влияет только на производительность запросов, получающих базу. Ресурсы регистров расчета Состав ресурсов регистра расчета влияет на возможность получения расчетной базы по данному регистру для запи- сей данного регистра или других регистров. Например, если в регистре основных начислений есть ресурс Резуль- тат, хранящий рассчитанную сумму начисления, то для записей этого или другого регистра можно получить рас- четную базу по этому полю, то есть сумму начислений всех записей по базовым видам расчета за базовый пери- од. Если числовой показатель необходимо хранить в ре- гистре, но в расчете по базе он не участвует, то такой по- казатель должен быть введен в структуру регистра как реквизит. Например, поле Размер начисления, отражаю- щее, например, тариф, по которому был рассчитан оклад или размер процента для начисления премии, не должно вводиться в регистр как ресурс, так как получать базу по этому полю бессмысленно. Ресурсы регистров расчета всегда имеют тип Число (рис. 10.36). Рис. 10.36. Ресурсы регистра расчета В приведенном примере база расчета премии будет со- держать данные по всем ресурсам регистра основных на- числений. В данном случае можно получить сумму базо- вых начислений (ресурс Результат) и общее количество отработанных дней в зачет (ресурс Дни). В данном при- мере в ресурсе Дни сохраняется значение количества от- работанных дней для целей последующего расчета опла- ты по среднему заработку. При расчете по среднему через механизм зависимости по базовому периоду мож- но будет получить как данные о сумме заработка, так и о количестве дней, засчитанных в отработанное время. Реквизиты регистров расчета Реквизиты регистра расчета — это произвольные дополни- тельные поля, которые необходимо хранить в регистре. Эти данные могут использоваться как при расчете записи, так и для формирования отчетов по регистру расчета. На- пример, реквизит Размер начисления участвует в формуле расчета записей, а реквизит Статья затрат может использо- ваться как группировка или отбор в отчете по начислени- ям. Добавление в регистр нового реквизита не оказывает принципиального влияния на учет и работу данного реги- стра (за исключением случаев, когда реквизит связан с графиком, о связи с графиком см. раздел «Настройка про- тяженных во времени расчетов», с. 332). Структура таблиц базы данных Данные каждого регистра расчета в базе хранятся в виде одной основной таблицы. Структура таблицы определя- ется настройками регистра. В зависимости от настроек,
Таблица 10.5. Таблица регистра расчета Период Реги- страции Реги- стратор Номер Строки Ввд Расчета Период Дейст- вия Период Действия Начало Период Действия Конец Базовый Период Начало Базовый Период Конец Актив- ность Сторно 01.02.05 ’Начисление зарплаты №1 1 Оклад 01.02.05 01.02.05 28.02.05 ИСТИНА ЛОЖЬ 01.02.05 ’Начисление зарплаты №1 2 Коман- дировка 01.02.05 03.02.05 12.02.05 ИСТИНА ложь 01.02.05 ’Начисление зарплаты №1 3 Оклад 01.02.05 01.02.05 28.02.05 ИСТИНА ложь 01.03.05 ’Начисление зарплаты №2 1 Оклад 01.03.05 01.03.05 31.03.05 ИСТИНА ложь 01.03.05 ’Начисление зарплаты №2 2 Надбав- ка 01.03.05 01.03.05 31.03.05 01.02.05 28.02.05 ИСТИНА ложь таблица будет содержать предопределенные поля, а так- же поля, добавленные разработчиком (табл. 10.5). Каки- ми настройками определяется существование в таблице этих полей, а также их предназначение, описано в разделе «Структура регистров расчета», с. 327. В данной таблице поля ПриодРегистрации, Регистратор, Но- мерСтроки, ВидРасчета, Активность и Сторно присутствуют в таблице регистра независимо от его настроек. Поля Пе- риодДействия, ПериодДействияНачало, ПериодДействияКонец, БазовыйПериодНачало и БазовыйПериодКонец будут при- сутствовать в таблице в зависимости от настроек, указан- ных выше. Кроме указанных полей, в таблице присутст- вуют дополнительные поля на каждое добавленное разра- ботчиком измерение, ресурс и реквизит. Важно помнить, что в полях ПериодРегистрации и Период- Действия хранятся даты начала соответствующего расчет- ного периода. Это нужно учитывать при построении от- четов. Например, при построении отчета по начислениям с условием по периоду действия с 03.02.2005 по 28.02.2005 в выборку не попадет ни одна запись, так как все записи, у которых период действия лежит в феврале, будут в поле ПериодДействия содержать значение 01.02.2005 00:00:00. Для регистров, использующих период действия, данные о фактическом периоде действия записей не хранятся в основной таблице. Для хранения этих данных для каждо- го такого регистра существует отдельная физическая таб- лица следующей структуры (табл. 10.6). Названия полей приведены условно, так как таблица не предназначена для работы напрямую средствами встро- енного языка. Заполнение таблицы производится систе- мой автоматически при записи в регистр расчета с фор- мированием фактического периода действия. Чтение данных этой таблицы доступно в запросе через виртуаль- ную таблицу ФактическийПериодДействия или специальными методами встроенного языка. Работа с этими методами подробно рассмотрена в разделе «Использование меха- низма вытеснения», с. 332. Таблица 10.6. Таблица фактического периода действия Регистратор Номер строки Дата начала интервала Дата окончания интервала ’Начислени е зарплаты №1 1 01.02.2005 13.02.2005 ’Начислени е зарплаты №1 1 25.02.2005 28.02.2005 ’Начислени е зарплаты №1 2 01.02.2005 28.02.2005 Значения полей Регистратор и Номер строки однозначно указывают на запись основной таблицы, то есть запись регистра расчета. Для каждой записи основной таблицы, то есть для каждой пары значений регистратора и номера строки, в таблице могут храниться несколько непересе- кающихся интервалов фактического периода действия, даты начала и окончания которых хранятся в соответст- вующих полях таблицы. В случае если запись имеет пус- той фактический период действия, в физической таблице даты начала и окончания интервала фактического перио- да действия для такой записи будут равны значению даты по умолчанию (‘01.01.0001 00:00:00’).
Настройка протяженных во времени расчетов Использование механизма вытеснения Настройка планов видов расчета и регистров расчета Для организации учета протяженных во времени расче- тов у плана видов расчета должно быть установлено свойство Использует период действия. Это позволит на- страивать в видах расчета взаимное вытеснение путем заполнения предопределенной табличной части Вытесняю- щиеВидыРасчета. В используемом регистре расчета должно быть установ- лено свойство Период действия, а также привязан график. При такой настройке все записи регистра помимо перио- да регистрации будут хранить данные о периоде дейст- вия, то есть о протяженности во времени. Формирование фактического периода действия При формировании записи в регистре расчета, поддержи- вающем период действия, происходит анализ конкуренции за период действия вводимого вида расчета с существую- щими в регистре записями. Результатом такой конкурен- ции будет изменение фактического периода действия вводимой или существующих записей. Понятие фактического периода действия применимо только к конкретной записи регистра расчета. При этом данные о фактическом периоде действия не хра- нятся в основной таблице регистра расчета, но могут быть получены системными средствами, о которых речь пойдет ниже. Фактический период действия за- писи можно представить в виде таблицы следующего вида (табл. 10.7). Каждая строка этой таблицы представляет собой один интервал фактического периода действия. При отсутст- вии вытесняющих записей результатом формирования фактического периода действия будет одна строка табли- цы. Интервал, заданный в этой строке, будет совпадать с периодом действия записи. При изменении фактическо- го периода действия в результате ввода вытесняющих за- писей, содержимое таблицы меняется, в ней остаются только интервалы, на которых запись не вытеснена дру- гими записями. Пример изменения фактического перио- да действия приведен на рис. 10.37. Таблица 10.7. Фактический период действия ДатаНачала ДатаОкончания 01.02.2005 13.02.2005 18.02.2005 28.02.2005 Таким образом, при вытеснении записи период действия не меняется, изменяется только состав таблицы фактиче- ского периода действия. При формировании фактического периода действия про- исходит анализ конкуренции записей только в рамках данного регистра расчета. Иными словами, запись регист- ра расчета может вытеснять только записи этого же реги- стра. При анализе конкуренции видов расчета на пересечении периодов действия учитывается период регистрации за- писей. Если запись с вытесняющим видом расчета имеет более поздний период регистрации, чем запись с вытес- няемым видом расчета, механизм вытеснения работать не будет. При этом конкурирующие записи все равно не могут иметь пересекающийся период действия, поэтому фактический период действия записи с более поздним периодом регистрации будет пустым на интервале пере- сечения. При этом при формировании фактического пе- риода действия учитывается наличие в анализируемом периоде сторно-записей по конкурирующим видам рас- чета. Если на интервале пересечения конкурирующих видов расчета присутствуют сторно-записи, то фактиче- ский период действия записи с более поздним периодом регистрации будет непустым на интервале периода дей- ствия сторно-записи конкурирующего вида расчета. Начальное состояние записи: вытеснения отсутствуют Рис. 10.37. Изменение фактического периода действия
Получение фактического периода действия средствами встроенного языка Данные о фактическом периоде действия записи регистра расчета можно получить, обратившись к свойству Факти- ческийПериодДействия объекта РегистрРасчетаЗапись. В этом свойстве в виде фиксированного массива хранятся дан- ные об интервалах фактического периода действия данной записи. Элементами этого массива являются значения типа ЭлементФактическогоПериодаДействия. Каждый элемент фактического периода действия имеет два собственных свойства — ДатаНачала и ДатаОкончания, отражающие начало и конец интервала фактического периода действия. Ниже приведен пример кода, который вычисляет количество календарных дней фактического периода действия, то есть общую длину интервалов, для каждой записи, вве- денной текущим документом (листинг 10.1). Этот фраг- мент присутствует в демо-конфигурации в обработке «Запросы и методы». Листинг 10.1. Вычисление количества календарных дней фактического периода действия нДлинаСуток = 24 * 60 * 60: Выборка = РегистрыРасчета.ОсновныеНачисленияРегл. ВыбратьПоРегистратору(Ссылка); Пока Выборка.Следующий() Цикл Запись = Выборка.ПолучитьЗапись(); ФактическийПериод = Запись.ФактическийПериодДействия; КоличествоДней = 0: Для Каждого Интервал из ФактическийПериод Цикл КоличествоДней = КоличествоДней + Окр((КонецДня(Интервал.ДатаОкончания) - Интервал.ДатаНачала + 1) / нДлинаСуток, 0, Режии0кругления.0кр15как20); КонецЦикла; Сообщить("Количество дней фактического периода для строки № " + Запись.НомерСтроки + " : " + КоличествоДней): КонецЦикла; Получение фактического периода действия при помощи запроса Для возможности получения фактического периода дей- ствия при помощи запроса предусмотрена виртуальная таблица фактического периода действия. Структура по- лей этой таблицы полностью идентична структуре основ- ной таблицы регистра расчета. Единственное ее отличие от основной таблицы состоит в том, что поля ПериодДей- ствияНачало и ПериодДействияКонец обозначают не собст- венно период действия, а интервал фактического периода действия. В случае если фактический период действия записи задается несколькими интервалами, то в вирту- альной таблице такая запись будет представлена несколь- кими строками (рис. 10.38). В каждой из этих строк все данные повторяют данные строки основной таблицы, за исключением полей Период- ДействияНачало и ПериодДействияКонец, которые обозна- чают границы интервалов фактического периода действия. Пример запроса, который считает количество календар- ных дней фактического периода действия каждой записи документа, представлен в листинге 10.2. Листинг 10.2. Получение количества календарных дней фактического периода действия запросом Запрос = Новый Запрос; Запрос.Текст = " ВЫБРАТЬ ФактическийПериод.НомерСтроки, СУММА(РАЗНОСТЪДАТ(ФактическийПериод.ПериодДействияНачало. КОНЕЦПЕРИОДА(ФактическийПериод. ПериодДействияКонец. ДЕНЬ). ДЕНЬ)) + 1 КАК КоличествоДней ИЗ РегистрРасчета.ОсновныеНачисленияРегл. ФактическийПериодДействия( Регистратор = &Регистратор) КАК ФактическийПериод СГРУППИРОВАТЬ ПО ФактическийПериод.НомерСтроки"; Запрос.УстановитьПараметр("Регистратор", Ссылка); Выборка = Залрос.ВыполнитьО.ВыбратьО; Пока Выборка.Следующий() Цикл Сообщить("Количество дней фактического периода для строки fe " + Выборка.НомерСтроки + " : " + Выборка.КоличествоДней): КонецЦикла; Этот фрагмент присутствует в обработке Запросы и методы в демонстрационной конфигурации «Сложные периоди- ческие расчеты», которая находится на прилагаемом ком- пакт-диске. Необходимо очень внимательно подходить к установке параметров виртуальных таблиц. Виртуальная таблица, по сути, представляет собой запрос, который платформа самостоятельно строит по таблицам базы данных. Вирту- альная таблица фактического периода действия форми- руется запросом по основной таблице регистра расчета и таблице фактического периода действия. У этой таблицы присутствует единственный параметр Условие, заполнив который можно передать определенное условие в запрос платформы, формирующий виртуальную таблицу. Основная таблица регистра расчета Пер нодРет нстрацим ВндРасчета Пер нодДе йств ня Пер и о дДе йств няНача л о Пер нодДе йств няКоиец 01.02.2005 Оклад 01.02.2005 01.02 2005 28 02 2005 0102 2005 Надбавка 01.02.2005 01.0 2 2005 28 0 2 2005 Виртуальная таблица ФахтнческннПернодДенствня Пе р но дРег метр ацнн ВндРасчета Пер ио дДейств ня Пер нодДе йств няНача л о Пе р нодДе йств няКоме ц 01.02.2005 Оклад 01.02.2005 01.02.2005 13 0 2 2005 01.02 2005 Оклад 01.0 2 2005 18.02.2005 28.0 2 2 005 01.02.2005 Надбавка 01.0 2 2005 01 02 2 005 28.02 2 005 Рис. 10.38. Фактический период действия
В данном случае нас интересует фактический период дей- ствия только по движениям одного документа, поэтому в параметр Условие необходимо передать текст Регистратор = &Регистратор, после чего указать ссылку на документ как значение параметра Регистратор. В этом случае в виртуаль- ную таблицу попадут только фактический период дейст- вия для записей этого документа. Если то же самое усло- вие задать не в виртуальной таблице, а в самом запросе через конструкцию ГДЕ, то результат будет аналогичным, но производительность существенно ниже, так как сначала будет сформирована виртуальная таблица фактического периода действия для всех записей регистр расчета, а по- том запрос отберет из них те, которые относятся к нужно- му документу. Таким образом, в запросе будет обработано большое количество лишней информации. В случае необходимости получить фактический период действия для нескольких записей регистра расчета (как в приведенном примере), рекомендуется использовать за- прос как более производительный способ получения дан- ных. Использование графиков Протяженные во времени расчеты тесно связаны с дан- ными графика, используемого в регистре расчета. Как уже отмечалось, данные графика содержат определенные значения для каждого календарного дня периода. Регистр расчета рассматривает график как таблицу следующего вида (табл. 10.8). Эти данные в системе хранятся в виде регистра сведений, созданного при разработке конфигурации. При этом дату графика платформа получает из измерения, заданного в свойствах регистра расчета в поле Дата графика, а значе- ние графика — из ресурса, указанного в поле Значение гра- фика. Рассмотрим использование данных графика на примере. Пусть в регистре сведений Графики работы хранятся следую- щие значения для календарных дней февраля (табл. 10.9). Фактически, этот график представляет собой пятиднев- ный график работы с двумя выходными и праздником 23 февраля. Рабочие дни в качестве значения имеют 1, выходные и праздники — 0. Использование данных графика для расчета записей Пример записи, расчет которой зависит от данных графи- ка, — оклад по месячной тарифной ставке. Для расчета этой записи используется размер тарифа, а также данные о количестве рабочих дней в периоде и о количестве фак- тически отработанных дней в этом периоде. Роль графика состоит в том, чтобы данные о фактически отработанных днях и норме дней могли быть получены системой авто- матически. Формула расчета результата начисления в данном случае выглядит следующим образом: Результат = Тариф * Кол-во отработанных дней/ Кол-во рабочих дней периода Таблица 10.8. «Таблица» графика Дата графика 01.02.2005 02.02.2005 03.02.2005 04.02.2005 ... 28.02.2005 Значение графика 1 1 1 1 Таблица 10.9. Календарный график февраля 1 2 3 4 5 6 7 8 9 10 1 1 1 1 1 1 1 1 11 12 13 14 15 16 17 18 19 20 1 1 1 1 1 1 1 21 22 23 24 25 26 27 28 1 1 1 1 I 2 3 4 5 б Т 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 И 24 25 26 27 20 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Сумма значений графика за период действия - норма дней (всего 19) 1 2 3 4 5 6 7 0 9 10 11 12 13 14 15 16 17 10 19 20 21 22 23 24 25 26 27 20 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Сумма значений графика за фактический период действия-отработано дней (всего 12) Рис. 10.39. Получение данных графика
Тариф может быть получен, например, из реквизита Раз- мер регистра расчетов (например, 5000 рублей). Для по- лучения количества отработанных и рабочих дней будут необходимы данные графика. Количество рабочих дней можно получить, просуммировав значения графика за пе- риод действия записи. Таким образом, если оклад назна- чен за месяц, будут просуммированы значения графика за весь месяц. Количество фактически отработанных ча- сов может быть получено путем суммирования значений графика за все интервалы фактического периода дейст- вия данной записи (рис. 10.39). Полученные таким образом данные могут быть использо- ваны в формуле расчета оклада: Результат = 5000 * 12 / 19 = 3157, 89 Использование данных графика для вычисления части записи В определенных ситуациях для протяженных во времени записей возникает необходимость вычислить значения ресурсов только части записи, попавшей в определенный интервал. Такая задача, в частности, возникает при час- тичном пересечении записью базового периода другой за- писи (рис. 10.40). Рис. 10.40. Частичное пересечение с записью базового периода В данном случае вводится запись о премии на первую по- ловину месяца. Следовательно, начисленный за месяц ок- лад в размере 10 000 рублей попадает в базовый период премии только частично. Таким образом, регистр расчета должен включить в базу расчета премии только часть из начисленных 10 000 рублей. Делить сумму по количеству календарных дней, в данном случае поровну, было бы не- корректно, так как в первой половине месяца могло быть больше рабочих дней, чем во второй. Поэтому для вычис- ления части записи, попадающей в определенный период, используются данные графика, которые служат относи- тельным весом каждого дня этого периода. Иными слова- ми база расчета премии в данном случае будет рассчитана системой следующим образом: База расчета = Результат оклада * (Значения графика, попавшие в базовый период / Значения графика за пери- од действия оклада) Расчетная база премии по окладу в этом случае составит (рис. 10.41): База расчета = 10 000 * 11 / 19 = 5 789,47 Настройка использования нескольких графиков в одном регистре расчета Выше было описано, каким образом можно привязать данные графика, хранящиеся в регистре сведений, к ре- гистру расчета. Однако, как правило, при расчете записей используются различные данные графика. Например, один из сотрудников получает оклад по дням, и для его расчета нужен график, где рабочие дни отмечены значе- нием 1, как в приведенных выше графиках. Другой со- трудник может получать оклад по часам, для расчета ко- торого нужен график, значением которого является количество рабочих часов в каждом календарном дне. Бо- лее того, сотрудники помогут работать по разным графи- кам работы. Например, бухгалтер работает по пятиднев- ке, а охранник — в режиме сутки через двое. Иными словами, для каждого сотрудника необходимо задавать различное значение графика для одной даты. При этом все эти начисления рассчитываются в одном регистре, а система позволяет привязать к регистру только один график. Для реализации хранения разных вариантов графика не- обходимо в соответствующем регистре сведений доба- вить новые измерения. Так, для хранения различных гра- фиков для целей расчета зарплаты по дням или по часам можно ввести в регистр сведений новое измерение Вид- УчетаВремени, тип которого — перечисление ВидыУчета- Времени с двумя возможными значениями — ПоДням и По- Часам. В этом случае для каждой даты графика можно будет указать два разных значения, каждое из которых будет соответствовать определенному виду учета времени. Для того чтобы реализовать возможность хранения раз- личных графиков работы (пятидневка, шестидневка и т. д.), можно добавить в регистр сведений еще одно измерение Сумма значений графика за весь период действия оклада (всего 19) Рис. 10.41. Получение данных графика
ГрафикРаботы, имеющий тип СправочникСсылка.ГрафикиРабо- ты. Такая настройка позволит в режиме «1 (^Предпри- ятие» создавать неограниченное количество графиков ра- боты и вводить данные по ним в регистр сведений. Для каждого графика работы можно будет заполнить график как по дням, так и по часам. Эти данные могут быть ис- пользованы в последующих расчетах. Структура регистра сведений после этих изменений по- казана на рис. 10.42. в-fa Регистры сведений В ГрафикиРаботы □ Измерения ; 1- t- Дата |--L. ЕидУчетаВременй i : t— ГрафикРабсты В Ресурсы g Значение : -s Реквизиты а Формы Макеты Рис. 10.42. Структура регистра расчета Такая структура обеспечивает хранение в одном регистре сведений неограниченного количества различных графи- ков. После разработки структуры регистра необходимо ука- зать регистру расчета, какой конкретно график должен быть использован для расчета каждой записи. Для этого необходимо связать измерения или ресурсы регистра рас- чета с измерениями регистра сведений графиков. Иными словами, в каждой записи регистра расчета должна содер- жаться информация, необходимая для построения отбо- ров по измерениям регистра сведений графиков. На осно- вании данных записи регистра расчета должен быть определен конкретный график работы. Например, для ре- гистра сведений приведенной выше структуры должны фиксироваться в регистре расчета данные о конкретном графике работы и о виде учета времени, которые должны быть использованы в данной записи. Для этого нужно добавить в структуру регистра расчета дополнительные поля (измерения или реквизиты в зависимости от специ- фики задачи), после чего связать эти поля с измерениями регистра сведений графиков (рис. 10.43). Пер кодРег метр ацин ВндРасчета Физ Лиц* ГрафикРаботы ВкдУчвтаВремеин 01 02 2005 Оклад Иванов Пятидневка ПоДням 01.02 2005 Оклад Петров Сутки через двое ПоЧасам Й--";. ГраФикиРаботы 5• J-* Измерения Н-Ц Дата ‘ Ц ВидУчетаВремени ____*-* ГрафикРаботы Рис. 10.43. Записи регистра расчета В этом случае для расчета оклада сотруднику Иванов бу- дет использован график работы Пятидневка с видом учета времени По дням, а сотруднику Петров оклад будет рассчи- тан по часам по графику работы Сутки через двое. Соответ- ствующие графики будут получены системой из регистра сведений с отбором по указанным в записи значениям из- мерений ГрафикРаботы и ВидУчетаВремени. Связь измерений и реквизитов регистра расчета с измере- ниями регистра сведений производится через свойство Связь с графиком соответствующих полей регистра расчета (рис. 10.44). Рис. 10.44. Связь измерения с графиком В данном примере для реквизита ГрафикРаботы регистра расчета в свойстве Связь с графиком указано соответствую- щее измерение регистра сведений, в котором хранятся данные графика. Получение данных графика средствами встроенного языка Данные графика можно получить для любой записи регист- ра расчета, поддерживающего период действия. Средствами встроенного языка можно получить данные графика как для конкретной записи, так и одновременно для нескольких записей регистра расчета. Для получения данных графика для нескольких записей используется метод ПолучитьДан- ныеГрафикаО объекта РегистрРасчетаМенеджер. В качестве па- раметров для метода указывается отбор записей регистра расчета, а также вид периода регистра расчета, за который необходимо получить данные графика. В качестве отбора можно передавать как значение типа Структура, так и зна- чение типа Отбор. В обоих случаях можно устанавливать отборы по регистратору, а также по измерениям регистра расчета. Отбор должен быть установлен как минимум по регистратору, поэтому в структуре обязательно должно присутствовать условие на регистратор, а если использу- ется значение типа Отбор, то в нем должен присутствовать элемент отбора по полю Регистратор. Во всех элементах отбора допустим только вид сравнения Равно. Вид периода задается как значение системного перечис- ления ВидПериодаРегистраРасчета и может принимать сле- дующие значения: БазовыйПериод, ПериодДействия, ПериодРе- гистрации, ФактическийПериодДействия. В каждом из случаев будут получены данные графика за соответствующий пе- риод каждой записи регистра. При использовании перио- да регистрации будут получены данные за весь период, в котором зарегистрирована запись (например, за весь месяц). Использование значения ПериодДействия позволит получить данные графика за интервал с даты ПериодДей- ствияНачало по дату ПериодДействияКонец. Метод ПолучитьДанныеГрафикаО объекта РегистрРасчетаМенед- жер возвращает таблицу значений следующей структуры (табл. 10.10). Таблица 10.10. Структура таблицы, возвращаемой методом ПолучитьДанныеГрафикаО LineNumber Значение 1 21 2 19 3 154
Количество строк таблицы равно количеству записей ре- гистра, соответствующих отбору. В первой колонке таб- лицы, которая называется LineNumber, указывается номер записи регистра расчета (по значению поля НомерСтроки). Повторение номеров исключено, так как отбор всегда со- держит условие на регистратор. Во второй колонке ука- зывается значение графика для данной строки. Имя ко- лонки совпадает с именем ресурса регистра сведений графиков, в котором хранится значение графика. Ниже приведен текст модуля, позволяющий получить данные графика за фактический период действия для ка- ждой строки документа (листинг 10.3). Этот фрагмент присутствует в демо-конфигурации в обработке «Запро- сы и методы». Листинг 10.3. Получение данных графика Менеджер = РегистрыРасчета.ОсновныеНачисленияРегл; Отбор = Новый Структура!"Регистратор", Ссылка); ДанныеГрафика = Менеджер. ПолучитьДанныеГрафикаСОтбор, ВидПериодаРегистраРасчета.ФактическийПериодДействия): Для Каждого Строка из ДанныеГрафика Цикл Сообщить("Данные графика по фактическому периоду для строки К» " + Строка.LineNumber + " : " + Строка.Значение); КонецЦикла; Для получения данных графика для конкретной записи можно использовать одноименный метод ПолучитьДанные- ГрафикаО объекта РегистрРасчетаЗапись. В качестве пара- метра указывается только вид периода регистра расчета. Метод возвращает таблицу значений, у которой одна строка и одна колонка. Имя колонки совпадает с именем ресурса регистра сведений графиков, в строке указывают- ся данные графика для записи. Получение данных графика при помощи запроса Для получения данных графика при помощи запроса ис- пользуется виртуальная таблица данных графика регист- ра расчета. Эта виртуальная таблица имеет единственный параметр Условие, позволяющий передать произвольное условие в запрос, который платформа формирует по таб- лицам базы данных для получения виртуальной таблицы. Виртуальная таблица данных графика расширяет струк- туру основной таблицы, добавляя для каждой ее стро- ки данные графика за все возможные виды периодов (рис. 10.45). Количество строк в виртуальной таблице равно количе- ству записей регистра расчета, удовлетворяющих усло- вию, заданному в параметр виртуальной таблицы. Первая часть полей виртуальной таблицы данных графика пол- ностью совпадает с полями основной таблицы регистра. Дополнительные поля добавляются по числу ресурсов регистра сведений графиков. На каждый ресурс в вирту- альной таблице данных графика будет добавлено 4 поля, в которых будут рассчитаны значения графика по данно- му ресурсу за каждый из возможных периодов: период действия, фактический период действия, базовый период и период регистрации. В отличие от метода ПолучитьДанныеГрафикаО использова- ние виртуальной таблицы данных графика позволяет по- лучить данные графика не только по ресурсу регистра сведений, являющемуся значением графика, но и по лю- бым другим ресурсам этого регистра. Виртуальная табли- ца также позволяет получить данные графика для набора записей с произвольным условием, например, не принад- лежащих одному регистратору. В-. П ериодРегистрации Регистратор НомерСтроки ВидРасчета ПериодДействия ПериодДействияНачало j Данные основной I таблицы регистра I расчета — БазовыйЛериодНачало — БазовыйЛериодКонец — Активность Сторно EJ ФизЛицо L. Организация ...| Результат i - — Размер |j — ГрафикРаботы Й™— ВидУчетаВремени ЗначениеПериодДействия ЗначениеФактическийПериодДействия I ———- ЗначениеБазовыйЛериод Г ЗначениеП ериодРегистрации J _ ДополнительноеЗначениеПериодДействия актическийПериод Действия Д опо лнительноеЗначениеБ азовыйП ериод ДополнигельноеЗначениеПериодРегистрации । Данные графика по 1 каждому ресурсу I регистра сведений { графиков Рис. 10.45. Виртуальная таблица ДанныеГрафика Ниже приведен текст модуля, позволяющий получить данные графика за фактический период действия для всех записей документа (листинг 10.4). Этот фрагмент присутствует в демо-конфигурации в обработке «Запро- сы и методы». Листинг 10.4. Получение данных графика запросом Запрос=Новый Запрос; Запрос.Текст=” ВЫБРАТЬ ДанныеГ рафика.НомерСтроки, ДанныеГрафика.ЗначениеФактическийПериодДействия КАК Данные ИЗ РегистрРасчета.ОсновныеНачисленияРегл.ДанныеГрафика! Регистратор = &Регистратор) КАК ДанныеГрафика"; Запрос.УстановитьПараметр("Регистратор", Ссылка); Выборка=3апрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл Сообщить("Данные графика по фактическому периоду для строки N? " + Выборка.НомерСтроки + " : " + Выборка.Данные): КонецЦикла; Сторнирование Конкуренция с записями более раннего периода регистрации Возможность указать для записи период действия, отлич- ный от периода регистрации, существует только у регист- ров, поддерживающих период действия. В этом случае, если у записи период действия раньше периода регистра- ции (то есть запись зарегистрирована «с опозданием»), эта запись может вступать в конкуренцию за период дей- ствия с записями более раннего периода регистрации.
При этом механизм вытеснения действовать не будет, так как запись имеет более поздний период регистрации, но конкуренция видов расчета останется. В результате у за- писи с более поздним периодом регистрации может обра- зоваться меньший фактический период действия в силу того, что она не может действовать одновременно с кон- курирующими видами расчета. Например, больничный за март, введенный в апреле, вступает в конкуренцию с дежурством, зарегистрирован- ным и действовавшим в марте. В результате фактический период действия больничного будет меньше периода дей- ствия, так как записи не могут пересекаться по фактиче- скому периоду действия (рис. 10.46). Рис. 10.46. Конкуренция в прошлом периоде В данном случае фактический период действия на ин- тервале с 15 по 22 марта будет пустым, так как этот ин- тервал уже занят конкурирующим расчетом, введенным ранее. Наличие сторно-записи по виду расчета Дежурство позво- лит записи о больничном занять весь свой период дейст- вия. При формировании фактического периода действия больничного будет учтен период действия сторно-записи по дежурству (рис. 10.47). Рис. 10.47. Использование сторно-записей Таким образом, при формировании записей, которые вступают в конкуренцию с записями более раннего пе- риода регистрации, необходимо ввести также сторно- записи по конкурирующим видам расчета, иначе фак- тический период действия будет пустым на интервалах пересечения периода действия конкурирующих запи- сей. Формирование сторно-записей. Метод ПолучитьДополнение() Сторно-записи, «прикрывающие» фактический период действия вводимой записи с более поздним периодом ре- гистрации, могут быть сформированы вручную стандарт- ными методами формирования записей регистра расчета. В этом случае разработчик должен самостоятельно пре- дусмотреть алгоритм, по которому будут сформированы сторно-записи, исходя из первоначального набора запи- сей. Это достаточно сложный путь, предполагающий са- мостоятельный анализ взаимодействия периодов дейст- вия конкурирующих записей. Вместо формирования собственных алгоритмов можно воспользоваться методом ПолучитьДополнениеО объекта Ре- гистрРасчетаНаборЗаписей. Суть его состоит в том, что сис- тема самостоятельно анализирует возможные конфликты формируемого набора записей с записями, имеющими более ранний период регистрации. Если обнаруживается пересечение периодов действия с конкурирующими за- писями, на каждое такое пересечение система предложит сформировать сторно-запись, которая позволит вводимо- му набору записей сохранить фактический период дейст- вия. При этом система укажет, по каким видам расчета необходимо ввести сторно-записи и какой период дейст- вия они должны иметь. Метод ПолучитьДополнениеО применяется к набору записей регистра расчета, поддерживающего период действия, и не требует указания параметров. Данный метод возвращает значение типа ТаблицаЗначений, в которой содержатся все необходимые данные для формирования сторно-записей. Таблица включает значение всех полей записей, для ко- торых должны быть введены сторно-записи (кроме полей Регистратор и НомерСтроки, которые не нужны для формиро- вания сторно-записей), а также дополнительные поля — период регистрации сторно-записи и даты начала и окон- чания периода действия сторно-записи. В приведенном примере для набора записей, состоящего из одной записи о больничном, метод ПолучитьДополнениеО вернет таблицу следующего вида (табл. 10.11). Полученная таблица позволяет ввести необходимые стор- но-записи без дополнительных вычислений. Ниже приве- ден текст модуля, в котором используется метод Получить- ДополнениеО и формируются сторно-записи в регистре расчета (листинг 10.5). Пример использования данного метода можно также посмотреть в демо-конфигурации в обработке «Запросы и методы». Листинг 10.5. Получение дополнения // Получить набор записей текущего документа НаборЗалисей=РегистрыРасчета.0сновныеНачисленияРегл. СоздатьНаборЗаписей(); НаборЗаписей.Отбор.Регистратор.Установить(Ссылка, Истина): НаборЗаписей.Прочитать(); // Получить таблицу сторно-записей для набора записей // текущего документа ТаблицаСторно = НаборЗаписей.ПолучитьДополнениеО; // Сформировать сторно-записи в регистре расчета Для Каждого СтрокаСторно из ТаблицаСторно Цикл Запись = Движения. ОсновныеНачисленияРегл.ДобавитьО; Запись.ВидРасчета = СтрокаСторно.ВидРасчета; Запись.ПериодРегистрации = СтрокаСторно. ПериодРегистрацииСторно;
Таблица 10.11. Запись дополнения Период Регистрации ВидРасчета Период Действия ... Период регистрации сторно Период действия начало сторно Период действия конец сторно 01.03.2005 Дежурство 01.03.2005 01.04.2005 15.03.2005 22.03.2005 Таблица 10.12. Сторно-запись по дежурству Период Регистрации ВидРасчета ПериодДействия Начало ПериодДействия Конец ... Сторно 01.04.2005 Дежурство 15.03.2005 22.03.2005 ИСТИНА Запись.ПериодДействияНачало = СтрокаСторно. ПериодДейств ияНачалоСторно; Запись.ПериодДействияКонец = СтрокаСторно. ПериодДействияКонецСторно; // Заполнить измерения и реквизиты записи // ... Запись.Сторно = Истина; КонецЦикла; Таким образом, сторно-записи имеют те же значения по- лей, что и исходные записи, за исключением периода реги- страции и периода действия. Сторно-записи отличаются от обычных записей значением ИСТИНА в предопределен- ном поле Сторно. Так, сторно-запись по дежурству будет выглядеть следующим образом (табл. 10.12). Значения ресурсов сторно-записи не переносятся из ис- ходной записи. Сторно-записи должны рассчитываться в том же порядке, что и обычные записи. Расчет записей подробно рассмотрен в разделе «Технология формирова- ния и расчета записей регистров расчета», с. 345. Настройка зависимости по базовому периоду Настройка планов видов расчета и регистров расчета Настройка зависимости от базы Для возможности ввода и расчета записей, зависимых по базовому периоду от других записей, необходимо настро- ить свойства соответствующих планов видов расчета и регистров расчета. В плане видов расчета, виды расчета которого будут зави- сеть по базовому периоду от других видов расчета, необ- ходимо настроить зависимость от базы. Для этого свойст- во Зависимость от базы плана видов расчета должно быть установлено в одно из значений Зависит по периоду дейст- вия или Зависит по периоду регистрации. Зависимость по периоду действия предполагает анализ пересечения фактического периода действия записей ба- зовых видов расчета с базовым периодом текущей записи. При такой зависимости возможно частичное попадание какой-либо записи в базу расчета текущей записи. Если у записи по базовому виду расчета нет периода действия, то будет проанализировано попадание периода регистра- ции этой записи в базовый период текущей записи. Рассмотрим механизм зависимости от базы по периоду действия на примере начисления премии за 3 месяца, у которой базовый период установлен с 15.01.2005 по 15.04.2005 (рис. 10.48). В список базовых видов расчета этой премии входят виды расчета Оклад и Премия за месяц. январь февраль март апрель май Рис. 10.48. Зависимость от базы по периоду действия Для базовых расчетов, имеющих период действия (в дан- ном случае оклад), будет анализироваться пересечение их фактического периода действия с базовым периодом пре- мии. В данном случае оклад за январь и за апрель попадут в базовый период частично, а оклады на февраль и март — полностью. В случае если расчет попал в базу частично, в расчетную базу попадет только часть значения ресурсов этой записи. При вычислении этой части будут использо- ваны данные графика записей об окладе. Подробно рас- чет части записи рассмотрен в разделе «Настройка протя- женных по времени расчетов», с. 332. Для базовых расчетов, не имеющих периода действия (в данном случае премия за месяц), будет проанализиро- вано попадание периода регистрации в базовый период премии. Так как период регистрации — это фиксирован- ная дата начала расчетного периода, такая запись либо
полностью попадет в базовый период, либо не попадет со- всем. В данном случае премия за январь вообще не будет учтена при расчете базы, а премия за апрель будет учтена полностью. Зависимость по периоду действия может быть установле- на независимо от того, использует ли данный план видов расчета период действия или нет. В данном случае важен период действия не рассчитываемой записи, а базовых за- писей, на основании которых она рассчитывается. В при- веденном примере премия не использует период дейст- вия, при этом она зависит по периоду действия от других записей, например начисленных окладов. Зависимость по периоду регистрации анализирует толь- ко попадание периода регистрации записей базовых ви- дов расчета в базовый период текущей записи. Период действия базовых записей в данном случае значения не имеет. Такой формат зависимости часто используется при расчете удержаний, так как удержания, как правило, рассчитываются с начисленных за период сумм, незави- симо от того, когда они действовали. В таких случаях ва- жен период регистрации базовых записей, а не период действия. Например, при расчете удержания по исполнительному листу за март будет учтена оплата больничного, начис- ленная в марте, даже если работник реально болел в фев- рале (рис. 10.49). Базовый период расчета удержания Больничный Н добавка ! Г ! февраль март апрель Рис. 10.49. Расчет удержания по исполнительному листу В данном случае в базу расчета удержания попадет оклад за март, а также больничный за февраль, зарегистриро- ванный в марте. При этом мартовская надбавка, зарегист- рированная в апреле, в базу расчета не попадет. При настройке расчетов, зависимых от базы по периоду реги- страции, необходимо помнить, что период регистрации — это всегда дата начала периода, поэтому базовый период должен заполняться с учетом этого. Например, если установить базовый период расчета удер- жания (при помесячном учете) с 03.03.2005 по 31.03.2005, то в базу никогда не попадет ни одна запись, так как период регистрации записей не может лежать в этом интервале. После настройки зависимости от базы необходимо ука- зать, от каких видов расчета могут зависеть по базовому периоду виды расчета текущего плана видов расчета. Для этого нужно указать список базовых планов видов расче- та в свойствах текущего плана видов расчета. В результа- те этой настройки в любом виде расчета текущего плана видов расчета в табличной части БазовыеВидыРасчета можно будет выбрать любой вид расчета отмеченных пла- нов видов расчета. В данном случае расчет дополнитель- ных начислений может базироваться на данных основных и дополнительных начислений. При такой настройке для вида расчета Премия за 3 месяца в списке базовых можно будет указать оклад из основных начислений и премию за месяц из дополнительных (рис. 10.50). Указанная настройка плана видов расчета будет действо- вать во всех регистрах расчета, где участвует этот план видов расчета. В данном случае рассчитывать премии от оклада можно будет как в регламентированном, так и в управленческом учете. Более того, можно будет рассчи- тать, например, управленческую премию по окладам, на- численным в регламентированном учете. Ввод записей, зависимых по базовому периоду Для того чтобы можно было рассчитать запись по базе других записей, у этой записи в регистре должен быть Базовые планы видов расчета Г0Ж ОсновныеНачисгения I <""0^- *^опс>г»^»1»^4й“ачисгенйя Удержания Рис. 10.50. Настройка зависимости по базовому периоду Таблица 10.13. Запись с указанием базового периода Период Регистрации ВндРасчета ... БазовыйПериодНачало БазовыйПериодКонец ... 01.05.2005 Премия за 3 месяца 15.01.2005 15.04.2005
указан базовый период, либо у соответствующего вида расчета должно быть установлено свойство Период дейст- вия является базовым периодом. В противном случае базовый период будет пустым и определить расчетную базу будет невозможно. Записи, зависимые по базовому периоду, могут формироваться только в регистре расчета, у кото- рого установлено свойство Базовый период. Базовый период записи задается двумя датами Базовый- ПериодНачало и БазовыйПериодКонец. В качестве базового периода можно указать произвольный интервал, в том числе перекрывающий несколько расчетных периодов. Запись о премии за 3 месяца будет выглядеть следующим образом (табл. 10.13). В базу расчета данной записи входят все записи любых регистров по видам расчета Оклад и Премия за месяц, у ко- торых фактический период действия пересекает интервал с 15 января по 15 апреля. Наиболее сложным вариантом зависимости по базовому периоду является установка у вида расчета свойства Пери - од действия является базовым периодом. В этом случае в каче- стве базового периода система будет использовать факти- ческий период действия записи с этим видом расчета. Это свойство является предопределенным и может быть зада- но только у видов расчета из плана видов расчета, исполь- зующего период действия, с установленным свойством Зависимость от базы по периоду действия или по периоду регистрации. Рассмотрим действие этого свойства на примере вида расчета Надбавка за вахту. Этот вид расчета предусматри- вает процентную надбавку к окладу на период работы на вахте. При этом надбавка за вахту не начисляется, если в это же время человек получает надбавку руководителю. Таким образом, вид расчета Надбавка за вахту зависит по базовому периоду от вида расчета Оклад, кроме этого, над- бавка за вахту вытесняется видом расчета Надбавка руко- водителю. То есть у вида расчета Надбавка за вахту в списке базовых указан Оклад, а в списке вытесняющих — Надбав- ка руководителю. Для расчета этой надбавки необходимо рассчитать сумму оклада за фактический период действия надбавки, так как необходимо учитывать вытеснение надбавкой руко- водителю. То есть базовым периодом надбавки должен быть ее фактический период действия. Такой базовый пе- риод нельзя задать только двумя датами БазовыйПериод- Начало и БазовыйПериодКонец, так как фактический пери- од действия может состоять из нескольких интервалов. Поэтому для вида расчета Надбавка за вахту необходимо установить свойство Период действия является базовым пе- риодом (рис. 10.51). То есть база расчета надбавки будет получена только за те интервалы, в которых она не была вытеснена надбавкой руководителю. Для того чтобы рассчитать сумму оклада за эти интервалы, будут использованы данные графика записи об окладе. Рис. 10.51. Расчет надбавки за вахту При установке свойства Период действия является базовым периодом принципы работы механизма зависимости по ба- зовому периоду не меняются, только вместо свойств за- писи, определяющих базовый период, система использу- ет фактический период действия записи. В зависимости от варианта зависимости (по периоду действия или по пе- риоду регистрации) система проанализирует пересечение соответственно периодов действия или периодов регист- рации базовых записей с фактическим периодом дейст- вия текущей записи. В записи, формируемой в регистре по виду расчета с уста- новленным свойством Период действия является базовым пе- риодом, поля БазовыйПериодНачало и БазовыйПериодКонец не заполняются (табл. 10.14). Получение базы средствами встроенного языка Платформа позволяет автоматически получить базовые данные для записи регистра расчета, у которого установ- лено свойство Базовый период. При этом базу можно полу- чать как для одной записи, так и сразу для нескольких. Для получения базовых данных по нескольким записям регистра расчета используется метод ПолучитьБазуО объ- екта РегистрРасчетаМенеджер. В качестве отбора необходимо передать значение типа Структура или Отбор. При этом от- бор можно устанавливать только по полю Регистратор и измерениям регистра расчета. Отбор по значению регист- ратора должен быть установлен всегда. Требования к это- му параметру аналогичны отбору в методе ПолучитьДанные- ГрафикаО. В базу текущей записи входят записи с базовыми видами расчета, зарегистрированные во всех регистрах, работаю- щих с базовыми планами видов расчета. Например, базой расчета премии будут являться записи об окладах во всех регистрах (например, управленческого и регламентиро- ванного учета). У этих регистров может быть разная структура, разный набор ресурсов, измерений и реквизи- тов. Поэтому при использовании метода ПолучитьБазуО необходимо специфицировать, какие именно данные в каких разрезах нужно получить. Таблица 10.14. Структура записи регистра расчета Период Регистрации ВидРасчета ... БазовыйПериод- Начало БазовыйПериод- Конец ... 01.03.2005 Надбавка за вахту
Для этого в параметре Ресурсы необходимо указать, итоги по каким ресурсам каких регистров расчета должны быть рассчитаны. Например, для расчета премии за 3 месяца необходимо вычислить итоги ресурса Результат регистра основных начислений и такого же ресурса регистра до- полнительных начислений. В параметр Ресурсы переда- ется значение типа Массив, каждый элемент которого — это строка, в которой через запятую перечисляются име- на ресурсов с указанием имени регистра по следующей схеме: <ИмяРегистраРасчета>. <ИмяРесурса> Например, это может быть строка следующего вида: ОсновныеНачисленияРегл.Результат, ДополнительныеНачисленияРегл.Результат Каждый элемент массива ресурсов является отдельным результатом расчета базы (колонка в выходной таблице). Название этого показателя определяется названием ре- сурса первого регистра, перечисленного в строке, в дан- ном случае Результат. Значением показателя будет яв- ляться итог по ресурсам Результат базовых записей обоих регистров. При необходимости получить базу по другому ресурсу нужно добавить в массив новый элемент. Напри- мер, если нужно рассчитать суммарное количество отра- ботанных дней, нужно добавить в массив следующую строку: « Основные Начисления? егл. Отработано Дней » В данном случае показатель базы ОтработаноДней сложит- ся только по ресурсу регистра основных начислений. В рамках одного элемента массива ресурсов не могут быть перечислены два ресурса одного регистра. Фактически, через параметр Ресурсы метод получает ин- формацию о том, по каким базовым регистрам необходи- мо собрать данные, и какие именно. Так как структура регистров может быть различной, дан- ные текущего регистра необходимо связать с данными ба- зовых регистров. Если в текущем регистре измерениями являются ФизЛицо и Организация, то необходимо указать, в каких измерениях эти же данные (о работнике и орга- низации) хранятся в базовых регистрах. Эта связь уста- навливается через параметр Измерения. В этот параметр необходимо передать значение типа Структура, элемента- ми которой являются строки с названиями измерений текущего регистра. Значением каждого элемента структу- ры также является строка, в которой через запятую указа- ны имена измерений базовых регистров, соответствую- щие данному измерению текущего регистра по схеме <ИмяРегистраРасчета>.<ИмяИзмерения> (рис. 10.52). В указанном случае значение, передаваемое в параметр Измерения, должно содержать следующую структуру (табл. 10.15): Таблица 10.15. Значения параметра Измерение Элемент Значение «ФизЛицо» «ОсновныеНачисленияРегл.ФизЛицо, ДополнительныеНачисленияРегл. ФизЛицо» «Организация» «ОсновныеНачисленияРегл.Организация, ДополнительныеНачисленияРегл. Организация» Количество элементов этой структуры не может быть больше, чем количество измерений текущего регистра. Имена элементов структуры должны четко совпадать с именами измерений. Значения элементов структуры должны иметь тип Строка и содержать имена измерений базовых регистров через запятую. Параметр Измерения по- зволяет отобрать данные базовых регистров по значениям измерений текущего регистра. Например, если рассчиты- вается премия сотрудника Иванов в организации Ромашка, то система установит отбор по сотруднику Иванов в изме- рениях регистров ОсновныеНачисленияРегл.ФизЛицо и До- полнительныеНачисленияРегл.ФизЛицо, а по организации Ромашка в соответствующих измерениях регистров, хра- нящих ссылку на организацию. Если для какого-либо из- мерения текущего регистра в структуре не указано соот- ветствующее измерение базового регистра, то в базовом регистре отбор по этому полю не будет установлен. Так, если при расчете премии сотруднику Иванов в структуре не указать соответствие для измерения Организация, то в качестве базы будут рассчитаны оклады сотрудника Ива- нов во всех организациях. Базу по указанным ресурсам и измерениям можно полу- чить как общей суммой по каждому ресурсу, так и деталь- но. Для того чтобы получить базу в определенных разре- зах, необходимо указать также параметр Разрезы. Этот параметр не является обязательным, если он не указан, база будет получена общей суммой по каждому ресурсу. Разрез базы можно получить по любым измерениям и ре- квизитам базовых расчетов. Например, базу расчета пре- мии можно получить в разрезе подразделений, если такой реквизит есть в базовых регистрах. В параметр Разрезы необходимо передать значение типа Массив, элементами которого являются строки, в которых Запись текущего регистра ДополиительиыеНачнслеиияРегл Период Регистрации ВидРасчета ФизЛицо Организация 01.05.2005 Премия за 3 месяца Иванов «Ромашка» Базовый регистр Основные 1ачисленияРег.г Базовый регистр Дополнительные На числе псяРегл Период Регистр ац ни Вид Расчета ФизЛицо Организация Период Регистра ции Вид Расчета ФизЛицо Организация 01.01.2003 Оклад Иванов «Ромашка» 01.01.200 5 Оклад Иванов «Ромашка» Рис. 10.52. Связь с данными базовых регистров
через запятую перечислены поля базовых регистров, хра- нящие нужное значение разреза. Например, при необхо- димости получить базу в разрезе подразделения и статьи затрат в параметр Разрезы нужно передать следующий массив (табл. 10.16). Таблица 10.16. Значение параметра Разрезы ОсновныеНачисленияРегл.Подразделение, ДополнительныеНачисленияРегл.Подразделение ОсновныеНачисленияРегл.СтатьяЗатрат, ДополнительныеНачисленияРегл.СтатьяЗатрат В качестве разрезов нельзя указывать измерения базовых регистров, переданные в параметр Измерения, так как в этом случае в базовом регистре будет произведен отбор по конкретному значению этого измерения, и получать по нему разрез не имеет смысла — измерение во всех за- писях будет содержать одинаковое значение. Метод ПолучитьБазуО возвращает значение типа Таблица- Значений. Если разрезы получения базы не заданы, число строк таблицы будет совпадать с числом записей, удовле- творяющих отбору. Если разрезы заданы, то количество строк будет больше (рис. 10.53). Ресурсы Разрезы Ыле Number Результат Отр або тало Днем Подразделе мне СтатьяЗатрат 1 12000 22 Бухгалтерия Административные расходы 2 20000 21 Цех Оплата труда рабочих 2 3000 Цех Премии рабочим Рис. 10.53. Структура таблицы, возвращаемой методом ПолучитьБазуО В колонке LineNumber будет указан номер строки записи регистра расчета, для которой рассчитана база. Если раз- резы не заданы, номера строк не будут повторяться, так как отбор по регистратору установлен всегда. Если разре- зы используются, по каждой исходной строке может быть несколько строк таблицы базы с различными значениями разрезов. В данном случае для строки 2 существуют ба- зовые записи с двумя различными значениями разреза СтатьяЗатрат. В таблице также будут присутствовать колонки ресурсов по числу элементов массива, переданного в параметр Ре- сурсы. Значения разрезов, если они заданы, будут также указаны в отдельных колонках по числу элементов мас- сива, переданного в параметр Разрезы. Ниже приведен текст модуля, позволяющий получить таблицу базы (листинг 10.6). Этот фрагмент присутству- ет в демо-конфигурации в обработке «Запросы и ме- тоды». Листинг 10.6. Получение таблицы базы И Получитье менеджер регистра расчета Менеджер = РегистрыРасчета.ДополнительныеНачисленияРегл; И Сформировать отбор по регистратору Отбор = Новый Структура!"Регистратор". Ссылка); // Сформировать массив ресурсов Ресурсы = Новый Массив(2); Ресурсы[О] = "ОсновныеНачисленияРегл. Результат, ДополнительныеНачисленияРегл.Результат"; // Сформировать структуру измерений Измерения = Новый Структура!"ФизЛицо, Организация"); Измерения.ФизЛицо ^''ОсновныеНачисленияРегл.ФизЛицо. ДополнительныеНачисленияРегл.ФизЛицо": Измерения.Организация =“ОсновныеНачисленияРегл.Организация, ДополнительныеНачисленияРегл.Организация"; // Сформировать массив разрезов Разрезы = Новый Массив(2); Разрезы[0] = "ОсновныеНачисленияРегл.Подразделение. ДополнительныеНачисленияРегл.Подразделение"; Разрезы[1] = "ОсновныеНачисленияРегл.СтатьяЗатрат, ДополнительныеНачисленияРегл.СтатьяЗатрат"; // Получить таблицу базы ТаблицаБазы = Менеджер.ПолучитьБазуСОтбор, Ресурсы, Измерения. Разрезы); Для того чтобы получить базы для одной записи, можно использовать метод ПолучитьБазуО объекта РегистрРасчета- Запись. Принцип использования этого метода аналогич- ный, за исключением того, что отбор записей в этом слу- чае не указывается. Получение базы при помощи запроса Для получения базы расчетов при помощи запроса ис- пользуются виртуальные таблицы регистров расчета, под- держивающих базовый период. У каждого регистра таких таблиц может быть несколько. Их число определяется ко- личеством регистров расчета, использующих планы видов расчета, которые являются базовыми по отношению к пла- ну видов расчета данного регистра. Например, план видов расчета Дополнительные начисления зависит по базе от пла- нов видов расчета Основные начисления и Дополнительные начисления. Эти планы видов расчета, в свою очередь, ис- пользуются в регистрах регламентированного и управлен- ческого учета (рис. 10.54). План видов расчета "Долвлнмгельиые начисления’ Зависит базе от План видов расчета "Основные начисления’* План видов расчета ‘Дыклиитвлывм начисления" Используется в регистрам Используется в регистрам Регистр "Основные начисления (упр)* Регистр "Основные начисления (регл)" Регистр “Дополнительные начисления(упр)" Регистр "Дополнительные начисления (регл)" т Рис. 10.54. Взаимосвязь планов видов расчета и регистров расчета Это означает, что любые записи регистра Дополнительные начисления (регл) могут зависеть по базовому периоду от записей любого из четырех регистров. В этом случае у ре- гистра Дополнительные начисления (регл) будет 4 виртуаль- ных таблицы базовых данных (рис. 10.55). Имя виртуальной таблицы формируется по следующей схеме: <ИмяОсновногоРегистра>.База<ИмяБазовогоРегистра>
Й-@ ДополнительныеН ачисленияРегл Ё-W ДополнительныеНачисленияРегл.БазаДополнигельныеНачисленияРегл Ё S ДополнительныеНачисленияРегл.БазаДополнительныеНачисленияУ пр Ё-рЯ ДополнительныеНачисленияРегл. БазаОсновныеНачисленияРегл Ё-S ДополнительныеНачисленияРегл.БазаОсновныеНачисленияУпр Рис. 10.55. Виртуальные таблицы базы Таким образом, например, таблица ДополнительныеНа- численияРегл.БазаОсновныеНачисленияРегл позволяет по- лучить записи регистра Основные начисления (регл), входя- щие в базу расчета записей регистра Дополнительные начисления (регл). В случае необходимости получить базу по нескольким регистрам нужно будет использовать в за- просе несколько виртуальных таблиц базовых данных. Виртуальные таблицы базовых данных требуют указания параметров, которые по смыслу схожи с параметрами ме- тода ПолучитьБазуО. ИзмеренияОсновногоРегистра — в этот параметр нужно пере- дать массив, элементами которого являются строки с назва- ниями измерений основного регистра, по которым нужно будет отбирать записи в базовых регистрах. Этот параметр схож с элементами структуры параметра Измерения метода ПолучитьБазуО. Для отбора данных по сотруднику и органи- зации в этот параметр нужно передать массив (табл. 10.17). Таблица 10.17. Структура массива «ФизЛицо» «Организация» Названия измерений основного регистра указываются без указания имени регистра, так как в данном случае по- нятно, что речь идет об основном регистре. ИзмеренияБазовогоРегистра — в этот параметр передается массив, элементами которого являются названия измере- ний базового регистра, соответствующие измерениям, пе- реданным в параметр ИзмеренияОсновногоРегистра. Число элементов этого массива должно совпадать с числом эле- ментов массива измерений основного регистра. Важен также порядок следования измерений, он должен быть таким же, как и в массиве измерений основного регистра. По измерениям, указанным в параметре ИзмеренияБазово- гоРегистра будет произведен отбор записей в базовом регистре. При этом в качестве значений отбора будут ис- пользованы значения соответствующих измерений ос- новного регистра. Например, при получении базы по основным начислени- ям для премии, начисленной Иванову в организации «Ро- машка», в виртуальную таблицу базы попадут только ба- зовые записи с аналогичными значениями измерений. Если названия измерений одинаковы, в параметры Изме- ренияОсновногоРегистра и ИзмеренияБазовогоРегистра можно передать один и тот же массив. В случае если названия различаются, нужно будет создать два массива (рис. 10.56). Разрезы — в этот параметр передается массив, содержащий названия полей базового регистра, по которым необходи- мо получить разрез базы. В отличие от аналогичного па- раметра метода ПолучитьБазуО, в запросе можно получить разрез не только по измерениям и реквизитам, но и по следующим предопределенным полям базового регистра: НомерСтроки, Регистратор, ВидРасчета, ПериодРегистрации, ПериодДействия. Рис. 10.56. Получение базы по основным начислениям Базовый регистр Названия измерений совпадают Названия измерений различаются Например, для получения базы в разрезе периода регист- рации и вида расчета в параметр Разрезы необходимо пе- редать следующий массив (табл. 10.18). Таблица 10.18. Структура массива «ПериодРегистрации» «ВидРасчета» Параметр Разрезы можно не указывать, в этом случае база будет получена общей суммой по каждому ресурсу базово- го регистра. В массиве недопустимо указание измерений, которые переданы в параметр ИзмеренияБазовогоРегистра, так как в этом случае на эти измерения будет наложен от- бор и получать по ним разрез не имеет смысла. Условие — в этот параметр можно передать произвольное условие на записи основного регистра. База будет полу- чена только для записей, удовлетворяющих этому усло- вию. В отличие от метода ПолучитьБазуО условия могут быть заданы произвольные. В запросе не обязательно от- бирать данные по регистратору, теоретически можно во- обще не указывать условий, тогда база будет получена для всех записей основного регистра. Виртуальная таблица базовых данных расширяет данные основной таблицы регистра расчета и имеет следующую структуру (рис. 10.57). 0- ПериодРегистрации Регистратор НомерСтроки ВидРасчета Б азовыйП ериодН ача до БазовыйПериодКонец Активность Сторно Ё L ФизЛицо В- t- Организация Данные основного регистра “• g Результат ....“ Размер Ё— Подразделение Е- — СтатьяЗатрат g РезультатБаза — П. • • азрез Е » РегистреторРазрез 1 — НомерСтрокиРазрез Ё — ВидРасчетаРазрез г— Период ДействияРазрез Ё U. ФизЛицоРазрез Ё-t- ОрганизацияРазрез РазмерРазрез Ё- — Г рафикРаботыРазрез Ё «• ВодУчетаВремениРазрез Ё— ПодразделениеРазрез Ё — СтатьяЗатрэтРазрез Ресурсы базового j регистра, по которым • может быть получена база _____• Поля базового регистра, I j по которым может быть * 1 получен разрез базы । L__________________________। Рис 10.57. Виртуальная таблица базы
В виртуальной таблице базовых данных будут присутст- вовать все данные основной таблицы основного регистра, а также отдельные поля для получения базы по всем ре- сурсам базового регистра, названия которых формируют- ся по схеме <ИмяРесурса>База. Если параметр Разрезы не за- дан, то в таблице не будет других полей, и для каждой записи основного регистра, удовлетворяющей условию, будет рассчитана база общей суммой по каждому ресурсу базового регистра. Если разрезы заданы, то в виртуаль- ной таблице будут присутствовать дополнительные поля по числу элементов массива разрезов. Названия этих полей в виртуальной таблице базовых данных будут формироваться по схеме <ИмяПоля>Разрез. Так, если в параметр Разрезы переданы значения Период- Регистрации и ВидРасчета, то в виртуальной таблице будут доступны поля ПериодРегистрацииРазрез и ВидРасчетаРаз- рез. Остальные поля, выводимые в конструкторе запроса, не будут доступны, и при выборе таких полей запрос не будет выполнен. Использование запроса для получения базы удобнее еще и тем, что его результаты легче обрабатывать. С таблицей значений, возвращаемой методом ПолучитьБазуО, работать гораздо сложнее. Например, в запросе можно получить итоги по значениям разрезов и использовать его для по- строения отчета следующего вида по базовым начислени- ям для расчета отпуска (рис. 10.58). Отчет по базовым начислениям _ □ X Рис 10.58. Отчет по базовым начислениям Ниже приведен текст запроса, который может служить основой для построения такого отчета (листинг 10.7). Этот фрагмент присутствует в демо-конфигурации в об- работке «Запросы и методы». Листинг 10.7. Отчет по базовым начислениям Запрос = Новый Запрос; Запрос.Текст = " ВЫБРАТЬ База.ПериодРегистрацииРазрез КАК ПериодРегистрацииРазрез, База.ВидРасчетаРазрез, СУММА(База.РезультатБаза) КАК РезультатБаза ИЗ РегистрРасчета.ДополнительныеНачисленияРегл. БазаОсновныеНачисленияРеглС «Измерения, «Измерения, «Разрезы, Регистратор = «(Регистратор И НомерСтроки = «НомерСтроки) КАК База СГРУППИРОВАТЬ ПО Баз а.ПериодРегистрацииРазрез, База.ВидРасчетаРазрез ИТОГИ СУММА(РезультатБаза) ПО ОБЩИЕ. ПериодРегистрацииРазрез"; И Сформировать массив измерений основного И и базового регистров (названия измерений совпадают, // поэтому используется один массив) Измерения = Новый Массив(2); Измерения[О] = "ФизЛицо"; Измерения[1] = “Организация"; // Сформировать массив разрезов Разрезы = Новый Массив(2); Разрезы[0] = "ПериодРегистрации"; Разрезы[1] = "ВидРасчета": // Передать параметры в запрос Запрос.УстановитьПараметр("Измерения", Измерения); Запрос.УстановитьПараметр("Разрезы", Разрезы): // Запрос строится по конкретной записи документа // с номером ТекущийНомерСтроки Запрос.УстановитьПараметр("Регистратор", Ссылка); Запрос.УстановитьПараметр("НомерСтроки", ВыбранныйНомерСтроки); Результат = Запрос.ВыполнитьО; Технология формирования и расчета записей регистров расчета Формирование записей регистра расчета Регистры расчета не поддерживают независимого форми- рования записей без использования документа-регистра- тора. Поэтому ввод записей в регистр расчета должен быть организован с применением документов. В докумен- те должны быть указаны все данные, необходимые для за- полнения всех полей записи регистра расчета, кроме ре- сурсов Такой документ заполняется пользователем в режиме 1С:Предприятие и формирует записи регистра рас- чета при проведении. В демонстрационной конфигура- ции «Сложные периодические расчеты», которая нахо- дится на прилагаемом компакт-диске, для формирования записей в регистрах расчета предусмотрен документ На- числение зарплаты (рис. 10.59). В шапке документа пользователь должен указать органи- зацию, по которой будет производиться начисление, а также расчетный период, в который должны попасть за- писи, то есть период регистрации. Для ввода записей в ка- ждый из регистров расчета в документе предусмотрена отдельная табличная часть. Так, для ввода записей в ре- гистр расчета ОсновныеНачисленияРегл предусмотрена за- кладка ОсновныеНачисления. На этой закладке пользова-
тель должен ввести начисления различным сотрудникам, указав физическое лицо, вид расчета, период действия за- писи и значения реквизитов регистра расчета. В данном случае пользователь должен указать значения реквизи- тов Размер и Подразделение. В реквизите Размер указыва- ется размер начисления, который будет влиять на его рас- чет. Например, для оклада размером является тарифная ставка, для премии — количество процентов премии. Для некоторых видов расчета размер указывать не нужно, так как он не влияет на расчет (например, сдельный зарабо- ток). В реквизите Подразделение указывается подразделе- ние, на затраты которого должно быть отнесено данное начисление. Рис. 10.59. Документ «Начисление зарплаты» Реквизит регистра График работы будет заполнен значени- ем, указанным в соответствующем реквизите выбранного физического лица. Это и будет график работы, по которо- му должна рассчитываться данная запись. Как правило, график работы у всех записей по одному сотруднику один и тот же. В приведенном примере реквизиты регистра ВидУчетаВре- мени и СтатьяЗатрат не вводятся в документ напрямую, а указываются как реквизиты вида расчета. Ресурсы реги- стра расчета не всегда заполняются из документа, они мо- гут рассчитываться при проведении. Технология расчета записей будет подробно рассмотрена в следующем раз- деле. Для формирования записей регистра расчета использу- ется метод ДобавитьО объекта РегистрРасчетаНаборЗаписей. (листинг 10.8). Листинг 10.8. Формирование записей регистра расчета // Процедура добавляет запись в регистр основных начислений Процедура ДобавитьСтрокуОсновныхНачислений( ДанныеСтроки, НаборЗаписей) Движение = НаборЗаписей.ДобавитьО; // Предопределенные поля Движение.ПериодРегистрации = ПериодРегистрации; Движение.ПериодДействияНачало = ДанныеСтроки.ДатаНачало; Движение.ПериодДействияКонец = ДанныеСтроки.ДатаКонец; Движение.ВндРасчета = ДанныеСтроки.ВндРасчета; Движение.Сторно = ДанныеСтроки.Сторно; // Измерения Движение.ФизЛицо = ДанныеСтроки.ФизЛицо; Движение.Организация = Организация; // Ресурсы Движение.Результат = ДанныеСтроки.Результат; // Реквизиты Движение.ГрафикРаботы = ДанныеСтроки.ФизЛицо.ГрафикРаботы; Движение.Размер = ДанныеСтроки.Размер; Движение.ВидУчетаВремени = ДанныеСтроки. ВндРасчета.ВидУчетаВремени; Движение.Подразделение = ДанныеСтроки.Подразделение; Движение.СтатьяЗатрат = ДанныеСтроки. ВидРасчета.СтатьяЗатрат; КонецПроцедуры //ДобавитьСтрокуОсновныхНачислений // Обработка проведения Процедура ОбработкаПроведения(Отказ) // Сформировать запрос по табличной части при помощи // функции общего модуля ВыборкаОсновныеНачисления = СформироватьЗапросПоТабличнойЧасти( ЭтотОбъект, "ОсновныеНачисления").Выбрать(); // По каждой строке табличной части сформировать // запись в регистр Пока ВыборкаОсновныеНачисления.СледующийО Цикл ДобавитьСтрокуОсновныхНачислений(ВыборкаОсновныеНачисления, Движения.ОсновныеНачисленияРегл); КонецЦикла; КонецПроцедуры // ОбработкаПроведения Настройка алгоритмов расчета Настройка способов расчета Способ расчета ресурсов записи может быть различным в зависимости от выбранного вида расчета и допол- нительных реквизитов записи. Как уже было отмечено, технология периодических расчетов в системе ^Пред- приятие предполагает возможность пользователю само- стоятельно вводить новые виды расчета в режиме 1 С:Пред- приятие. Поэтому прописать в конфигураторе алгоритмы расчета каждого вида расчета нельзя. Пользователю долж- на быть предоставлена возможность настроить способ расчета того или иного вида расчета в режиме 1С:Предпри- ятие. Под способом расчета подразумевается алгоритм или формула, по которой будут вычислены значения ре- сурсов записи регистра, исходя из параметров этой запи- си. При этом различные виды расчета могут иметь один и тот же способ расчета. Например, виды расчета Премия и Надбавка за вахту, по сути, имеют один и тот же способ расчета, предполагающий умножение расчетной базы за- писей с этими видами расчета на определенный процент. Так как все способы расчета должны быть прописаны разработчиком, их набор должен быть фиксированным и для их описания логичнее всего использовать перечис- ление. В демонстрационной конфигурации «Сложные пе- риодические расчеты», которая находится на прилагае- мом компакт-диске, все доступные способы расчета описаны в перечислении СпособыРасчета. При необходи- мости ввести в систему новый способ расчета не обойтись без изменения конфигурации, так как алгоритм расчета нужно будет прописать в модулях. Для возможности настройки способа расчета для видов расчета в режиме 1 С:Предприятие необходимо добавить в план видов расчета реквизит СпособРасчета, имеющий тип ПеречислениеСсылка. СпособыРасчета. В этом случае в любом
Таблица 10.19. Назначение видов расчета Имя Алгоритм расчета Пример использования ПоМесячнойСтавке Результат = Размер * Отработанное время/ Норматив рабочего времени Используется для расчета окладов. В качестве отработанного времени используются данные графика за фактический период действия, нор- матив рабочего времени — данные графика за период действия. В поле Размер указывается та- рифная ставка ПроцентомОтБазы Результат = Размер * Расчетная база/100 Можно использовать для расчета премий. В по- ле Размер указывается процент премии. Расчет- ная база складывается из суммы по ресурсу Результат базовых записей за базовый период ФиксированнойСуммой Результат = Размер Простейший способ, может использоваться для начисления фиксированных надбавок ПоСдельнойВыработке Результат = Сдельная выработка за период действия Используется для начисления зарплаты производ- ственным рабочим. Сдельная выработка собирает- ся по регистру накопления СдельнаяВыработка за интервал периода действия записи виде расчета данного плана видов расчета можно будет указать одно из значений перечисления, определив тем самым способ расчета записей с этим видом расчета. В де- монстрационной конфигурации «Сложные периодиче- ские расчеты», которая находится на прилагаемом ком- пакт-диске, предусмотрены следующие способы расчета (табл. 10.19). Настройка приоритета видов расчета При расчете нескольких записей в одном документе очень важен порядок расчета этих записей. Если рассчи- тывать записи в произвольном порядке, то может полу- читься, что запись, зависимая по базовому периоду, будет рассчитана раньше, чем базовая запись. Например, запись с видом расчета Надбавка руководителю будет рассчитана раньше, чем запись с видом расчета Оклад. В этом случае база этой надбавки будет равна 0, так как оклад еще не рассчитан и не записан в регистр. В результате часть за- писей будет рассчитана неправильно. Для того чтобы та- кой набор записей был рассчитан правильно, необходимо рассчитывать эти записи в правильной последовательно- сти. При этом разработчик должен самостоятельно про- думать механизм, который будет упорядочивать расчет записей регистра. Рассмотрим принципы упорядочивания расчетов на при- мере следующего набора записей, рассчитываемого в од- ном документе (рис. 10.60). В данном примере производится расчет нескольких запи- сей регистра расчета. При этом существует зависимость по базовому периоду этих записей между собой. В част- ности, надбавка руководителю зависит по базовому пе- риоду от оклада, а вид расчета Индексация заработка зависит от всех перечисленных видов расчета (Оклад, Командиров- ка, Надбавка руководителю), так как предполагает начисле- ние доплаты в размере 10% от заработка. Если рассчитывать эти записи в том порядке, который приведен на схеме, результат расчета записей, зависимых по базовому периоду, будет неверным. В частности, над- бавка руководителю будет равна 0, так как на момент расчета в регистре не будет данных об окладе. При расче- те записи по индексации заработка не будет учтена ко- мандировка, а надбавка руководителю будет учтена с не- верной суммой. Записи регнстоа оасчета (расчет в произвольном порядке) Рис. 10.60. Набор расчитываемых записей Таким образом, для того чтобы определить, в каком по- рядке должны следовать записи, необходимо проанали- зировать взаимную зависимость по базовому периоду ви- дов расчета, участвующих в этих записях. Виды расчета Оклад и Командировка не являются зависимыми по базово- му периоду (табличная часть БазовыеВидыРасчета не со- держит строк), поэтому они должны быть рассчитаны в первую очередь. Для их расчета не требуется наличия в регистре других рассчитанных записей. Такие виды рас- чета можно назвать первичными, приоритет их расчета равен 1, то есть они должны быть рассчитаны в первую очередь. Вид расчета Надбавка руководителю является зависимым по базовому периоду, при этом в его табличной части БазовыеВидыРасчета содержатся только первичные виды расчета (в данном случае оклад). Запись с таким видом расчета можно записывать сразу после расчета первич- ных записей, так в этот момент база их расчета сформиро- вана полностью. Такие виды расчета можно назвать зави- симыми первого уровня, приоритет их расчета равен 2 (то есть они рассчитываются во вторую очередь).
Наконец, вид расчета Индексация заработка в списке базо- вых видов расчета содержит не только первичные виды расчета (оклад, командировка), но и зависимые первого уровня (надбавка руководителю). Поэтому эта запись мо- жет быть рассчитана только после того, как рассчитаны первичные записи и зависимые первого уровня. Такой вид расчета можно назвать зависимым второго уровня, приоритет его расчета равен 3. Таким образом, приоритет вида расчета определяется со- ставом его базовых видов расчета (рис. 10.61). Надбавка Индексация ИКОМММНМК Окжж Первичный Приоритет-1 Рис. 10.61. Приоритет видов расчета Зависимый первого уровня Приоритет 2 Зависимый второго уровня Приоритет- 3 Если текущий вид расчета в списке базовых содержит хотя бы один вид расчета, который является зависимым перво- го уровня, то такой вид расчета является зависимым вто- рого уровня и должен иметь меньший приоритет. Количе- ство уровней зависимости теоретически не ограничено. Если применить полученные значения приоритета к ис- ходному набору записей, результат их расчета окажется правильным (рис. 10.62). Приоритет, который будет иметь тип Число. В этом случае пользователь должен указать приоритет видов расчета в этом реквизите. В дальнейшем при расчете записей раз- работчик должен предусмотреть модуль расчета таким образом, чтобы сначала были рассчитаны записи с вида- ми расчета приоритета 1, затем 2, 3, 4 и так далее. Расчет записей регистра расчета Расчет записей регистра расчета может производиться в любой момент, определенный разработчиком. Напри- мер, расчет записей может производиться при проведе- нии документа регистрации записей. В этом случае значе- ния ресурсов будут рассчитываться в момент проведения, и пользователь не сможет вручную изменить результат расчетов. Также можно инициировать расчет записей из формы документа. Для этого можно создать на форме кнопку Рассчитать, при нажатии на которую будет произ- водиться расчет. В этом случае результат расчета можно поместить в табличную часть документа, для того чтобы пользователь мог скорректировать его вручную. При про- ведении такого документа записи регистра расчета будут сформированы с учетом ручных корректировок (рис. 10.63). Рис. 10.63. Формирование записей регистра расчета В том и в другом случае схема расчета модулей будет схо- жа (рис. 10.64). Рис. 10.62. Приоритет расчета записей Записи в рамках одного приоритета могут быть рассчита- ны в произвольном порядке. Так, оклад и командировка могут быть рассчитаны в любой последовательности. По- сле расчета записей каждого приоритета полученные зна- чения ресурсов должны быть записаны в регистр расчета перед началом расчета следующих записей. Это связано с тем, что механизм зависимости по базовому периоду реа- лизован в регистре расчета. Запись значений ресурсов в регистр формирует базу для расчета записей со следую- щим приоритетом. Настройка приоритета видов расчета должна быть дос- тупна пользователю в режиме ^Предприятие. Вид этой настройки разработчик определяет самостоятельно. На- пример, можно добавить в план видов расчета реквизит Рис. 10.64. Схема расчета
Таким образом, расчет записей без проведения документа отличается только наличием двух дополнительных эта- пов. Рассчитанные значения ресурсов необходимо помес- тить в табличную часть документа в соответствующие поля, для того чтобы пользователь мог их изменить. По- сле этого необходимо удалить созданные в процессе рас- чета записи регистров расчета, так как пользователь в данном случае не просил проводить документ. Тем не ме- нее расчет не может быть выполнен без временной записи данных в регистр расчета, так как все расчетные механиз- мы платформы (вытеснение, зависимость по базовому пе- риоду, расчет по графику, перерасчет) применимы только к записям регистров расчета. Если в документе настроен расчет записей без проведе- ния, то в момент проведения такого документа собствен- но расчета уже не происходит. В ресурсы регистра расче- та попадают значения из табличной части документа, которые пользователь мог скорректировать после расчета. Рассмотрим основные этапы расчета записей более подроб- но. Далее будет рассмотрен вариант расчета без проведения документа на примере регистра расчета ОсновныеНачисле- нияРегл. Все рассматриваемые процедуры доступны в демо- конфитурации в документе НачислениеЗарплаты, а также в об- щем модуле Расчеты. Формирование набора записей по данным документа Для расчета записей необходимо сначала сформировать набор этих записей в регистре расчета, это позволит ис- пользовать расчетные механизмы платформы. Формиро- вание записей при расчете аналогично рассмотренному выше модулю формирования записей при проведении. Однако если при проведении в качестве набора записей выступали движения документа по регистру (Движения ,0с- нонвыеНачисленияРегл), то при расчете без проведения та- кой набор необходимо создать. Ниже приведен модуль, позволяющий сформировать набор записей регистра расчета по данным документа (листинг 10.9). В тексте используется процедура До- бавитьСтрокуОсновныхНачисленийО, описанная выше. Этот модуль является начальным этапом процедуры Рассчи- татьОсновныеНачисленияО, которая вызывается при нажа- тии на кнопку Рассчитать в форме документа. Листинг 10.9. Формирование набора записей регистра расчета Процедура РассчитатьОсновныеНачисленияО Экспорт // Расчет записей выполняется в транзакции НачатьТранзакциюО: // Создать набор записей регистра расчета НаборОсновныеНачисления = РегистрыРасчета. ОсновныеНачисленияРегл. Соз дат ьНаборЗаписей(); НаборОсновныеНачисления.Отбор.Регистратор.Значение = Ссылка; ВыборкаОсновныеНачисления = СфорнироватьЗапросПоТабличнойЧастиС ЭтотОбъект, "ОсновныеНачисления").Выбрать(); Пока ВыборкаОсновныеНачисления.СледующийО Цикл ДобавитьСтрокуОсновныхНачисленийС ВыборкаОсновныеНачисления. НаборОсновныеНачисления); КонецЦикла; // Расчет записей набора //..... ЗафиксироватьТранзакциюО; КонецПроцедуры // РассчитатьОсновныеНачисления При формировании набора записей значения ресурсов роли не играют, так как они будут в дальнейшем измене- ны при расчете. В том числе эти значения могут быть пус- тыми. Добавление в набор сторно-записей Если в рассчитываемом регистре установлено свойство Период действия, в сформированном наборе могут присут- ствовать записи, у которых период действия принад- лежит более раннему периоду, чем период регистрации. В этом случае они могут вступать в конкуренцию на этом периоде действия с записями более раннего периода ре- гистрации. Чтобы такие записи могли иметь непустой фактический период действия, необходимо дополнить сформированный набор соответствующими сторно-запи- сями. Подробнее механизм сторнирования был рассмот- рен в разделе «Сторнирование», с. 337. Добавление сторно-записей происходит с использовани- ем метода ПолучитьДополнениеС) набора записей регистра. Ниже приведен текст модуля, позволяющий добавить в набор сторно-записи. Добавление записи происходит при помощи вызова процедуры ДобавитьСтрокуСторноОсновных- Начислений(), которая должна быть описана в модуле. При этом для каждой сторно-записи необходимо доба- вить новую строку в табличную часть документа, чтобы при проведении запись попла в регистр (листинг 10.10). Листинг 10.10. Добавление сторно-записей // Добавить сторно-записи в набор и в табличную часть Процедура ДобавитьСтрокуСторноОсновныхНачисленийС ДанныеСтроки, НаборЗаписей, ТабличнаяЧасть = Неопределено) Движение = НаборЗаписей. ДобавитьО; И Предопределенные поля Движение.ПериодРегистрации = ДанныеСтроки. ПериодРегистрацииСторно; Движение.ПериодДействияНачало = ДанныеСтроки. ПериодДействияНачалоСторно; Движение.ПериодДействияКонец = ДанныеСтроки. ПериодДействияКонецСторно; Движение. ВидРасчета = ДанныеСтроки. Ви дРасчета; Движение.Сторно = Истина; // Измерения Движение.ФизЛицо = ДанныеСтроки.ФизЛицо; Движение.Организация = ДанныеСтроки.Организация; И Реквизиты Движение.ГрафикРаботы= ДанныеСтроки.ГрафикРаботы; Движение.Размер = ДанныеСтроки.Размер; Движение.ВидУчетаВремени = ДанныеСтроки.ВидУчетаВремени; Движение.Подразделение3 ДанныеСтроки.Подразделение; Движение.СтатьяЗатрат3 ДанныеСтроки.СтатьяЗатрат; Если Не ТабличнаяЧасть = Неопределено Тогда НоваяСтрока = ТабличнаяЧасть.ДобавитьО; НоваяСтрока.ФизЛицо 3 ДанныеСтроки.ФизЛицо; НоваяСтрока.ВидРасчета = ДанныеСтроки.ВидРасчета; НоваяСтрока.ДатаНачало = ДанныеСтроки. ПериодДействияНачалоСторно; НоваяСтрока.ДатаКонец = ДанныеСтроки. ПериодДействияКонецСторно;
НоваяСтрока.Размер = ДанныеСтроки.Размер; НоваяСтрока.Подразделение = ДанныеСтроки.Подразделение; НоваяСтрока.Сторно = Истина; КонецЕсли; КонецПроцедуры // ДобавитьСтрокуСторноОсновныхНачислений // Процедура расчета основных начислений Процедура РассчитатьОсновныеНачисленияО Экспорт НачатьТранзакциюО; // Сформировать набор записей //... // Сформировать таблицу сторно-записей ТаблицаСторно = НаборОсновныеНачисления. ПолучитьДополнениеО; // Добавить сторно-записи в набор Для Каждого СтрокаСторно из ТаблицаСторно Цикл ДобавитьСтрокуСторноОсновныхНачислений(СтрокаСторно, НаборОсновныеНачисления. ОсновныеНачисления); КонецЦикла; ЗафиксироватьТранзакциюО; КонецПроцедуры // РассчитатьОсновныеНачисления При формировании сторно-записей данные всех измере- ний и реквизитов записи указаны в строке дополнения. Также в этой строке содержатся данные о периоде регист- рации и периоде действия сторно-записи. Ресурсы стор- но-записи не заполняются, так как запись будет рассчита- на в общем порядке. Расчет набора записей в общем модуле Сформированный документом набор записей регистра расчета рекомендуется рассчитывать в процедурах обще- го модуля. Это связано с тем, что формирование записей, как правило, происходит в нескольких документах, тогда как модуль расчета этих записей один и тот же. Напри- мер, оплата отпусков может вводиться отдельным доку- ментом конфигурации, при этом записи об отпуске рас- считываются в общем порядке. Таким образом, функция документов в решениях по периодическим расчетам сво- дится, как правило, к формированию первоначального набора записей в регистре, а все сложные алгоритмы рас- чета должны быть расположены в общем модуле как еди- ные для всех документов. Ниже приведен пример вызова процедуры общего модуля РассчитатьЗаписиРегистраРасчета() (листинг 10.11). Сама процедура будет описана позже. Листинг 10.11. Пример процедуры РассчитатьОсновныеНачисления Процедура РассчитатьОсновныеНачисленияО Экспорт // Расчет записей выполняется в транзакции НачатьТранзакциюО; // Сформировать набор и добавить сторно-записи //... // Передать набор записей в процедуру // общего модуля для расчета РассчитатьЗаписиРегистраРасчетаС'ОсновныеНачисленияРегл", НаборОсновныеНачисления, ОсновныеНачисления); // Удалить движения по регистру НаборОсновныеНачисления.ОчиститьО; НаборОсновныеНачисления.Записать!); ЗафиксироватьТранзакциюО; КонецПроцедуры // РассчитатьОсновныеНачисления В качестве параметров в процедуру расчета в данном слу- чае передается название регистра, набор записей для рас- чета, а также табличная часть документа, в которую будут возвращены результаты расчетов. После получения ре- зультатов расчетов происходит удаление записей регистра расчета, так как документ рассчитывался без проведения. Результаты расчетов помещаются в табличную часть, и пользователь может их скорректировать. Окончатель- ные записи регистра расчета формируются по табличной части документа при его проведении (рис. 10.65). Рис 10.65. Схема взаимодействия объектов В процедуре общего модуля, выполняющей расчет запи- сей переданного набора, необходимо предусмотреть вы- полнение следующих действий (рис. 10.66). Рассмотрим эти действия подробнее. В данном случае эти действия выполняются в процедуре общего модуля Расче- ты, которая называется РассчитатьЗаписиРегистраРасчета(). Запись набора с формированием фактического периода действия Перед тем как рассчитывать записи каждого регистра рас- чета, в котором документ создает движения, необходимо сформировать и записать в регистр набор всех записей до- кумента по этому регистру. Первоначальная запись движе- ний в регистр расчета необходима для формирования пра- вильного фактического периода действия этих записей В случае последовательного ввода и расчета записей без предварительной записи всего набора результат расчета мо- жет оказаться неверным. Рассмотрим влияние этого дейст- вия на следующем примере записей документа (рис. 10.67). При последовательной записи и расчете этих начислений результат расчета оклада будет неверным, так как в мо- мент расчета оклада записи о командировке еще не будет в регистре, соответственно, фактический период действия оклада будет совпадать с периодом действия, и сотруднику будет начислен полный тариф оклада. В момент записи командировки произойдет вытеснение, и фактический пе
Рис. 10.66. Действия в процедуре общего модуля Рис 10.67. Пример расчета записей регистра Фактический верно» действия на момент расчета записи Рис, 10.68. Формирование фактического периода действия риод действия оклада изменится, но на результат его рас- чета это уже не повлияет, так как запись уже рассчитана. Для формирования правильного фактического периода действия с учетом всех вытеснений в рамках одного набо- ра записей необходимо предварительно записать весь на- бор в регистр. В момент записи сработает механизм вы- теснения, и будет сформирован фактический период действия каждой записи. В этом случае в момент расчета каждая запись будет иметь правильный фактический пе- риод действия (рис. 10.68). Для того чтобы запись производилась с расчетом факти- ческого периода действия и формированием записей пе- рерасчетов, о которых будет сказано в следующем разде- ле, необходимо при вызове метода Записать О набора записей регистра расчета во второй параметр метода (па- раметр ТолькоЗапись) передать значение Ложь. При установ- ке параметра ТолькоЗапись в значение Истина записи будут помещены в регистр без пересчета фактического периода действия (листинг 10.12). Листинг 10.12. Пример расчета записей регистра Процедура РассчитатьЗаписиРегистраРасчета( ИняРегистра, НаборЗаписей, ТабличнаяЧасть = Неопределено) Экспорт // Первоначальная запись набора с формированием // фактического периода действия НаборЗаписей.Записать(Истина, Ложь); // Расчет записей //................... КонецПроцедуры
Классификация записей по приоритету видов расчета Как уже отмечалось выше, расчет записей одного доку- мента необходимо производить в последовательности, определяемой приоритетом видов расчета, участвующих в этих записях. Поэтому исходный набор записей должен быть разбит на несколько поднаборов, в каждом из кото- рых будут записи одного приоритета. Затем необходимо последовательно рассчитать записи каждого из поднабо- ров, записав результат расчета в регистр. Запись каждого рассчитанного поднабора необходима для формирования базы расчета следующих по приоритету поднаборов. Ниже приведен пример процедуры, которая классифици- рует записи исходного набора по приоритету видов рас- чета и для каждого уровня приоритета вызывает процеду- ру расчета поднабора записей. В данном случае из набора записей выгружается массив видов расчета, после чего по этим видам расчета строится запрос с иерархией по прио- ритету (листинг 10.13). Листинг 10.13. Расчет записей по приоритету видов расчета Процедура РассчитатьЗаписиРегистраРасчета( ИмяРегистра, НаборЗаписей, ТабличнаяЧасть = Неопределено) Экспорт НаборЗаписей.Записать(Истина, Ложь); // Определить название плана видов расчета для запроса ИмяПланаВидовРасчета = Метаданные.РегистрыРасчета[ИмяРегистра]. ПланВидовРасчета.Имя; // Получить массив видов расчета из набора записей ТаблицаВидовРасчета = НаборЗаписей.ВыгрузитьО; ТаблицаВидовРасчета.Свернуть("ВидРасчета"); МассивВидовРасчета = ТаблицаВидовРасчета. ВыгрузитьКолонку("ВидРасчета"); // Запрос по приоритетам видов расчета Запрос = Новый Запрос; Запрос.Текст = " ВЫБРАТЬ РАЗЛИЧНЫЕ Приоритет ИЗ ПланВидовРасчета.” + ИмяПланаВидовРасчета + " КАК " + ИмяПланаВидовРасчета + ” ГДЕ Ссылка В (&МассивВидовРасчета) УПОРЯДОЧИТЬ ПО " + ИмяПланаВидовРасчета + ".Приоритет ИТОГИ ПО Приоритет"; Запрос.УстановитьПараметр("МассивВидовРасчета", МассивВидовРасчета); ВыборкаПриоритетов = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса. ПоГруппировкам); // Для каждого значения приоритета выполнить расчет записей Пока ВыборкаПриоритетов.Следующий() Цикл РассчитатьНаборЗаписей(НаборЗаписей, ВыборкаПриоритетов. Приоритет, ТабличнаяЧасть); // Записать набор в регистр для расчета записей // следующего приоритета, фактический период действия // не пересчитывается НаборЗаписей.Записать(Истина, Истина); КонецЦикла; КонецПроцедуры После расчета записей каждого приоритета необходимо перезаписать весь набор в регистр для образования базы расчета для записей следующего приоритета. При этом параметр ТолькоЗапись метода ЗаписатьО должен быть ус- тановлен в значение Истина, так как пересчитывать факти- ческий период действия уже не нужно, он был рассчитан при первоначальной записи. ПРИМЕЧАНИЕ После расчета записей последнего приоритета набор запи- сей можно не перезаписывать, но только в том случае, если в документе после этого не будет производиться рас- чет записей другого регистра, который может использовать данные текущего регистра как базу. Например, если после расчета регистра основных начислений в модуле будет сра- зу производиться расчет дополнительных начислений, то записи регистра основных начислений после расчета по- следнего приоритета должны быть перезаписаны. Получение данных для расчета Собственно процесс расчета записей каждого поднабора состоит в получении всех необходимых данных для рас- чета каждой записи и вычислении значений ресурсов этой записи по формуле, определяемой способом расчета данной записи. Например, для расчета записи об окладе нужно будет получить данные графика этой записи, для расчета премии необходимо будет рассчитать базу и так далее. Ниже приведен пример процедуры, осуществляющей рас- чет набора записей одного приоритета. Для каждой записи при помощи функции ПолучитьДанныеДляРасчета() возвра- щается структура данных, которая передается в процедуру РассчитатьЗапись() (листинг 10.14). Процедура Рассчитать- Запись() будет описана позже. Листинг 10.14. Расчет набора записей одного приоритета Процедура РассчитатьНаборЗаписей(НаборЗаписей, Приоритет, ТабличнаяЧасть = Неопределено) Для каждого Запись из НаборЗаписей Цикл Если Запись.ВидРасчета.Приоритет = Приоритет Тогда // Получить данные для расчета записи ДанныеДляРасчета = ПолучитьДанныеДляРасчета(Запись); // Вызвать процедуру расчета записи РассчитатьЗапись(Запись, ДанныеДляРасчета); // Возвратить результат расчета в табличную // часть документа Если Не ТабличнаяЧасть = Неопределено Тогда СтрокаТабличнойЧасти = ТабличнаяЧасть. Получить(Запись.НомерСтроки-1); СтрокаТабличнойЧасти.Результат = Запись.Результат; КонецЕсли; КонецЕсли; КонецЦикла; КонецПроцедуры В функции ПолучитьДанныеДляРасчета() должны быть про- писаны алгоритмы, при помощи которых можно получить данные для расчета записи с любым способом расчета, су- ществующим в конфшурации. Ниже приведен пример функции, которая получает данные для 3-х способов рас- чета (листинг 10.15).
Листинг 10.15. Получение данных для 3-х видов расчета Функция ПолучитьДанныеДляРасчета(Запись) СпособРасчета = Запись.ВидРасчета.СпособРасчета; СтруктураДанных = Новый Структура: Если СпособРасчета = Перечисления.СпособыРасчета. ПоМесячнойСтавке Тогда // Получить данные графика Запрос = Новый Запросе |ВЫБРАТЬ | ДанныеГрафика.ЗначениеФактическийПериодДействия | КАК ГрафикФакт. ДанныеГрафика.ЗначениеПериодДействия КАК ГрафикНорма |ИЗ РегистрРасчета.ОсновныеНачисленияРегл.ДанныеГрафика( Регистратор = (^Регистратор И НомерСтроки = &НомерСтроки) КАК ДанныеГрафика"): Запрос.УстановитьПаранетр(”Регистратор", Запись. Регистратор); Запрос.УстановитьПараметр("НомерСтроки". Запись. НомерСтроки): Выборка = Запрос. Выполнить О. Выбрать О: Если Выборка.Следующий() Тогда СтруктураДанных.Вставить("ОтработаноВремени", Выборка.ГрафикФакт); СтруктураДанных.Вставить("НормаВремени”, Выборка. ГрафикНорма): Иначе СтруктураДанных.Вставить("ОтработаноВремени", 0): СтруктураДанных.Вставить("НормаВремени", 0); КонецЕсли; ИначеЕсли СпособРасчета = Перечисления.СпособыРасчета. ПроцентомОтБазы Тогда Запрос = Новый Запросе |ВЫБРАТЬ | База.РезультатБаза |ИЗ |РегистрРасчета.ОсновныеНачисленияРегл. БазаОсновныеНачисленияРегл( Измерения, &Измерения, , Регистратор = &Регистратор | И НомерСтроки = &НомерСтроки) КАК База"): Измерения = Новый Массив(2): Измерения[0] = "ФизЛицо”: Измерения[1] = “Организация": Запрос.УстановитьПараметр("Регистратор", Запись. Регистратор); Запрос.УстановитьПараметреНомерСтроки", Запись. НомерСтроки); Запрос.УстановитьПараметр("Измерения”, Измерения); Выборка = Запрос.Выполнить().Выбрать(); Если Выборка.Следующий() Тогда СтруктураДанных.Вставить("База", Выборка. РезультатБаза): Иначе СтруктураДанных.Вставить("База", 0): КонецЕсли; ИначеЕсли СпособРасчета = Перечисления.СпособыРасчета. ПоСдельнойВыработке Тогда // Получить данные регистра накопления // фактическая выработка за период действия записи Запрос = Новый Запросе ВЫБРАТЬ СУММА(Сдел ь ная Выработ каОбороты.Выработ каОборот) КАК ВыработкаОборот ИЗ PerистрНакопления.СдельнаяВыработка.Обороты( ВДатаНачало, ВДатаКонец, . Организация = («Организация И ФизЛицо = &ФизЛицо) КАК СдельнаяВыработкаОбороты"); Запрос.УстановитьПараметрСДатаНачапо", НачалоДняС Запись.ПериодДействияНачало)): Запрос.УстановитьПараметр("ДатаКонец”, КонецДня( Запись.ПериодДействияКонец)); Запрос.УстановитьПараметр("ФизЛицо”, Запись.ФизЛицо); Запрос,УстановитьПараметр( "Организация", Запись.Организация); Выборка = Запрос. Выполнить О.ВыбратьО; Если Выборка.Следующий() Тогда СтруктураДанных.Вставить("Выработка", Выборка. ВыработкаОборот); Иначе СтруктураДан ных.Встав и т ь("Выработка", 0): КонецЕсли: КонецЕсли; Возврат СтруктураДанных; КонецФункции //ПолучитьДанныеДляРасчета В данном случае для расчета записей со способом ПоМе- сячнойСтавке система получит данные графика за период действия и фактический период действия, для способа ПроцентомОтБазы будет получена расчетная база записи, а для способа ПоСдельнойВыработке будут рассчитаны обо- роты по соответствующему регистру накопления за ин- тервал периода действия записи. Способ расчета Фиксиро- ваннойСуммой не требует получения данных. Функция ПолучитьДанныеДляРасчета() возвращает струк- туру, содержащую различные поля в зависимости от спо- соба расчета, применяемого в данной записи. Расчет значений ресурсов записи После того как данные для расчета получены, необходи- мо прописать в модуле формулу для заполнения реквизи- тов каждой записи в соответствии со способом расчета. В данном случае эту функцию выполняет процедура РассчитатьЗапись(). В процедуре РассчитатьЗапись() для ка- ждого возможного способа расчета описывается форму- ла, позволяющая из реквизитов записи и полученных данных рассчитать значения ресурсов этой записи (лис- тинг 10.16). Листинг 10.16. Процедура расчета записей Процедура Рассчитать3апись(3апись, ДанныеДляРасчета) СпособРасчета = Запись.ВидРасчета.СпособРасчета: Если СпособРасчета = Перечисления.СпособыРасчета. ПоМесячнойСтавке Тогда Если Не ДанныеДляРасчета.НормаВремени = 0 Тогда Результат = Запись.Размер * ДанныеДляРасчета. ОтработаноВремени / ДанныеДляРасчета.НормаВремени; Иначе Результат = 0: КонецЕсли; ИначеЕсли СпособРасчета = Перечисления.СпособыРасчета. ПроцентомОтБазы Тогда Результат = Запись.Размер * ДанныеДляРасчета.База / 100;
ИначеЕсли СпособРасчета = Перечисления.СпособыРасчета. ФиксированнойСунмой Тогда Результат = Запись.Размер: ИначеЕсли СпособРасчета = Перечисления.СпособыРасчета. ПоСдельнойВыработке Тогда Результат = ДанныеДляРасчета.Выработка: КонецЕсли; Запись.Результат = Результат * ’(Запись.Сторно, -1, 1): КонецПроцедуры // Рассчитать запись При расчете записей следует учитывать, что сторно-за- писи рассчитываются в общем порядке. Поэтому в ре- сурсы сторно-записи должно попадать отрицательное значение результата расчета. Например, сторно-запись отменяет начисленный оклад за период 5 дней. При рас- чете такой записи по формуле система получит сумму оклада за 5 дней, например 1200 руб. В ресурс сторно- записи в этом случае должно быть записано значе- ние -1200. Перерасчет записей регистров расчета Объект конфигурации Перерасчет Платформа позволяет автоматически отслеживать влия- ние ввода и изменения записей регистра расчета на дру- гие записи регистров расчета. Например, при изменении записи об окладе может потерять актуальность запись о начисленной премии. Автоматическое отслеживание за- писей, потерявших актуальность в результате изменения или ввода других записей в регистры расчета, произво- дится при помощи механизма перерасчетов. Перерасчет в системе представляет собой отдельную фи- зическую таблицу, в которой хранится информация о за- писях конкретного регистра расчета, которые необходимо перерасчитать. В конфигурации можно создавать не- сколько таблиц перерасчета для различных регистров расчета, в том числе несколько таких таблиц может быть у одного регистра расчета. Для создания и настройки объ- ектов Перерасчет предусмотрена отдельная ветка в объекте конфигурации Регистр расчета (рис. 10.69). Е-13 Регистры расчета Й-СТ ОсновныеН ачисленияРегл Измерения Й - Д, Ресурсы E g Реквизиты Ё Перерасчеты •О ПерерасчетО сновныхНачислений ! Ё ® Формы : Макеты Рис. 10.69. Перерасчеты Таблица перерасчета, создаваемая внутри определенного регистра расчета в дереве конфигурации, будет хранить информацию о записях только этого регистра расчета. При этом физически таблица перерасчета представляет собой отдельную таблицу базы данных, никак не связан- ную с регистром расчета. При создании в рамках регистра расчета таблицы пере- расчета без дополнительных настроек эта таблица будет иметь следующую структуру (табл. 10.20). Таблица 10.20. Структура таблицы перерасчета ОбъектПерерасчета ВидРасчета ’Начисление зарплаты №1 ’Надбавка руководителю ’Начисление зарплаты №1 ’Надбавка за вахту ’Начисление зарплаты №2 ’Надбавка руководителю В таблице перерасчета всегда присутствуют две колонки. В колонке Объект перерасчета хранится ссылка на доку- мент, который ввел в базу данных запись регистра расче- та, которую необходимо перерасчитать, а в колонке Вид расчета — ссылка на вид расчета, записи по которому по- теряли актуальность. В приведенном примере из таблицы перерасчета можно сделать вывод о том, что в документе Начисление зарплаты №1 необходимо перерасчитать записи с видами расчета Надбавка руководителю и Надбавка за вахту, а в документе Рис. 10.70. Формирование записей перерасчета
Начисление зарплаты №2 — только записи с видом расчета Надбавка руководителю. Формирование записей таблицы перерасчета происходит при записи в регистр расчета данных по видам расчета, которые являются ведущими по отношению к другим ви- дам расчета. Например, в списке ведущих для таких ви- дов расчета, как Надбавка руководителю и Премия за месяц, содержится вид расчета Оклад. Это означает, что при вво- де или изменении записи об окладе в таблицы перерасче- та соответствующих регистров попадет запись о тех над- бавках и премиях, которые в результате этого потеряли актуальность (рис. 10.70). Так как ведущими могут выступать виды расчета любых планов видов расчета конфигурации, при вводе записи в один регистр расчета могут возникать записи в таблицах перерасчета нескольких регистров. В данном случае при вводе оклада в регистр Основные начисления (регл) форми- руются записи в таблицах перерасчетов регистров Основ- ные начисления (регл) и Дополнительные начисления (регл). Порядок заполнения таблицы перерасчета будет подроб- нее рассмотрен позже. Важно понимать, что записи пере- расчета имеют рекомендательный характер, то есть плат- форма лишь сигнализирует, что определенные записи потеряли актуальность. Собственно алгоритм перерасче- та записей разработчик должен предусмотреть самостоя- тельно. Измерения перерасчета В приведенном выше примере при изменении оклада в таблицу перерасчета попадает информация о том, в ка- ких документах нужно перерасчитать записи с опреде- ленными видами расчета. При этом зачастую эти данные недостаточно информативны, так как в таблице не указа- но, записи с какими значениями измерений необходимо перерасчитать. В частности, при изменении оклада толь- ко одному сотруднику в одной организации в таблице пе- рерасчета возникнут записи обо всех документах, в кото- рых были начислены премии и надбавки для всех сотруд- ников всех организаций. В этом случае, если таблица пе- рерасчета имеет приведенную выше структуру, придется перерасчитывать все указанные записи. Для того чтобы в таблице перерасчета хранилась инфор- мация о значении измерений регистра расчета, данные по которым необходимо перерасчитать, предусмотрена воз- можность настройки измерений перерасчета. При добав- лении в перерасчет измерений в таблице перерасчета до- бавляются новые колонки. Например, если в перерасчет основных начислений добавить два измерения ФизЛицо и Организация, таблица перерасчета примет следующий вид (табл. 10.21). Данная таблица более информативна, так как в ней спе- цифицированы конкретные сотрудники организаций, для которых необходимо выполнить перерасчет записей ука- занных видов расчета в указанных документах. При вводе записи об окладе по конкретному сотруднику в таблицу перерасчета данной структуры попадут не все записи по зависимым видам расчета, а только записи по этому со- труднику. Фактически, при анализе существования зависимых за- писей, которые необходимо перерасчитать, платформа будет анализировать данные регистров с отбором по кон- кретным значениям измерений. При этом структура реги- стра, в который вводится ведущая запись, может отли- чаться от структуры зависимого регистра. Поэтому при настройке измерений перерасчета необходимо указать связь измерений регистра, для которого будут формиро- ваться записи перерасчета, с данными ведущих регист- ров. Ведущими регистрами являются регистры расчета, при вводе или изменении записей которых необходимо создавать записи перерасчета для текущего регистра. Настройка такой связи производится через свойства из- мерения перерасчета (рис. 10.71). В свойстве Измерение регистра указывается измерение те- кущего регистра, на которое будет установлен отбор при анализе существования зависимых записей. Таблица 10.21. Таблица записей перерасчета ОбъектПерерасчета ВидРасчета ФизЛицо Организация •Начисление зарплаты №1 •Надбавка руководителю •Иванов •Ромашка •Начисление зарплаты №1 •Надбавка за вахту •Иванов •Ромашка •Начисление зарплаты №2 •Надбавка руководителю •Кузнецова •Ромашка X Выбор объекта Комментарий ’Связь. $• Измерение регистра Данные ведущих регистров ФизЛицо Ф из Л ицо,Ф из Л ицо В- ОсновныеНачисленияРегл Измерения Ь-р] U ФизЛицо —Г~| U Организация Я Реквизиты ДополнительныеНачисленияРегл Измерения : |~0 Ц ФизЛицо 1 -П U Организация Ё-Я Реквизиты 0-0 УдержанияРегл й В ОсновныеНачисленияУпр ЕНЗ ДополнительныеНачисленияУпр | Отмена ] В Б Рис. 10.71. Настройка измерений перерасчета
В свойстве Данные ведущих регистров перечисляются изме- рения или реквизиты ведущих регистров, в которых хра- нится значение, по которому должен быть установлен этот отбор. Если измерение или реквизит какого-либо регистра не будет указано в этом свойстве, то при вводе записей в этот регистр не будет происходить формиро- вание записей перерасчета для текущего регистра. На- пример, если в измерении ФизЛицо перерасчета регистра Дополнительные начисления (регл) не указана ссылка на соответствующее измерение регистра Основные начисле- ния (упр), то при вводе оклада для управленческого учета записи перерасчета регламентированных премий созда- ны не будут. Перерасчет может действовать и в рамках одного регист- ра. Например, при изменении оклада нужно перерасчи- тать надбавку руководителю, которая учитывается в том же регистре. В этом случае необходимо в свойстве Данные ведущих регистров указать связь соответствующего измере- ния регистра с самим собой. Автоматическое формирование записей перерасчета при вводе вытесняющих расчетов Как уже отмечалось, платформа может создавать записи таблиц перерасчетов автоматически. В частности, анализ необходимости формирования записей перерасчетов про- изводится системой в момент записи набора записей ре- гистра расчета, содержащего виды расчета, которые явля- ются вытесняющими по отношению к другим видам расчета. Если при вводе набора происходит вытеснение каких-либо записей регистра расчета, информация об этих записях будет автоматически записана в таблицу пе- рерасчета. Например, при вводе Командировки, которая вытесняет существующий Оклад, запись об Окладе попадет в таблицу перерасчета. Механизм формирования записей перерасчетов при вво- де вытесняющих расчетов действует независимо от того, включены ли соответствующие виды расчета в список ве- дущих по отношению к текущему виду расчета. Тем не менее в определенных случаях есть смысл включить вы- тесняющий расчет в список ведущих, такие случаи будут рассмотрены в разделе «Особенности использования таб- лицы вытесняющих видов расчета», с. 357. Автоматическое формирование записей перерасчета при вводе прочих расчетов Необходимость в формировании записей перерасчетов возникает не только в случае вытеснения. В частности, при вводе или изменении записей с базовыми видами расчета необходимо перерасчитать записи, которые от них зависят по базовому периоду. Например, при измене- нии Оклада необходимо сформировать запись перерасчета по Премии. Для того чтобы записи перерасчетов, не связанные с вы- теснением, сформировались автоматически, должны быть выполнены следующие условия. Зависимость видов расчета Для настройки зависимости видов расчета для целей перерасчета используется предопределенная табличная часть ведущих видов расчета. При анализе необходимо- сти перерасчета система проверяет, является ли вид расчета во вводимой записи регистра ведущим по отно- шению к видам расчета существующих записей регист- ров. В перерасчет попадут только те записи, по отноше- нию к которым данный вид расчета является ведущим. Поэтому для автоматического формирования записей перерасчета необходимо настроить списки ведущих ви- дов расчета во всех видах расчета, которые должны пе- рерасчитываться. Например, если в виде расчета Премия за месяц не указать Оклад как ведущий вид расчета, то запись о перерасчете Премии в случае изменения Оклада создана не будет. Связь измерений и реквизитов через измерения перерасчета Если у перерасчета есть измерения, формирование запи- сей этого перерасчета будет производиться только в слу- чае ввода или изменения записей тех регистров, измере- ния или реквизиты которых указаны в свойстве Данные ведущих регистров измерений перерасчета. При этом в текущем регистре будет установлен отбор по значениям соответствующих полей ведущих регистров. Например, при вводе Оклада сотруднику Иванов в реги- стре дополнительных начислений будут анализиро- ваться только записи по сотруднику Иванов. В случае отсутствия измерения перерасчета, для соответствую- щей таблицы выполнение этого условия проверяться не будет. Зависимость по базовому периоду При анализе существования зависимых записей учитыва- ется, попадает ли ведущая запись в базовый период зави- симой. Запись о перерасчете будет формироваться только в том случае, если ведущая запись пересекает базовый пе- риод зависимой. Например, при вводе оклада за март в таблицу перерасчета попадут только те премии, базовый период которых пересекает март (рис. 10.72). При этом учитывается способ зависимости от базы, на- строенный в плане видов расчета зависимого регистра: зависимость по периоду действия или по периоду регист- рации. Принцип работы этих способов подробно описан в разделе «Настройка зависимости по базовому периоду», с. 339. При выполнении всех трех указанных условий записи таблиц перерасчетов будут формироваться платформой автоматически.
Базовый период расчета премии При вводе оклада запись о перерасчете премии создана не будет Регистр "Основные начисления” о перерасчете Премии не будет создана автоматически при изменении Оклада. Невыход вытеснение по Периоду действия зависимость по базе Премия Рис. 10.73. Пример зависимости видов расчета Регистр '"Дополнительные начисления” Базовый период расчета премии Оклад При вводе оклада будет создана запись о перерасчете премии Регистр "Основные начисления** Премия за месяц Настройка, указанная на схеме, в принципе достаточна для правильной работы начислений. При вводе или изме- нении Невыхода будет создана запись о необходимости перерасчета Оклада. После перерасчета Оклада и записи его в регистр система просигнализирует, что теперь воз- никла необходимость перерасчета Премии, так как Оклад является ведущим по отношению к Премии. Несмотря на то что зависимость отражена правильно, при такой настройке перерасчет записей приходится вы- полнять в два этапа. Первый раз таблица перерасчета ана- лизируется после изменения Невыхода, после чего произ- водится перерасчет Оклада. Затем необходимо повторно анализировать таблицу перерасчета, после чего перерас- читывать Премию (рис. 10.74). Регистр "Дополнительные начисления** Рис. 10.72. Формирование записей перерасчета Т аблица перерасчета: Премия __________JE_________ Т аблица перерасчета: Оклад Особенности использования таблицы вытесняющих видов расчета Таким образом, при заполнении табличной части веду- щих видов расчета необходимо учитывать следующие об- щие правила: ♦ вытесняющие виды расчета в список ведущих включать не обязательно, так как автоматическое формирование записей перерасчета по вытесняемым записям произой- дет и без этого; ♦ базовые виды расчета рекомендуется включить в спи- сок ведущих, в противном случае при изменении запи- си с базовым видом расчета текущая запись не попадет в таблицу перерасчетов автоматически. Однако в определенных случаях есть смысл включить в список ведущих в том числе и вытесняющие виды рас- чета. Рассмотрим следующий пример зависимости видов расчета (рис. 10.73). В данном случае вид расчета Невыход является вытесняю- щим по отношению к виду расчета Оклад, а Оклад, в свою очередь, является базовым по отношению к виду расчета Премя. При такой зависимости включать Невыход в спи- сок ведущих для Оклада необязательно, так как перерас- чет сработает в любом случае. А вот сам Оклад необходи- мо включить в список ведущих для Премии, иначе запись Рис. 10.74. Последовательность перерасчета записей Для того чтобы избежать необходимости поэтапного пе- рерасчета, следует настроить зависимость таким образом, чтобы запись о перерасчете Премии возникала сразу при изменении Невыхода, без промежуточного перерасчета Оклада. Для этого достаточно включить Невыход в список ведущих видов расчета по отношению к Премии (рис. 10.75). вытеснение по периоду действия у Оклад зависимость по базе Рис. 10.75. Пример зависимости видов расчета В результате этого перерасчет можно будет выполнить за один раз, так как при изменении Невыхода в таблицу пере-
расчета попадут и Оклад и Премия одновременно. Необхо- димо учитывать, что перерасчет записей об Окладе и Пре- мии в данном случае должен быть выполнен в правильной последовательности: сначала Оклад, затем Премия (рис. 10.76). Рис. 10.76. Последовательность перерасчета записей Формирование записей перерасчета средствами встроенного языка Во всех случаях, когда выполнить указанные выше условия не представляется возможным, записи таблиц перерасче- та в случае необходимости должны быть сформированы средствами встроенного языка. Такая необходимость мо- жет возникнуть, например, если в регистре не использу- ется базовый период. В этом случае таблица перерасчета данного регистра не будет формироваться автоматически. Также ручное формирование записей перерасчета может потребоваться в случае, когда необходимо отслеживать изменения данных, хранящихся не в регистре расчета, а, например, в регистре накопления. В этом случае при вводе данных в регистр накопления разработчик может предусмотреть ввод данных о перерасчете записей реги- стра расчета средствами встроенного языка. В частности, в демонстрационной конфигурации «Слож- ные периодические расчеты», которая находится на при- лагаемом компакт-диске, способ расчета ПоСдельнойВыра- ботке предполагает расчет начислений на основе данных регистра накопления СдельнаяВыработка. При изменении данных этого регистра за определенный период может возникать необходимость перерасчета уже рассчитанных начислений по сдельному заработку. Записи в соответст- вующую таблицу перерасчета в этом случае должны быть сформированы средствами встроенного языка в момент изменения данных регистра накопления СдельнаяВыработка. Формирование записей таблицы перерасчета происхо- дит с использованием метода СоздатьНаборЗаписейО объ- екта ПерерасчетМенеджер. Создаваемый набор записей дол- жен всегда содержать отбор по полю ОбъектПерерасчета. Для записи созданного набора применяется метод Запи- сатьО объекта ПерерасчетНаборЗаписей. В качестве пара- метра указывается значение типа Булево. Если будет пе- редано значение Истина, перед записью набора будут удалены записи таблицы, удовлетворяющие установлен- ному отбору. Установка параметра в значение Ложь по- зволит добавить созданные записи в таблицу без заме- щения существующих. Ниже приведен пример модуля, формирующего записи таблицы перерасчета основных начислений (листинг 10.17). В запросе выбираются записи регистра расчета основных начислений с предопределенным видом расчета Сдельный, период действия которых содержит дату движения по ре- гистру накопления. В результате для каждого сотрудника каждой организации запрос возвращает значение доку- мента, который ввел данную запись о сдельном заработке в регистр. Данная процедура вызывается сразу после формирования движений по регистру накопления. Фраг- мент доступен в демо-конфигурации в модуле документа РегистрацияСдельнойВыработки. Листинг 10.17. Формирование записей перерасчета Процедура СформироватьЗаписиПерерасчета() // Запрос по записям регистра расчета Запрос = Новый Запросе ВЫБРАТЬ РАЗЛИЧНЫЕ Сдель наяВыработка.ФизЛицо, СдельнаяВыработка.Организация, ОсновныеНачисленияРегл.Регистратор, ОсновныеНачисленияРегл.ВидРасчета ИЗ РегистрНакопления.СдельнаяВыработка КАК СдельнаяВыработка ЛЕВОЕ СОЕДИНЕНИЕ РегистрРасчета.ОсновныеНачисленияРегл КАК ОсновныеНачисленияРегл ПО СдельнаяВыработка.ФизЛицо = ОсновныеНачисленияРегл. ФизЛицо И СдельнаяВыработка.Организация = ОсновныеНачисленияРегл.Организация И (СдельнаяВыработка.Период МЕВДУ ОсновныеНачисленияРегл.ПериодДействияНачало И ОсновныеНачисленияРегл. ПериодДействияКонец) ГДЕ ОсновныеНачисленияРегл.ВидРасчета = &ВидРасчета И СдельнаяВыработка.Регистратор = &Регистратор ИТОГИ ПО Регистратор”); Запрос.УстановитьПараметрС“ВидРасчета", ПланыВидовРасчета. ОсновныеНачисления.Сдельный); Запрос.УстановитьПараметрС'Регистратор". Ссылка); Выборка = Запрос.Выполнить!).ВыбратьО; // Получить объект ПерерасчетМенеджер Перерасчет = РегистрыРасчета.ОсновныеНачисленияРегл. Перерасчеты. ПерерасчетОсновныхНачислений: ВыборкаДркументов = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса. ПоГруппировкам); Пока ВыборкаДркументов.Следующий() Цикл // Создать набор записей НаборЗаписей = Перерасчет.СоздатьНаборЗаписейО; НаборЗаписей.Отбор.ОбъектПерерасчета.Значение = ВыборкаДокументов.Регистратор; Выборка = ВыборкаДокументов. Выбрать О; // Создать записи перерасчета Пока Выборка.Следующий() Цикл Запись = НаборЗаписей.ДобавитьО; Запись.ВидРасчета = Выборка.ВидРасчета; Запись.Организация = Выборка.Организация; Запись. ФизЛицо = Выборка.ФизЛицо; КонецЦикла; // Записать в таблицу без замещения НаборЗаписей.Записать(Ложь); КонецЦикла; КонецПроцедуры
Автоматическое удаление записей перерасчета Записи автоматически удаляются платформой из таблицы перерасчета только в том случае, если из регистра расчета удалена запись, которую необходимо перерасчитать. При этом необходимо учитывать, что удаление записей регист- ра расчета происходит не только при отмене проведения соответствующего документа, но и при его перепроведе- нии, а также при повторном расчете. Расчет документа предполагает, что записи формируются и рассчитываются заново, при этом предыдущие записи документа удаля- ются. Собственно при перерасчете записей регистра расчета платформа автоматически не удалит записи из табли- цы перерасчета, так как при перерасчете не происходит удаления записи, меняются лишь значения ее ресурсов. Поэтому при формировании процедуры перерасчета раз- работчик должен предусмотреть удаление записей пере- расчета средствами встроенного языка. Пример такой процедуры будет рассмотрен в разделе «Реализация пере- расчета записей регистра расчета», с. 360. Анализ данных таблицы перерасчета Данные таблицы перерасчета недоступны пользователю для интерактивного просмотра и изменения в режиме 1С:Предприятие. Поэтому для возможности интерактив- ной работы пользователя с этими данными следует пре- дусмотреть соответствующий отчет или обработку. На- пример, это может быть обработка, в которой выведены данные о записях перерасчета по конкретной организа- ции в следующем виде (рис. 10.77). Рис 10.77. Обработка «Перерасчет зарплаты» Данная обработка в верхнем списке отображает список сотрудников данной организации, по которым необходи- мо выполнить перерасчет записей. В нижней таблице приводится подробная информация о записях по текуще- му сотруднику с указанием документа и вида расчета. Выбрав в списке нужных сотрудников, пользователь мо- жет нажать на кнопку Выполнить перерасчет и иницииро- вать перерасчет записей по соответствующим сотрудни- кам. Ниже приведен текст модуля, заполняющий список физических лиц, а также таблицу записей по выбранному сотруднику (листинг 10.18). Полностью данная обработка представлена в демонстрационной конфигурации «Слож- ные периодические расчеты», которая находится на при- лагаемом компакт-диске. Листинг 10.18. Заполнение списка сотрудников и заполнение таблицы записей по выбранному сотруднику // Заполнение списка физлиц для перерасчета по выбранной организации Процедура ЗаполнитьФизлицаПоОрганизацииО Запрос = Новый Запрос; Запрос.УстановитьПараметрС"Организация", Организация); Запрос.Текст = ” ВЫБРАТЬ РАЗЛИЧНЫЕ ПерерасчетОсновныхНачислений.ФизЛицо, ИСТИНА КАК Пометка ИЗ РегистрРасчета.ОсновныеНачисленияРегл. ПерерасчетОсновныхНачислений КАК ПерерасчетОсновныхНачислений ГДЕ ПерерасчетОсновныхНачислений.Организация = Организация ОБЪЕДИНИТЬ ВЫБРАТЬ РАЗЛИЧНЫЕ ПерерасчетДополнительныхНачислений.ФизЛицо, ИСТИНА ИЗ РегистрРасчета.ДополнительныеНачисленияРегл. ПерерасчетДополнительныхНачислений КАК ПерерасчетДрполнительныхНачислений ГДЕ ПерерасчетДополнительныхНачислений.Организация = Организация"; ТаблицаФизлиц = Запрос.Выполнить().Выгрузить(); ТаблицаФизлиц.Свернуть("Физлицо"): МассивФизлиц = ТаблицаФизлиц.ВыгрузитьКолонку("ФизЛицо"); Физлица.ЗагрузитьЗначения(МассивФизлиц); КонецПроцедуры // Заполнить таблицу записей по выбранному физлицу Процедура ЗаполнитьЗаписиПоФизлицу(ФизЛицо) Запрос = Новый Запрос; Запрос.УстановитьПараметрС"ФизЛицо", ФизЛицо): Запрос.Текст = " ВЫБРАТЬ РАЗЛИЧНЫЕ ПерерасчетОсновныхНачислений.ОбъектПерерасчета, ПерерасчетОсновныхНачислений.ВидРасчета ИЗ РегистрРасчета.ОсновныеНачисленияРегл. ПерерасчетОсновныхНачислений КАК ПерерасчетОсновныхНачислений ГДЕ ПерерасчетОсновныхНачислений.ФизЛицо = &ФизЛицо ОБЪЕДИНИТЬ ВЫБРАТЬ РАЗЛИЧНЫЕ ПерерасчетДополнительныхНачислений.ОбъектПерерасчета, ПерерасчетДополнительныхНачислений.ВидРасчета ИЗ РегистрРасчета.ДополнительныеНачисленияРегл. ПерерасчетДополнительныхНачислений КАК ПерерасчетДополнительныхНачислений ГДЕ ПерерасчетДополнительныхНачислений.ФизЛицо = &ФизЛицо"; ЗаписиПоФизЛицу = Запрос.ВыполнитьО.ВыгрузитьО; ЭлементыФормы.ЗаписиПоФизлицу.СоздатьКолонки(); КонецПроцедуры
Процедура инициации перерасчета состоит в вызове соответствующей экспортной процедуры документа, записи которого должны быть перерасчитаны. Сама процедура описана в следующем разделе. Ниже приве- ден текст модуля, вызывающего процедуру перерасчета документов с передачей списка сотрудников, по кото- рым должен быть выполнен перерасчет. Для этого при помощи запроса строится выборка документов из таб- лиц перерасчета по выбранному списку сотрудников (листинг 10.19). Листинг 10.19. Пример вызова процедуры перерасчета Процедура Кноп каВыполни т ьНажат не (Кноп ка) СписокФизлиц = Новый СписокЗначений; Для каждого Элемент из ФизЛица Цикл Если Элемент.Пометка Тогда СписокФизлиц.Добавить(Элемент.Значение); КонецЕсли; КонецЦикла; Запрос = Новый Запрос; Запрос.УстановитьПараметр("ФизЛица", СписокФизлиц); Запрос.Текст = " ВЫБРАТЬ РАЗЛИЧНЫЕ ПерерасчетОсновныхНачислений.ОбъектПерерасчета ИЗ РегистрРасчета.ОсновныеНачисленияРегл. ПерерасчетОсновныхНачислений КАК ПерерасчетОсновныхНачислений ГДЕ ПерерасчетОсновныхНачислений.ФизЛицо В (&ФизЛица) ОБЪЕДИНИТЬ ВЫБРАТЬ РАЗЛИЧНЫЕ ПерерасчетДополнительныхНачислений.ОбъектПерерасчета ИЗ РегистрРасчета.ДополнительныеНачисленияРегл. ПерерасчетДрполнительныхНачислений КАК ПерерасчетДополни тел ь ныхНач ислени й ГДЕ ПерерасчетДополнительныхНачислений.ФизЛицо В (&ФизЛица)"; ВыборкаДокументов = Запрос.ВыполнитьО.Выбрать; // выборка по документам, требующим перерасчета Пока ВыборкаДокументов.СледующийО Цикл // Получить объект ДокументОбъект = ВыборкаДокументов.ОбъектПерерасчета.ПолучитьОбъект(): // Вызвать процедуру перерасчета Попытка ДокументОбъект.Перерассчитать(СписокФизлиц): Исключение Сообщить("Документ не может быть перерассчитан! " + ВыборкаДокументов.ОбъектПерерасчета); КонецПопытки; КонецЦикла; КонецПроцедуры Реализация перерасчета записей регистров расчета Как уже отмечалось, записи перерасчета имеют рекомен- дательный характер, поэтому алгоритм собственно пе- рерасчета записей регистра расчета, то есть изменения значения ресурсов этих записей, разработчик должен предусмотреть самостоятельно. Алгоритм перерасчета за- писей, по сути, не отличается от алгоритма их расчета, описанного в разделе «Технология формирования и рас- чета записей регистров расчета», с. 345. Специфика пере- расчета состоит в его выборочной работе, перерасчет не предполагает, что все записи документа будут заново рас- считаны. В частности, если в документе начислены пре- мии нескольким тысячам сотрудников, то при изменении оклада только одного из них, в процессе перерасчета пре- мий не должны быть заново рассчитаны все записи. Мо- дуль перерасчета должен быть настроен таким образом, чтобы были выборочно изменены значения ресурсов только тех записей, которые пользователь попросил пере- расчитать. В процессе перерасчета не происходит создания новых записей регистров расчета или удаления существующих. При получении от пользователя команды о перерасчете записей по конкретным значениям измерений система должна произвести следующие действия (рис. 10.78). Рис. 10.78. Действия, которые необходимо выполнить по команде пользователя Перед началом перерасчета необходимо проанализиро- вать необходимость перерасчета. Это связано с тем, что с момента, когда пользователь получил информацию о наличии записей в таблице перерасчета, до момента, ко- гда он инициировал процедуру, данные регистра могли измениться, и необходимость в перерасчете могла от- пасть. Например, за это время выполнить перерасчет мог успеть другой пользователь. Необходимость перерасчета может быть проверена, например, с использованием та- кой функции (листинг 10.20). Листинг 10.20. Проверка необходимости перерасчета // Проверяет необходимость выполнения перерасчета документа Функция НеобходимостьПерерасчета(Регистратор) Экспорт Запрос = Новый Запрос( "ВЫБРАТЬ ПЕРВЫЕ 1 Перерасчет.ФизЛицо ИЗ (ВЫБРАТЬ ПЕРВЫЕ 1 Перерасчет.ФизЛицо КАК ФизЛицо ИЗ РегистрРасчета.ОсновныеНачисленияРегл. ПерерасчетОсновныхНачислений КАК Перерасчет ГДЕ Перерасчет.ОбъектПерерасчета = йпарамРегистратор ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ПЕРВЫЕ 1 Перерасчет.ФизПицо ИЗ РегистрРасчета.ДополнительныеНачисленияРегл. ПерерасчетДополнительныхНачислений КАК Перерасчет ГДЕ Перерасчет.ОбъектПерерасчета = &Регистратор) КАК Перерасчет "): Запрос.УстановитьПараметрС"Регистратор", Регистратор); Если Запрос.Выполнить().Пустой() Тогда Возврат Ложь; Иначе Возврат Истина; КонецЕсли; КонецФункции // НеобходимостьПерерасчета Данная функция возвращает значение Истина, если хотя бы в одной из таблиц перерасчета есть хотя бы одна за- пись по данному документу. Если таких записей нет, то функция вернет значение Ложь, и перерасчитывать записи этого документа не нужно. Функция приведена в демо- конфигурации в общем модуле Расчеты. Собственно перерасчет записей, как и их расчет, рекомен- дуется выполнять в процедуре общего модуля по тем же причинам, что и расчет. Процедура перерасчета отличает- ся от процедуры расчета только тем, что в расчете участ- вуют не все записи документа, а только удовлетворяющие условиям проводимого перерасчета. Например, только записи по конкретным сотрудникам и конкретным видам расчета. Наконец, после того как нужные записи перерасчитаны, необходимо средствами встроенного языка удалить соот- ветствующие записи из таблицы перерасчета, так как пе- рерасчет больше не требуется. Процедуру перерасчета записей документа рекоменду- ется помещать в модуле этого документа как экспорт- ную процедуру. В этом случае она может быть вызвана из других модулей, в том числе из обработки перерасче- та, описанной в предыдущем разделе. В качестве пара- метров в процедуру должна передаваться информация о том, какие именно записи документа необходимо пере- расчитать. Ниже приведен пример такой процедуры, где в качестве параметра используется список сотрудников, по которым необходимо выполнить перерасчет (лис- тинг 10.21). Листинг 10.21. Процедура перерасчета записей документа Процедура Перерассчитать(Физлица = Неопределено) Экспорт // Перерасчет выполняется в транзакции НачатьТранзакциюО; Если Не НеобходиностьПерерасчета(Ссылка) Тогда Возврат; КонецЕсли; // Считать движения документа по регистрам расчета Движения. ОсновныеНачисленияРегл. ПрочитатьО; Движения.ДополнительныеНачисленияРегл.Прочитать(); // Перерасчет и перезапись движений по регистрам расчета ПерерассчитатьЗаписиРегистраРасчетаСОсновныеНачисленмяРегл", Движения.ОсновныеНачисленияРегл. ОсновныеНачисления, Физлица); Движения.ОсновныеНачисленияРегл.Записать( Истина, Истина); ПерерассчитатьЗаписиРегистраРасчетаС' ДополнительныеНачисленияРегл", Движения.ДополнительныеНачисленияРегл, ДополнительныеНачисления, Физлица); Движения.ДополнительныеНачисленияРегл.Записать( Истина, Истина): // Записать измененные данные табличных частей документа ЗаписатьО; // Удалить записи перерасчета, по которым // выполнен перерасчет Для Н=1 По 2 Цикл Если Н=1 Тогда НаборЗаписей = РегистрыРасчета. ОсновныеНачисленияРегл. Перерасчеты.ПерерасчетОсновныхНачислений. СоздатьНаборЗаписейО; Иначе НаборЗаписей = РегистрыРасчета. ДополнительныеНачисленияРегл. Перерасчеты. ПерерасчетДополнительныхНачислений. СоздатьНаборЗаписейО; КонецЕсли; НаборЗаписей.Отбор.ОбъектПерерасчета.Значение = Ссылка; Если Физлица <> НеОпределено Тогда НаборЗаписей.Прочитать О; СтрокиКУдалению = Новый Массив: Для Каждого СтрокаПерерасчета из НаборЗаписей Цикл Если Физлица.НайтиПоЗначению( СтрокаПерерасчета.Физлицо) <> НеОпределено Тогда СтрокиКУдалению.Добавить(СтрокаПерерасчета); КонецЕсли; КонецЦикла: Для Каждого Строка Из СтрокиКУдалению Цикл НаборЗаписей.Удалить(Строка); КонецЦикла; КонецЕсли; НаборЗаписей.Записать(); КонецЦикла; // Перерасчет выполняется в транзакции ЗафиксироватьТранзакцию(); КонецПроцедуры Процедуры общего модуля, выполняющие непосредствен- ный перерасчет записей, по алгоритму схожи с процедура- ми расчета. Основное отличие состоит в том, что в процеду- рах перерасчета происходит расчет только тех записей, которые удовлетворяют заданным условиям. В данном слу- чае это записи по заданному списку сотрудников. Также при перерасчете не нужно производить предварительную запись набора с формированием фактического периода дей- ствия, так как набор уже записан в регистр (перерасчиты- ваемый документ всегда проведен). Ниже приведен пример процедур ПерерассчитатьЗаписиРегистраРасчета() и Перерас- считатьНаборЗаписей(). Эти процедуры используют вызов тех же самых процедур и функций, которые используются при расчете (листинг 10.22). Листинг 10.22. Процедуры перерасчета записей Процедура ПерерассчитатьНаборЗаписей(НаборЗаписей, Приоритет, ТабличнаяЧасть = Неопределено, ФизЛица = Неопределено)
Для каждого Запись из НаборЗаписей Цикл Если Запись.ВидРасчета.Приоритет = Приоритет Тогда Если НЕ ФизЛица.НайтиПоЗначениюС Запись.Физлицо)=Неопределено Тогда // Получить данные для расчета записи ДанныеДляРасчета = ПолучитьДанныеДляРасчетаС Запись); // Вызвать процедуру расчета записи РассчитатьЗапись(Запись, ДанныеДляРасчета); // Вернуть результат расчета в табличную часть // документа Если Не ТабличнаяЧасть = Неопределено Тогда СтрокаТабличнойЧасти = ТабличнаяЧасть.Получить( Запись.НомерСтроки-1); СтрокаТабличнойЧасти.Результат = Запись.Результат; КонецЕсли; КонецЕсли; КонецЕсли; КонецЦикла; КонецПроцедуры Процедура ПерерассчитатьЗаписиРегистраРасчетаС ИмяРегистра, НаборЗаписей. ТабличнаяЧасть = Неопределено, Физлица = Неопределено) Экспорт Регистратор = НаборЗаписей.Отбор.Регистратор.Значение; // Запрос по приоритетам видов расчета // только записей заданных сотрудников Запрос = Новый Запрос; Запрос.Текст=" ВЫБРАТЬ РАЗЛИЧНЫЕ " + ИияРегистра + ".ВидРасчета.Приоритет КАК Приоритет ИЗ РегистрРасчета." + ИмяРегистра + " КАК " + ИмяРегистра + ” ГДЕ ФизЛицо В (&СписокФизлиц) И Регистратор = &Регистратор УПОРЯДОЧИТЬ ПО Приоритет ИТОГИ ПО " + ИмяРегистра + ".ВидРасчета.Приоритет": Запрос.УстановитьПараметрССписокФизлиц", Физлица): Запрос.УстановитьПараметрС"Регистратор", Регистратор): ВыборкаПриоритетов = Запрос. ВыполнитьО. ВыбратьСОбходРезультатаЗапроса.ПоГ руппировкам); // Для каждого значения приоритета выполняется // расчет записей Пока ВыборкаПриоритетов.Следующий() Цикл ПерерассчитатьНаборЗаписей(НаборЗаписей, ВыборкаПриоритетов.Приоритет, ТабличнаяЧасть, Физлица); // Записать набор в регистр для расчета записей // следующего приоритета, фактический период действия // не пересчитывается НаборЗаписей.Записать(Истина, Истина); КонецЦикла; КонецПроцедуры
Глава 11. Механизм бизнес-процессов С точки зрения автоматизации, деятельность любой орга- низации, предприятия представляет собой набор совер- шаемых сотрудниками операций. Очень часто эти операции не существуют «по отдельности», а являются логическим следствием выполнения предыдущих действий (опера- ций), то есть являются элементом какой-либо техноло- гической цепочки. Простым примером такой цепочки может являться процесс получения денег подотчетным лицом. В нем можно выделить следующие этапы: ♦ заявка на получение денежных средств; ♦ рассмотрение заявки руководителем подразделения (на предмет необходимости); ♦ рассмотрение заявки главным бухгалтером (на предмет наличия денежных средств); ♦ выдача кассиром денежных средств; ♦ отчет об израсходованных средствах (авансовый отчет). Главный бухгалтер не будет рассматривать возможность выдачи денежных средств без наличия визы руководителя подразделения, кассир не будет выдавать деньги без указа- ния главного бухгалтера или если денег попросту нет и т. д. Другим примером может являться операция продажи то- вара оптовому покупателю. В данной операции можно выделить следующие этапы: ♦ выписка заказа покупателя; ♦ получение оплаты за товар; ♦ сборка заказа на складе; ♦ отгрузка товара. В контексте последней цепочки представим одну из за- дач, которая может возникнуть перед руководством орга- низации, предприятия. Компания стремительно набирает «обороты» (огромное спасибо сотрудникам отдела рекламы). Для того чтобы «рост» организации в какой-то момент не остановился, не- обходимо заранее подумать о своевременном наборе (и обу- чении) сотрудников, расширении штата. И вот он сам во- прос: «Кого набирать?» Набрать сотрудников в отдел рек- ламы,... но если не хватает персонала на выписке счетов, то это может привести не к росту, а, наоборот, к падению обо- ротов компании (за организацией может закрепиться репу- тация «не желающих даже счет выписать»). Набрать менед- жеров по выписке счетов, но если сотрудники склада не будут справляться с задачей своевременной подготовки то- вара к отгрузке, это также может привести к плачевному ре- зультату. Что же делать? Спросить у персонала? Ответить на этот вопрос практически невозможно, если при решении задачи использовать данные только об отдельно осуществляемых операциях. Эти операции необходимо рас- сматривать как этапы единой цепочки действий. Только при рассмотрении данного процесса как единого целого можно определить узкий (и потенциально опасный) его участок. С другой стороны, в реальной жизни не бывает простых процессов. Обычно этапы, из которых они состоят, конкрет- ные исполнители этих этапов определяются в ходе выпол- нения процесса и зависят от множества факторов. При отражении в учете таких «сложных цепочек» перед сотруд- ником (который ведет учет) может встать довольно сложная задача: «Какие документы использовать, в какой последова- тельности их вводить и как...». Любая программа (конфигу- рация) дает пользователю определенную свободу действий по отражению той или иной отдельно взятой операции, но с точки зрения всего процесса может оказаться, что сущест- вует только один, единственно правильный вариант. Чтобы не ошибиться, сотрудник должен в полном объеме представ- лять особенности отражаемого процесса и особенности ра- боты конфигурации, в которой ведется учет. Что при нали- чии большого количества таких «цепочек» (и определенной текучке в кадрах) не всегда достижимо. Кроме этого, конкретный исполнитель иногда (можно сказать, что и «чаще всего») и не должен знать всю цепоч- ку, он отвечает только за ее конкретный участок. Не зная всей картины, он, по определению, не может принять оп- тимального (верного) решения. Как говорится: «Как он может думать, не зная всех входных условий процесса?» Получается, что при таком варианте организации рабо- ты конечного пользователя должен быть кто-то (или что-то), кто «подсказывал» бы пользователю, что имен- но сейчас нужно сделать именно так и ни как иначе. Воз- ложить эту операцию на человека? (См. абзац выше...) Идеальным вариантом (для учета сложных процессов) явля- ется переход от учета «от документа» (когда пользователь должен знать, какие документы, в какой последовательности, с какими особенностями он должен завести) к «процессно- му» учету, когда сам программный комплекс будет подска- зывать пользователю, что он сейчас должен сделать. В со- ответствии с логикой процесса, особенностями его старта, определяется текущий этап, по возможности определяется исполнитель, особенности отражения операции и т. п. Для ведения учета (и автоматизации) «цепочек дейст- вий» в конфигурациях 1С:Предприятие могут использо- ваться такие объекты, как бизнес-процессы и задачи. Первое знакомство Бизнес-процессы в 1С:Предприятии позволяют объеди- нить отдельные операции в цепочки взаимосвязанных действий, приводящих к достижению конкретной цели. Они позволяют формализовать процедуры обработки тех или иных событий, возникающих в деятельности органи- зации, и обеспечить участие в них исполнителей.
Цепочки взаимосвязанных действий бизнес-процесса пред- ставляются с помощью карты маршрута бизнес-процес- са. Карта маршрута описывает логику бизнес-процесса и весь его жизненный цикл от точки старта до точки завер- шения. Она реализована в виде схематического изобра- жения последовательности прохождения взаимосвязан- ных точек маршрута. Точка маршрута отражает определенный этап жизненно- го цикла бизнес-процесса и обычно связана с выполнени- ем какой-либо операции (ручной или автоматической). Задачи в 1С:Предприятии соответствуют пользователь- ским заданиям (что должен сделать определенный поль- зователь). Выполнение задачи приводит к продвижению бизнес-процесса от одной точки к другой. Сами задачи могут создаваться как бизнес-процессом (в соответствии с картой маршрута), так и программно. Опишем цепочку продажи товара с точки зрения введен- ных терминов. Цепочка действий, выполняемая по одному выписанному счету, будет являться элементом (экземпляром) бизнес- процесса. Можно провести аналогию со справочником. Как справочник Номенклатура хранит данные обо всей но- менклатуре (соответствующий объект конфигурации оп- ределяет состав реквизитов, табличных частей, формы справочника), а отдельный элемент хранит данные о ка- ком-либо одном товаре (но в соответствии со структурой, определенной для всего справочника), так и элемент биз- нес-процесса содержит данные об отдельно взятом про- цессе (начатом с выписки конкретного счета), но состав этапов, логика их прохождения определяются в соответ- ствии с объектом конфигурации Бизнес-процесс. При переходе к очередному «этапу», в рамках какого-ли- бо процесса, будет создаваться задача. Задача содержит данные о бизнес-процессе, в рамках которого она создана, этапе этого бизнес-процесса. Кроме этого задача может содержать данные о пользователе, который должен ее вы- полнить (либо какие-то другие характеристики такого пользователя, такие как должность, принадлежность к подразделению и т. и.). К примеру, после выписки счета может создаваться за- дача Оплата товара. При поступлении денежных средств от покупателя данная задача считается выполненной и в соответствии с картой бизнес-процесса производится создание следующей задачи Подготовка к отгрузке (осу- ществляется переход к следующему «этапу»). Во вновь созданной задаче может быть указано, что она должна быть выполнена пользователем с должностью Кладов- щик. Карта маршрута Для редактирования карты маршрута необходимо на за- кладке Прочее окна редактирования бизнес-процесса на- жать кнопку Карта маршрута (рис. 11.1). \ Бизнес-процесс Продажа! овара Основные Данные Нумерация Формы Макеты Подсистемы Ввод на основании Права Интерфейсы - Обмен данными 1 к Прочее Вкл Модель объекта j Карта маршрута Ей Бизнес-процесс Продажа!овара: U ОтделПродаж : Выписка счета и ! расходной накладной Рис. 11.1. Редактирование карты маршрута После открытия окна карты маршрута для ее создания, корректировки можно использовать панель Вставка эле- ментов схемы, в которой определены все возможные точки маршрута, кнопки вставки декораций, линий (рис. 11.2). Рис. 11.2. Панель Вставка элементов схемы Панель по умолчанию размещается в нижней части окна конфигуратора, но, как и любая панель инструментов, может быть размещена в любом его месте. При определении карты маршрута допускается использо- вание следующих видов маршрутизации: ♦ Жесткая. Линейная, без каких-либо ветвлений; ♦ Свободная. Адресаты точки карты маршрута бизнес- процесса не установлены и определяются программно или интерактивно в течение жизненного цикла бизнес- процесса; ♦ Условная. Карта маршрута предусматривает проверку условий и переход по соответствующим ветвям. Пере- ходы могут быть как бинарными (условие), так и мно- жественными (выбор варианта); ♦ Параллельная. Карта маршрута предусматривает разде- ление бизнес-процесса на параллельные ветви с воз- можностью последующего слияния (ожидания). Про- движение бизнес-процесса по каждой из параллельных ветвей происходит независимо, по мере выполнения со- ответствующих задач. На рис. 11.3 приведен пример карты маршрута с жесткой маршрутизацией. В данном бизнес-процессе «этапы» расположены жестко друг за другом, задачи создаются, выполняются строго в соответствии с их порядком в карте маршрута. На рис. 11.4 приведен пример карты маршрута с услов- ной маршрутизацией.
Рис. 11.3. Пример карты маршрута с жесткой маршрутизацией Данный бизнес-процесс реализует механизм согласова- ния какого-либо документа. После отработки задачи Ут- верждение в зависимости от результата (проверяемого в точке условия «Утвержден?») либо производится завер- шение бизнес-процесса, либо переход к доработке доку- мента, с последующим возвратом на утверждение. К условному виду маршрутизации данная карта относит- ся из-за отсутствия параллельных (сходящихся) ветвей. К параллельному виду маршрутизации можно отнести карту следующего вида (рис. 11.5). В данном бизнес-процессе считается, что после выписки счета его оплата и подготовка к отгрузке (сборка заказа) могут выполняться параллельно, но отгрузка возможна только после выполнения обеих задач (и оплаты, и подго- товки отгрузки). Чаще всего в реальных бизнес-процессах встречаются смешанные виды маршрутизации (и условная, и парал- лельная ит. и.). При работе с бизнес-процессами существует возможность отображения карты маршрута в пользовательском режи- ме. При этом в ней будет отражаться текущее состояние бизнес-процесса. Для этой цели в форме бизнес-процесса можно размес- тить элемент управления Поле графической схемы и в нуж- ном месте разместить следующий фрагмент кода (лис- тинг 11.1). Листинг 11.1. Пример отображения карты маршрута // Карта маршрута - элемент управления // "Поле графической схемы” // ПолучитьКартуМаршрутаО метод объекта // БизнесПроцессОбъект.Имя ЭлементыФормы.КартаМаршрута. УстановитьСхему(ПолучитьКартуМаршрутаО); В результате, к примеру, можно увидеть следующую кар- тину (рис. 11.6). Рис. 11.4. Карта маршрута бизнес-процесса с условной маршрутизацией Рис 11.5. Пример карты маршрута бизнес-процесса с параллельной маршрутизацией Действия* i [ер IISI Ife | "Ф j Перейти * [(?] Рис. 11.6. Пример отображения карты маршрута
Пройденные точки маршрута отмечаются штриховкой, текущая точка (точки) отмечается красной пунктирной линией (точки для которых существуют невыполненные задачи). При возникновении необходимости просмотра карты мар- шрута в «других» формах (не в форме самого бизнес-про- цесса), можно использовать следующий фрагмент кода (листинг 11.2). Результат будет таким же, как и в предыдущем случае. Листинг 11.2. Пример отображения карты маршрута в форме обработки // БизнесПроцессСсылка - Ссылка на интересующий // бизнес-процесс БизнесПроцессОбъект = БизнесПроцессСсылка.ПолучитьОбъектО; ЭлементыФормы.КартаМаршрута.УстановитьСхему( БизнесПроцессОбъект.ПолучитьКартуМаршрутаО): Точки маршрута Процесс определения карты маршрута (логики пове- дения бизнес-процесса) состоит в «нанесении» в карту точек маршрута, определения связей между ними, опре- делении обработчиков событий, специфических для каж- дой точки. Существует несколько точек маршрута: ♦ Точка старта; ♦ Точка завершения; ♦ Точка действия; ♦ Точка условия; ♦ Точка выбора варианта; ♦ Точка разделения; ♦ Точка слияния; ♦ Точка обработки; ♦ Точка вложенного бизнес-процесса. У точек некоторых видов есть специфические свойства и события. Например, свойство Групповая есть только у точки действия, а событие ПроверкаУсловия — только у точ- ки условного перехода. Также следует отметить, что по умолчанию (если иное поведение бизнес-процесса не описано программно) соз- дание задачи (задач) происходит только при переходе на такие точки маршрута, как точка действия и точка вло- женного бизнес-процесса. В остальных точках может про- изводиться какая-либо обработка данных: проверка усло- вия, выбор варианта продвижения по карте, обработка каких-либо объектов системы и т. п. Рассмотрим точки маршрута более подробно. Точка старта, точка завершения Схематическое изображение данных точек показано на рис. 11.7. Рис. 11.7. Точка старта и точка завершения Точка завершения С точки старта бизнес-процесс стартует, в точке заверше- ния (если иное не определено программно) он завершает- ся. У бизнес-процесса может быть определено несколько точек старта и (или) несколько точек завершения. При- мером такого бизнес-процесса может быть выдача денеж- ных средств под отчет. Карта бизнес-процесса может иметь следующий вид (рис. 11.8). Старт с демонстрацией Старт без демонстрации Отгрузить товар Продажа состоялась Рис. 11.8. Карта бизнес-процесса выдачи денег Предположим, что старт бизнес-процесса осуществля- ется оператором, принимающим заявки по телефону. В ходе разговора с потенциальным клиентом он выяс- няет, интересует ли клиента предпродажная демонстра- ция изделия (клиент уже может быть знаком с данной продукцией и вследствие этого откажется от демонст- рации). В зависимости от варианта ответа клиента выбирается та или иная точка старта бизнес-процесса. В случае если по- сле демонстрации клиент решает купить товар, выполня- ется цепочка действий, ответственных за продажу. Завершение бизнес-процесса производится либо при по- купке товара (продажа состоялась), либо при отказе по- сле демонстрации. Более подробно особенности работы с данными точками (их событиями) описаны в разделах «Старт бизнес-про- цесса», с. 372, и «Завершение бизнес-процесса», с. 376.
Точка действия Точка действия является одной из точек, при переходе на которую создается задача или несколько задач (если иное поведение не было определено программно). Допустим вариант, что при переходе на данную точку не будет соз- дана ни одна задача. Эти и другие механизмы, связанные с определением обработчиков событий данной точки мар- шрута, рассматриваются в разделах, связанных с форми- рованием и выполнением задач. Схематическое представление точки на карте маршрута имеет следующий вид (рис. 11.9). В табл. 11.1 приведен пример заполнения регистра сведе- ний. Таблица 11.1. Пример заполнения регистра сведений Сотрудник Роль исполнителя Подразделение Иванов Отдел продаж Петров Бухгалтер Администрация Сидоров Кладовщик Оптовый склад Федоров Руководитель отдела Отдел продаж Адресация Точка действия Рис. 11.9. Точка действия «Привязка» системы адресации (регистра сведений) к биз- нес-процессу осуществляется через объект Задача (при кон- фигурировании бизнес-процесса в нем указывается ссылка на объект конфигурации Задача). В самой задаче на заклад- ке свойств Адресация определяется ссылка на используемый регистр сведений, и, кроме этого, необходимо определить используемые реквизиты адресации (рис. 11.11). Как уже сказано выше, обычно при переходе на точку действия производится формирование задачи (или не- скольких задач). Одним из важных моментов, которому уделяется внимание (при создании задач), является опре- деление их исполнителей. За данный механизм отвечает так называемая система адресации бизнес-процессов. Можно выделить два вида адресации (адресной маршру- тизации), реализованной в платформе: ♦ Персональная. Пользователь (исполнитель) определя- ется в явном виде; ♦ Ролевая. Исполнитель определяется исходя из назна- ченных ему ролей, принадлежности к подразделению, а также других реквизитов адресации. Примером персональной адресации может являться ука- зание, что данная задача должна выполняться «таким-то» пользователем системы. При использовании ролевой ад- ресации может указываться, что задача должна быть вы- полнена пользователем с должностью Кладовщик, рабо- тающем в подразделении Оптовый склад. Данные, используемые системой адресации, определяют- ся в регистре сведений. Каждое измерение такого регист- ра определяет возможный «адресный» разрез. Одно из измерений обычно связывают с персональной адресаци- ей. Пример структуры такого регистра сведений приве- ден на рис. 11.10. Рис 11.10. Структура регистра сведений Исходя из структуры данного регистра, можно утвер- ждать, что при определении исполнителей задач могут использоваться данные о его роли, принадлежности к ка- кому-либо подразделению, либо исполнитель может на- значаться в явном виде (измерение Сотрудник). Рис. 11.11. Установка свойств задачи В качестве основного реквизита адресации обычно выби- рают реквизит адресации, отвечающий за персональную адресацию. В свойство Текущий исполнитель выбирается параметр сеан- са, содержащий текущего пользователя (обычно значение в данный параметр сеанса записывается при запуске ЮПредприятие исходя из данных авторизации). При определении реквизита адресации указывается его тип и производится привязка к измерению выбранного регистра сведений (рис. 11.12). Рис. 11.12. Свойства реквизита адресации Исходя из этого, при самостоятельном определении зада- чи (а именно свойств, связанных с адресацией) необходи- мо придерживаться следующего порядка действий. 1. Выбор ссылки на регистр сведений. 2. Заведение реквизитов адресации. 3. Выбор основного реквизита адресации.
Для решения задачи адресации в каждой точке действия карты маршрута можно использовать свойства группы Адресация (рис. 11.13). ▼Адресация: ____________________ Пояснение Г рупповая О Сотрудник РольИсполнителя Подразделение Кладовщик ОтделПродаж Рис. 11.13. Свойства точки действия карты маршрута бизнес-процесса В этой группе каждому определенному в задаче реквизи- ту адресации соответствует по свойству. На этапе конфи- гурирования в них уже можно устанавливать необходи- мые значения. Однако следует помнить, что для того, чтобы именно в режиме конфигурирования (создания, редактирования карты маршрута) можно было выбирать необходимые значения, они должны быть определены как предопределенные. Если в группе свойств Адресация точки действия установ- лены значения, показанные на рис. 11.13, то при переходе бизнес-процесса к данной точке будет создана одна зада- ча (если иного не определено программно). В соответст- вующих ее реквизитах адресации будут автоматически записаны указанные при конфигурировании значения (РольИсполнителя = Кладовщик и Подразделение = ОтделПродаж). При отметке свойства Групповая в данной точке будет соз- даваться столько задач, сколько записей в регистре сведе- ний, ответственном за адресацию, будет найдено с уста- новленными значениями реквизитов адресации. К примеру, если настройка группы свойств Адресация бу- дет выглядеть так, как показано на рис. 11.14, а регистр сведений будет заполнен данными, согласно табл. 11.2, то при переходе бизнес-процесса к данной задаче будут сформированы две задачи с соответствующими значе- ниями реквизитов адресации (табл. 11.3). ▼Адресация: Пояснение IГ pjipnoe-ая Сотрудник. РольИсполнителя Подразделение ОтделПродаж Рис. 11.14. Свойства точки маршрута бизнес-процесса Таблица 11.2. Данные регистра сведений Сотрудник Роль исполнителя Подразделение Иванов Отдел продаж Петров Бухгалтер Администрация Сидоров Кладовщик Оптовый склад Федоров Руководитель отдела Отдел продаж Таблица 11.3. Значения реквизитов адресации Сотрудник Роль исполнителя Подразделение Иванов Отдел продаж Федоров Руководитель отдела Отдел продаж Точка условия Для реализации условного ветвления бизнес-процесса используется точка условного перехода. Точка условия обозначается в карте маршрута следующим образом (рис. 11.15). 1ет / Условие *. Да выполнено? Рис. 11.15. Точка условия Важной особенностью этой точки является обработчик проверки условия, наличие которого обязательно и кон- тролируется при проверке карты маршрута перед сохра- нением бизнес-процесса (листинг 11.3). Листинг 11.3. Синтаксис обработчика ПроверкаУсловия ПроверкаУсловия(ТочкаМаршрутаБизнесПроцесса. Результат): В зависимости от значения, переданного в параметр Ре- зультат (Истина, Ложь), бизнес-процесс пойдет по ветви Да или Нет. По умолчанию результат устанавливается рав- ным значению Ложь. Приведем пример обработчика события ПроверкаУсловия для карты маршрута со следующей схемой (рис. 11.16). Рис. 11.16. Пример карты маршрута В точке условия «Скидка по счету выше стандартной?» проверяется тот факт, чтобы в табличной части докумен- та Счет (ссылка на него определена в реквизите бизнес- процесса Счет) не было скидки, превышающей значение, хранимое в константе (листинг 11.4). Не стоит путать значение по умолчанию, устанавливае- мое обработчиком события, и функциональность пере- менной СкидкаБольшеОбычной. С помощью указанной переменной реализуется следующий алгоритм: «Если найдено превышение, то оставшиеся строки табличной части не перебираются».
Листинг 11.4. Пример обработчика события ПроверкаУсловия Процедура УсловиеОграниченияСкидкиПроверкаУсловия( ТочкаМаршрутаБизнесПроцесса, Результат) // Определяем значение функции по умолчанию СкидкаБолыиеОбычной = Ложь; ОбычнаяСкидка = Константы. ОбычнаяСкидка.ПолучитьО; // Проверяем, что скидка не превышает обычную Для Каждого Элемент Из Счет.Состав Цикл Если Элемент.Скидка > ОбычнаяСкидка Тогда СкидкаБолыиеОбычной = Истина; Прервать; КонецЕсли; КонецЦикла; Результат = СкидкаБолыиеОбычной; КонецПроцедуры; Значение по умолчанию (Ложь) говорит о том, что если оп- ределить данный обработчик пустым (не содержащим внутри код на встроенном языке), то бизнес-процесс пой- дет по ветви Нет точки условия. Точка выбора варианта Для реализации многовариантного выбора можно ис- пользовать несколько последовательно соединенных то- чек условного перехода, однако удобнее для этого приме- нять точку выбора варианта. Точка выбора варианта обозначается в карте маршрута следующим образом (рис. 11.17). тролируется при проверке карты маршрута перед сохра- нением бизнес-процесса (листинг 11.5). Листинг 11.5. Синтаксис обработчика события Обработка ВыбораВарианта ОбработкаВыбораВариантаСГочкаВыбораВарианта, Результат); В переменную Результат должен быть записан один из оп- ределенных в точке маршрута вариантов. Для этой цели может использоваться следующий фрагмент кода (лис- тинг 11.6). Листинг 11.6. Пример установки значения параметра Результат Результат = ТочкаВыбораВарианта.Варианты.Наличная; Если в процедуре-обработчике выбора варианта не уста- новить какое-либо значение параметра Результат, то это приведет к ошибке и откату транзакции, в рамках кото- рой выполнялся выбор варианта. Точка разделения, слияния Для разделения бизнес-процесса на несколько парал- лельно (одновременно и независимо) исполняемых вет- вей используется точка разделения. Точка разделения имеет один вход и неограниченное количество выходов (рис. 11.19). Разделение,/ , Слияние т Рис. 11.19. Точка разделения и точка слияния Рис 11.17. Точка выбора варианта Для синхронизации разделенных ранее ветвей использу- ется точка слияния. Бизнес-процесс не будет выполняться дальше точки слияния, пока все входящие в нее ветви не будут пройдены. Таким образом, точка слияния является этапом бизнес-процесса, на котором должны быть завер- шены все задачи по разделенным ранее веткам (рис. 11.20). Для определения нужного количества вариантов можно использовать пункты контекстного меню точки выбора Добавить вариант, Удалить вариант. Настройка имени вари- анта производится в свойствах варианта, в нижней его части (группа свойств Вариант) (рис. 11.18). Рис. 11.18. Свойства точки выбора варианта Следует обратить внимание на тот факт, что на рисунке включен отбор формы свойств Показывать только важные. Важной особенностью этой точки является обработчик выбора варианта, наличие которого обязательно и кон- Рис. 11.20. Использование точек разделения и слияния В приведенном выше примере пока не будут выполнены обе задачи: и оплата товара, и подготовка к отгрузке бизнес- процесс «не пойдет» дальше точки слияния. В ней бизнес- процесс ожидает «закрытия» всех сходящихся в ней веток. Разделение может быть и без слияния. В этом случае биз- нес-процесс будет иметь несколько параллельных ветвей до своего завершения (в нем будет несколько точек завер- шения).
Точка обработки Предназначена для выполнения автоматических дейст- вий. Схематическое изображение точки на карте маршру- та следующее (рис. 11.21). Обработка Рис. 11.21. Точка обработки Совершаемые в данном случае действия определяются в обработчике события Обработка (листинг 11.7). Листинг 11.7. Синтаксис обработчика события Обработка Обработка (Точ каМаршрутаБи з несПроцесса) ; В данном обработчике события могут определяться раз- личные регламентные или другие операции, связанные с обработкой данных, выполняемые над объектами базы данных в случае, если их выполнение необходимо для дальнейшего продвижения бизнес-процесса. Обработка проводится в автоматическом режиме и не приводит (в общем случае) к созданию задач. После завершения обработчика бизнес-процесс переходит к следующей точке маршрута в соответствии с картой. Точка вложенного бизнес-процесса Точка позволяет запустить вложенные бизнес-процессы. Схематическое представление на карте маршрута имеет следующий вид (рис. 11.22). Вложенный процесс Рис. 11.22. Точка вложенного бизнес-процесса При переходе бизнес-процесса на данную точку маршру- та формируется массив задач. Для каждой задачи старту- ет свой вложенный бизнес-процесс. После завершения вложенного бизнес-процесса соответствующая задача считается выполненной. При выполнении всего массива задач основной бизнес-процесс осуществляет переход к следующей точке по карте маршрута. Одно из важных свойств данной точки — это свойство Бизнес-процесс. Оно содержит ссылку на вид вложенного бизнес-процесса. Пример использования данной точки маршрута приво- дится в разделе «Бизнес-процесс Обход», с. 392. Состояния бизнес-процесса Бизнес-процесс может находиться в одном из трех со- стояний: ♦ Не стартовал — нет ни одной задачи, связанной с дан- ным бизнес-процессом. Такое состояние устанавлива- ется, если создать и записать бизнес-процесс без вызова метода СтартО; ♦ Стартовал — существует хотя бы одна задача, связан- ная с данным бизнес-процессом; ♦ Завертел — у бизнес-процесса установлено свойство За- вершен. Наличие или отсутствие связанных с данным биз- нес-процессом задач никак не влияет на это состояние. Состояние бизнес-процесса отражается с помощью одно- именных свойств (Стартован, Завершен). Данные свойства имеют тип значения Булево и могут устанавливаться как интерактивно, так и программно. Следует помнить, что «самостоятельная» запись значений в данные свойства имеет определенные особенности. При записи в свойство Стартован значения Истина старт бизнес-процесса не производится (не создается ни одной задачи). Попытка после этого выполнить метод СтартО приведет к ошибке (бизнес-процесс уже стартован). Прямая установка свойства Стартован может использо- ваться в бизнес-процессах со свободной маршрутизацией. Это может позволить произвольным образом создавать задачи (с произвольной привязкой их к точкам маршрута карты бизнес-процесса). Если у бизнес-процесса, по которому уже существуют ка- кие-либо задачи, установить данное свойство в значение Ложь, а потом выполнить старт бизнес-процесса, то он «распараллелится». С одной стороны бизнес-процесс продолжит продвижение в соответствии с существовав- шими до сброса свойства задачами, с другой стороны за- пустится его повторное «прохождение» с самой началь- ной точки схемы бизнес-процесса. Рассмотрим пример поведения бизнес-процесса, обладающего следующей схе- мой (рис. 11.23). Рис. 11.23. Карта маршрута бизнес-процесса
Процесс рассматривается с учетом того, что не определе- но ни одного обработчика событий, который меняет стан- дартный порядок формирования и завершения задач. Последовательность интерактивных действий и реакция системы на эти действия приведены в табл. 11.4. Таблица 11.4. Последовательность интерактивных действий и реакция системы Интерактивные действия Реакция системы Старт бизнес-процесса Создание задачи Выписка счета Выполнение задачи Выписка счета Создание задачи Оплата товара Установка у бизнес- процесса свойства Стартован в значение Ложь Старт бизнес-процесса (например, по кнопке ОК) Создание задачи Выписка счета К этому моменту в бизнес-процессе существует две невы- полненные задачи: ♦ оплата товара (от первого старта); ♦ выписка счета (от второго старта). Дальнейшая последовательность действий представлена в табл. 11.5. Таблица 11.5. Последовательность интерактивных действий и реакция системы Интерактивные действия Реакция системы Выполнение задачи Оплата товара Не приводит к созданию задачи, система будет ожидать, когда параллельный процесс «догонит» ранее стартовавший Выполнение задачи Выписка счета Создание задачи Оплата товара Выполнение задачи Оплата товара Создание задачи Отгрузка товара Выполнение задачи Отгрузка товара Завершение бизнес- процесса Особый интерес представляет то факт, что при выполне- нии задачи Оплата товара (созданной первой) не произ- водится создание следующей по схеме задачи (Отгрузка товара). Можно сказать, что фактически бизнес-процесс выполнялся по следующей схеме (рис. 11.24). Даже если бы после рестарта бизнес-процесса стали бы исполняться задачи второй ветки, то, дойдя до точки слияния бизнес-процесса для создания задачи Отгрузка то- вара, он ожидал бы выполнения задачи Оплата товара пер- вой ветви. Свойство Завершен устанавливается системой автоматиче- ски в значение Истина при переходе бизнес-процесса на точку завершения при условии отсутствия невыполнен- ных задач. Это свойство можно установить и самостоя- тельно. Если у завершенного бизнес-процесса в свойство Завершен записать значение Ложь и создать невыполненную задачу (либо отменить статус выполненной у ранее суще- ствовавшей), то бизнес-процесс продолжит свою работу в соответствии с его схемой. Рис. 11.24. Фактическая схема выполнения бизнес-процесса Если у незавершенного бизнес-процесса в это свойство записать значение Истина, то бизнес-процесс будет счи- таться завершенным, и выполнение какой-либо его зада- чи не приведет созданию новой в соответствии со схемой бизнес-процесса. При необходимости полностью завершить бизнес-про- цесс рекомендуется, помимо записи значения Истина в свойство Завершен, получать все невыполненные задачи данного бизнес-процесса и устанавливать для них статус выполненных. Визуально (например, в форме списка) бизнес-процессы в разных состояниях имеют разные значки (иконки) (рис. 11.25). Рис. 11.25. Пиктограммы бизнес-процессов Нестартованный бизнес-процесс имеет серую иконку, в стартованном она цветная.
Старт бизнес-процесса Жизненный цикл бизнес-процесса начинается с его стар- та. В карте бизнес-процесса место старта отражается с по- мощью точки старта (рис. 11.26). 9 Рис 11.26. Точка старта бизнес-процесса У данной точки маршрута можно определить обработчик события ПередСтартом. У данной процедуры два параметра. Первый параметр — это точка маршрута, с которой про- изошел вызов обработчика (у бизнес-процесса может быть несколько точек старта), второй параметр: Отказ. При записи в переменную Отказ значения Истина будет произведен отказ от старта бизнес-процесса. В обработчике события Перед стартом можно проверять условия, необходимые для старта бизнес-процесса, созда- вать «сопутствующие» объекты, ссылки на которые необ- ходимо хранить в самом бизнес-процессе. Пример обработчика данного события для бизнес-про- цесса Продажа товара (считаем, что в бизнес-процессе должны храниться ссылки на документы Счет и Расходная накладная) приведен в листинге 11.8. Листинг 11.8. Пример обработчика события ПередСтартом Процедура СтартПередСтартом( ТочкаМаршрутаБизнесПроцесса, Отказ) И Признак, определяющий, изменялся ли бизнес-процесс // в данном обработчике НужноЗаписать = Ложь; // Если реквизит бизнес-процесса "Счет" // содержит пустую ссылку, // создадим документ и запишем ссылку на него Если Счет.ПустаяО Тогда СчетОбъект = Документы.Счет.СоздатьДокумент(); СчетОбъект.Дата = ТекущаяДатаО; СчетОбъект.Записать О; Счет = СчетОбъект.Ссылка: // Бизнес-процесс изменен (реквизит "Счет") НужноЗаписать = Истина; КонецЕсли; // Если реквизит бизнес-процесса "РасходнаяНакладная” И содержит пустую ссылку, создадим документ // и запишем ссылку на него Если РасходнаяНакладная.Пустая() Тогда РасходнаяНакладнаяОбъект = Документы. РасходнаяНакладная. СоздатьДокументО: РасходнаяНакладнаяОбъект. Дата = ТекущаяДатаО; РасходнаяНакладнаяОбъект.Записать(); РасходнаяНакладная = РасходнаяНакладнаяОбъект.Ссылка; НужноЗаписать = Истина; КонецЕсли; Если НужноЗаписать Тогда ЗаписатьО; КонецЕсли; Сообщить("Старт бизнес-процесса: ” + . + ЭтотОбъект.МетаданныеО.Синоним + .); КонецПроцедуры При определении обработчика данного события в нем не рекомендуется реализовывать механизмы, организующие диалог с пользователем (открытие различных диалого- вых форм). Сам старт бизнес-процесса может производиться по-раз- ному: ♦ программный старт бизнес-процесса (из кода на встро- енном языке); ♦ интерактивный старт (нажатие на кнопку ОК формы бизнес-процесса) и т. п.; ♦ старт бизнес-процесса как вложенного. При использовании любого их перечисленных вариантов бизнес-процесс может иметь несколько точек старта (но в любом случае необходимо будет «уточнять», какая из то- чек используется). Программный старт Для реализации старта бизнес-процесса из встроенного языка может использоваться следующий фрагмент кода (листинг 11.9). Листинг 11.9. Пример программного старта бизнес-процесса БП = БизнесПроцессы.ПродажаТовара.СоздатьБизнесПроцессО: И Дата должна быть определена явным образом БП.Дата = ТекущаяДатаО; // Перед стартом бизнес-процесс должен быть // обязательно записан БП.ЗаписатьО; БП.СтартО; В этом случае происходят следующие действия (рис. 11.27). Старт бизнес-процесса Рис. 11.27. Действия, выполняемые при программном старте бизнес-процесса
Следует отметить, что программно можно определить и интерактивный старт бизнес-процесса. Данную воз- можность иллюстрирует следующий фрагмент кода (лис- тинг 11.10). Листинг 11.10. Пример интерактивного старта бизнес- процесса средствами встроенного языка БП = БизнесПроцессы.ПродажаТовара.СоздатьБизнесПроцессО; БП.Дата=ТекущаяДата(); БП.Записать!); БП.СтартО; // Вызов метода возможен только для стартованного // бизнес-процесса БП.АктивироватьИнтерактивноО; Вызов метода интерактивной активации бизнес-процесса приводит к возникновению события Обработка интерактив- ной активации как для самого бизнес-процесса, так и для его невыполненных задач. Следует отметить, что у задач данное событие возникает в том случае, если в обработчи- ке события самого бизнес-процесса порядок обработки события оставлен стандартным. Активацию бизнес-про- цесса можно производить не только для только что стар- товавших процессов, но и для любых незавершенных (по которым существуют невыполненные задачи). Последовательность действий, выполняемых системой при активации бизнес-процесса, следующая (рис. 11.28). Вызвать обработчик события бизнес-процесса ОбработкаИ нгерактивнойАктивации[СтандартнаяО бработка) Стандартная обработка? Получение списка всех nmreiLeibi! задач по данному бизнес-процессу и по текущему исполнителю. Рис. 11.28. Последовательность действий при выполнении метода АктивироватьИнтерактивноО Обработчик события Обработка интерактивной активации бизнес-процесса можно использовать для определения действий, характеризующих интерактивную активацию самого бизнес-процесса вне зависимости от его положе- ния на карте маршрута. Данный обработчик определяет- ся в модуле объекта (бизнес-процесса). Обработчик события задачи может использоваться для определения каких-либо особенностей поведения задачи при ее интерактивной активации. Для задач данный обра- ботчик размещается в модуле объекта (задачи). Довольно часто этот обработчик события используется для регистра- ции задач в других объектах (например, в нем произво- дится запись в регистр сведений). Представим себе, что какой-либо пользователь (группа пользователей) решает задачи, которые могут формиро- ваться в контексте большого количества бизнес-процес- сов. Заставлять таких пользователей постоянно просмат- ривать все бизнес-процессы (задачи) не стоит. Им можно упростить процесс работы, создав «специализированные рабочие места» — обработки. Механизм работы таких обработок заключается в том, что при интерактивной активации задач данные о задаче записываются в регистр сведений, содержимое которого и отображает соответствующее «рабочее место пользова- теля». Пример подобного обработчика события приводится в листинге 11.11. Листинг 11.11. Пример обработчика события ОбработкаИнтерактивнойАктивации Процедура ОбработкаИнтерактивнойАктивации(СтандартнаяОбработка) // Регистр сведений "Просмотр задач" используется // для регистрации данных // по текущим (не выполненным) задачам НаборЗаписей = РегистрыСведений. ПросмотрЗадач. СоздатьНаборЗаписейО; НаборЗаписей.Отбор.Задача.Значение = Ссылка; НаборЗаписей.Отбор.Задача.Использование = Истина; // В параметре "Текущий исполнитель" находится ссылка // на текущего пользователя: этот параметр сеанса // выбран в свойство "Текущий пользователь" // соответствующей задачи НаборЗаписей.Отбор.Сотрудник.Значение = ПараметрыСеанса.ТекущийИсполнитель; НаборЗаписей.Отбор.Сотрудник.Использование = Истина; НаборЗаписей.Прочитать(); Если НаборЗаписей.Количество!) = 0 Тогда //В набор записей добавляем новую запись, // характеризующую активизированную задачу НоваяЗапись = НаборЗаписей.Добавить!); НоваяЗапись.Задача = Ссылка; НоваяЗапись.Сотрудник = ПараметрыСеанса. ТекущийИсполнитель; Попытка НаборЗаписей.Записать(); Исключение Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное); КонецПопытки; КонецЕсли; КонецПроцедуры Следует обратить внимание на тот факт, что событие Об- работка интерактивной активации для задачи (определенная в модуле объекта) срабатывает и при открытии формы задачи, при выполнении одноименной команды контек- стного меню при нахождении в списке задач или при выполнении метода АктивироватьИнтерактивноО у объекта ЗадачаОбьект.<Имя>. Обработчик события Обработка интерактивной активации в точке маршрута (точке действия) может использовать- ся для открытия форм «сопутствующих» объектов кон- фигурации. К примеру, когда пользователь захочет акти-
вировать задачу Получение наличной оплаты, то в этом случае будет крайне полезно, чтобы открылась не форма задачи, а форма счета (для того, чтобы на его основании ввести приходный кассовый ордер) и т. п. (листинг 11.12). Листинг 11.12. Пример обработчика события ОбработкаИнтерактивнойАктивации Процедура ОплатаОбработкаИнтерактивнойАктивацииСТочкаМаршрутаБП. Задача, СтандартнаяОбработка); Счет.ПолучитьФорму("ФормаДокумента").Открыть(); СтандартнаяОбработка = Ложь; КонецПроцедуры Интерактивный старт бизнес-процесса Пользователь может произвести запуск бизнес-процесса интерактивно. Возможны следующие варианты. В форме списка бизнес-процесса пользователь создает новый бизнес-процесс. В форме нового бизнес-процесса нажимается кнопка ОК. В данном случае бизнес-процесс записывается, стартует и производится его активация. Последовательность возникновения событий, порядок работы с их обработчиками такой же, как и при про- граммном старте с активацией. Пользователь может после создания бизнес-процесса только записать его. Далее в форме списка или в форме самого бизнес-процесса, используя команды контекстно- го меню (или пункта меню Действия), произвести его старт (рис. 11.29). И Продажа товара Продажа товара 11 от 15 10 2005 23:23.34 _ О X Ct(kS Активировать Записать Записать и закрыть Установить время X Закрыть —?...."тхуитделта Ж' Выписка счета и расходной накладной Рис. 11.29. Интерактивный старт бизнес-процесса Старт бизнес-процесса как вложенного При определении карты маршрута можно предусматри- вать старт вложенных бизнес-процессов. В этом случае основной бизнес-процесс ждет завершения вложенного бизнес-процесса и только после этого переходит к сле- дующей точке маршрута. На карте маршрута такая точка маршрута определяется с помощью следующего элемента (рис. 11.30). Вложенный процесс Рис. 11.30. Вложенный бизнес-процесс Одной из важных характеристик (свойств) данной точки маршрута является ссылка на запускаемый бизнес-про- цесс. Кроме этого, есть возможность определить ряд об- работчиков событий. Рассмотрим порядок вызова части из них (последовательность действий представлена на рис. 11.31). Начало транзакции Завершение транзакции Рис. 11.31. Вызов событий при старте вложенного бизнес-процесса При формировании массива задач могут использоваться два обработчика событий: Перед созданием задач и При соз- дании задач. Порядок работы с этими обработчиками бо- лее подробно рассматривается в разделе «Задачи», с. 376. В том же разделе более подробно рассматривается работа обработчиков событий, связанных с выполнением задач (Перед выполнением и При выполнении). «Входными» данными в процессе, указанном на схеме, является массив задач. Перед созданием массива задач вызывается обработчик события Перед созданием вложенных бизнес-процессов. Если данный обработчик события не оп- ределен, то на каждую задачу из сформированного масси- ва задач создается по бизнес-процессу. У созданных биз- нес-процессов устанавливается дата и ссылка на ведущую задачу. Обработчик события Перед созданием вложенных бизнес-про- цессов рекомендуется использовать для определения мас- сива задач по своему усмотрению. Если в этом обработчи- ке событий сформировать массив бизнес-процессов, но при этом флаг стандартной обработки оставить в значе- нии Истина, созданные в обработчике задачи будут сбро- шены и сработает стандартный механизм формирования задач. Если флаг стандартной обработки установить в значение Ложь, но при этом массив сформированных биз- нес-процессов не будет содержать ни одного элемента, то ведущая задача будет считаться выполненной и (если все
задачи в данной точке маршрута выполнены) будет про- изведен переход бизнес-процесса к следующей точке мар- шрута. Пример соответствующего обработчика события (в нем принудительно создается один вложенный бизнес-про- цесс) приведен в листинге 11.13. Листинг 11.13. Пример обработчика события ПередСозданиемВложенныхБизнесПроцессов Процедура ОбходПередСоз даниемВложенныхБизнесПроцессов( ТочкаМаршрутаБизнесПроцесса, ФормируемыеБизнесПроцессы, Отказ) БП = БизнесПроцессы.Поручение.СоздатьБизнесПроцессО; БП.Дата = ТекущаяДатаО: БП.Автор = ПараметрыСеанса.ТекущийИсполнитель; БП.Записать О; ФормируемыеБи з несПроцессы.Доба витьСБП): СтандартнаяОбработка = Ложь; КонецПроцедуры После того как массив вложенных бизнес-процессов сфор- мирован (в обработчике события Перед созданием вложенных бизнес-процессов или штатным образом), вызывается об- работчик события При создании вложенных бизнес-процессов. Его рекомендуется использовать для корректировки (до- бавления, частичного удаления) массива сформирован- ных вложенных бизнес-процессов. Если данный массив в результате таких изменений не будет содержать ни одно- го элемента (и иное не предусмотрено в обработчике со- бытия При создании вложенных бизнес-процессов), то соответ- ствующая ведущая задача будет считаться выполненной. Предположим, что в исходном бизнес-процессе опреде- лена табличная часть Участники. В определенной точке маршрута для созданных вложенных бизнес-процессов необходимо уточнить ряд характеристик (свойств). Для изменения свойств созданных вложенных процессов ис- пользуем обработчик событий При создании вложенных биз- нес-процессов (листинг 11.14). Листинг 11.14. Пример обработчика события ПриСозданииВложенныхБизнесПроцессов Процедура ОбходПриСозданииВложенныхБизнесПроцессов( ТочкаМаршрутаБизнесПроцесса, ФормируемыеПроцессы, Отказ) // Обходим табличную часть Для Каждого Элемент Из Участники Цикл // Обходим массив задач Для Каждого Процесс Из ФормируемыеПроцессы Цикл // Настраиваем вложенный бизнес-процесс Процесс.Автор = ПараметрыСеанса.ТекущийИсполнитель; Если ПустаяСтрока(Элемент.НаименованиеЗадачи) Тогда Процесс.Тема = Наименование: Иначе Процесс.Тема = Элемент.НаименованиеЗадачи; КонецЕсли; Процесс.Исполнитель = Элемент.Сотрудник; Процесс.ИсполнительРоль = Элемент.РольИсполнителя; Процесс.ИсполнительОтдел = Элемент.Подразделение: Процесс.Записать О; КонецЦикла; КонецЦикла; КонецПроцедуры Старт бизнес-процесса с несколькими точками старта Наличие нескольких точек старта предполагает, что вы- бор конкретной точки для старта определяется внешни- ми, по отношению к бизнес-процессу условиями. Если же бизнес-процесс обладает всей необходимой ин- формацией, чтобы при старте самостоятельно принять решение о выборе того или иного маршрута, то достаточ- но одной точки старта, следом за которой будет идти точ- ка проверки условия или точка выбора варианта. Если бизнес-процесс имеет несколько точек старта, то при вызове метода Старт О необходимо указать конкретную точ- ку, в противном случае будет выдано сообщение об ошибке. Поэтому при создании бизнес-процесса с несколькими точками старта необходимо: ♦ переопределить команду Старт в форме списка и в фор- ме объекта бизнес-процесса; ♦ переопределить кнопку ОК в форме объекта бизнес-про- цесса. Смысл всех модификаций, которые необходимо произвести заключается в том, что при выполнении метода Старт () в него в качестве параметра необходимо передать точку старта бизнес-процесса. Примером бизнес-процесса с несколькими точками стар- та может быть торговля товаром, для которого возможна предварительная демонстрация (на дому, рабочем месте потенциального клиента). Заявка либо на покупку, либо на демонстрацию поступает к оператору (сотруднику компании). После опроса клиента им выясняется, какой из вариантов предпочтителен потенциальному покупате- лю. Если выбирается предварительная демонстрация, то после ее окончания менеджер по продажам уточняет же- лание клиента приобрести товар. В случае если клиент согласен, выполняется ветка бизнес-процесса, связанная с продажей товара. Карта такого бизнес-процесса может выглядеть следующим образом (рис. 11.32). Старт с демонстрацией Проовмостхюевть I Менеджер Выйти на контакт с Кассир Получить оплату I — Склад__________ Отгрузить товар Рис. 11.32. Пример бизнес-процесса выдачи денег
Если данный бизнес-процесс является вложенным для других бизнес-процессов, то в соответствующих точках маршрута нужно прописать обработчик При создании вло- женных бизнес-процессов так, чтобы записывать и старто- вать с нужной точки все бизнес-процессы из массива сформированных (листинг 11.15). Листинг 11.15. Пример обработчика события ПриСозданииВложенныхБизнесПроцессов Процедура ОбходПриСозданииВложенныхБизнесПроцессов( ТочкаМаршрутаБизнесПроцесса, ФормируемыеПроцессы, Отказ) // Обходим табличную часть Для Каждого Элемент Из Участники Цикл // Обходим массив задач Для Каждого Процесс Из ФормируемыеПроцессы Цикл // Настраиваем вложенный бизнес-процесс Процесс.Автор = ПараметрыСеанса. ТекущийИсполнитель; Если ПустаяСтрока(Элемент.НаименованиеЗадачи) Тогда Процесс.Тема = Наименование; Иначе Процесс.Тема = Элемент.НаименованиеЗадачи; КонецЕсли; Процесс.Исполнитель = Элемент.Сотрудник; Процесс.ИсполнительРоль = Элемент.РольИсполнителя; Процесс.ИсполнительОтдел = Элемент.Подразделение; Процесс.Записать!); // Явное указание точки старта Процесс.Старт(БизнесПроцессы.ДемонстрацияИПродажа. ТочкиМаршрута. СтартДемонстрации); КонецЦикла; КонецЦикла; КонецПроцедуры В остальном использование бизнес-процессов с несколь- кими точками старта ничем не отличается от обычных бизнес-процессов. Завершение бизнес-процесса Завершение является последним этапом в жизненном цик- ле бизнес-процесса. Бизнес-процесс автоматически стано- вится завершенным (свойству Завершен устанавливается значение Истина) при достижении точки завершения и при условии отсутствия невыполненных задач по этому бизнес- процессу. У бизнес-процесса может быть несколько точек завершения. В карте бизнес-процесса они отмечаются с по- мощью элемента «точка завершения» (рис. 11.33). Рис 11.33. Точка завершения бизнес-процесса При переходе на точку завершения вызывается обра- ботчик При завершении. Если установить Отказ (параметр процедуры-обработчика) равным Истине, например, если не выполнены все необходимые условия заверше- ния бизнес-процесса, то обработка прерывается. Задача по точке маршрута, выполнение которой привело к пе- реходу на точку завершения, при этом остается невы- полненной. Рассмотрим следующую ситуацию. Существует бизнес- процесс, который отслеживает процесс согласования и выдачи денежных средств под отчет. При завершении бизнес-процесса (переход к этой точке осуществляется после ввода очередного авансового отчета) необходимо проверить, что подотчетник полностью отчитался за по- лученные им средства. Такую проверку можно размес- тить в обработчике события При завершении точки заверше- ния бизнес-процесса (листинг 11.16). Листинг 11.16. Пример обработчика события ПриЗавершении Процедура ПодотчетникПриЗавершении! ТочкаМаршрутаБизнесПроцесса, Отказ) // РКО - реквизит бизнес-процесса. содержащий ссылку // на докунент "Расходный кассовый ордер" // Исполнитель - реквизит бизнес-процесса, // содержащий ссылку на подотчетника Если Не обДолгПодотчетника(РКО,Исполнитель) = 0 Тогда Сообщить("Есть долг! Бизнес-процесс: " + ЭтотОбъект.Метаданные!). Синоним + " не завершен"); Отказ = Истина; КонецЕсли; КонецПроцедуры Если у бизнес-процесса установлено свойство ВедущаяЗа- дача, то есть он является вложенным, то при своем завер- шении он помечает эту задачу как выполненную. Это, в свою очередь, приводит к продвижению основного биз- нес-процесса дальше по маршруту. Установка свойству Завершен значения Истина (средствами встроенного языка или интерактивно) может использо- ваться для прерывания хода бизнес-процесса или для ис- ключения его из списка активных (незавершенных) биз- нес-процессов. При этом никакие обработчики кроме ПередЗаписью и ПриЗаписи не вызываются. Выполнение ве- дущей задачи при этом не производится. Задачи При продвижении бизнес-процесса по карте маршрута в определенных его точках, а именно при переходе на точку действия или вложенный бизнес-процесс, могут создаваться задачи. Упрощенно их можно назвать поль- зовательскими заданиями, которые должны быть кем-то выполнены.
Каждая задача (конкретный элемент) существует в кон- тексте какого-либо экземпляра (элемента) бизнес-про- цесса и какой-либо его точки маршрута (в задаче содер- жатся ссылки на перечисленные объекты). Создать задачу, не связав ее с каким-либо бизнес-процессом и точкой это- го бизнес-процесса, нельзя. Связь бизнес-процесса (как объекта конфигурации) с со- ответствующей задачей устанавливается при конфигури- ровании бизнес-процесса (в свойствах бизнес-процесса указывается объект конфигурации Задача) (рис. 11.34). Рис. 11.34. Свойства бизнес-процесса Можно сказать, что у задачи существуют следующие «предопределенные» свойства: ♦ ПометкаУдаления; ♦ Дата (тип Дата, состав даты Дата и время); ♦ Номер (числовой или строковый); ♦ Наименование (тип Строка); ♦ Выполнена (тип Булево); ♦ БизнесПроцесс (ссылка на любой бизнес-процесс); ♦ ТочкаМаршрута (ссылка на точку маршрута бизнес-про- цесса). Кроме этого в объекте конфигурации Задача могут опре- деляются некие общие моменты (свойства) касающиеся «пользовательского задания» и которые в общем случае не зависят от бизнес-процесса и его текущего состояния (один объект конфигурации Задача может быть связан с несколькими объектами конфигурации БизнесПроцесс). К примеру, в каждой задаче должны храниться данные о пользователе, ее выполнившем. С этой целью можно определить реквизит задачи Исполнитель. Можно опреде- лить ряд других реквизитов: ДатаВыполнения, ДатаАвтовы- полнения (для реализации стратегии «время вышло, зна- чит, задача выполнена») и т. д. В случае возникновения хранения списков можно определить любое количество табличных частей с произвольным составом. Формирование задач При прохождении маршрута бизнес-процесс на точках действия или точках вложенных бизнес-процессов может создавать одну или несколько задач. Несколько задач бу- дут сформированы в том случае, если у точки маршрута установлен признак Групповая либо задачи формируются программно (в соответствующих обработчиках событий). В случае если в точке маршрута установлен признак Груп- повая, бизнес-процесс отбирает в регистре сведений, от- ветственном за адресацию, все записи, соответствующие установленным в данной точке реквизитам адресации, и для каждой из них формирует свою задачу. Рассмотрим последовательность действий, порядок сле- дования обрабатываемых событий, возникающих при формировании задач (рис. 11.35). Начало транзакции Завершение транзакции Рис. 11.35. Последовательность вызова событий при формировании задач Обработчик события Перед созданием задач может исполь- зоваться для создания собственного набора задач. При- чем можно создавать как одну задачу, так и несколько, вне зависимости от установленного в свойствах точки маршрута признака Групповая. Если при создании собст- венного массива задач в параметр процедуры Стандартная обработка не записать значение Ложь, то созданный массив очистится и заполнится задачами исходя из поведения системы по умолчанию (так, как если бы этот обработчик определен не был). Пример обработчика события ПередСозданиемЗадач приве- ден в листинге 11.17. Листинг 11.17. Пример обработчика события ПередСозданиемЗадач Процедура НакладнаяПередСозданиемЗадач( ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи, СтандартнаяОбработка) Задача = Задачи. Задача. СоздатьЗадачу(); Задача. Дата = ТекущаяДатаО; Задача.БизнесПроцесс = Ссылка; Задача.ТочкаМаршрута = БизнесПроцессы.ПродажаТовара.ТочкиМаршрута.Отгрузка; Задача.Наименование = "Формирование расходной накладной"; ФормируемыеЗадачи.Добавить(Задача); СтандартнаяОбработка = Ложь; КонецПроцедуры При формировании задач стандартным образом для них автоматически определяются следующие свойства: ♦ наименование устанавливается равным наименованию соответствующей точки маршрута, например Выписка счета;
♦ ссылка на экземпляр бизнес-процесса, породившего эту задачу; ♦ ссылка на точку маршрута бизнес-процесса; ♦ реквизиты адресации задачи устанавливаются равными реквизитам адресации соответствующей точки маршрута. При возникновении необходимости определения других свойств задачи либо для корректировки состава массива задач может использоваться обработчик события При соз - Дании задач (листинг 11.18). Листинг 11.18. Пример обработчика события П риСозда н и иЗадач Процедура 0тгрузкаПриСозданииЗадач( ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи, Отказ) Склад = Справочники.Подразделения. НайтиПоНаименованию(РасходнаяНакладная.Склад); Если Не Склад.Пустая() Тогда Для Каждого Задача Из ФормируемыеЗадачи Цикл Задача.Подразделение = Склад; КонецЦикла; КонецЕсли; КонецПроцедуры Следует отметить, что допускается создание новых задач и в обработчике события При создании задач. В этом случае обработчик события Перед созданием задач может содер- жать одну строку (листинг 11.19). Листинг 11.19. Пример обработчика события ПередСозданиемЗадач Процедура НакладнаяПередСозданиемЗадач( ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи, СтандартнаяОбработка) СтандартнаяОбработка = Ложь; КонецПроцедуры Во всех обработчиках, представленных на схеме, не стоит реализовывать какие-либо механизмы, осуществляющие диалог с пользователем (открытие любых форм). В Задачи Задача Действия* ;;Н< ПТК р а JZL а а и. 0. Е 0. □ 2 5 Вьписка счета и расходной накладной Утверждение счета________ Получение наличной оплаты На согласование__________ На согласование 6 Обработать результаты сап Добавить 17 05.2005 9:5322 | Скопировать Изменить Удалить непосредственно [Продаж Ins F9 F2 8 9 10 11 Выписка счета и расходной нак "М Отгрузка товара со склада Выписка счета и расходной нак||от||Т Выписка счета и расходной нак|ДУ1 Выполнена Выбрать Установить пометку удаления Рис. 11.36. Контекстное меню формы списка задачи Shift-Del Del Необходимо обратить внимание на тот факт, что у задачи есть свойство Выполнена (тип Булево). В данное свойство можно установить значение Истина как программно, так и в форме задачи (если данное свойство представлено в диалоге формы задачи с помощью соответствующего эле- мента управления). Но данное действие не приведет к вызову специфических обработчиков событий (Перед вы- полнением и При выполнении) и в случае выполнения всех за- дач в точке маршрута к продвижению к следующей точке по карте маршрута бизнес-процесса. Выборка всех активных (невыполненных) задач и прямая установка в свойство Выполнена значения Истина рекомен- дуется в случае возникновения необходимости принуди- тельного завершения бизнес-процесса. Порядок действий системы, последовательность вызы- ваемых обработчиков событий при выполнении задачи представлен на рис. 11.37. Выполнение задач Выполнение задач может производиться как интерак- тивно (используя основные интерфейсные возможности 1С:Предприятие), так и программно. Следует отметить, что есть понятие интерактивной активации задач, и оно отличается от понятия интерактивного выполнения. Осо- бенности интерактивной активации рассматривались в главе «Старт бизнес-процесса», с. 372. Под интерактивным выполнением задач будем понимать выполнение задачи, вызванной либо нажатием на кнопку ОК в форме задачи, либо выполнением команды контекст- ного меню Выполнена в форме задачи или в форме списка задач (рис. 11.36). Программное выполнение задач возможно с помощью методов ВыполнитьЗадачуО и ВыполнитьЗадачуИнтерактивноО. Эти методы существуют у объекта ЗадачаОб1ект.<Имя>. Рис. 11.37. Последовательность вызова событий при выполнении задачи Следует отметить, что в рамках пункта «Запись объекта задачи» вызывается еще ряд обработчиков событий, по- казанных далее (рис. 11.38). Если хоть в одном из обработчиков (связанных с выпол- нением задачи) параметр Отказ установлен равным значе- нию Истина, то дальнейшая обработка выполнения пре- кращается, и задача не помечается как выполненная.
Рис. 11.38. Обработчики событий, вызываемые в процессе записи объекта задачи Рассматривая различные варианты выполнения задач, следует отметить, что выполнение метода ВыполнитьЗада- чу() команды Выполнена контекстного меню формы списка задач, приводит к выполнению цепочки, находящейся в рамках транзакции. Выполнение метода ВыполнитьЗадачуИнтерактивноО приво- дит к выполнению всех действий (вызову обработчиков событий), представленных на схеме. Обработчик события Перед выполнением задачи часто ис- пользуется для заполнения реквизитов задачи, характе- ризующих ее выполнение (например, производится за- пись исполнителя и т. п.). Пример реализации обработчика события ПередВыполнени- ем приведен в листинге 11.20. Листинг 11.20. Пример обработчика события ПередВыполнением Процедура ПередВыполнением(Отказ) // ДатаВыполнения и Исполнитель - реквизиты задачи Если ДатаВыполнения = '00010101' Тогда ДатаВыполнения = ТекущаяДатаО; КонецЕсли: Если Исполнитель. Пустая О Тогда Исполнитель = ПараметрыСеанса.ТекущийИсполнитель; КонецЕсли; КонецПроцедуры Обработчик события При выполнении задачи может исполь- зоваться для регистрации факта выполнения задачи в других объектах конфигурации. К примеру, таким объек- том может быть регистр сведений, используемый при соз- дании планировщиков — автоматизированных рабочих мест пользователей. Пример реализации обработчика события ПриВыполнении приведен в листинге 11.21. Листинг 11.21. Пример обработчика события ПриВыполнении Процедура ПриВыполнении(Отказ) СообщитьС'Задача выполнена: " + . + Наименование + ...): // Просмотр задач - регистр сведений, предназначенный // для отражения невыполненных задач // разных бизнес-процессов НаборЗаписей = РегистрыСведений.ПросмотрЗадач. СоздатьНаборЗаписей(); НаборЗаписей.Отбор.Задача.Значение = Ссылка; НаборЗаписей.Отбор.Задача.Использование = Истина: // Попытка прочитать записи регистра, содержащие данные // о выполняемой задаче НаборЗаписей.Прочитать(); НаборЗаписей.Очистить(); Попытка // Попытка записать пустой набор записей НаборЗаписей.Записать(Истина); Исключение Сообщить(0писание0шибки(), СтатусСообщения.Важное); КонецПопытки; КонецПроцедуры Проверка выполнения Выполнение задач осуществляется не только пользовате- лями, но и автоматизированными процедурами. Мало того, в бизнес-процессе может быть предусмотрен этап, который выполняется не строго в цепочке бизнес-процес- са (может быть выполнен раньше). В этом случае при - переходе на какую-либо точку маршрута необходимо произвести соответствующую проверку: если действие выполнено, то выполнить и задачу, если нет, то иници- ировать выполнение действия и т. п. Например, если за- дача предусматривает проведение документа, то автома- тическая процедура слежения за такими задачами может определять, что нужный документ уже проведен, и поме- чать задачу как выполненную, путем вызова у нее метода ВыполнитьЗадачуО. Для организации такого рода автоматизированных про- цедур предназначен метод ПроверитьВыполнениеО у задачи и соответствующие ему обработчики у задачи и точки маршрута (листинг 11.22). Листинг 11.22. Пример использования метода ПроверитьВыполнениеО Если Задача.ПроверитьВыполнениеО Тогда Задача.ВыполнитьЗадачу(); КонецЕсли При вызове метода ПроверитьВыполнениеО выполняется сле- дующая последовательность действий (рис. 11.39). Рис. 11.39. Последовательность действий при вызове метода ПроверитьВыполнениеО
Если в обработчике события задачи сразу записать в па- раметр Результат значение Ложь, то обработка метода пре- кращается (вызов обработчика точки маршрута не произ- водится) и он возвращает значение Ложь. Форма списка задач Для работы со списком задач пользователи могут исполь- зовать форму списка задач. По умолчанию при открытии формы в ней устанавливается отбор, в результате дейст- вия которого в списке отображаются только не выпол- ненные задачи (рис. 11.40). □ Задачи Задача _ □ X Рис. 11.40. Отбор в форме списка задач Отбор можно менять как интерактивно, так и программно. В диалоге формы списка расположено табличное поле, связанное с основным реквизитом формы. У этого эле- мента управления есть свойства, являющиеся расшире- нием табличного поля списка задач. Одно из них — это ОтображениеЗадач. Можно установить это свойство (Отображение задач группа свойств Использование) в значение По исполнителю (второе возможное значение, оно же является значением по умол- чанию Все задачи) (рис. 11.41). ▼ Использование:____________________________________________________ Т ОЛЬК.0 просмотр Q И вменять состав строк 0 Разрешить начало перетаскивания 0 Разрешить перетаскивание Q Изменять настройку колонок 0 Изменять позицию колонок 0 Способ редактирования | В диалоге Изменять способ раьж’К»»**** 0 Проверка отображения новой строки [Сообщать о несоответствии отбору |М| Рис. 11.41. Свойства табличного поля списка задач При отображении задач по исполнителю активно исполь- зуются настройки объекта конфигурации Задача, размещен- ные на закладке Адресация. Предположим, что существует список задач (несколько экземпляров, а не несколько объектов конфигурации) с разными значениями реквизи- тов адресации. При открытии формы списка (рассматривается пове- дение по умолчанию) из параметра сеанса, указанного в свойстве задачи Текущий исполнитель выбирается его зна- чение. Из регистра сведений выбираются записи, у которых в измерении, выбранном в качестве основного реквизита адресации, находится значение, взятое из параметра сеан- са, либо пустая ссылка. Далее все задачи проверяются на «непротиворечивость» значений остальных реквизитов адресации и измерений регистра сведений. Данный алгоритм можно представить в виде следующей схемы (рис. 11.42). Рис. 11.42. Алгоритм отображения задач по исполнителю Рассмотрим следующую ситуацию. Структура регистра сведений, отвечающего за адресацию, представлена в табл. 11.6. Таблица 11.6. Структура регистра сведений Измерение Тип измерения Сотрудник СправочникСсылка. Сотрудники РольИсполнителя СправочникСсылка.РолиИсполнителей Подразделение СправочникСсылка.Подразделения Заполнение регистра данными показано в табл. 11.7. Таблица 11.7. Данные, содержащиеся в регистре сведений Сотрудник Роль исполнителя Подразделение Иванов Отдел продаж Петров Бухгалтер Сидоров Кладовщик Оптовый склад Федоров Отдел продаж Федоров Руководитель отдела Отдел продаж Степанов Кладовщик Оптовый склад Объекта, конфигурации Задача имеет имя Задача, и для него заданы следующие свойства (табл. 11.8). Есть следующий список задач (приводятся только значе- ния их реквизитов адресации) (табл. 11.9). Если в параметре сеанса будет ссылка на пользователя Петров, то, несмотря на тот факт, что нет ни одной задачи,
в которой нужное значение было бы в основном реквизи- те адресации задач, список задач для данного исполните- ля будет содержать две строки (табл. 11.10). Таблица 11.8. Свойства объекта Задача Реквизиты адресации Тип реквизита Сотрудник Справ очникСсылка. Сотрудники РольИсполнителя СправочникСсылка. Роли И спол нителей Подразделение СправочникСсылка. Подразделения Таблица 11.9. Список задач № Основной рек- визит адресации (Сотрудник) Роль исполнителя Подразделение 1 Отдел продаж 2 Руководитель отдела Отдел продаж 3 Бухгалтер 4 Федоров Руководитель отдела Отдел продаж 5 Федоров 6 Федоров 7 Оптовый склад 8 Бухгалтер 9 Отдел продаж Таблица 11.10. Список задач для пользователя Петров № Основной рек- визит адресации (Сотрудник) Роль исполнителя Подразделение 3 Бухгалтер 8 Бухгалтер Фактически среди задач отбираются те, у которых в рек- визите адресации Роль исполнителя установлено значение Бухгалтер, а в остальных реквизитах адресации находятся пустые ссылки. Если в параметре сеанса будет записана ссылка на эле- мент справочника, представляющего пользователя Федо- ров, то перечень задач будет следующим (табл. 11.11). В данном случае в список задач попадают те из них, кото- рые в основном реквизите адресации содержат ссылку на сотрудника Федоров, или если в нем находится пустая ссылка, то тогда в подразделении указывается Отдел про- даж и в роли исполнителя либо пустая ссылка, либо зна- чение Руководитель отдела (в регистре адресации на данно- го сотрудника существует две записи). Для сотрудника Иванов список задач будет следующим (табл. 11.12). Таблица 11.11. Список задач для пользователя Федоров № Основной рек- визит адресации (Сотрудник) Роль исполнителя Подразделение 1 Отдел продаж 2 Руководитель отдела Отдел продаж 4 Федоров Руководитель отдела Отдел продаж 5 Федоров 6 Федоров 9 Отдел продаж Таблица 11.12. Список задач для сотрудника Иванов № Основной рек- визит адресации (Сотрудник) Роль исполнителя Подразделение 1 Отдел продаж Обратная связь Для эффективного использования механизма бизнес- процессов возникает необходимость автоматически вы- полнять соответствующие задачи при выполнении тре- буемых операций с другими объектами информационной базы. К примеру, при активизации задачи Выплата денеж- ных средств лучше открыть форму нового документа Рас- ходный кассовый ордер (для этой цели можно использовать механизм активизации). Но при проведении документа бизнес-процесс должен понять, что задача выполнена, и про- должить движение по карте маршрута. Такой механизм и называется обратной связью. Обратная связь может настраиваться несколькими спосо- бами. Какой способ выбрать, зачастую зависит от особен- ностей прикладной задачи. Но не смотря на это, можно выделить два основных варианта организации обратной связи: ♦ использование обработчиков ожидания; ♦ использование механизма оповещения. Строить механизм обратной связи на обработчиках ожи- дания (возможности процедур вызываются через уста- новленные промежутки времени) лучше всего, когда кри- терий выполнения не находится в информационной базе 1С:Предприятие. В этом случае можно периодически вы- полнять запрос и в случае получения нужного признака программно выполнять задачу. Реализовывать обратную связь на механизме оповеще- ния лучше всего в том случае когда выполнение задачи связано с каким-либо действием над объектом базы данных. Бывают ситуации, когда критерий выполнения задачи не простой, а составной (требуется заведение ряда докумен- тов, окончания выполнения каких-либо механизмов). В этом случае «напрашивается» организация механизма обратной связи с использованием обработчиков ожидания. Но все же более предпочтительным вариантом (в общем
случае) является распараллеливание участков карты биз- нес-процесса и реализация механизма обратной связи с использованием механизма оповещения. Рассмотрим пример реализации механизма обратной свя- зи с использованием механизма оповещения. Постановка задачи. В карте маршрута существует точка действия Выдача наличных денег, при переходе на нее соз- дается задача. При интерактивной активации этой задачи создается документ Расходный кассовый ордер. Документ заполняется на основании данных бизнес-процесса. Кас- сир как исполнитель должен только сохранить документ, чтобы данная задача считалась выполненной. Как это ор- ганизовать? Предположим, что в бизнес-процессе определен реквизит РКО, содержащий ссылку на оформляемый документ. В модуле формы документа Расходный кассовый ордер (от- слеживаем интерактивные действия пользователя) в об- работчике события «После записи» (если нет смысла не за- писывать документ, в случае не выполнения задачи, то и не нужно реализовывать механизм в транзакции записи) определяем следующую строку (листинг 11.23). Листинг 11.23. Вызов метода ОповеститьО Оповестить ("ЗаписьРасходногоКассовогоОрдера", , ЭтотОбъект): В модуле приложения следует разместить определение следующей процедуры (листинг 11.24). Листинг 11.24. Процедура ОбработчикОповещения Процедура ОбработчикОповещения( ИмяСобытия, Параметр. Источник) Экспорт Если ИмяСобытия = "ЗаписьРасходногоКассовогоОрдера" Тогда Запрос = Новый Запрос; Запрос.УстановитьПараметрС"Парам". Источник.Ссылка); Запрос.Текст = "ВЫБРАТЬ Задача.Ссылка ИЗ Задача.Задача.ЗадачиПоИсполнителю КАК Задача ВНУТРЕННЕЕ СОЕДИНЕНИЕ БизнесПроцесс. ВыдачаДенегПодотчетнику КАК ВыдачаДенегПодотчетнику ПО Задача. БизнесПроцесс - ВыдачаДенегПодотчетнику.Ссылка ГДЕ Задача.Выполнена = ЛОЖЬ И ВыдачаДенегПодотчетнику.РКО = &Парам"; Выборка = Запрос.Выполнить().ВыбратьО; Пока Выборка.Следующий() Цикл ТекущаяЗадача = Выборка.Ссылка.ПолучитьОбъектО; Если ТекущаяЗадача.ТочкаМаршрута = БизнесПроцессы. ВыдачаДенегПодотчетнику. ТочкиМаршрута. ОформлениеВыплаты Тогда Если Вопросе"Пометить задачу .. + ТекущаяЗадача.Наименование + ... как выполненную?", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да Тогда ТекущаяЗадача.ВыполнитьЗадачуС); КонецЕсли; КонецЕсли; КонецЦикла; КонецЕсли; // ИмяСобытия = "ЗаписьРасходногоКассовогоОрдера" КонецПроцедуры В первую очередь в данном обработчике проверяется имя обрабатываемого события (в общем случае их может быть больше одного). После этого выполняется запрос. В выборку результатов запроса попадают (в общем случае) все не выполненные задачи бизнес-процесса, значение реквизита РКО которого совпадает со значением, переданным в параметр запроса (значение берется из параметра обработчика оповеще- ния). Поэтому при работе с полученной выборкой необ- ходимо проверять принадлежность задачи интересующей нас точке маршрута. При «прохождении» всех условий задается вопрос о вы- полнении найденной задачи. В случае положительного ответа выполняется метод задачи ВыполнитьЗадачуО (при- водит к отметке задачи как выполненной и продвижению бизнес-процесса к следующей точке по карте бизнес-про- цесса). То, что процедура ОбработчикОповещения О будет являться обработчиком оповещения, определяется (как вариант) выполнением следующей строки кода, размещенной в обработчике события При начале работы системы (лис- тинг 11.25). Листинг 11.25. Подключение обработчика оповещения ПодключитьОбработчикОповещения("ОбработчикОповещения"); Примеры реализации бизнес-процессов В данном разделе разберем реализацию ряда бизнес-про- цессов. Следует воспринимать их как примеры (не пре- тендующие на истину в последней инстанции), иллюст- рирующие механизмы бизнес-процессов. Единый объект Задача Во всех рассматриваемых бизнес-процессах будет ис- пользоваться один объект конфигурации Задача и, соот- ветственно, один регистр сведений, отвечающий за адре- сацию. Этот регистр сведений будет иметь следующий состав из- мерений (табл. 11.13). Регистр имеет следующее наполнение (табл. 11.14). Таблица 11.13. Измерения регистра сведений Измерение Тип измерения Сотрудник СправочникСсылка. Сотрудники РольИсполнителя СправочникСсылка.РолиИсполнителей Подразделение Справочник Ссылка. Подразделения
Таблица 11.14. Данные регистра сведений Сотрудник Роль исполнителя Подразделение Иванов Отдел продаж Петров Бухгалтер Сидоров Кладовщик Оптовый склад Федоров Отдел продаж Федоров Руководитель отдела Отдел продаж Степанов Кладовщик Оптовый склад Объект конфигурации Задача имеет имя Задача и следую- щие реквизиты (табл. 11.15). Таблица 11.15. Реквизиты объекта конфигурации Задача Реквизиты адресации Тип реквизита Сотрудник СправочникСсылка. Сотрудники РольИсполнителя СправочникСсылка. РолиИсполнителей Подразделение СправочникСсылка. Подразделения Реквизиты задачи Тип реквизита Контрольный Срок Дата (состав Дата и Время) ДатаВыполнения Дата (состав Дата и Время) Исполнитель СправочникСсылка.Сотрудники Приоритет Число ДатаАвтоВыполнения Дата (состав Дата и Время) В качестве основного реквизита адресации выбран рекви- зит адресации Сотрудник. В свойство Текущий исполнитель выбран параметр сеанса ТекущийИсполнитель (тип СправочникСсылка.Сотрудники). Данный параметр сеанса заполняется в обработчике со- бытия ПриНачалеРаботыСистемы модуля приложения (лис- тинг 11.26). Листинг 11.26. Заполнение параметра сеанса ТекущийИсполнитель ПараметрыСеанса. ТекущийИсполнитель = Справочники.Сотрудники.НайтиПоКодуСИмяПользователя()); Считается, что имя пользователя, указываемое при входе в систему, совпадает с кодом справочника Сотрудники. Для заполнения ряда реквизитов задачи в модуле объекта Задача определен следующий обработчик события Перед- Выполнением (листинг 11.27). Листинг 11.27. Обработчик события ПередВыполнением Процедура ПередВыполнением(Отказ) // Проверка даты на пустое значение Если ДатаВыполнения = '00010101' Тогда ДатаВыполнения = ТекущаяДатаС); КонецЕсли: // Если исполнитель до начала выполнения неопределен, // он записывается из параметра сеанса. //В этом случае записывается пользователь, И в контексте которого запущено 1С:Предприятие Если Исполнитель.ПустаяО Тогда Исполнитель = ПараметрыСеанса.ТекущийИсполнитель; КонецЕсли; КонецПроцедуры Данный обработчик события определяет, что при выпол- нении задачи (программном, интерактивном) в ней со- храняется время выполнения и исполнитель. Для удобства работы пользователей со списком задач, создадим форму списка. Определим имя формы списка как ФормаСпискаПоИсполнителю. В табличном поле, свя- занным с основным реквизитом, установим свойство Ото- бражение задач (группа свойств Использование) в значение По исполнителю. Следует отметить тот факт, что при этом идет речь не о реквизите задачи Исполнитель, а о свойстве (параметре) — расширении табличного поля списка задач (рис. 11.43). vИспользование Только просмотр □ Изменять состав строк 0 Разрешить начало перетаскивания □ Разрешить перетаскивание □ Изменять настройку колонок 0 Изменять позицию колонок 0 Способ редактирования | В диалоге Изменять способ >фРН1«1 0 (Отображение доч [По ис по пните дю QI Проверка отображения новой строки Сообщать о несоответствии отбору Рис. 11.43. Свойства табличного поля списка задач Более подробно описание механизма отображения спи- ска задач по исполнителю описано в разделе «Форма спи- ска задач», с. 380. У табличного поля, связанного со списком задач, сущест- вует свойство (расширение табличного поля списка за- дач) Исполнитель. Данный параметр доступен как на чте- ние, так и для записи. Воспользуемся им для организации возможности просмотра списка задач разных пользовате- лей. Создадим реквизит формы списка Сотрудник (тип Справоч- никСсылка. Сотрудники). Определим в диалоге элемент управ- ления поле ввода и свяжем его через свойство Данные с ре- квизитом формы Сотрудник. Определим обработчики событий ПриИзменении поля ввода (листинг 11.28) и ПриОткрытии формы (листинг 11.29). Листинг 11.28. Обработчик события ПриИзменении поля ввода И Процедура-обработчик изменения поля ввода "Сотрудник'' Процедура СотрудникПриИзменении(Элемент) ЭлементыФормы.ЗадачаСписок.Исполнитель = Сотрудник; КонецПроцедуры Листинг 11.29. Обработчик события ПриОткрытии формы // Процедура-обработчик события "ПриОткрытии" формы Процедура ПриОткрытииО ЭлементыФормы.ЗадачаСписок.АвтоОбновление = Истина: ЭлементыФормы.ЗадачаСписок.ПериодАвтоОбновления = 5; ЗадачаСписок.Порядок.Установить("Дата Убыв"); Сотрудник = ПараметрыСеанса.ТекущийИсполнитель; КонецПроцедуры
В первой процедуре (листинг 11.28) при изменении зна- чения в элементе управления, связанном с реквизитом формы «Сотрудник», новое значение записывается в свой- ство расширения табличного поля. Это приводит к тому, что в списке отображаются задачи только по выбранному исполнителю. Во второй процедуре (листинг 11.29) устанавливаем ре- жим автоматического обновления с периодичностью 5 се- кунд. Устанавливается порядок сортировки списка задач (по убыванию даты) и инициализируется реквизит фор- мы (значением из параметра сеанса). При работе со списком задач ФормаСпискаПоИсполнителю в нем фактически отражаются задачи со статусом Не вы- полнена (или и Выполнена, если снять отбор Выполнена = Ложь), можно просматривать значения реквизитов адреса- ции, реквизитов задачи. В ряде случаев этого может быть не достаточно. К примеру, необходимо отслеживать, была ли хоть раз выполнена интерактивная активация задачи (была ли хоть раз предпринята попытка открыть форму задачи или выполнены другие действия по интерактив- ной активации). Постараемся решить эту задачу. Создадим регистр сведений ПросмотрЗадач (табл. 11.16). Таблица 11.16. Структура регистра ПросмотрЗадач Измерение Тип измерения Задача ЗадачаСсылка.Задача Сотрудник СправочникСсылка. Сотрудники Ресурсов и реквизитов у данного регистра сведений нет. Сама идея механизма довольно проста: при выполнении интерактивной активации в регистр сведений будут запи- сываться данные о задаче и пользователе, ее выполнив- шем. При выполнении задачи данные о ней будут из реги- стра сведений удаляться. Это можно реализовать с помощью обработчиков собы- тий ОбработкаИнтерактивнойАктивации (листинг 11.30) и При- Выполнении (листинг 11.31) модуля объекта Задача. Листинг 11.30. Обработчик события ОбработкаИнтерактивнойАктивации Процедура ОбработкаИнтерактивнойАктивации(СтандартнаяОбработка) НаборЗаписей = РегистрыСведений.ПросмотрЗадач. СоздатьНаборЗаписей(); НаборЗаписей.Отбор.Задача.Значение = Ссылка; НаборЗаписей.Отбор.Задача.Использование = Истина; НаборЗаписей.Отбор.Сотрудник.Значение = ПараметрыСеанса.ТекущийИсполнитель; НаборЗаписей.Отбор.Сотрудник.Использование = Истина; // Производим попытку чтения набора записей // с установленными отборами НаборЗаписей.Прочитать О; Если НаборЗаписей.КоличествоО = 0 Тогда // Если набор записей пуст, производим запись данных // в регистр сведений НоваяЗапись = НаборЗаписей.Добавить О; НоваяЗапись.Задача = Ссылка: НоваяЗапись.Сотрудник = ПараметрыСеанса. ТекущийИсполнитель; Попытка НаборЗаписей.Записать(); Исключение Сообщить(ОписаниеОшибкиС). СтатусСообщения.Важное); КонецПопытки: #Если ВнешнееСоединение Тогда #Иначе СброситьСведенияОЗадаче(Ссылка): #КонецЕсли КонецЕсли: КонецПроцедуры Листинг 11.31. Обработчик события ПриВыполнении // Процедура обработчик события "ПриВыполнении” Процедура ПриВыполнении(Отказ) Сообщить("Задача выполнена: " + ... + Наименование + ....); НаборЗаписей = РегистрыСведений.ПросмотрЗадач. СоздатьНаборЗаписейО; НаборЗаписей.Отбор.Задача.Значение = Ссылка; НаборЗаписей.Отбор.Задача.Использование = Истина; // Получить набор записей с отбором по задаче НаборЗаписей.Прочитать(); // Очищаем полученный набор НаборЗаписей.Очистить(); Попытка // Пытаемся записать пустой набор записей в регистр // фактически удаляем из него данные о задаче, // если они там были НаборЗаписей.Записать(Истина); Исключение Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное); КонецПопытки; #Если ВнешнееСоединение Тогда #Иначе СброситьСведенияОЗадаче(Ссылка); ^КонецЕсли КонецПроцедуры В данных обработчиках событий пока есть только один нерассмотренный момент, а именно: вызов процедуры СброситьСведенияОЗадаче. Назначение и код данной про- цедуры рассмотрим чуть позже. Одно дело записать (и вовремя удалить) данные в ре- гистр сведений, другое дело, — это организовать для пользователя удобный механизм просмотра этих данных. Для решения этой задачи вернемся к форме списка. Для отображения «дополнительных» статусов задачи (каждая задача в списке, естественно, может иметь свой статус) воспользуемся событием При выводе строки таблич- ного поля, связанного со списком задач. Определим обработчик события ПриВыводеСтроки (лис- тинг 11.32). Листинг 11.32. Обработчик события ПриВыводеСтроки // Процедура-обработчик события "ПриВыводеСтроки" Процедура ЗадачаСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки) СведенияОЗадаче = ПолучитьСведения03адаче( ДанныеСтроки.Ссылка): Если СведенияОЗадаче.Просмотрена = Ложь Тогда ОформлениеСтроки.Шрифт = мЖирныйШрифт; КонецЕсли;
Если ДанныеСтроки.Ссылка.Приоритет > 0 Тогда ОфорнлениеСтроки.ЦветТекста = ИеЬЦвета.Коричневый; КонецЕсли; Если ДанныеСтроки.Ссылка.Приоритет < 0 Тогда ОфорнлениеСтроки.ЦветТекста = ИеЬЦвета.ТемноСерый; КонецЕсли: Если ДанныеСтроки.Ссылка.Выполнена Тогда ОфорнлениеСтроки.Шрифт = нЗачеркнутыйШрифт; КонецЕсли; КонецПроцедуры В разделе описания переменных модуля формы списка размещается определение двух переменных (листинг 11.33). Листинг 11.33. Описание переменных модуля формы // ПЕРЕМЕННЫЕ МОДУЛЯ Перен мЖирныйШрифт; Перем нЗачеркнутыйШрифт; В основном разделе модуля формы списка эти перемен- ные инициализируются (листинг 11.34). Листинг 11.34. Инициализация переменных модуля формы нЖирныйШрифт = Новый Шрифте . . Истина); нЗачеркнутыйШрифт = Новый Шрифте ...... Истина); Порядок работы обработчика события При выводе строки заключается в том, что первоначально вызывается функ- ция ПолучитьСведенияОЗадаче, которая возвращает струк- туру, которая содержит значение с ключом Просмотрена. Далее, исходя из полученного значения, а также исходя из значения реквизита задачи Приоритет, определяются элементы оформления выводимой строки. Можно предположить, что в функции ПолучитьСведенияО- Задаче производится обращение к регистру сведений и проверяется, есть ли в нем запись по этой задаче или нет. Если есть, то задача была «прочитана» (была произведена ее интерактивная активация). Но если вспомнить (обработчик события При открытии формы списка), что событие При выводе строки будет вызы- ваться каждые пять секунд для каждой строки списка, по- пытка «лобового» решения этой задачи может привести к плачевному результату (система будет «тормозить»). Одним из вариантов оптимизации процесса может слу- жить следующий механизм. В модуле приложения определяется переменная мСведе- нияОЗадачах (локально для модуля приложения). В ос- новном разделе модуля она инициализируется (лис- тинг 11.35). Листинг 11.35. Инициализация переменной мСведенияОЗадачах мСведенияОЗадачах = Новый Соответствие; Далее определяются функция ПолучитьСведенияОЗадаче (листинг 11.36) и процедуры СброситьСведенияОЗадаче (лис- тинг 11.37) и СброситьСведенияОВсехЗадачах (листинг 11.38). Механизм, реализуемый данными процедурами и функ- циями, состоит в том, что при «первом» обращении к ре- гистру по какой-либо задаче данные о «статусе» записы- ваются в соответствие (ключом соответствия выступает ссылка на задачу). Повторная попытка получения дан- ных об этой задаче приводит к тому, что (в пределах временного ограничения, накладываемого на переменную Возраст) обращение к регистру сведений не производится, что позволяет значительно ускорить процесс отображе- ния списка задач. Листинг 11.36. Функция ПолучитьСведенияОЗадаче Функция ПолучитьСведенияОЗадаче(Задача) Экспорт СведенияОЗадаче = мСведенияОЗадачах.Получить(Задача); Если СведенияОЗадаче = Неопределено Тогда // Если в соответствии нет сведений // о полученной задаче, // создается структура с двумя ключами: // Просмотрена и ДатаВремя СведенияОЗадаче = Новый Структура! "Просмотрена, ДатаВремя"); НаборЗаписей = РегистрыСведений.ПросмотрЗадач. СоздатьНаборЗаписейО; НаборЗаписей.Отбор.Задача.Значение = Задача; НаборЗаписей.Отбор.Задача.Использование = Истина; НаборЗаписей.Отбор.Сотрудник.Значение = ПараметрыСеанса.ТекущийИсполнитель; НаборЗаписей.Отбор.Сотрудник.Использование = Истина: НаборЗаписей.Прочитать(); СведенияОЗадаче.Просмотрена = (НаборЗаписей. Количество!) о 0); // По ключу ДатаВремя записывается время (с датой) // создания структуры СведенияОЗадаче.ДатаВремя = ТекущаяДата!): мСведенияОЗадачах.Вставить(Задача. СведенияОЗадаче); Иначе Возраст = ТекущаяДата!) - СведенияОЗадаче.ДатаВремя; // Сведения о задаче могли устареть Если Возраст > 20 Тогда СброситьСведенияОЗадаче(Задача); КонецЕсли КонецЕсли; Возврат СведенияОЗадаче; КонецФункции // ПолучитьСведенияОЗадаче Листинг 11.37. Процедура СброситьСведенияОЗадаче Процедура СброситьСведенияОЗадаче(Задача) Экспорт мСведенияОЗадачах.Удалить(Задача); КонецПроцедуры // СброситьСведенияОЗадаче Листинг 11.38. Процедура СброситьСведенияОВсехЗадачах Процедура СброситьСведенияОВсехЗадачахО Экспорт // Полная очистка соответствия мСведенияОЗадачах.Очистить(); КонецПроцедуры // СброситьСведенияОВсехЗадачах Вернемся к обработчикам событий ОбработкаИнтерактив- нойАктивации и ПриВыполнии модуля объекта Задача. В них есть строки (листинг 11.39). Листинг 11.39. Фрагмент обработчиков событий #Если ВнешнееСоединение Тогда #Иначе СброситьСведенияОЗадаче(Ссылка); ^КонецЕсли
Если модуль исполняется при внешнем соединении (через СОМ- коннектор), модуль приложения не компилируется и поэтому обращение к процедуре СброситьСведенияОЗадаче приведет к ошибке. Определять данную процедуру в общем модуле (с видимостью во внешнем соединении) смысла не имеет, так как она участвует в реализации интерфейсного механизма работы пользователя. Сам вызов вышеуказанной процедуры в этих обработчи- ках событий обусловлен тем, что как при выполнении, так при интерактивной активации статус задачи меняется. Бизнес-процесс Продажа товара Данный бизнес-процесс позволяет отследить процесс, на- чинающийся с выписки счета менеджером, получением оплаты бухгалтером и произведением отгрузки товара кладовщиком. При этом производится проверка на раз- мер установленной менеджером скидки. Если она превы- шает некий предел, установленный для фирмы, то такой счет предварительно идет на утверждение к руководите- лю отдела. У бизнес-процесса определено два реквизита: ♦ Счет (ссылка на документ); ♦ Расходная Накладная (ссылка на документ). Карта маршрута бизнес-процесса имеет следующий вид (рис. 11.44). 4 Выписать счет и расходную накладную Отмена Рис. 11.44. Карта маршрута бизнес-процесса Перед тем как перейти к рассмотрению внутренних меха- низмов данного бизнес-процесса, следует обратить вни- мание на тот факт, что для более удобной работы пользо- вателей с задачами данного бизнес-процесса необходимо организовывать так называемый механизм обратной свя- зи. При интерактивной активации задач будут откры- ваться формы других объектов (документа Счет, Расходная накладная). Для этой цели необходимо внести изменения в сами документы. К примеру, в обработчик события ПриЗаписи основной формы документа Счет можно поместить сле- дующую строку кода (листинг 11.40). Листинг 11.40. Вызов метода Оповестить () ОповеститьСЗаписьСчета", , ЭтотОбъект): В тот же обработчик документа Расходная накладная мож- но добавить аналогичную строку, но с другим именем со- бытия (листинг 11.41). Листинг 11.41. Вызов метода Оповестить () Оповестить("ЗаписьРасходнойНакладной", . ЭтотОбъект): В модуле приложения следует определить процедуру, ко- торая будет являться обработчиком при оповещении (лис- тинг 11.42). Листинг 11.42. Процедура ОбработчикОповещения Процедура ОбработчикОповещения( ИмяСобытия, Параметр. Источник) Экспорт Если ИмяСобытия = “ЗаписьРасходнойНакладной" Тогда Запрос = Новый Запрос: Запрос.УстановитьПараметр("Парам", Источник.Ссылка); Запрос.Текст = "ВЫБРАТЬ Задача.Ссылка ИЗ БизнесПроцесс.ПродажаТовара КАК ПродажаТовара ЛЕВОЕ СОЕДИНЕНИЕ Задача.Задача. ЗадачиПоИсполнителю КАК Задача ПО ПродажаТовара.Ссылка = Задача.БизнесПроцесс ГДЕ (Задача.Выполнена = ЛОЖЬ) И ПродажаТовара.РасходнаяНакладная = &Парам"; Выборка = Запрос.ВыполнитьО .Выбрать О; Пока Выборка.Следующий() Цикл ТекущаяЗадача = Выборка.Ссылка.ПолучитьОбъектО: Если ТекущаяЗадача.ТочкаМаршрута = БизнесПроцессы.ПродажаТовара. ТочкиМаршрута.ВыпискаСчета ИЛИ ТекущаяЗадача.ТочкаМаршрута = БизнесПроцессы.ПродажаТовара. ТочкиМаршрута.Отгрузка Тогда ФормаСчета = ТекущаяЗадача. БизнесПроцесс.Счет.ПолучитьФорму(); Если ФормаСчета.ОткрытаО о Истина ИЛИ ТекущаяЗадача.ТочкаМаршрута <> БизнесПроцессы.ПродажаТовара. ТочкиМаршрута.ВыпискаСчета Тогда Если Вопросе"Пометить задачу ... + ТекущаяЗадача.Наименование + ... как выполненную?", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да Тогда ТекущаяЗадача.ВыполнитьЗадачу(); КонецЕсли; КонецЕсли; КонецЕсли; КонецЦикла: КонецЕсли; И ИмяСобытия = "ЗаписьРасходнойНакладной" Тогда Если ИмяСобытия = "ЗаписьСчета" Тогда Запрос = Новый Запрос: Запрос.УстановитьПараметр("Парам", Источник.Ссылка); Запрос.Текст =
"ВЫБРАТЬ | Задача.Ссылка |ИЗ БизнесПроцесс.ПродажаТовара КАК ПродажаТовара ЛЕВОЕ СОЕДИНЕНИЕ Задача.Задача. ЗадачиПоИсполнителю КАК Задача ПО ПродажаТовара.Ссылка = Задача.БизнесПроцесс I ГДЕ | (Задача.Выполнена = ЛОЖЬ) И | ПродажаТовара.Счет = &Парам"; Выборка = Запрос.ВыполнитьО.ВыбратьО; Пока Выборка.СледующийО Цикл ТекущаяЗадача = Выборка.Ссылка.ПолучитьОбъектО; Если ТекущаяЗадача.ТочкаМаршрута = БизнесПроцессы.ПродажаТовара. ТочкиМаршрута.ВыпискаСчета ИЛИ ТекущаяЗадача.ТочкаМаршрута = БизнесПроцессы.ПродажаТовара. ТочкиМаршрута.ПолучениеОплаты ИЛИ ТекущаяЗадача.ТочкаМаршрута = БизнесПроцессы.ПродажаТовара. ТочкиМаршрута.УтверждениеСчета Тогда ФормаНакладной = ТекущаяЗадача. БизнесПроцесс. РасходнаяНакладная. ПолучитьФормуО; Если ФормаНакладной.ОткрытаО <> Истина ИЛИ ТекущаяЗадача.ТочкаМаршрута <> БизнесПроцессы.ПродажаТовара. ТочкиМаршрута.ВыпискаСчета Тогда Если Вопросе"Пометить задачу .. + ТекущаяЗадача.Наименование + ... как выполненную?", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да Тогда ТекущаяЗадача.ВыполнитьЗадачу(); КонецЕсли; КонецЕсли: КонецЕсли; КонецЦикла: КонецЕсли; // ИмяСобытия = "ЗаписьСчета" КонецПроцедуры Остается в обработчике события При начале работы системы назначить вышеописанную процедуру обработчиком опо- вещения. Сделать это можно с помощью строки следую- щего вида (листинг 11.43). Листинг 11.43. Подключение обработчика оповещения ПодключитьОбработчикОповещения("ОбработчикОповещения"); В итоге получается, что при записи какого-либо докумен- та он оповещает об этом систему. В обработчике оповеще- ния производится поиск соответствующей задачи, и она выполняется. В дальнейшем (в данном) разделе, когда будем говорить о выполнении задачи, при интерактивной активации ко- торой открывались формы документов (а форма самой задачи нет), будет подразумевать вышеописанный меха- низм. Вернемся к бизнес-процессу. При запуске (старте) бизнес-процесса выполняются сле- дующие события (листинг 11.44). Листинг 11.44. Обработчик события ПередСтартом Процедура СтартПередСтартомС ТочкаМаршрутаБизнесПроцесса, Отказ) НужноЗаписать = Ложь; Если Счет.ПустаяО Тогда СчетОбъект = Документы. Счет. СоздатьДокументО; СчетОбъект. Дата = ТекущаяДатаО: СчетОбъект.Записать О; Счет = СчетОбъект.Ссылка: НужноЗаписать = Истина; КонецЕсли: Если РасходнаяНакладная.Пустая() Тогда РасходнаяНакладнаяОбъект = Документы.РасходнаяНакладная.СоздатьДокумент(); РасходнаяНакладнаяОбъект. Дата = ТекущаяДатаО; РасходнаяНакладнаяОбъект.Записать(); РасходнаяНакладная = РасходнаяНакладнаяОбъект.Ссылка; НужноЗаписать = Истина; КонецЕсли; Если НужноЗаписать Тогда ЗаписатьО; КонецЕсли: Сообщить("Старт бизнес-процесса: " + .." + ЭтотОбъект.МетаданныеО.Синоним + ....): КонецПроцедуры // СтартПередСтартом(ТочкаМаршрутаБизнесПроцесса, Отказ) В этом обработчике производится проверка на заполнен- ность реквизитов Счет и РасходнаяНакладная. Если рекви- зиты содержат пустые ссылки (бизнес-процесс может вводиться на основании, либо пользователь перед стар- том в форме бизнес-процесса мог выбрать нужные доку- менты), то тогда создаются документы соответствующих видов и ссылки на них записываются в бизнес-процессе. После старта бизнес-процесс переходит к точке действия Выписка счета и расходной накладной. В этой точке установ- лено значение реквизита адресации Подразделение в зна- чение ОтделПродаж. В результате при переходе к этой точке маршрута создается задача с установленным реквизитом адресации Подразделение. В случае если бизнес-процесс активирован интерактивно (или соответствующая задача активирована интерактив- но), выполняется следующий обработчик события (лис- тинг 11.45). Листинг 11.45. Обработчик события ОбработкаИнтерактивнойАктивации Процедура ВыпискаСчетаОбработкаИнтерактивнойАктивации( ТочкаМаршрутаБизнесПроцесса. Задача. СтандартнаяОбработка) РасходнаяНакладная.ПолучитьФорму("ФормаДокумента"). ОткрытьО; Счет.ПолучитьФорму("ФормаДокумента").ОткрытьО; СтандартнаяОбработка = Ложь; КонецПроцедуры // Результатом будет открытие формы расходной наклад- ной и счета, форма задачи при этом открыта не будет (СтандартнаяОбработка = Ложь). При попытке выполнения задачи точки маршрута Выпис- ка счета и расходной накладной срабатывает следующий об- работчик события (листинг 11.46).
Листинг 11.46. Обработчик события ПередИнтерактивнымВыполнением Процедура ВыпискаСчетаПередИнтерактивнымВыполнением( ТочкаМаршрутаБизнесПроцесса, Задача, Отказ) Если Счет.Состав.КоличествоО = 0 Тогда Отказ = Истина; КонецЕсли; КонецПроцедуры В процедуре проверяется количество строк табличной части документа Счет (можно было проверять и расход- ную накладную, но на данном этапе считаем, что этого де- лать не нужно). Если количество строк табличной части равно нулю, задача не будет выполнена и бизнес-процесс не пойдет дальше по карте маршрута. При выполнении задачи точки маршрута Выписка счета и расходной накладной бизнес-процесс переходит к точке условия Скидка по счету выше стандартной?. Обработчик проверки условия имеет следующий вид (листинг 11.47). Листинг 11.47. Обработчик события ПроверкаУсловия // Процедура обработчик события "ПроверкаУсловия" // точки маршрута "УсловиеОграниченияСкидки" Процедура УсловиеОграниченияСкидкиПроверкаУсловия( ТочкаМаршрутаБизнесПроцесса, Результат) СкидкаБолыиеОбычной = Ложь; ОбычнаяСкидка = Константы.ОбычнаяСкидка.Получить О; // Проверяем, что скидка не превышает обычную Для Каждого Элемент Из Счет.Состав Цикл Если Элемент.Скидка > ОбычнаяСкидка Тогда СкидкаБолыиеОбычной = Истина; Прервать; КонецЕсли: КонецЦикла; Результат = СкидкаБолыиеОбычной; КонецПроцедуры Если скидка хотя бы в одной строке табличной части до- кумента больше величины, определенной в константе, то в параметр процедуры Результат записывается значение Истина и бизнес-процесс идет по ветви Да (на утверждение скидки). В этом случае бизнес-процесс продвигается до точки Утверждение счета, в которой происходит создание задачи с установленным реквизитами адресации РольИс- полнителя в значение РуководительОтдела, Подразделение в ОтделПродаж (соответствующие значения определены в свойствах группы Адресация точки действия). Следует отметить, что в соответствии с такими значениями рек- визитов адресации данная задача (в форме списка Фор- маСпискаПоИсполнителю) будет отображаться только для пользователя Федоров. При интерактивной активации созданной задачи выпол- няется следующий обработчик события (листинг 11.48). Листинг 11.48. Обработчик события ОбработкаИнтерактивнойАктивации Процедура УтверждениеСчетаОбработкаИнтерактивнойАктивации( ТочкаМаршрутаБиз несПроцесса. Задача, СтандартнаяОбработка) Счет.ПолучитьФорму("ФормаДокумента").Открыть(); СтандартнаяОбработка = Ложь; КонецПроцедуры При его выполнении открывается форма счета, а форма задачи не открывается. После выполнения текущей задачи бизнес-процесс пере- ходит к точке условия Счет утвержден?. Обработчик про- верки условия имеет следующий вид (листинг 11.49). Листинг 11.49. Обработчик события ПроверкаУсловия Процедура УсловиеУтвержденияПроверкаУсловия( ТочкаМаршрутаБизнесПроцесса. Результат) // Проверяем, что скидки согласованы Результат = Счет.СкидкаСогласована; КонецПроцедуры Признаком утверждения счета является отметка в доку- менте Счет флага СкидкаСогласована (запись в соответст- вующий реквизит значения Истина). Если в параметр Результат записано значение Ложь, бизнес- процесс переходит к точке завершения Отмена и бизнес- процесс завершается. В другом случае бизнес-процесс переходит к точке карты маршрута Получение оплаты (к этой же точке маршрута бизнес-процесс перейдет в случае, если скидка в счете не превышает порогового значения). Эта точка является точкой действия, поэтому при переходе к ней создается задача с установленным реквизитом адресации РольИс- полнителя в значение Бухгалтер (в соответствии с наполне- нием регистра сведений, ответственным за адресацию данная, задача будет присутствовать для пользователя Петров). При интерактивной активации задачи выполнится сле- дующий обработчик события (листинг 11.50). Листинг 11.50. Обработчик события ОбработкаИнтерактивнойАктивации Процедура ПолучениеОплатыОбработкаИнтерактивнойАктивации( ТочкаМаршрутаБизнесПроцесса. Задача, СтандартнаяОбработка) Счет.ПолучитьФорму(“ФормаДокумента").Открыть(); СтандартнаяОбработка = Ложь; КонецПроцедуры Откроется форма документа Счет (ссылка на который хранится в бизнес-процессе), форма задачи открыта не будет. После выполнения данной задачи (приема оплаты), биз- нес-процесс перейдет к следующей точке карты маршру- та Отгрузка товара со склада. В данной точке свойство (группы свойств Адресация) РольИсполнителя установлено в значение Кладовщик. В данной точке определено два обработчика событий: ПриСозданииЗадач (листинг 11.51) и ОбработкаИнтерактивной- Активации (листинг 11.52). Один из них срабатывает при создании задачи. Листинг 11.51. Обработчик события ПриСозданииЗадач Процедура ОтгрузкаПриСозданииЗадач( ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи. Отказ)
Склад = Справочники.Подразделения. НайтиПоНаименованиюСРасходнаяНакладная.Склад): Если Не Склад.Пустая() Тогда Для Каждого Задача Из ФормируемыеЗадачи Цикл Задача.Подразделение = Склад: КонецЦикла: КонецЕсли: КонецПроцедуры В справочнике Подразделения ищется значение, равное по наименованию складу из документа Расходная накладная. В случае успеха (найденная ссылка не пустая) получен- ное значение записывается в реквизит адресации задачи Подразделение. При интерактивной активации задачи открывается фор- ма расходной накладной. Текст обработчика приведен ниже (листинг 11.52). Листинг 11.52. Обработчик события ОбработкаИнтерактивнойАктивации Процедура ОтгрузкаОбработкаИнтерактивнойАктивацииС ТочкаМаршрутаБизнесПроцесса, Задача, СтандартнаяОбработка) РасходнаяНакладная. ПолучитьФормуС’ФормаДокумента").Открытье); СтандартнаяОбработка = Ложь; КонецПроцедуры Кладовщик уточняет перечень отгружаемых товарных позиций и выполняет задачу. После выполнения текущей задачи бизнес-процесс пере- ходит к точке Нормальное завершение и завершается. Бизнес-процесс Продажа товара с предоплатой Автоматизируемый бизнес-процесс очень похож на ранее рассмотренный (см. раздел «Бизнес-процесс Продажа то- вара», с. 386). Но есть одна отличительная особенность. Во взаиморасчетах между покупателем и продавцом воз- можны случаи предоплат. Применительно к ранее рас- смотренному бизнес-процессу это означает, что при пере- ходе к точке маршрута Получение наличной оплаты в случае достаточности средств «на балансе покупателя» эта точка маршрута должна быть пройдена автоматически. Карта бизнес-процесса такая же, как и в предыдущем слу- чае. Рассмотрим один из вариантов учета данной специ- фической особенности. Достаточно следующим образом определить обработчик события Перед созданием задач точки маршрута Получение наличной оплаты (листинг 11.53). Листинг 11.53. Обработчик события ПередСозданиемЗадач Процедура ПолучениеОплатыПередСозданиемЗадач ( ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи, СтандартнаяОбработка) // С помощью реализованной в общем модуле функции // получаем сумму возможного аванса СостояниеВзаиморасчетов = ПолучитьСостояниеВзаиморасчетов( Счет.Контрагент); СуммаПоДокументу = Счет.Состав.ИтогС'Сумма"): Если СостояниеВзаиморасчетов > СуммаПоДокументу Тогда ЗафиксироватьОплату(Счет): СтандартнаяОбработка = Ложь; КонецЕсли; КонецПроцедуры Смысл механизма заключается в том, что при выполне- нии данного обработчика проверяется наличие предопла- ты. В случае если суммы предоплаты достаточно для оплаты данного счета, параметр СтандартнаяОбработка ус- танавливается в значение Ложь. Это приводит к тому, что штатный механизм формирования задач не срабатывает. А так в данном обработчике массив задач не формировал- ся (и обработчик При создании задач для данной точки так- же не определялся), это приводит к тому, что не создается ни одной задачи и бизнес-процесс автоматически перехо- дит к следующей точке бизнес-процесса. Следует обратить внимание, что попытка реализации данного процесса приведет к изменению текста процеду- ры — обработчика оповещения. Бизнес-процесс Поручение Данный процесс автоматизирует последовательно выда- чи поручения (на проведение какого-либо действия). На- пример: кто-то должен заказать авиабилеты для директо- ра (поездки в командировку), кто-то этот процесс должен проконтролировать и т. п. У бизнес-процесса определены следующие реквизиты (табл. 11.17). Карта бизнес-процесса имеет следующий вид (рис. 11.45). Рис. 11.45. Карта маршрута бизнес-процесса У данного бизнес-процесса определены две точки старта. Попытка запустить процесс «штатными» средствами приведет к ошибке (не определена точка старта). Забегая
вперед скажем, что данный бизнес-процесс будет исполь- зоваться как вложенный (в этом случае и будет использо- ваться точка старта Без автора). «Самостоятельный» старт будет происходить с точки Старт. Как другую особенность данного бизнес-процесса можно отметить тот факт, что во всех точках действия не определено ни одно из свойств, ответственных за адресацию (определяются программно). Таблица 11.17. Реквизиты бизнес-процесса Поручение Реквизит Тип Автор СправочникСсылка. Сотрудники Исполнитель СправочникСсылка. Сотрудники И сполнитель Роль СправочникСсылка. РолиИсполнителей ИсполнительОтдел СправочникСсылка. Подразделения Контролер СправочникСсылка. Сотрудники КонтролерРоль СправочникСсылка. РолиИсполнителей Контр олерОтдел СправочникСсылка. Подразделения Приоритет Число Тема Строка ТекстПоручения Строка ОтчетО Выполнении Строка ОтчетО Контроле Строка ПараллельныйКонтроль Булево ДатаВыполнения Дата ДатаКонтроля Дата КонтрольныйСрок Дата ОтметкаОВыполнении Булево ОтметкаОСнятииСКонтроля Булево Старт бизнес-процесса можно реализовывать разными способами. Рассмотрим вариант, когда в модуле прило- жения определяется процедура (листинг 11.54). Листинг 11.54. Процедура, выполняющая старт бизнес-процесса Процедура ОсновнойДействиеЗО Экспорт БизнесПроцесс = БизнесПроцессы.Поручение. СоздатьБизнесПроцессО: БизнесПроцесс. Дата = ТекущаяДатаО; БизнесПроцесс.Записать(); БизнесПроцесс.СтартСБизнесПроцессы.Поручение. ТочкиМаршрута.Старт); БизнесПроцесс. АктивироватьИнтерактивноО; КонецПроцедуры Вызов данной процедуры можно разместить в главном меню программы. В самой процедуре уточняется точка старта, и, кроме этого, бизнес-процесс активируется инте- рактивно. При старте выполняется следующий обработчик точки старта бизнес-процесса (листинг 11.55). Листинг 11.55. Обработчик события ПередСтартом Процедура СтартПередСтартом( ТочкаМаршрутаБизнесПроцесса, Отказ) Автор = ПараметрыСеанса.ТекущийИсполнитель: КонтрольныйСрок = КонецНедели(ТекущаяДатаО); ЗаписатьО; Сообщить("Старт бизнес-процесса: " + .. + ЭтотОбъект.МетаданныеО.Синоним + ..); КонецПроцедуры В нем в реквизит бизнес-процесса Автор записывает- ся значение из параметра сеанса, содержащего текущего пользователя (элемент справочника). Устанавливается контрольный срок исполнения. После старта бизнес-процесс переходит к точке действия Выдать поручения. Следует отметить, что в данной точке отключен механизм создания задач по умолчанию. В ней определен обработчик события Перед созданием задач (лис- тинг 11.56). Листинг 11.56. Обработчик события ПередСозда н иемЗадач Процедура ВыдатьПоручениеПередСозданиемЗадач( ТочкаМаршрутаБизнесПроцесса. ФормируемыеЗадачи, СтандартнаяОбработка) Задача = Задачи. Задача. СоздатьЗадачуО; Задача.БизнесПроцесс = Ссылка: Задача.ТочкаМаршрута = ТочкаМаршрутаБизнесПроцесса; Задача. Дата = ТекущаяДатаО; Задача.Сотрудник = Автор; Задача. Наименование = ТочкаМаршрутаБизнесПроцесса. НаименованиеЗадачи; Если Не ПустаяСтрока(Тема) Тогда Задача.Наименование = Задача. Наименование + ": " + Тена; КонецЕсли; ФормируемыеЗадачи.Добавить(Задача); СтандартнаяОбработка = Ложь; КонецПроцедуры В качестве значения реквизита адресации задачи устанав- ливается значение из реквизита бизнес-процесса Автор. Стандартный механизм создания задач отключается. При интерактивной активации данной задачи выполня- ется следующий обработчик события (листинг 11.57). Листинг 11.57. Обработчик события ОбработкаИнтерактивнойАктивации Процедура ВыдатьПоручениеОбработкаИнтерактивнойАктивации( ТочкаМаршрутаБизнесПроцесса, Задача, СтандартнаяОбработка) Форма = ПолучитьФормуС'ФормаПоручения"); Форма.Задача = Задача; Форма.Открыть(); СтандартнаяОбработка = Ложь; КонецПроцедуры
Форма ФормаПоручения — специфическая форма бизнес- процесса, в которой каждый из участников процесса мо- жет оставлять какие-либо отметки, замечания. В ней реа- лизовано разграничение прав доступа к различным по- лям (реквизитам бизнес-процесса) в зависимости от роли сотрудника. К примеру, исполнитель не может исправить текст поручения и т. и. Перед выполнением задачи, созданной в точке Выдача по- ручений, необходимо проверить: не пустой ли текст пору- чения, определен ли его исполнитель. Данные проверки выполняются в обработчике события Перед выполнением. Текст обработчика приведен ниже (листинг 11.58). Листинг 11.58. Обработчик события ПередВыполнением Процедура ВыдатьПоручениеПередВыполнением ( ТочкаМаршрутаБизнесПроцесса. Задача. Отказ) Отказ = Ложь; // Проверяется заполнение хотя бы одного реквизита. // который будет использоваться в качестве значений // реквизита адресации задачи Если Исполнитель.Пустая О И ИсполнительРоль.Пустая() И ИсполнительОтдел.Пустая О Тогда Отказ = Истина; КонецЕсли: Если ПустаяСтрока(ТекстПоручения) Тогда Отказ = Истина: КонецЕсли; КонецПроцедуры В идеальном случае такую же проверку необходимо было бы реализовать и для сотрудника, осуществляющего кон- троль за исполнением поручения. После выполнения задачи бизнес-процесс переходит к точ- ке проверки условия. В ней производится выбор вариан- та выполнения бизнес-процесса. Выбор осуществляется в соответствии со значением реквизита бизнес-процесса ПараллельныйКонтроль (установленным интерактивно). Обработчик проверки условия содержит фактически од- ну строку (листинг 11.59). Листинг 11.59. Обработчик события ПроверкаУсловия Результат = ПараллельныйКонтроль; Предположим (для начала), что был выбран вариант с па- раллельным контролем (то есть контролер может устано- вить отметку об успешности/не успешности результатов исполнения раньше, чем сам исполнитель зарегистрирует факт исполнения). При таком варианте бизнес-процесс распараллеливается и одновременно переходит к точкам действия Выполнить поручение и Контроль исполнения. К ка- ждой из них формирование задач производится про- граммно в обработчике события Перед созданием задач. Текст обработчика для точки действия Выполнить поруче- ние имеет следующий вид (листинг 11.60). В качестве значений реквизитов адресации задачи уста- навливаются значения из соответствующих реквизитов бизнес-процессов. Обработчик события Перед созданием задач для точки действия Контроль исполнения имеет такой же код, за исключением того, что реквизиты адресации зада- чи заполняются значениями реквизитов бизнес-процесса, связанные с сотрудником, выполняющим контроль. Листинг 11.60. Обработчик события ПередСозданиемЗадач Процедура ВыполнитьПоручениеПередСозданиемЗадач( ТочкаМаршрутаБизнесПроцесса. ФормируемыеЗадачи, СтандартнаяОбработка) Задача = Задачи.Задача.СоздатьЗадачуО; Задача.БизнесПроцесс = Ссылка; Задача.ТочкаМаршрута = ТочкаМаршрутаБизнесПроцесса; Задача. Дата = ТекущаяДатаО; Задача.Приоритет = Приоритет; Задача.КонтрольныйСрок = КонтрольныйСрок; Если Не Исполнитель.ПустаяО Тогда Задача.Сотрудник = Исполнитель; КонецЕсли; Если Не ИсполнительРоль.Пустая() Тогда Задача.РольИсполнителя = ИсполнительРоль; КонецЕсли; Если Не ИсполнительОтдел.Пустая() Тогда Задача.Подразделение = ИсполнительОтдел; КонецЕсли; Задача. Наименование = ТочкаМаршрутаБизнесПроцесса. НаименованиеЗадачи; Если Не ПустаяСтрока(Тема) Тогда Задача.Наименование = Задача.Наименование + ": " + Тема; КонецЕсли; ФормируемыеЗадачи.Добавить(Задача); СтандартнаяОбработка = Ложь; КонецПроцедуры При интерактивной активации обеих задач вызывается следующая процедура (листинг 11.61). Листинг 11.61. Обработчик события ОбработкаИнтерактивнойАктивации Процедура ВыполнитьПоручениеОбработкаИнтерактивнойАктивации( ТочкаМаршрутаБизнесПроцесса, Задача, СтандартнаяОбработка) Форма = ПолучитьФормуС'ФормаПоручения"); Форма.Задача = Задача; Форма.ОткрытьО; СтандартнаяОбработка = Ложь; КонецПроцедуры Ее выполнение приводит к открытию формы ФормаПору- чения, (форма задачи при этом не открывается. После того как обе задачи будут выполнены, бизнес-про- цесс «пройдет» точку слияния и перейдет к точке провер- ки условия Снято с контроля. В обработчике проверки условия проверяется значение реквизита ОтметкаОСнятии- СКонтроля (устанавливается интерактивно в форме Фор- маПоручения сотрудником осуществляющим контроль, и означает, что поручение выполнено). В случае если по- ручение не выполнено, производится возврат к точке проверки условия Параллельный контроль, в другом слу- чае бизнес-процесс завершается (осуществляется переход к точке завершения).
Рассмотрим поведение бизнес-процесса в случае, когда в точке проверки условия Параллельный контроль выпол- нение бизнес-процесса пойдет по ветви Нет. В соответствии с картой маршрута бизнес-процесс пере- ходит к точке действия Выполнить поручение. Обработчик события Перед созданием задач для точки дей- ствия Выполнить поручение используется такой же, как и у точки Выполнить поручение при выполнении параллельно- го контроля (листинг 11.62). Листинг 11.62. Обработчик события ПередСозданиемЗадач Процедура ВыполнитьПоручениеПередСозданиемЗадач( ТочкаМаршрутаБизнесПроцесса. ФормируемыеЗадачи, СтандартнаяОбработка) Задача = Задачи. Задача. Соз датьЗадачу О; Задача.БизнесПроцесс = Ссылка; Задача.ТочкаМаршрута = ТочкаМаршрутаБизнесПроцесса; Задача.Дата = ТекущаяДатаО: Задача.Приоритет = Приоритет; Задача.КонтрольныйСрок = КонтрольныйСрок; Если Не Исполнитель.Пустая() Тогда Задача.Сотрудник = Исполнитель; КонецЕсли; Если Не ИсполнительРоль.ПустаяО Тогда Задача.РольИсполнителя = ИсполнительРоль; КонецЕсли; Если Не ИсполнительОтдел.ПустаяО Тогда Задача.Подразделение = ИсполнительОтдел; КонецЕсли; Задача.Наименование = ТочкаМаршрутаБизнесПроцесса. НаименованиеЗадачи; Если Не ПустаяСтрока(Тема) Тогда Задача.Наименование = Задача. Наименование + ": " + Тема; КонецЕсли; ФормируемыеЗадачи.Добавить(Задача); СтандартнаяОбработка = Ложь; КонецПроцедуры В качестве значений реквизитов адресации задачи уста- навливаются значения из соответствующих реквизитов бизнес-процессов. При интерактивной активации вызывается та же проце- дура, что определена для точки «Выполнить поручение» при выполнении параллельного контроля (листинг 11.63). Листинг 11.63. Обработчик события Обработка ИнтерактивнойАктивации Процедура ВыполнитьПоручениеОбработкаИнтерактивнойАктивации( ТочкаМаршрутаБизнесПроцесса, Задача, СтандартнаяОбработка) Форма = ПолучитьФормуС'ФормаПоручения"); Форма.Задача = Задача: Форма.Открытье); СтандартнаяОбработка = Ложь; КонецПроцедуры Ее выполнение приводит к открытию формы ФормаПору- чения, форма задачи при этом не открывается. После выполнения задачи бизнес-процесс переходит к точке проверки условия Нужен контроль?. Обработчик проверки условия содержит следующий текст (лис- тинг 11.64). Листинг 11.64. Обработчик события ПроверкаУсловия Процедура НуженКонтрольПроверкаУсловия( ТочкаМаршрутаБизнесПроцесса. Результат) Результат = Истина; Если Контролер.Пустая() И КонтролерРоль.Пустая() И КонтролерОтдел.Пустая() Тогда Результат = Ложь; КонецЕсли; КонецПроцедуры В процедуре производится проверка на заполненность какого-либо реквизита, значение которого может исполь- зоваться в качестве значения реквизитов адресации зада- чи. В случае если все соответствующие реквизиты содер- жат пустые ссылки, бизнес-процесс переходит по ветви Нет к своему завершению. В случае если выполнение по- шло по ветви Да, в соответствии с картой бизнес-процесса производится переход к точке действия Контроль исполне- ния. Обработчики событий у данной точки описаны та- ким же образом, как и в точке Контроль исполнения при па- раллельном варианте проведения контроля. После выполнения задачи, созданной в точке маршрута Контроль исполнения, бизнес-процесс переходит к точке проверки условия Снято с контроля. В случае успешного выполнения поручения (критерии были описаны ранее) бизнес-процесс завершается. Бизнес-процесс Обход Данный бизнес-процесс позволяет выдавать последова- тельные поручения (выполняемые друг за другом). Перво- начально должен выполнить поручение сотрудник, знача- щийся первым в списке, потом второй и т. д. Карта бизнес-процесса имеет следующий вид (рис. 11.46). Рис. 11.46. Карта маршрута бизнес-процесса Следует обратить внимание на тот факт, что в данной карте нет ни одной точки действия, но есть точка вложен-
лого бизнес-процесса. В свойстве БизнесПроцесс данной точки выбрано значение Поручение. У бизнес-процесса определена табличная часть Участники со следующим составом реквизитов табличной части (табл. 11.18). Таблица 11.18. Реквизиты табличной части бизнес-процесса Реквизит табличной части Тип Сотрудник СправочникСсылка. Сотрудники РольИсполнителя СправочникСсылка. РолиИсполнителей Подразделение СправочникСсылка. Подразделения НаименованиеЗадачи Строка ПризнакОбхода Булево В точке старта обработчик события Перед стартом неопре- делен, поэтому после старта бизнес-процесс без пред- варительной обработки переходит к точке вложенного бизнес-процесса. В данной точке определен обработчик события При создании вложенных бизнес-процессов. Текст об- работчика приведен в листинге 11.65. Листинг 11.65. Обработчик события ПриСозданииВложенныхБизнесПроцессов Процедура 0бходПриСозданииВложенныхБизнесПроцессов( ТочкаМаршрутаБизнесПроцесса, ФормируемыеПроцессы. Отказ) Для Каждого Элемент Из Участники Цикл Если Не Элемент.ПризнакОбхода Тогда Для Каждого Процесс Из ФормируемыеПроцессы Цикл И Настраиваем вложенный бизнес-процесс Процесс.Автор = ПараметрыСеанса. ТекущийИсполнитель; Если ПустаяСтрока(Элемент. НаименованиеЗадачи) Тогда Процесс.Тема = Наименование; Иначе Процесс.Тема = Элемент.НаименованиеЗадачи; КонецЕсли; Процесс.Исполнитель = Элемент.Сотрудник; Процесс. ИсполнительРоль = Элемент. РольИсполнителя; Процесс.ИсполнительОтдел = Элемент. Подразделение; Процесс.ПараллельныйКонтроль = Ложь: Процесс.ЗаписатьО; Процесс.Старт(Биз несПроцессы. Поручение. ТочкиМаршрута. СтартБезАвтора): Элемент.ПризнакОбхода = Истина; КонецЦикла; ЗаписатьО: Возврат; КонецЕсли; КонецЦикла; КонецПроцедуры При переходе к точке вложенного бизнес-процесса систе- мой создается одна задача (иного не было определено программно). На каждую задачу (у нас одна) создается вложенный бизнес-процесс. У созданного бизнес-процесса в свойство Ведущая задача записывается ссылка на задачу, ее породившую. После этого производится вызов обра- ботчика события При создании вложенных бизнес-процессов. Через параметр ФормируемыеПроцессы передается массив сформированных вложенных бизнес-процессов (в нашем случае один элемент). После этого производится обход табличной части бизнес- процесса. Ищется строка, в которой реквизит табличной части ПризнакОбхода установлен в значение Ложь (обхода данной задачи еще не было). Следует отметить, что могут использоваться и другие данные по адресации (не обяза- тельно явно указывать сотрудника). Для текущей строки табличной части (со значением при- знака равным Ложь) настраиваем полученный через пара- метр бизнес-процесс. После этого стартуем его, и при этом выбирается точка старта СтартБезАвтора бизнес-про- цесса Поручение. Реквизит табличной части ПризнакОбхо- да устанавливается в значение Истина. Далее производим выход из процедуры-обработчика. Исходя из заполняемых у вложенного бизнес-процесса свойств можно с уверенностью сказать, что (именно при такой настройке бизнес-процесса) из всей определенной для бизнес-процесса карты маршрута будет использо- ваться следующий фрагмент (рис. 11.47). Рис. 11.47. Карта маршрута бизнес-процесса После завершения вложенного бизнес-процесса ведущая задача (породившая бизнес-процесс) завершается и осу- ществляется переход к точке проверки условия Обошли весь список?. Обработчик проверки условия имеет следующий вид (листинг 11.66). В обработчике проверяется, есть в табличной части стро- ки, в которых признак обхода установлен в значение Ложь. Если таких строк нет, то производится завершение биз- нес-процесса, в противном случае осуществляется пере- ход на точку вложенного бизнес-процесса. Обобщенно вышеописанный алгоритм можно предста- вить в виде следующей схемы (рис. 11.48).
Листинг 11.66. Обработчик события ПроверкаУсловия Процедура УсловиеОбходаПроверкаУсловия( ТочкаМаршрутаБизнесПроцесса, Результат) Для Каждого Элемент Из Участники Цикл Если Не Элемент.ПризнакОбхода Тогда Результат = Ложь: Возврат; КонецЕсли; КонецЦикла: Результат = Истина: КонецПроцедуры Рис. 11.48. Схема выполняемого алгоритма Бизнес-процесс Согласование В ходе деятельности предприятия, организации может возникать необходимость согласования каких-либо доку- ментов. В рамках задачи существует понятие рецензент (кто участвует в процессе рассмотрения). Рассмотрение документа рецензентами может осуществляться парал- лельно, но в каждом конкретном случае согласования их может быть произвольное количество (решает инициа- тор). В качестве примера реализации такого механизма рассмотрим бизнес-процесс Согласование. У бизнес-процесса определены следующие реквизиты (табл. 11.19). Определена табличная часть Рецензии (для указания спи- ска рецензентов и получения рецензий) (табл. 11.20). Карта маршрута бизнес-процесса имеет следующий вид (рис. 11.49). Бизнес-процесс имеет одну точку старта. В этой точ- ке определен обработчик события Перед стартом (лис- тинг 11.67). Таблица 11.19. Реквизиты бизнес-процесса Реквизит Тип ДокументНаСогласование ДокументСсылка Инициатор СправочникСсылка. Сотрудники КонтрольныйСрок Дата Важное Булево Согласовано Булево ОбработатьРецензии Булево ПовторноеСогласование Булево Пояснение Строка Таблица 11.20. Реквизиты табличной части бизнес-процесса Реквизит табличной части Тип Рецензент СправочникСсылка. Сотрудники РольИсполнителя СправочникСсылка. РолиИсполнителей Подразделение СправочникСсылка. Подразделения Рецензия Строка Исполнено Булево g Инициатор Определить список рецензентов 4 ~ Рецензенты Передать на согласование Рис. 11.49. Карта маршрута бизнес-процесса Листинг 11.67. Обработчик события ПередСтартом Процедура СтартПередСтартом( ТочкаМаршрутаБизнесПроцесса, Отказ) Инициатор = ПараметрыСеанса.ТекущийИсполнитель: Записать(); Сообщить("Старт бизнес-процесса: " + + ЭтотОбъект. Мет аданныеО .Синоним + ..); КонецПроцедуры
В качестве инициатора бизнес-процесса записывается поль- зователь, в контексте которого был произведен старт биз- нес-процесса. После старта в соответствии с картой маршрута бизнес- процесс переходит к точке действия Определить список ре- цензентов. В данной точке определен обработчик события Перед созданием задач (листинг 11.68). Листинг 11.68. Обработчик события ПередСозданиемЗадач Процедура ОпределитьСписокРецензентовПередСозданиемЗадач( ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи, СтандартнаяОбработка) Если Рецензии.КоличествоО = 0 Тогда НоваяЗадача = Задачи.Задача.СоздатьЗадачуО; НоваяЗадача.БизнесПроцесс = Ссылка; НоваяЗадача.ТочкаМаршрута = БизнесПроцессы. Согласование. ТочкиМаршрута. ОпределитьСписокРецензентов; НоваяЗадача.Дата = ТекущаяДатаО; НоваяЗадача.Наименование = БизнесПроцессы. Согласование. ТочкиМаршрута. ОпределитьСписокРецензентов. НаименованиеЗадачи; НоваяЗадача.Сотрудник = ПараметрыСеанса. ТекущийИсполнитель; Если Важное Тогда НоваяЗадача.Приоритет = 1; КонецЕсли; ФормируемыеЗадачи.Добавить(НоваяЗадача); КонецЕсли; СтандартнаяОбработка = Ложь; КонецПроцедуры В обработчике события проверяется состав табличной части Рецензии. Если количество строк табличной части равно нулю, создается задача, в реквизит адресации Со- трудник которой (персональная адресация) записывается пользователь, в контексте которого стартовал бизнес- процесс. Если к моменту выполнения обработчика Перед созданием задач список рецензентов уже определен, задача не созда- ется, и так как обработчик При создании задач не был опре- делен, в точке действия не создается ни одной задачи. В результате она считается пройденной, и бизнес-процесс продолжает движение по карте маршрута. Вернемся к случаю, когда задача была создана. При инте- рактивной активации задачи выполнится следующий об- работчик события (листинг 11.69). Листинг 11.69. Обработчик события ОбработкаИнтерактивнойАктивации Процедура 0пределитьСписокРецензентов0бработкаИнтерактивнойАктивации( ТочкаМаршрутаБизнесПроцесса. Задача, СтандартнаяОбработка) ПолучитьФормуС'ОсновнаяФорма”) .ОткрытьО; СтандартнаяОбработка = Ложь; КонецПроцедуры В результате будет открыта форма бизнес-процесса с име- нем Основная (в ней можно определить список рецензен- тов), форма задачи не открывается. При выполнении задачи выполнится следующий обра- ботчик события (листинг 11.70). Листинг 11.70. Обработчик события ПриВыполнении Процедура ОпределитьСписокРецензентовПриВыполнении( ТочкаМаршрутаБизнесПроцесса, Задача. Отказ) ПроверитьСогласованиеО; КонецПроцедуры В теле процедуры производится вызов процедуры Прове- ритьСогласование. Текст процедуры приведен ниже (лис- тинг 11.71). Листинг 11.71. Процедура ПроверитьСогласование Процедура ПроверитьСогласованиеС) Для Каждого Элемент Из Рецензии Цикл Если Не Элемент.Согласовано Тогда Согласовано = Ложь; Возврат; КонецЕсли; КонецЦикла; Согласовано = Истина; ЗаписатьО; КонецПроцедуры Можно сказать, что в данной процедуре устанавливается «общий» статус согласования. Если у какого-либо рецен- зента определен статус согласования Ложь, то в целом в реквизит бизнес-процесса Согласовано записывается это значение. Следует отметить тот факт, что задачи в данный момент непосредственно до рецензентов еще не дошли (еще не были созданы) и подобная ситуация Согласовано = Ложь характеризует пессимистическую оценку инициатором процесса согласования (при заполнении табличной части он может проставлять значения согласования «по умол- чанию» для каждого рецензента). После выполнения задачи бизнес-процесс переходит к сле- дующей точке действия На согласование. Свойство опре- делено таким образом лишь для того, чтобы визуально на карте отметить «групповую» особенность данной точ- ки маршрута (стандартный механизм создания задач отключается, фактически установка свойства «не рабо- тает»). Определен обработчик события Перед созданием задач (листинг 11.72). Листинг 11.72. Обработчик события ПередСозданиемЗадач Процедура НаСогласованиеПередСозданиемЗадач( ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи, СтандартнаяОбработка) СтандартнаяОбработка = Ложь; КонецПроцедуры
Установка параметра обработчика СтандартнаяОбработка в значение Ложь отключает стандартный механизм форми- рования задач. Это приводит к тому, что на «входе» в об- работчик события При создании задач массив Формируемые- Задачи не содержит ни одной задачи. Текст обработчика При создании задач представлен в лис- тинге 11.73. Листинг 11.73. Обработчик события ПриСозданииЗадач Процедура НаСогласованиеПриСозданииЗадач( ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи. Отказ) Для Каждого Элемент Из Рецензии Цикл // По умолчанию согласовано Элемент.Согласовано = Истина; НоваяЗадача = Задачи. Задача. СоздатьЗадачу(); НоваяЗадача.БизнесПроцесс = Ссылка; НоваяЗадача.ТочкаМаршрута = БизнесПроцессы. Согласование. ТочкиМаршрута. НаСогласование; НоваяЗадача. Дата = ТекущаяДатаО; НоваяЗадача. Наименование = БизнесПроцессы. Согласование. ТочкиМаршрута. НаСогласование. НаименованиеЗадачи; Если Важное Тогда НоваяЗадача.Приоритет = 1; КонецЕсли; // Даты НоваяЗадача.КонтрольныйСрок = КонтрольныйСрок; НоваяЗадача.ДатаАвтоВыполнения = КонтрольныйСрок; // Реквизиты адресации НоваяЗадача.Сотрудник = Элемент.Рецензент: НоваяЗадача.РольИсполнителя = Элемент.РольИсполнителя; НоваяЗадача.Подразделение = Элемент.Подразделение; ФормируемыеЗадачи.Добавить(НоваяЗадача); НоваяЗадача.Записать(); КонецЦикла: ЗаписатьО; КонецПроцедуры Количество сформированных задач равно количеству строк табличной части (на каждого рецензента по задаче). Рек- визиты адресации создаваемых задач совпадают с адрес- ными данными, указываемыми при определении списка рецензентов в табличной части бизнес-процесса. Не смотря на «пессимистический» взгляд инициатора, статус согласования в каждой задаче проставляется рав- ным Истина, хотя можно и «прислушаться» к автору биз- нес-процесса. При интерактивной активации каждой задачи вызывает- ся следующий обработчик события (листинг 11.74). Открывается форма, специализированная для работы ре- цензента (обеспечивающая его удобную работу), в рекви- зит формы Задача передается текущая (активируемая) за- дача. При выполнении задачи вызывается обработчик события При выполнении задачи. В теле процедуры содержится толь- ко одна строка (вызов процедуры, текст и назначение ко- торой уже рассматривались выше) (листинг 11.75). Листинг 11.74. Обработчик события Об ра ботка И нте ра кти в н о й Акти ва ци и Процедура НаСогласованиеОбработкаИнтерактивнойАктивации( ТочкаМаршрутаБизнесПроцесса, Задача, СтандартнаяОбработка) Форма = ПолучитьФормуС'ФормаРецензента”): Форма.Задача = Задача; Форма.Открыть О; СтандартнаяОбработка = Ложь; КонецПроцедуры Листинг 11.75. Текст обработчика события ПриВыполнении ПроверитьСогласованиеС); Назначение обработчика — определение общего статуса процесса согласования. После выполнения задачи бизнес-процесс переходит на точку проверки условия Обработать рецензии. В теле про- цедуры обработчика проверки условия содержится одна строка (проверка значения реквизита бизнес-процесса, имеющего тип Булево) (листинг 11.76). Листинг 11.76. Текст обработчика события ПроверкаУсловия Результат = ОбработатьРецензии; В случае если обрабатывать рецензии нет необходимости, то бизнес-процесс идет по ветви Нет и завершается (осу- ществляется переход к точке завершения). В противном случае бизнес-процесс переходит к точке действия Обра- ботать результаты согласования. При переходе к этой точке выполняется обработчик со- бытия Перед созданием задач, в котором производится соз- дание задачи, в основной реквизит адресации которой за- писывается инициатор бизнес-процесса (листинг 11.77). Листинг 11.77. Обработчик события ПередСозданиемЗадач Процедура ОбработатьРезультатыПередСозданиемЗадачС ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи, СтандартнаяОбработка) НоваяЗадача = Задачи.Задача.СоздатьЗадачу(); НоваяЗадача.БизнесПроцесс = Ссылка; НоваяЗадача.ТочкаМаршрута = БизнесПроцессы. Согласование. ТочкиМаршрута. ОбработатьРезультаты; НоваяЗадача.Дата = ТекущаяДатаО; НоваяЗадача.Наименование = БизнесПроцессы. Согласование. ТочкиМаршрута. ОбработатьРезультаты. НаименованиеЗадачи; НоваяЗадача.Сотрудник = Инициатор; Если Важное Тогда НоваяЗадача.Приоритет = 1; КонецЕсли; ФормируемыеЗадачи.Добавить(НоваяЗадача); СтандартнаяОбработка = Ложь; КонецПроцедуры Стандартный механизм формирования задач отключается.
При интерактивной активации задачи открывается фор- ма, специализированная для обработки полученных ре- цензий, форма задачи не открывается (листинг 11.78). Листинг 11.78. Обработчик события ОбработкаИнтерактивнойАктивации Процедура 0бработатьРезультаты0бработкаИнтерактивнойАктивации( ТочкаМаршрутаБизнесПроцесса, Задача, СтандартнаяОбработка) Форма = ПолучитьФормуС'ФормаОбработкиРецензий"); Форма.Задача - Задача: Форма.Открытье): СтандартнаяОбработка = Ложь; КонецПроцедуры После выполнения этой задачи бизнес-процесс перехо- дит к точке проверки условия Согласовать повторно. Обра- ботчик проверки условия содержит одну строку (лис- тинг 11.79). Листинг 11.79. Текст обработчика события ПроверкаУсловия Результат = ПовторноеСогласование; Флаг необходимости повторного согласования устанав- ливается в форме обработки рецензий самим инициа- тором. В случае установки этого флага бизнес-процесс возвращается на согласование, в противном случае пере- ходит к точке завершения и завершается. Рассмотрение данного бизнес-процесса можно считать законченным, если не обратить внимание на строку обра- ботчика события При создании задач (при создании задач для рецензентов) (листинг 11.80). Листинг 11.80. Текст обработчика события ПриСозданииЗадач НоваяЗадача.ДатаАвтоВыполнения = КонтрольныйСрок; Предполагается, что если при наступлении «даты автовы- полнения» рецензент не «разобрался» с задачей, она должна быть выполнена автоматически. Те средства, ко- торые до сих пор были рассмотрены, не позволяют этого сделать. Для выполнения автоматической обработки «просрочен- ных» (не исполненных в назначенный срок) задач можно предусмотреть следующую процедуру (листинг 11.81). Следует отметить, что данный механизм является част- ным случаем так называемой «эскалации действия» (ко- гда система может принять решение об эскалации — либо передать задачу другому, либо принять решение о ее вы- полнении). Смысл этой процедуры заключается в том, что выбира- ются все невыполненные задачи, далее вызывается метод, проверяющий их выполнение. В случае возвращения зна- чения Истина задача выполняется. Для того чтобы этот ме- ханизм работал, остается в точке действия На согласова- ние (как раз где могут «спать») определить обработчик события Обработка проверки выполнения (листинг 11.82). Листинг 11.81. Процедура АвтоОбработкаЗадач Процедура АвтоОбработкаЗадачО Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ Ссылка | ИЗ Задача.Задача I ГДЕ Выполнена <> Истина"; Выборка = Запрос.ВыполнитьО.ВыбратьО: Пока Выборка. Следующий О Цикл НачатьТранзакциюО; ТекущаяЗадача = Выборка.Ссылка.ПолучитьОбъектО; Попытка Если ТекущаяЗадача.ПроверитьВыполнениеО Тогда ТекущаяЗадача.ВыполнитьЗадачу(); КонецЕсли; Исключение КонецПопытки; ЗафиксироватьТранзакциюС); КонецЦикла; КонецПроцедуры Листинг 11.82. Обработчик события ОбработкаПроверкиВыполнения Процедура НаСогласованиеОбработкаПроверкиВыполнения( ТочкаМаршрутаБизнесПроцесса, Задача, Результат) Результат = Ложь: Если Задача.ДатаАвтоВыполнения <> '00010101' И Задача.ДатаАвтоВыполнения <= ТекущаяДатаО Тогда Результат = Истина: КонецЕсли; КонецПроцедуры В данном обработчике события проверяется: если время указано и «вышло», то задача выполнена. Вызов процедуры АвтоОбработкаЗадач можно производить по-разному: ♦ определить в модуле приложения и вызывать каждый час. Минусы: вызываться процедура «каждый час» бу- дет в рамках каждого запуска 1С:Предприятие; ♦ определить во внешнем модуле и вызывать с необходи- мой периодичностью из внешнего скрипта (в рамках информационной базы это действительно будет «раз в час»); Если в выполнении согласования заинтересован инициа- тор, разместить вызов процедуры в обработке (форме бизнес-процесса), являющейся его «рабочим местом». Кроме этого, следует отметить, что при наличии большо- го количества бизнес-процессов в информационной базе необходимо в самой процедуре АвтоОбработкаЗадач уста- навливать дополнительные проверки на принадлежность задачи к нужному бизнес-процессу, какой-либо его кон- кретной точке маршрута.
Глава 12. Использование механизма анализа данных и прогнозирования Механизм анализа данных и прогнозирования позволя- ет реализовывать в прикладных решениях различные средства для выявления закономерностей, которые обычно скрываются за большими объемами информа- ции. Например, проанализировав данные о продажах товаров, можно выявить группы товаров, которые обычно покупа- ются вместе. В дальнейшем (один из многочисленных ва- риантов) эта информация может использоваться при рас- кладке товара в розничном магазине. Товары могут располагаться «вместе» (пришел покупатель за мангалом, увидел рядом жидкость для растопки, угли, мясо, удочки, резиновую лодку... в итоге купил все), могут располагать- ся в разных углах торгового зала (пришел покупатель за молоком, пока дойдет до хлеба, пройдет через весь мага- зин и еще чего-нибудь купит). Другим примером использования механизма анализа данных является прогнозирование поведения контраген- та, исходя из имеющихся данных о нем. Проведя такой анализ, можно выяснить, как зависит объем их закупок от территориального расположения, размера компании, вре- мени сотрудничества и прочих показателей. На основа- нии этих зависимостей можно спрогнозировать поведе- ние нового контрагента и выбрать соответствующую стратегию для работы с ним. Используя возможность построения прогнозов можно планировать закупочную компанию. Рассмотрим пример: в прошлом месяце зоомагазин продал 100 морских сви- нок. Нужно спланировать закупку товара на следующий месяц. Одним из вариантов (очень часто используемых) является ввод поправочного коэффициента на продажи прошлых периодов. Считаем, что поправочный коэффи- циент (коэффициент повышения спроса) равен 1,5. В итоге при планировании закупок описанным методом будем к следующему месяцу планировать закупку 150 морских свинок. Но если проанализировать, что обычно покупают клиенты после покупки таких питомцев, то можно прий- ти к совершенно другому выводу. Воспользовавшись воз- можностью проведения анализа данных, построения про- гноза по этому анализу, можно получить, что закупать на следующий месяц нужно корм, различные наполнители, сено и другие «аксессуары». Следует отметить, что материал данной главы в первую очередь будет посвящен обзору механизмов ^Предпри- ятие 8.0 и только косвенно будет касаться (на простых при- мерах) способов использования полученной информации. Общие положения Общую схему работы механизма анализа и прогнозиро- вания данных можно представить следующим образом (рис. 12.1). Механизм позволяет работать как с данными, получен- ными из информационной базы, так и с данными, полу- ченными из другого источника, предварительно загру- женными в таблицу значений или табличный документ. Применяя к исходным данным один из видов анализа, можно получить результат анализа. Результат анализа представляет собой некую модель поведения данных. Ре- зультат анализа может быть отображен в итоговом доку- менте или сохранен для дальнейшего использования. Дальнейшее использование результата анализа заключа- ется в том, что на его основе может быть создана модель прогноза, позволяющая прогнозировать поведение новых данных в соответствии с имеющейся моделью. Например, можно проанализировать, какие товары при- обретаются вместе (в одной накладной), и сохранить соз- данную на основе данного анализа модель прогноза в базе данных. В дальнейшем, при создании очередной наклад- ной, ранее сохраненную модель прогноза можно извлечь из информационной базы, подать ей «на вход» новые дан- ные, содержащиеся в этой накладной, и «на выходе» по- лучить прогноз — список товаров, которые очередной клиент тоже приобретет (с определенной долей вероятно- сти), если их ему предложить. Рис. 12.1. Схема взаимодействия элементов механизма анализа данных и прогнозирования
Основные объекты механизма Схематично взаимосвязь основных объектов механизма анализа данных и прогнозирования можно показать сле- дующим образом (рис. 12.2). Рис. 12.2. Взаимосвязь основных объектов АнализДанных — объект, непосредственно выполняющий анализ данных. Ему устанавливается источник данных, задаются параметры и исходные данные. Результатом ра- боты данного объекта является результат анализа дан- ных, причем для каждого типа анализа существует свой объект для работы с результатом анализа: ♦ РезультатАнализаДанныхОбщаяСтатистика; ♦ РезультатАнализаДанныхПоискАссоциаций; ♦ РезультатАнализаДанныхПоискПоследовательностей; ♦ РезультатАнализаДанныхДеревоРешений; ♦ РезультатАнализаДанныхКластеризация. Настройка колонок анализа данных — коллекция вход- ных колонок анализа данных. Для каждой колонки ука- зывается тип данных, содержащихся в ней, роль, выпол- няемая колонкой, дополнительные настройки, зависящие от типа производимого анализа. Параметры анализа данных — набор параметров произ- водимого анализа данных. Состав параметров зависит от типа анализа. Например, для кластерного анализа указы- вается количество кластеров, на которые необходимо раз- бить исходные объекты, тип измерения расстояния меж- ду объектами и т. и. Источник данных — исходные данные для анализа. В ка- честве источника данных может выступать результат за- проса, область ячеек табличного документа, таблица зна- чений. Результат анализа данных — специальный объект, содер- жащий информацию о результате анализа. Для каждого вида анализа предусмотрен свой результат. Например, результатом анализа данных дерево решений будет объ- ект типа РезультатАнализаДанныхДеревоРешений. В дальней- шем результат может быть выведен в табличный доку- мент при помощи построителя отчета анализа данных, может быть выведен посредством программного доступа к его содержимому, может быть использован для созда- ния модели прогноза. Любой результат анализа данных может быть сохранен для последующего использования. Модель прогноза — специальный объект, позволяющий выполнять прогноз на основании входных данных (вы- борка для прогноза, настройки колонок выборки и ре- зультата, результат анализа). Тип модели прогноза зависит от типа результата анализа данных. Например, модель, созданная для типа анализа поиск ассоциаций, будет иметь тип МодельПрогнозаПоискАссоциаций. Такая модель сможет выдавать прогнозы типа: так как данный покупатель ку- пил заданный набор товаров, то с определенно вероятно- стью он должен купить и другой набор товаров. На вход модели прогноза передается источник данных для прогно- за. Результатом является таблица значений, содержащая прогнозируемые значения. Настройка входных колонок — набор специальных объек- тов, показывающих соответствие между колонками моде- ли прогноза и колонками выборки прогноза. Например, колонки модели прогноза с именем Товар может соответ- ствовать колонка выборки Номенклатура. Настройка колонок результата — позволяет управлять тем, какие колонки будут помещены в результирующую таблицу модели прогноза. Например, для поиска ассоциа- ций мы можем вывести в результат номенклатуру, кото- рую, скорее всего, приобретет клиент, и вероятность по- добной покупки. Колонки результата — таблица значений, состоящая из колонок, как указано в настройках результирующих ко- лонок, и содержащая прогнозируемые данные. Конкрет- ное содержимое определяется типом анализа. Типы анализа данных В механизме анализа данных и прогнозирования реали- зовано несколько типов анализа данных. Общая статистика Тип анализа общая статистика представляет собой меха- низм для сбора общей информации о данных, находя- щихся в полученном источнике данных. Этот тип анализа предназначен для предварительного исследования анали- зируемой информации. Анализ показывает ряд характеристик дискретных и не- прерывных полей. При выводе отчета в табличный доку- мент заполняются круговые диаграммы для отображения состава полей. Поиск ассоциаций Данный тип анализа осуществляет поиск часто встречае- мых вместе групп объектов или значений характеристик, а также производит поиск правил ассоциаций. Поиск ас- социаций может использоваться, например, для опреде- ления часто приобретаемых вместе товаров или услуг. Этот тип анализа может работать с иерархическими дан- ными, что позволяет, например, находить правила не только для конкретных товаров, но и для их групп. Важ-
ной особенностью этого типа анализа является возмож- ность работать как с объектным источником данных, в котором каждая колонка содержит некоторую характе- ристику объекта, так и с событийным источником, где ха- рактеристики объекта располагаются в одной колонке. Поиск последовательностей Тип анализа поиск последовательностей позволяет выяв- лять в источнике данных последовательные цепочки собы- тий. Например, это может быть цепочка товаров или услуг, которые часто последовательно приобретают клиенты. Этот тип анализа позволяет осуществлять поиск по иерархии, что дает возможность отслеживать не только последовательности конкретных событий, но и последо- вательности родительских групп. Кластерный анализ Кластерный анализ позволяет разделить исходный набор исследуемых объектов на группы объектов таким обра- зом, чтобы каждый объект был более схож с объектами из своей группы, чем с объектами других групп. Анализируя в дальнейшем полученные группы, называемые кластера- ми, можно определить, чем характеризуется та или иная группа, принять решение о методах работы с объектами различных групп. Например, при помощи кластерного анализа можно разделить клиентов, с которыми работает компания, на группы, для того чтобы применять различ- ные стратегии при работе с ними. При помощи параметров кластерного анализа пользова- тель может настроить алгоритм, по которому будет про- изводиться разбиение, а также может динамически изме- нять состав характеристик, учитываемых при анализе, настраивать для них весовые коэффициенты. Результат кластеризации может быть выведен в дендро- грамму — специальный вид диаграммы, предназначен- ный для графического отображения результатов кластер- ного анализа. Дерево решений Тип анализа дерево решений позволяет построить иерар- хическую структуру классифицирующих правил, пред- ставленную в виде дерева. Для построения дерева решений необходимо выбрать це- левой атрибут, по которому будет строиться классифика- тор и ряд входных атрибутов, которые будут использо- ваться для создания правил. Целевой атрибут может содержать, например, информацию о том, перешел ли клиент к другому поставщику услуг, удачна ли была сделка, качественно ли была выполнена работа и т. д. Входными атрибутами, для примера, могут выступать возраст сотрудника, стаж его работы, материальное состоя- ние клиента, количество сотрудников в компании и т. и. Результат работы анализа представляется в виде дерева, каждый узел которого содержит некоторое условие. Для принятия решения, к какому классу следует отнести не- кий новый объект, необходимо, отвечая на вопросы в уз- лах, пройти цепочку от корня до листа дерева, переходя к дочерним узлам в случае утвердительного ответа и к со- седнему узлу в случае отрицательного. Набор параметров анализа позволяет регулировать точ- ность полученного дерева. Модели прогноза Модели прогноза, создаваемые механизмом, представля- ют собой специальные объекты, которые создаются из ре- зультата анализа данных, и позволяют в дальнейшем ав- томатически выполнять прогноз для новых данных. Например, модель прогноза поиска ассоциаций, постро- енная при анализе покупок клиентов, может быть ис- пользована при работе с осуществляющим покупку кли- ентом, для того, чтобы предложить ему товары, которые он с определенной степенью вероятности приобретет вместе с выбранными им товарами. Тип анализа общая статистика Тип анализа общая статистика может использоваться для предварительного анализа данных (перед выполнением другого вида анализа) и т. п. В качестве источника данных, которые будут подвергать- ся анализу, может использоваться результат запроса, таб- лица значений или область ячеек табличного документа. Данные в источнике (с точки зрения проводимого анали- за) могут иметь непрерывный или дискретный вид. К не- прерывным относятся такие типы, как Число, Дата. Осталь- ные типы относятся к дискретным. Для колонок разных видов предусмотрено получение различной информации. Дискретные данные: ♦ Количество значений. Количество значений, встреченных в колонке источника данных (Null значением не счита- ется); ♦ Количество уникальных значений (с исключением по- вторяющихся значений); ♦ Мода. Значение, которое в источнике данных встреча- ется наиболее часто. Если в данных несколько значе- ний, встречаемых с одинаковой частотой, в качестве моды берется первое найденное; ♦ Частота. Количество вхождений значения в выборку данных; ♦ Относительная частота. Определяется как отношение количества вхождения значения к общему количеству значений; ♦ Накопленная частота. Считается как сумма частоты значения и сумма частот предыдущих значений выбор- ки данных; ♦ Накопленная относительная частота. Считается как сумма накопленной частоты значения и сумма относи- тельных частот предыдущих значений.
Непрерывные данные: ♦ Количество значений', ♦ Минимум значения', ♦ Максимум значения; ♦ Среднее', ♦ Размах. Разность между максимальным и минималь- ным значениями; ♦ Стандартное отклонение (среднеквадратичное откло- нение); ♦ Медиана. Значение, лежащее в середине выборки. Следует отметить, что если анализируется одновременно несколько полей различных видов, их анализ проводится вне зависимости друг от друга (исключается взаимная корреляция). Рассмотрим указанные характеристики на примере. Считаем, что выборка данных (источник анализа) имеет следующее наполнение (табл. 12.1). Таблица частот для значений номенклатуры будет иметь следующий вид (табл. 12.4). Таблица 12.4. Таблица частот Значение Частота Относи- тельная частота Накоп- ленная частота Накоп- ленная относи- тельная частота Стол кухонный раскладной 2 40 2 40 Стол кухонный раскладной 2 40 4 80 Табурет круглый 1 20 5 100 Таблица 12.1. Состав источника данных Номенклатура Количество Стол кухонный раскладной 1 Табурет круглый 2 Стол кухонный раскладной 3 Табурет круглый 4 Стол обеденный 5 Для поля Количество (вид данных анализа Непрерывные) бу- дут рассчитаны следующие характеристики. Таблица 12.2. Характеристики, рассчитанные для поля Количество Характеристика Значение Значений 5 Минимум 1 Максимум 5 Среднее 3 Размах 4 Стандартное отклонение 1,5811 Медиана 3 Для поля Номенклатура будут получены следующие ха- рактеристики (табл. 12.3). Таблица 12.3. Характеристики, рассчитанные для поля Номенклатура Характеристика Значение Количество значений 5 Количество уникальных значений 3 Мода Стол кухонный раскладной Относительная частота в виде диаграммы представлена на рис. 12.3. Номенкла. ™Табурет “круглый Стол кухонный раскладной г—>Стол обеденный Рис. 12.3. Относительная частота Для выполнения данного анализа может использоваться фрагмент кода, аналогичный приведенному (листинг 12.1). Листинг 12.1. Пример выполнения анализа общая статистика Анализ = Новый АнализДанных; Анализ.ТипАнализа = ТипС'АнализДанныхОбщаяСтатистика"); Запрос = Новый Запрос: Запрос.Текст = " ВЫБРАТЬ ПродажиОбороты.Номенклатура, ПродажиОбороты.Количество ИЗ РегистрНакопления.Продажи КАК ПродажиОбороты": Анализ. ИсточникДанных = Запрос.ВыполнитьО; РезультатАнализа = Анализ.ВыполнитьО; Построитель = Новый ПостроительОтчетаАнализаДанныхО: Построитель.Макет = Неопределено: Построитель. ТипАнализа = ТипСАнализДанныхОбщаяСтатистика"): ТабДок = Новый ТабличныйДркумент: Построитель.Вывести(РезультатАнализа, ТабДок) ТабДок.ПоказатьО:
Работа по проведению анализа данных начинается с соз- дания одноименного объекта. После создания произво- дится выбор типа проводимого анализа. Далее по тексту определяется запрос. Результат запроса устанавливается как источник данных анализа. Сам ана- лиз выполняется в процессе работы метода ВыполнитьО. Сам анализ не имеет средств по визуализации результата полученного анализа. Для этой цели используется объ- ект ПостроительОтчетаАнализаДанных. При создании данного объекта повторно указывается тип проводимого анализа. Далее в качестве первого параметра метода Вывести О передается результат полученного анализа, вторым пара- метром передается ранее созданный объект ТабличныйДо- кунент. В конце алгоритма табличный документ с результатом анализа открывается в отдельном окне. В результате будут получены данные, аналогичные рас- смотренным выше. Тип анализа поиск ассоциаций Как уже было сказано ранее, данный тип анализа осуще- ствляет поиск часто встречаемых вместе комбинаций объектов или значений характеристик. С его помощью можно определять группы одновременно закупаемых то- варов, выявлять наиболее привлекательные источники информации (в процессе «оптимизации» затрат на них) и т. п. Схематично процесс проведения анализа поиск ассоциа- ций можно представить следующим образом (рис. 12.4). Рис. 12.4. Схема выполнения анализа поиск ассоциаций В качестве источника данных может использоваться ре- зультат запроса, таблица значений или область ячеек таб- личного документа. С точки зрения данного типа анализа колонки источника можно разделить на: ♦ Неиспользуемая. Игнорируются анализом; ♦ Объект. Данные из этой колонки используются как объ- екты (или события) проводимого анализа. Исходя из значения данной колонки значения другой колонки (Элемент) относятся к одной ассоциируемой группе; ♦ Элемент. Данные из этой колонки используются для по- лучения устойчивых групп значений, построения ассо- циативных правил. Кроме настройки типов колонок, на результат проводи- мого анализа влияют следующие параметры анализа: ♦ МинимальныйПроцентСлучаев. Определяется минимальный процент случаев, в которых должна встречаться комби- нация элементов. Группы, у которых данное значение меньше указанного, не попадают в результат анализа; ♦ МинимальнаяДостоверность. Показывает минимальное зна- чение процента случаев, когда правило соблюдается; ♦ МинимальнаяЗначимость. Группы, у которых данное зна- чение меньше указанного, не попадают в результат ана- лиза; ♦ ТипОтсеченияПравил. Один из вариантов системного пере- числения ТипОтсеченияПравилАссоциации: Избыточные (отсе- кать избыточные правила), Покрытые (отсекать правила, покрытые другими правилами). В результате выполнения анализа получаем: ♦ информация о данных (количество объектов, количест- во элементов, среднее количество элементов в объекте, количество найденных групп, количество найденных правил ассоциаций); ♦ найденные группы элементов. Указывается состав груп- пы, количество случаев, процент случаев в которых эта группа встречается; ♦ найденные ассоциативные правила. Указывается ис- ходный состав элементов, следствие (состав элемен- тов), процент случаев, достоверность, значимость пра- вила. Рассмотрим особенности проведения данного типа ана- лиза на следующей выборке данных (постараемся оп- ределить состав одновременно закупаемых товаров) (табл. 12.5). Таблица 12.5. Список закупленных товаров Регистратор Номенклатура Регистратор 1 Пиво Балтика №7 Раки вареные Регистратор 2 Пиво Балтика №7 Крабы вареные Регистратор 3 Пиво Балтика №7 Раки вареные Регистратор 4 Пиво Балтика №7 Раки вареные Крабы вареные Регистратор 5 Раки вареные Крабы вареные
Признаком, по которому данные относятся к одной груп- пе, будем считать значение регистратора (номенклатура, указанная в одном документе, считается закупленной од- новременно). То есть Регистратор будет объектом анализа, Номенклатура — элементом. Для проведения анализа будем использовать следующий фрагмент кода (листинг 12.2). Листинг 12.2. Пример выполнения анализа поиск ассоциаций Анализ = Новый АнализДанных; Анализ. ТипАнализа = ТипСАнализДанныхПоискАссоциаций"): Запрос = Новый Запрос; Запрос.Текст = " ВЫБРАТЬ ПродажиОбороты.Регистратор, ПродажиОбороты.Номенклатура ИЗ РегистрНакопления.Продажи КАК ПродажиОбороты"; Анализ. ИсточникДанных = Запрос.ВыполнитьО; И строка приводится в качестве примера, И такое значение типа колонки по умолчанию Анализ.НастройкаКолонок.Номенклатура.ТипКолонки = ТипКолонкиАнализаДанныхПоискАссоциаций.Элемент; И строка приводится в качестве примера. И такое значение типа отсечения по умолчанию Анализ. Параметры. Т ипОтсеченияПравмл. Значение = ТипОтсеченияПравилАссоциации.Избыточные: РезультатАнализа = Анализ. Выполнить О; Построитель = Новый ПостроительОтчетаАнализаДанныхО: Построитель. Макет = Неопределено; Построитель.ТипАнализа = ТипСАнализДанныхПоискАссоциаций"); ТабДок = Новый ТабличныйДокумент; Построитель.Вывести(РезультатАнализа. ТабДок): ТабДок. Показать О; Информация о данных ..... — Количество элементов Количество объектов Среднее количество элементов в объекте: И ----- ~ Результат аналиаа Найдено часто встречаемых групп: Найдено ассоциативных правил: Рис. 12.5. Результат анализа поиск ассоциаций М° [Количество случаен [Процент случаев^ Состав________________________________________ 1| 1| 20,00 Номенклатура = Крабы вареные_______________ Номенклатура = Раки вареные________________ Номенклатура = Пиво Балтика №7 Рис. 12.6. Найденная группа товаров Результат анализа будет выглядеть следующим образом (рис. 12.5). В выборе используются данные из пяти документов (ссыл- ка содержится в поле Регистратор), количество различных номенклатурных позиций равно трем (табл. 12.6). Таблица 12.6. Различные номенклатурные позиции Пиво Балтика №7 Раки вареные Крабы вареные Найдена следующая группа товаров (рис. 12.6). Вся группа встречается в документе только в одном слу- чае из пяти (это и показано в колонках Количество случаев и Процент случаев). Получены следующие ассоциативные правила (рис. 12.7). Разберем первое из них. В трех случаях из пяти в доку- менте вместе с позицией Раки вареные встречалась пози- ция Пиво Балтика №7. Исходя из этого и был рассчитан процент случаев: (3/5 * 100 = 60%). Достоверность была рассчитана следующим образом: обе номенклатурные позиции закупались в трех случаях, то- варная позиция Раки вареные встречалась в покупках 4 раза. Исходя из этого достоверность равна: 3/4 * 100 = 75%. Значимость определяется как отношение достоверности правила к проценту нахождения Пиво Балтика №7 в заку- паемых товарах. Эта позиция встречается в 4 документах из пяти (80%). Значимость равна: 75%/80% = 0,935. Типы отсечения правил Рассмотрим такой важный параметр данного типа анали- за, как ТипОтсеченияПравил. Возможные значения отсечения содержатся в системном перечислении ТипОтсеченияПравил- Ассоциации, их состав: * Покрытые; ♦ Избыточные. Перед тем как перейти к рассмотрению особенностей ва- риантов отсечения, рассмотрим несколько общих момен- тов, применимых к правилам ассоциации. Любое правило состоит из предпосылки и следствия, на- пример: Предпосылка: Если купили Товар №1. Следствие: То купят Товар №2. Исходный набор Следствие Процент случаев Достоверность Значимость 1 60,00 75,00 0,94 Номенклатура = Раки вареные Номенклатура = Пиво Балтика №7 2 60.00 75,00 0,94 Номенклатура = Пиво Балтика №7 Номенклатура = Раки вареные 3 40,00 66,67 0,83 Номенклатура = Крабы вареные Номенклатура = Раки вареные 4 40,00 66,67 0,83 Номенклатура » Крабы вареные Номенклатура = Пиво Балтика №7 Рис. 12.7. Ассоциативные правила
При этом не надо забывать, что следствие наступает с оп- ределенной достоверностью. При отсечении правил, ве- роятностные характеристики могут рассматриваться, а могут и игнорироваться (важно только содержание пра- вила). Отсечение покрытых правил Рассмотрим вариант отсечения Покрытые. Правило может быть покрыто как по предпосылке, так и по следствию, например: Правило №1: Если купили товар №1 и №3, То купят то- вар №2. Правило №2: Если купили товар №1, То купят товар №2. В этом случае правило №1 будет считаться покрытым, так как предпосылка первого правила получается «из- быточной» по отношению к предпосылке второго пра- вила. Пример покрытия по следствию: Правило №1: Если купили товар №1, То купят товар №2, №3. Правило №2: Если купили товар №1, То купят товар №3. Правило №2 будет покрыто по следствию, так как следст- вие правила №1 более «полное». Отсечение избыточных правил Покрытие не учитывает вероятностных характеристик правил, они учитываются в случае, если используется ва- риант отсечения Избыточные. Правило будет считаться избыточным по предпосылке, если оно покрыто по предпосылке и его достоверность равна достоверности покрывающего правила, например: Правило №1: Если купили товар №1 и №3, То купят то- вар №2 с достоверностью 75%. Правило №2 Если купили товар №1, То купят товар №2 с достоверностью 75%. Правило №1 избыточно по отношению к правилу № 2 (оно содержит дополнительное условие не вносящее «воз- мущения» в вероятностные характеристики правила). Правило будет считаться избыточным по следствию, если количество случаев данного правила равняется количест- ву случаев покрывающего правила. Правило №1: Если купили товар №1, То купят товар №2, №3 в Зх случаях. Правило №2: Если купили товар №1, То купят товар №3 в Зх случаях. Правило №2 будет считаться избыточным по отношению к правилу №1, так как оно содержит более «простое» следствие с теми же вероятностными характеристиками. Поиск последовательностей Данный вид анализа позволяет выявить цепочки возни- кающих событий (шаблоны последовательностей). Он может использоваться тогда, когда одним из важных ана- лизируемых показателей является последовательность наступления событий во времени. Например, можно вы- явить последовательность товаров, которые закупаются друг за другом в течение какого-либо определенного про- межутка времени и т. п. Схематично процесс проведения анализа поиск последо- вательностей можно представить следующим образом (рис. 12.8). Рис. 12.8. Схема выполнения анализа поиск последовательностей В качестве источника данных может использоваться ре- зультат запроса, таблица значений, область ячеек таблич- ного документа. С точки зрения данного типа анализа ко- лонки источника можно разделить на: ♦ Неиспользуемая. Игнорируются анализом; ♦ Последовательность. Данные из этой колонки использует- ся для анализа как объект события последовательно- сти. По значению данной колонки анализ и ассоцииру- ет данные с одной цепочкой событий; ♦ Элемент. Данные из этой колонки используются как эле- менты последовательности; ♦ Время. Именно по данной колонке определяется время наступления события. Наличие данной колонки обяза- тельно при проведении данного типа анализа; Кроме настройки типов колонок, на результат проводи- мого анализа влияют следующие параметры анализа: ♦ МинимальныйПроцентСлучаев. Минимальный процент по- следовательностей, в которых наблюдается найденный шаблон последовательности; ♦ МинимальныйИнтервал. Признак установки минимального интервала последовательности (должна быть установ- лена единица измерения интервала, кратность); ♦ МаксимальныйИнтервал. Признак установки максимально- го интервала последовательности (должна быть уста- новлена единица измерения интервала, кратность); ♦ ИнтервалЭквивалентностиВремени. Признак установки ин- тервала эквивалентности времени (должна быть уста- новлена единица интервала эквивалентности времени, ее кратность);
♦ МинимальнаяДлина — Минимальная длина искомых после- довательностей ♦ ПоискПоИерархии. Признак осуществления поиска по иерар- хии (распространяется на колонки с типом Элемент). Ряд свойств оперирует таким понятием, как ТипЕдиницыИн- тервалаВремениАнализаДанных. Данное системное перечисле- ние содержит следующие значения (табл. 12.7). Контрагент Номенклатура Бондарев Стол кухонный раскладной Петров Стол кухонный раскладной Иванов Стол кухонный раскладной Сидоров Стол кухонный раскладной Степанов Т абурет круглый через 4 недели через 6 недель Бондарев___________| Табурет круглый____________j ,. Петров | Стчл деревянный | . | Иванов | Табчрет круглый | , | Сидоров | Ст^л деревянный I Степанов | Диван мягкий через 2 недели через 5 недель через 5 недель Таблица 12.7. Значения системного перечисления ТипЕдиницыИнтервалаВремениАнализаДанных Секунда Минута ТекущаяМинута Час ТекущийЧас День ТекущийДень Неделя ТекущаяНеделя Декада ТекущаяДекада Месяц ТекущийМесяц Квартал ТекущийКвартал Полугодие ТекущееПолугодие Год ТекущийГод Рис. 12.9. Схема событий Основным результатом анализа являются найденные шаб- лоны последовательностей. Этот шаблон содержит сле- дующую информацию: ♦ состав шаблона последовательности; ♦ количество случаев, в котором наблюдалась данная по- следовательность; ♦ максимальные интервалы между событиями (в случае если событий 2, то интервал один); ♦ минимальные интервалы между событиями (в случае если событий 2, то интервал один); ♦ процент случаев, когда данная последовательность вы- полнилась; ♦ средние интервалы между событиями (в случае если событий 2, то интервал один). Особенности выполнения данного типа анализа рассмот- рим на примере следующей выборки данных (табл. 12.8, рис. 12.9). Данные из колонки Контрагент будут определять принад- лежность к определенной цепочке событий, то есть они определяют последовательность анализа. Номенклатура будет являться элементом получаемой последовательности. Для проведения анализа может использоваться фрагмент кода, аналогичный приведенному ниже (листинг 12.3). Листинг 12.3. Пример выполнения анализа поиск последовательностей Анализ = Новый АнализДанных; Анализ.ТипАнализа = ТипС'АнализДанныхПоискПоследовательностей"): Запрос = Новый Запрос: Запрос.Текст = " ВЫБРАТЬ ПродажиОбороты.Контрагент, ПродажиОбороты.Номенклатура. ПродажиОбороты.Период ИЗ РегистрНакопления.Продажи КАК ПродажиОбороты"; Анализ.ИсточникДанных = Запрос.ВыполнитьО; Анализ.НастройкаКолонок.Период.ТипКолонки = ТипКолонкиАнализаДанныхПоискПоследовательностей.Время: РезультатАнализа = Анализ.ВыполнитьО; Построитель = Новый ПостроительОтчетаАнализаДанныхО; Построитель.Макет = Неопределено; Построитель.ТипАнализа = ТипС'АнализДанныхПоискПоследовательностей”); ТабДок = Новый ТабличныйДокумент; Построитель.Вывести(РезультатАнализа. ТабДок); ТабДок.Показать!); Поле Период определяется как Время непосредственно из кода (самостоятельно анализом не определяется). Параметры анализа, установленные по умолчанию (рис. 12.10). Таблица 12.8. Выборка данных Контрагент Первая покупка Вторая покупка Интервал Бондарев Стол кухонный раскладной Табурет круглый 4 недели Петров Стол кухонный раскладной Стул деревянный 6 недель Иванов Стол кухонный раскладной Табурет круглый 2 недели Сидоров Стол кухонный раскладной Стул деревянный 5 недель Степанов Табурет круглый Диван мягкий 5 недель
Параметры анхлии Минимальный процент случаев Минимальный интервал________________ Максимальный интервал: Интервал эквивалентности времени: Минимальная длина последовательности: я я Рис. 12.10. Параметры анализа После проведения анализа получены следующие «общие данные» (рис. 12.11). Ин формация о данных Количество элементов- 4 Количество последовательностей: 5 Ре зультат анализа Найдено последовательностей: 2| Рис. 12.11. «Общие» данные анализа Количество элементов равно четырем. Ровно столько но- менклатурных позиций встречается в приведенной вы- борке данных. Найдены две последовательности (рис. 12.12). . I Т I _J Na , Количество случаев | Процент случаев Средний интервал интервал интервал Состав 1| 2| 40,00 Номенклатура - Стол кухонный раскладной Номенклатура = Стул деревянный 24 д 12 час 20 д 24 час 27 д 24 час 2| 2| 40,00 Номенклатура - Стол кухонный раскладной Номенклатура = Табурет круглый 21 д 12 час 14* 12час 28д 12 час Рис. 12.12. Найденные последовательности Первая последовательность встречается в 2-х случаях из 5. Исходя их этого процент случаев равен 40 %. Так как глу- бина последовательности равна 2, существует по одному значению каждого из приводимых интервалов. Тип анализа дерево решений С помощью данного типа анализа можно получить при- чинно-следственную иерархию условий, приводящую к определенному решению. Например, получить дерево ус- ловий, по которому (с определенной долей вероятности) можно понять причину расторжения договоров с клиента- ми компании, определения условий, влияющих на вариант заключаемого договора. Можно проводить «профилирова- ние» менеджеров компании по различным видам ее клиен- тов и т. п. Схематично процесс проведения анализа дерево решений можно представить следующим образом (рис. 12.13). ♦ МаксимальнаяГлубина — максимальная глубина дерева; ♦ ТипУпрощения — тип упрощения дерева решений. В результате проведенного анализа можно получить: ♦ дерево решений; ♦ ошибки классификации. Разберемся с особенностью данного типа анализа на при- мере следующей выборки данных (табл. 12.9). Параметры анализа Минимальное количество элементов в узле Максимальная глубина дерева И - база 1С:Предприягие Источник Входная Прогнозируемая Тип упрощения дерева решений Результат анализа Информация о данных Результат анализа Дерево решений Ошибки классификации Таблица 12.9. Исходная выборка данных Вид контрагента Срок работы Количество автомобилей Состояние взаимоотно- шений Оптовик От года до 3 0 Не прекращены Оптовик От года до 3 1 Банкротство Розница От года до 3 0 Прекращены Розница От года до 3 1 Не прекращены Рис. 12.13. Схема выполнения анализа дерево решений С точки зрения данного типа анализа колонки источника можно разделить на: ♦ Неиспользуемая; ♦ Входная; ♦ Прогнозируемая. Используемые параметры анализа: ♦ МинимальноеКоличествоСлучаев — минимальное количест- во элементов в узле; Для проведения анализа может использоваться фрагмент кода, аналогичный приведенному ниже (листинг 12.4). Листинг 12.4. Пример выполнения анализа дерево решений Анализ = Новый АнализДанных; Анализ.ТипАнализа = ТипС'АнализДанныхДеревоРешений"): Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ Контрагенты.Вид, Контрагенты. КоличествоРозничныхТочек, Контрагенты.КоличествоАвтомобилей, Контрагенты.ВремяРаботыОрганизации, Контрагенты.ВремяЗаключенияДоговора. Контрагенты.ПрекрашениеОтношений
| ИЗ I Справочник.Контрагенты КАК Контрагенты |ГДЕ | (НЕ Контрагенты.ЭтоГруппа)’’; Анализ.ИсточникДанных = Запрос.Выполнить(): Анализ.Параметры.ТилУлрощения.Значение = ТипУпрощенияДереваРешений .НеУпрощать; РезультатАнализа = Анализ. ВыполнитьО; Построитель = Новый ПостроительОтчетаАнализаДанныхО: Построитель. Макет = Неопределено; Построитель.ТипАнализа = ТипС'АнализДанныхДеревоРешений"); ТабДок = Новый ТабличныйДокумент; Построитель.Вывести(РезультатАнализа. ТабДок); ТабДок.ПоказатьО; В результате проведения анализа получено следующее дерево решений (рис. 12.14). OiLmBkh классификации Рис. 12.16. Ошибки классификации Дерево решений Условие__________ Корень Вид = Розница КоличествоАвтомобипей <= 0,5 КояичествоАвтомобилей > 0,5 Решение________________ ПрекрашениеОтношений = Не прекрасны______________ ПрекрашениеОтношений = Банкротство____________ ПрекрашениеОтношений = Не прекращены _________ ПрекрашениеОтношений = Банкротство Вид = Оптовик КоличестноАвтомобилей <- 0,5 КояшествоАвтомобилей > 0,5 ПрекраиениеОтношений = Не прекращены______________ ПрекрашениеОтношений = Прекрицение контрагентом ПрекрашениеОтношений = Не прекращены Рис. 12.14. Дерево решений Вероятность 50,00 Количество 50,00 2 100,00 1 100,00 1 Данное дерево можно представить в виде следующей схе- мы (рис. 12.15). Дерево решений Условие Решение Вероятность Количество Корень ПрекрашениеОтношений = Не прекращены 50,00 4 ВОД = Розница ПрекрашениеОтношений = Банкротство 50,00 2 Вцд = Оптовик ПрекрашениеОтношений = Не прекращены 50,00 2 Рис. 12.17. Дерево решений При принятии решения о том, будет произведено преоб- разование узла в лист, учитывается: ♦ Ошибок (О) — количество ошибок в узле; ♦ ОшибокДочерних (ОД) — количество ошибок в дочерних узлах; ♦ Листов (Л) — количество листов в узле; ♦ Случаев (С) — количество случаев. Ошибки классификации показывают, в каких случаях полученные правила расходятся с «действительностью» (исходной выборкой данных) (рис. 12.16). Исходя из приведенных данных видно, что ошибок в по- лученной классификации нет. Предыдущий пример получен исходя из значения НеУпро- щать параметра анализа ТипУпрощения. Если установить это значение в Упрощать, дерево решений примет такой вид (рис. 12.17). Упрощение дерева заключается в том, что по определен- ным правилам (формулам, которые будут рассмотрены ниже) узлы дерева превращаются в листья (отсекается «лишнее» ветвление). СКОшибки = Решение о превращении узла в лист принимается в слу- чае выполнения условия: О + 0,5 < ОД + + СКОшибки. Рис. 12.18. Ошибки классификации
В нашем примере для узлов Вид условие выполняется (0,5 < 1). В связи с использованием упрощений появились и ошиб- ки в классификации, что показано в результате анализа (рис. 12.18). К примеру, существует один случай, когда по полученной классификации «должно» быть значение Банкротство, а в реальной выборке данных было значение Не прекращено и т. п. Тип анализа кластеризация Кластерный анализ — математическая процедура много- мерного анализа, позволяющая на основе множества пока- зателей, характеризующих ряд объектов, сгруппировать их в группы (кластеры) таким образом, чтобы объекты, входя- щие в один кластер, были более однородными, сходными по сравнению с объектами, входящими в другие кластеры. В основе данного анализа лежит вычисление расстояния между объектами. Именно исходя из расстояний между объектами и производится их группировка по кластерам. Определение расстояния может проводиться разными способами (по разным метрикам). Поддерживаются сле- дующие метрики: ♦ Евклидова метрика; ♦ Евклидова метрика в квадрате; ♦ Метрика города; ♦ Метрика доминирования. После определения расстояний между объектами может использоваться один из нескольких алгоритмов распре- деления объектов по кластерам. Поддерживаются сле- дующие методы кластеризации: ♦ Ближняя связь; ♦ Дальняя связь; ♦ Центр тяжести; ♦ «к средних». Схематично механизм проведения кластерного анализа можно представить следующим образом (рис. 12.19). Рис. 12.19. Схема выполнения кластерного анализа На «вход» объекту АнализДанных подается источник данных. В качестве источника может выступать результат запроса, таблица значений, область ячеек табличного документа. Колонки источника определяются как входные либо не используемые. Следует отметить, что все значения колонок содержатся в системном перечислении ТипКолонкиАнализа- ДанныхКластеризация. В этом перечислении значений больше (чем не используемые и входные), но другие значения ис- пользуется при построении прогнозов. Анализ производится в соответствии с установленными параметрами анализа. В качестве примера, иллюстрирующего возможность про- ведения кластерного анализа, будем использовать следую- щий фрагмент кода (листинг 12.5). Листинг 12.5. Пример выполнения кластерного анализа Анализ.ТипАнализа = ТипС'АнализДанныхКластеризация"); Запрос = Новый Запрос; Запрос.Текст = " |ВЫБРАТЬ Контрагенты.КоличествоРозничныхТочек. Контрагенты.КоличествоАвтомобилей |ИЗ Справочник.Контрагенты КАК Контрагенты |ГДЕ (НЕ Контрагенты.ЭтоГруппа) Анализ. ИсточникДанных = Запрос.ВыполнитьО; // выбор метрики Анализ.Параметры.МераРасстояния.Значение = ТипМерыРасстоянияАнализаДанных.ЕвклидоваМетрикаВКвадрате; // выбор метода кластеризации Анализ.Параметры.МетодКластеризации.Значение = МетодКластеризации.КСредних; РезультатАнализа = Анализ.ВыполнитьО; Построитель = Новый ПостроительОтчетаАнализаДанныхО; Построитель.Макет = Неопределено: Построитель.ТипАнализа = ТипС'АнализДанныхКластеризация”): ТабДок = Новый ТабличныйДркумент; Построитель.Вывести(РезультатАнализа, ТабДок); Определим группы контрагентов (запрос выполняется именно по этому справочнику). Обращаем внимание на условие в запросе, которое фак- тически исключает из выборки данных значения Null (в нашем случае КоличествоАвтомобилей и КоличествоРоз- ничныхТочек определены только для элементов справоч- ника Контрагенты). То есть подвергаем анализу только элементы данного справочника. Выполнение указанного кода приведет к тому, что в каче- стве начальных установок анализа данных будут опреде- лены следующие значения (часть установлено явно, часть «по умолчанию») (рис. 12.20).
Па раметры аналиаа Количество искомых кластеров. 3 Стандартизация. Стандартизирова ь Мера расстояния: Евклидова метри а в квадрате Метод кластеризации: Метод к-средних Ко ломки источника данных Вх одные колонки Имя колонки Тип данных Вес КоличествоРозничныхТочек Непрерывный 1 КоличествоАвтомобилей Непрерывный 1 Рис. 12.20. Параметры анализа Состав колонок определился исходя из состава полей вы- борки запроса. По умолчанию они определены с равным «весом». Для типов Число и Дата определен вид данных Не- прерывные, для остальных типов — Дискретные. При необхо- димости изменить параметры колонок это можно сделать по аналогии с приведенным фрагментом (листинг 12.6). Листинг 12.6. Пример изменения параметров колонок Анализ. НастройкаКолонок. КоличествоАвтомобилей. ДополнительныеПараметры.Вес = 2; В данной строке для колонки КоличествоАвтомобилей уве- личен вес. Выборка данных, для которых будет произведен анализ, имеет следующее наполнение (табл. 12.10). Таблица 12.10. Исходная выборка данных Количество автомобилей Количество розничных точек 1 6 2 5 3 4 4 3 5 2 6 1 5 5 Результат анализа будет получен в следующем виде (рис. 12.21). Иь формация о данных Количество объектов 7 Ре >ультат аналиаа Найдено кластеров 3 Кл астеры Иг кластера Количество объектов Процент 1 2 28,57 2 2 28,57' 3 3 42,86| нтры кластеров 1 Поле 1 Кластер 1 Количест в оРозничныхТочек 1,5000 4,00 ОС 5,00001 КоличествоАвтомобилей 5,5000 4.500С 2,00001 Расстояния «между кластерами Кластеры 1 2 3 1 2,2390 7,5662 2 2,2390 2,2390 3 7,5662 2,2390 Рис. 12.21. Результат кластерного анализа Отметим тот факт, что в результате анализа получаются данные именно о найденных кластерах (их количество, центры, расстояния между ними). В результате анализа не получаются данные о том, какие объекты (в нашем случае контрагенты) в какие кластеры входят. Подобное поведение наблюдается в случае, если настройка пара- метров проводимого анализа не проводится явным обра- зом (а именно параметра ТипЗаполненияТаблицы). Для того чтобы в результате анализа увидеть распределе- ние объектов по кластерам, необходимо перед выполне- нием анализа (но после определения его типа) опреде- лить следующую строку кода (листинг 12.7). Листинг 12.7. Установка параметра Т ипЗаполненияТ аблицы Анализ.Параметры.ТипЗаполненияТаблицы.Значение = ТипЗаполненияТаблицыРезультатаАнализаДанных. ИспользуемыеПоля; Используемые метрики Сразу отметим тот факт, что, несмотря на то, что в преды- дущем примере входные колонки имели непрерывный тип (для этого типа очевидно понятие «расстояния»), при анализе могут использоваться и колонки дискретных ти- пов (ссылки на справочники, значения перечислений и т. п.). Разберемся с метриками, которые могут использоваться при проведении кластерного анализа. Евклидова метрика В данной метрике расстояние между двумя объектами вычисляется по формуле: Расстояние = (1^ * (-У, - У, )2), где ♦ Х„ Y, — значения атрибутов двух объектов (между кото- рыми определяется расстояние); ♦ W, — весовой коэффициент атрибута (устанавливается в колонке анализа); ♦ г — номер атрибута, от 1 до и; ♦ п — число атрибутов. Предположим, что объекты характеризуются одним свойством, которое у одного объекта имеет значение 9, у другого 5. Весовой коэффициент данного атрибута ра- вен единице. Расстояние между объектами будет равно: ^(МЦ-б,)2) = 7£(Ь(4)2) = 4. Евклидова метрика в квадрате В данной метрике расстояние между двумя объектами вычисляется по формуле: Расстояние = y^(U^*(X, — У,)2), где ♦ Хь Y, — значения атрибутов двух объектов (между кото- рыми определяется расстояние);
♦ Wj — весовой коэффициент атрибута (устанавливается в колонке анализа); ♦ г — номер атрибута, от 1 до п; • п — число атрибутов. Предположим, что объекты характеризуются одним свойством, которое у одного объекта имеет значение 5, у другого 3. Весовой коэффициент данного атрибута ра- вен двум. Расстояние между объектами будет равно: £(21*(51-31)2)=£(21*(2)2) = 8. Метрика города В данной метрике расстояние между двумя объектами вычисляется по формуле: Расстояние = (И'* | Xt — Pj ), где ♦ Х„ Yj — значения атрибутов двух объектов (между кото- рыми определяется расстояние); ♦ W, — весовой коэффициент атрибута (устанавливается в колонке анализа); ♦ г — номер атрибута, от 1 до и; ♦ п — число атрибутов. Предположим, что объекты характеризуются двумя атри- бутами, которые имеют значения 3 и 5, 7 и 3. Вес первого равен 2, вес второго равен 1 (рис. 12.22). Рис. 12.22. Характеристики объектов Расстояние = 2*(|3—7|)+1*(|5 — 3|) = 10. Метрика доминирования В данной метрике расстояние между двумя объектами вычисляется по формуле: MAX(Wi*\Xi -У,.|), где ♦ X,; Y/ — значения атрибутов двух объектов (между кото- рыми определяется расстояние); ♦ Wj — весовой коэффициент атрибута (устанавливается в колонке анализа); ♦ г — номер атрибута, от 1 до п; * п — число атрибутов. Предположим, что объекты характеризуются двумя атри- бутами, которые имеют значения 3 и 5, и 7 и 3. Вес перво- го равен 2, вес второго равен 1 (см. рис. 10.22). Расстояние = = МАХЩ * (| X, - Y, | ), W2* (| Х2 - У2| )) = = АМХ(2*(|3-7|), 1*(|5 — 3|) = 8. Методы кластеризации Вариант метода кластеризации определяет, исходя из ка- ких «принципов» объект соотносится к той или иной группе, по какому алгоритму производится формирова- ние кластеров. Можно сказать, что целью любого алгоритма кластериза- ции является: ♦ минимизировать изменчивость внутри кластеров; ♦ максимизировать изменчивость между кластерами. Различия между методами будем рассматривать на объ- ектах, представленных на рис. 12.23. Будем считать, что объекты образуют две группы. Первая состоит из объектов 1, 2 и 3. Вторая группа состоит из объектов 4, 5 и 6. Рис. 12.23. Группы объектов Ближняя связь Метод кластеризации, в котором объект присоединяется к той группе, для которой расстояние до ближайшего объекта минимально. В рассматриваемом примере объект 7 будет включен в группу, в которой находится объект 4. Самыми близки- ми объектами двух групп являются объекты 4 и 3. Рас- стояние до объекта 4 минимально. Дальняя связь Метод кластеризации, в котором объект присоединяется к той группе, для которой расстояние до наиболее дальне- го объекта минимально. В рассматриваемом примере объект 7 будет включен в группу, в которой находится объект 5. Самыми дальни- ми объектами двух групп являются объекты 1 и 5. Рас- стояние до объекта 5 меньше. Центр тяжести Метод центр тяжести. Метод кластеризации, в котором объект присоединяется к той группе, для которой рас- стояние до центра тяжести минимально (рис. 12.24). В примере, рассмотренном на рисунке, объект 7 добавит- ся в группу, содержащую объекты 4, 5 и 6. Расстояние до центра тяжести (некого мифического объекта со средни- ми значениями атрибутов) минимально.
Рис. 12.24. Группы объектов «к средних» В данном методе выбираются объекты, находящиеся пер- выми в выборке. Они считаются центрами кластеров. Да- лее выбирается следующий объект и, в соответствии с расстоянием до центров кластеров, относится к тому или иному кластеру. Центр кластера, к которому был добав- лен объект, пересчитывается. Процедура повторяется до полного перебора всех объек- тов. Далее опять производится новая выборка объектов (начиная с первого). Процедура повторяется до тех пор, пока изменяются центры кластеров (рис. 12.25). жду» объектом 1 и 3). Объект 4 добавляется ко второму кластеру (его центр также перерасчитывается). После перебора всех анализируемых объектов к первому кластеру относятся объекты 1 и 3, ко второму остальные объекты (его центр предположительно находится в цен- тре треугольника из объектов 4,7,6). Далее опять производится выборка объектов и распреде- ление их по кластерам (относительно постоянно рассчи- тываемых центров кластеров). Где-то на третьей выборке объектов (скорее всего) объект 2 (который изначально был центром второго кластера) ста- нет относиться к первому кластеру. В конце алгоритма к первому кластеру будут относиться объекты 1,2,3. Ко второму объекты 4,5,6,7. Вывод данных в дендрограмму При выводе данных кластерного анализа, в случае если используется алгоритм, отличный от алгоритма «к сред- них», результаты кластерного анализа выводятся в виде дендрограммы (алгоритм анализа должен предусматри- вать вывод распределения анализируемых объектов по кластерам) (рис. 12.26). Рис. 12.25. Пример расположения объектов Предположим, что произвольно выбраны в качестве цен- тров кластеров объекты 1 и 2. Объект 3 добавляется к кластеру, центром которого является объект 1. Центр первого кластера перерасчитывается (он находится «ме- Рис. 12.26. Дендрограмма Проведение прогнозов Если рассмотреть задачу прогнозирования в общем, то в ней можно выделить две важные части: ♦ обучение модели на какой-либо выборке данных; ♦ использование обученной модели для работы с факти- ческими данными для получения какого-либо прог- ноза Даже в реальной жизни, когда речь идет о каком-либо экспертном заключении можно говорить об этих этапах. Прежде чем давать заключения, прогнозы человек — экс- перт — длительное время учится принимать правильные решения, изучает закономерности в интересующей его прикладной области и т. п. С точки зрения 1 С: Предприятия в качестве такого экс- перта выступает модель прогноза. Данный объект может быть получен только на основании проведенного анализа данных. Можно сказать, что при проведении анализа про- изводится обучение будущей модели прогноза (правиль- нее сказать, что она создается после проведения анализа на некой аналитической выборке). После создания в мо- дель прогноза может быть передана некая фактическая выборка данных, по которой (на основании закономерно- стей, полученных во время анализа) будет построен про- гноз (рис. 12.27). Создание модели прогноза доступно для всех типов ана- лиза за исключением общей статистики. Поставим задачу определить рекомендуемый товар кли- енту, который подобрал уже какой-то набор номенкла- турных позиций. Прогноз будет производить с помощью следующего фрагмента кода (листинг 12.8).
анализ Рис. 12.27. Схема прогнозирования Листинг 12.8. Пример прогнозирования Перем МодельПрогноза; Процедура ПолучитьПрогноз(Кнопка) ТаблицаЗначений = Новым ТаблицаЗначений; МодельПрогноза.ИсточникДанных = Состав. ВыгрузитьО; ТаблицаЗначенийПоследовательности = МодельПрогноза. Выполнить (); Если ТаблицаЗначенийПоследовательности. КоличествоО > 0 Тогда РезультатПрогноза.Очистить(); Для Каждого Строка Из ТаблицаЗначенийПоследовательности Цикл НоваяСтрока = РезультатПрогноза.ДобавитьО; НоваяСтрока.Следствие = Строка.Следствие; НоваяСтрока.Достоверность = Строка.Достоверность; КонецЦикла; КонецЕсли; Если РезультатПрогноза.КоличествоО = 0 Тогда Предупреждение("Предложений нет"); Иначе ЗлементыФормы.РезультатПрогноза.СоздатьКолонки(); КонецЕсли; КонецПроцедуры Процедура ПолучитьМодельПрогноза(Кнопка) Анализ = Новый АнализДанных; Анализ.ТипАнализа = ТипС'АнализДанныхПоискАссоциаций"); Запрос = Новый Запрос: Запрос.Текст = " |ВЫБРАТЬ Продажи.Регистратор. Продажи.Номенклатура |ИЗ РегистрНакопления.Продажи.ОборотыС , , Регистратор) КАК Продажи РезультатЗапроса = Запрос. Выполнить О; Анализ.ИсточникДанных = РезультатЗапроса; РезультатАнализа = Анализ.ВыполнитьО; МодельПрогноза = РезультатАнализа.СоздатьМодельПрогнозаО; КонецПроцедуры РезультатПрогноза.Колонки.Добавить("Следствие", , . 35); РезультатПрогноза.Колонки.Добавить("Достоверность”, , , 5); Обучение модели (переменная модуля МодельПрогноза) производится в процедуре ПолучитьМодельПрогноза(). В ней выполняется анализ (поиск ассоциаций), направ- ленный на выявление одновременно закупаемых пози- ций. После выполнения анализа создается модель про- гноза. Сам прогноз осуществляется в процедуре ПолучитьПрог- ноз(). Считается, что номенклатурные позиции, которые уже подобрал себе покупатель, находятся в табличной части Состав (в ней определен реквизит Номенклатура). Кроме этого, в диалоге формы определен элемент управ- ления ТабличноеПоле (имя РезультатПрогноза, тип Таблица- Значений), в который и производится вывод полученного прогноза: какой товар чаще всего закупается совместно с теми, которые уже выбрал покупатель. Модель прогноза Модель прогноза обладает определенными свойствами, с помощью которых можно управлять проводимым про- гнозом. При работе с коллекцией колонок Колонки можно указы- вать следующие типы колонок (значение системного пе- речисления ТипКолонкиМоделиПрогноза): ♦ Входная; ♦ КолонкаИсточникаДанных; ♦ Прогнозируемая. Следует отметить, что для кластерного анализа в коллек- ции Колонки определено свойство ДополнительныеПараметры (определяется вес колонки и значение нормализации). Коллекция НастройкаВходныхКолонок содержит описание со- ответствия колонок источника данных (по которому строится прогноз) колонкам модели прогноза. Коллекция КолонкиРезультата содержит колонки, выводи- мые в результат прогноза. Пример работы с данными ко- лонками приведен в листинге 12.9. Листинг 12.9. Пример работы с колонками модели прогноза МодельПрогноза.КолонкиРезультата.Добавить( МодельПрогноза.Колонки.Найти("Следствие”, ТипКолонкиМоделиПрогноза.Прогнозируемая)); МодельПрогноза.КолонкиРезультата.Добавить( МодельПрогноза.Колонки.Найти("Достоверность", Т ипКолонкиМоделиПрогноза.Прогнозируемая)):
Глава 13. Средства построения отчетов Общее описание средств для построения отчетов По большому счету, информационная база, создаваемая с помощью системы ЮПредприятие, выполняет две ос- новные задачи: ♦ ввод и хранение информации; ♦ получение и представление обобщенных (итоговых) данных о хранимой информации в различных разрезах. Важным моментом является то, что получение обобщен- ных данных, как правило, является не только «конечной» задачей, но и требуется в процессе ввода данных в инфор- мационную базу. Например, при вводе расходной наклад- ной обычно контролируются остатки товаров на складах, это означает, что для правильного ввода новых данных (информации о проданных товарах) требуется получение обобщенных данных (текущего количества товаров на складах). Система 1С:Предприятие содержит различные средства для получения обобщенных данных и создания различно- го рода отчетов. Отличительной особенностью является то, что совокупность этих средств представляют собой определенную иерархию, состоящую из нескольких уров- ней их использования. Также примечательным фактом является то, что часть средств для построения отчетов может быть использована не только разработчиком, но и конечным пользователем системы. Самым нижним уровнем иерархии средств для построения отчетов является уровень встроенного языка ЮПред- приятия. На этом уровне основным инструментом для получения информации из базы данных является язык за- просов. С его помощью можно получать сложные выборки данных, используя группировки, сортировку, построение итогов и т. д. Полученные таким образом данные могут быть впоследствии представлены пользователю с помощью различных объектов системы: текстовый документ, таблич- ный документ, географическая схема, сводная таблица, диа- грамма, сводная диаграмма и диаграмма Ганта (рис. 13.1). Рис. 13.1. Средства отображения данных, полученных с помощью языка запросов Можно сказать, что написание текста запроса, его выпол- нение и последующий вывод в какой-либо из перечислен- ных объектов является самым низшим уровнем работы с объектами встроенного языка. Наряду с этим встроенный язык содержит ряд объектов, которые позволяют разработчику организовывать инте- рактивное взаимодействие с пользователем в процессе формирования запроса и вывода полученных данных. К таким «интеллектуальным» объектам относятся по- строитель отчета и объекты, составляющие механизм ана- лиза данных (рис. 13.2). Рис. 13.2. Уровень встроенного языка Основой работы построителя отчета является текст за- проса, который перед выполнением может быть изменен пользователем в режиме Ю: Предприятия. Таким обра- зом, пользователь может настроить запрос, который бу- дет выполняться «под себя», указав нужные группиров- ки, выводимые поля, расположение полей в строках и колонках отчета и пр. Механизм анализа данных позволяет анализировать дан- ные, полученные из базы данных, используя различные виды анализа данных, а также строить прогнозы на осно- ве создаваемых моделей. В состав механизма анализа данных входит специальный объект (построитель отчета анализа данных), позволяющий пользователю настраи- вать анализ данных и получать результаты анализа в удоб- ном для восприятия виде. Результаты анализа данных могут быть отображены с ис- пользованием табличного документа, диаграммы и денд- рограммы. Данные, полученные с помощью построителя отчета, также могут быть выведены в табличный доку- мент, а кроме этого, в сводную таблицу, диаграмму и свод- ную диаграмму (рис. 13.3). Рис. 13.3. Представление данных, полученных с помощью построителя отчета и механизма анализа данных
Более подробно о построителе отчета можно прочитать в разделе «Построитель отчета», с. 415. Механизмы ана- лиза данных подробно описаны в главе 12 «Использование механизма анализа данных и прогнозирования», с. 398. Следующим уровнем средств для построения отчетов яв- ляется уровень визуального конструирования. На этом уровне используются два инструмента: конструктор за- проса и конструктор выходной формы (рис. 13.4). Уровень визуального Рис. 13.4. Уровень визуального конструирования Конструктор запроса позволяет составлять текст запроса исключительно визуальными средствами. С помощью мыши разработчик перетаскивает нужные таблицы, поля, устанавливает связи межу таблицами и т. д. В результате конструктор создает синтаксически правильный текст за- проса, который остается только вставить в нужное место модуля. Таким образом, разработчик может составить ра- ботоспособный запрос, даже не владея синтаксисом язы- ка запросов — необходимые синтаксические конструкции конструктор сгенерирует автоматически. Кроме этого конструктор позволяет редактировать текст запроса, ко- торый уже имеется в программе, — достаточно устано- вить курсор в тексте запроса и вызвать конструктор. Конструктор выходной формы представляет собой еще более универсальный инструмент. Он позволяет создать полностью готовый отчет: форму, макет, набор связанных процедур, которые могут располагаться в различных мо- дулях. В своей работе для создания текста отчета конст- руктор выходной формы использует конструктор запро- са. В качестве инструмента для получения данных он может использовать как запрос, так и построитель запро- са, включая всю его интерактивную функциональность. Отчет, созданный с помощью конструктора выходной формы, может использовать для представления получен- ных данных табличный документ, сводную таблицу, диа- грамму и сводную диаграмму (рис. 13.5). Третьим, самым верхним уровнем средств для построе- ния отчетов является интерактивный уровень. На этом уровне в режиме 1 С:Предприятия используются две внеш- ние обработки — консоль запросов и консоль отчетов (рис. 13.6). Использование этих обработок позволяет создавать отче- ты, не изменяя конфигурацию, прямо в режиме ^Пред- приятия. Рис. 13.5. Представление данных с помощью конструктора выходной формы Рис. 13.6. Интерактивный уровень Консоль запросов предназначена в основном для разра- ботчиков и для опытных пользователей. С помощью этой обработки можно составить текст запроса, выполнить его и проанализировать полученные результаты. Для получе- ния данных консоль запросов использует объект встроен- ного языка Запрос, а в процессе работы может быть вызван конструктор запроса, что позволяет создавать текст за- проса средствами визуального конструирования. Обработка консоль отчетов предназначена в основном для опытных пользователей и позволяет создавать и оформлять отчеты любой сложности. Для получения дан- ных консоль отчетов использует построитель отчета. Результаты работы консоли запросов могут быть выведе- ны в табличный документ и сводную таблицу. Консоль от- четов также может использовать эти объекты для вывода результатов, и, кроме этого, позволяет выводить получен- ные данные в диаграмму и сводную диаграмму (рис. 13.7). Рис. 13.7. Представления результатов консолью запросов и консолью отчетов
Построитель отчета Построитель отчета является объектом встроенного язы- ка, который позволяет выполнять настройку запроса в ре- жиме 1 С:Предприятие (интерактивно или программно), выполнять запрос и выводить результат запроса в таб- личный документ, сводную таблицу или диаграмму. Кро- ме этого, построитель отчета позволяет обрабатывать и выводить данные, полученные из произвольного источ- ника данных (например, таблицы значений или набора записей регистра). Основой для работы построителя отчета является текст за- проса, который предназначается для модификации в режиме ЮПредприятие и последующего выполнения (рис. 13.8). Рис 13.8. Схема использования построителя отчета Для вывода результата запроса построитель отчета само- стоятельно генерирует макет или может использовать ма- кет, назначаемый разработчиком. Модификация текста запроса может выполняться как интерактивно пользова- телем, так и программно. Для того чтобы пользователь или разработчик могли модифицировать текст запроса, построитель отчета содержит ряд свойств, позволяющих динамически изменять запрос. Эти свойства называются настройками построителя отчета (рис. 13.9). Настройки Отбор Измерения строки Выбранные поля Порядок Измерения колонки Условное оформление Рис. 13.9. Настройки построителя отчета При помощи настроек можно выполнять следующие из- менения текста запроса построителя отчета: ♦ свойство Отбор позволяет изменять условия, наклады- ваемые на поля из списка выборки; ♦ свойство Порядок позволяет изменять условия и поря- док сортировки результата запроса; ♦ свойство Выбранные поля позволяет изменять состав по- лей, выводимых в результат запроса; ♦ свойства Измерения строки и Измерения колонки позволяют управлять расположением группировок в строках или колонках итогового отчета; ♦ свойство УсловноеОформление позволяет оформлять ито- говый отчет в зависимости от данных, содержащихся в отчете. Рис 13.10. Обработка ПостроительОтчета
Для того чтобы наглядно продемонстрировать, каким об- разом настройки построителя отчета позволяют изменять текст запроса, воспользуемся обработкой ПостроительОт- чета, которая находится на прилагаемом компакт-диске. Настройки построителя отчета могут быть выбраны в ка- честве источника данных табличных полей, расположенных в форме. Это позволяет легко создавать формы отчетов, предоставляя пользователю возможность настраивать за- прос в зависимости от своих требований. Запустим обработку, нажмем Выполнить, Текст запроса и перейдем на закладку Текст запроса (рис. 13.10). Рис. 13.11. Изменение отбора построителя отчета Обработка Построитель отчета _ П X Рис. 13.12. Изменение порядка построителя отчета
В нижнем поле представлен текст запроса, который был передан построителю отчета. В верхней части формы рас- положены поля настроек. Сейчас наша цель состоит в том, чтобы продемонстрировать суть работы построителя отчета, поэтому пока мы не будем останавливаться на том, как построителю отчета был передан текст запроса и каким образом были заполнены настройки построителя отчета в соответствии с текстом запроса. Итак, как уже было сказано, свойство Отбор позволяет изменять условия, накладываемые на поля из списка выборки. Добавим в табличное поле Отбор новое поле Качество. В данном случае это одно из измерений реги- стра накопления Товары на складах. Установим условие: Качество равно новый. Нажмем кнопку Текст запроса и по- смотрим, какие изменения произошли в тексте запроса (рис. 13.11). Построитель отчета добавил в параметры виртуальной таблицы РегистрНакопления.ТоварыНаСкладах.Обороты условие на измерение Качество регистра накопления. Свойство Порядок позволяет изменять условия и порядок сортировки результата запроса. Если в табличное поле Порядок добавить сортировку по убыванию кода номенк- латуры, то построитель отчета добавит в текст запроса предложение УПОРЯДОЧИТЬ ПО (рис. 13.12). Если изменить порядок полей в измерениях строки и ука- зать нужный тип измерения, то построитель отчета вы- полнит соответствующие изменения в секции описания итогов запроса (рис. 13.13). Добавление или удаление выбранных полей будет приво- дить к соответствующим изменениям в предложении за- проса ВЫБРАТЬ. В нашем случае при удалении поля Количе- ствоРасход построитель отчета удалит это поле из секции описания (рис. 13.14). Добавление полей в настройки построителя отчета может выполняться как интерактивно, так и программно. И в том и в другом случае, система разрешит добавить только те поля, которые соответствующим образом описаны в дос- тупных полях построителя отчета (свойство ДоступныеПоля). Доступные поля представляют собой коллекцию полей настройки, которая может формироваться построителем запроса автоматически (на основании анализа исходного текста запроса) и которая также может модифицировать- ся средствами встроенного языка. Каждое поле настрой- ки, входящее в эту коллекцию, имеет ряд свойств, кото- рые задают возможность выбора этого поля в качестве поля отбора, поля порядка, поля измерения или выбран- ного поля. Возможность выбора полей для задания условий оформления определяется также на основании перечис- ленных свойств. Более подробно об этом рассказывается в разделе «Доступные поля», с. 426. На рис. 13.15 пред- ставлены доступные поля, сформированные построите- лем запроса автоматически, на основании анализа текста запроса из предыдущего примера. Обратите внимание, что в некоторых случаях доступные поля позволяют выбирать не только сами поля, описан- ные в этой коллекции, но и их подчиненные поля (через точку). При начальном заполнении настроек построителя отчета разработчик может указать возможность выбора подчиненных полей у тех или иных полей (это будет рас- смотрено далее). Добавление доступных полей интерактивными средства- ми невозможно. При начальном заполнении настроек по- строителя отчета он формирует список доступных полей, и в дальнейшем пользователь может использовать их только для выбора в настройки построителя отчета. Од- нако средствами встроенного языка можно модифициро- Рис. 13.13. Изменение измерений построителя отчета
Рис. 13.14. Изменение выбранных полей построителя отчета Рис. 13.15. Доступные поля построителя отчета вать состав доступных полей, что может быть использо- вано для более тонкой настройки построителя отчета. Построитель отчета имеет методы получения и установки настроек, таким образом, настройки, однажды созданные пользователем, могут быть сохранены и использованы в дальнейшем. Для получения настроек построителя отчета используется метод ПолучитьНастройкиО. Этот метод возвращает значение типа НастройкиПостроите- ляОтчета, которое может быть сериализовано, то есть со- хранено методами СохранитьЗначение и ЗначениеВФайл или помещено в объект ХранилищеЗначения. В методе Получить-
Настройки О можно указать, следует ли получать отбор, по- рядок, измерения, выбранные поля построителя отчета и условное оформление. Для установки построителю отчета сохраненных ранее настроек используется метод УстановитьНастройкиО. Этот метод также позволяет указывать, следует ли устанавли- вать каждую из настроек построителя отчета или нет. Автоматическое заполнение настроек построителя отчета Первоначальное заполнение настроек построителя отчета может быть выполнено несколькими способами. Пер- вый — это автоматическое заполнение на основе текста запроса, передаваемого построителю отчета. Исходный текст запроса передается построителю отчета че- рез свойство Текст. После того как текст передан, необходимо выполнить метод ЗаполнитьНастройкиО. В результате выпол- нения этого метода текст запроса будет проанализирован, и настройки будут установлены по следующим правилам: ♦ в доступные поля будут добавлены: все поля из списка выборки (предложение ВЫБРАТЬ) с возможностью выбора подчиненных полей и при- знаками, что они могут выбираться в порядок, отбор и выбранные поля; все поля из предложения ИТОГИ ПО с возможностью выбора подчиненных полей и признаком, что они мо- гут выбираться в измерения строки и измерения ко- лонки; * все параметры виртуальных таблиц (расположенных на верхнем уровне запроса) с признаком, что они мо- гут выбираться в отбор; измерения виртуальных таблиц (расположенных на верхнем уровне запроса), которые могут быть исполь- зованы в параметре Условие виртуальной таблицы, с признаком, что они могут выбираться в отбор; ♦ в измерения строки будут добавлены: поля из предложения ИТОГИ ПО; ♦ в выбранные поля будут добавлены: * поля из списка выборки (предложение ВЫБРАТЬ). Например, выполнение следующего кода (листинг 13.1) приведет к тому, что настройки построителя отчета будут заполнены так, как показано в табл. 13.1-13.3. Листинг 13.1. Автоматическое заполнение настроек построителя отчета ТекстЗапроса = "ВЫБРАТЬ ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОбороты.Склад КАК Склад, СУММА(ТоварыНаСкладахОбороты. КоличествоПриход) КАК КоличествоПриход, СУММАСТоварыНаСкл ад ахОбороты. КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах. Обороты КАК ТоварыНаСкладахОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОбороты. Склад, ТоварыНаСкладахОбороты. Номенклатура |ИТОГИ ПО ОБЩИЕ. | Склад, Номенклатура" Построитель = Новый ПостроительОтчета(ТекстЗапроса): Построитель.ЗаполнитьНастройки(); Таблица 13.1. Заполнение доступных полей построителя отчета Поле Причина включения в доступные поля Номенклатура Входит в состав полей из списка выборки Склад Входит в состав полей из списка выборки КоличествоПри- ход Входит в состав полей из списка выборки КоличествоРас- ход Входит в состав полей из списка выборки НачалоПериода Параметр виртуальной таблицы РегистрНакопления.ТоварыНаСкладах.Обороты КонецПериода Параметр виртуальной таблицы РегистрНакопления.ТоварыНаСкладах.Обороты Периодичность Параметр виртуальной таблицы РегистрНакопления.ТоварыНаСкладах.Обороты Характеристика- Номенклатуры Измерение виртуальной таблицы РегистрНакопления.ТоварыНаСкладах.Обороты Серия- Номенклатуры Измерение виртуальной таблицы РегистрНакопления.ТоварыНаСкладах.Обороты Качество Измерение виртуальной таблицы РегистрНакопления.ТоварыНаСкладах.Обороты Таблица 13.2. Заполнение измерений строк построителя отчета Поле Причина включения в измерения строки Склад Входит в состав полей из предложения ИТОГИ ПО Номенклатура Входит в состав полей из предложения ИТОГИ ПО Таблица 13.3. Заполнение выбранных полей построителя отчета Поле Причина включения в выбранные поля Склад Входит в состав полей из списка выборки Номенклатура Входит в состав полей из списка выборки Количество- Приход Входит в состав полей из списка выборки КоличествоРас- ход Входит в состав полей из списка выборки
Заполнение настроек построителя отчета с использованием языка запросов построителя отчета Вторым способом, используемым для заполнения настроек построителя отчета, является использование в исходном тексте запроса специальных синтаксических конструк- ций, предназначенных для анализа построителем отчета. Такие конструкции заключаются в фигурные скобки {...} и содержат предложения, написанные на языке запросов построителя отчета. Эти конструкции игнорируются при обычном выполнении запроса и служат только для уста- новки настроек построителя отчета. После того как текст запроса, содержащий управляющие конструкции на языке запросов построителя отчета, будет установлен в качестве значения свойства Текст построителя отчета, соответст- вующие настройки станут доступны для интерактивного или программного изменения. Ключевые слова языка запросов построителя отчета В общем случае предложение языка запросов построите- ля отчетов имеет следующий синтаксис: {КЛЮЧЕВОЕСЛОВО «список полей>} Язык запросов построителя отчета содержит всего четы- ре ключевых слова для построения предложений: ВЫБРАТЬ, ГДЕ, УПОРЯДОЧИТЬ ПО и ИТОГИ ПО. Далее мы рассмотрим их бо- лее подробно. «список полей> представляет собой перечисление, через за- пятую, полей, которые будут доступны в настройках по- строителя отчета. В качестве этих полей могут быть ис- пользованы как поля таблиц исходного запроса, так их псевдонимы. Для каждого поля допускается указание псевдонима для построителя запроса, используя ключе- вое слово КАК (листинг 13.2). Листинг 13.2. Пример использования псевдонима поля {ВЫБРАТЬ Склад КАК МестоХранения} После имени поля может использоваться конструкция «.*». Применение этой конструкции означает, что в на- стройках построителя отчета может быть выбрано не только само указанное поле, но и все подчиненные поля, то есть поля «через точку» от данного поля (лис- тинг 13.3). Листинг 13.3. Пример указания использования подчиненных полей {ВЫБРАТЬ Номенклатура.* КАК Товар} Ключевое слово ВЫБРАТЬ Ключевое слово ВЫБРАТЬ позволяет описать поля, которые будут доступны для выбора в качестве выбранных полей построителя отчета. Если поля, перечисленные в этом предложении, совпада- ют с полями выборки запроса или с их псевдонимами, то эти поля также автоматически будут добавлены в вы- бранные поля построителя отчета. Например, в следующем примере поля Товар, Склад и При- ход будут добавлены в доступные поля и в выбранные поля построителя отчета (листинг 13.4). Листинг 13.4. Пример использования ключевого слова ВЫБРАТЬ ВЫБРАТЬ {ВЫБРАТЬ Номенклатура КАК Товар, Склад. КоличествоПриход КАК Приход} ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура. ТоварыНаСкладахОбороты.Склад КАК Склад, СУММА(ТоварыНаСкладахОбороты.КоличествоПриход) КАК КоличествоПриход, СУММА(ТоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоРасход. В следующем примере (листинг 13.5) поля Товар, Склад и Приход также будут добавлены в доступные поля и в выбранные поля построителя отчета, но кроме этого в доступных полях будет существовать возможность вы- брать также и все поля, подчиненные полю Номенклатура (рис. 13.16). Листинг 13.5. Пример использования ключевого слова ВЫБРАТЬ ВЫБРАТЬ {ВЫБРАТЬ Номенклатура.* КАК Товар, Склад, КоличествоПриход КАК Приход} ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОбороты.Склад КАК Склад, СУММАСТоварыНаСкладахОбороты.КоличествоПриход) КАК КоличествоПриход, СУММАСТоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоРасход, Пометка удаления Поедежмое не»»с*1 Е Родитель Это группа Код ...Наименование Полное наименование Артикул Е Единица хранения остатков Е-Базовая единица измерения Ё Ставка НДС . Комментарии f - Услуга Набор Е Номенклатурная группа Е Номенклатурная группа i..Весовой коэффициент вхождения Вести учет по характеристикам * Вести учет по сериям Ё Ответственный менеджер за покупки Ё- Основной поставщик Ё Статья затрат Ё- Основное изображение Е - Страна происхождения Ё Номер ГТД Ё- Единица для отчетов 1..Весовой Ё Тип штрихкода Рис. 13.16. Подчиненные поля поля Товар Обратите внимание, что в качестве имен полей, доступ- ных для выбора, выводятся синонимы реквизитов спра- вочника Номенклатура.
Ключевое слово ГДЕ Ключевое слово ГДЕ позволяет описать поля, которые будут доступны для выбора в качестве отбора построите- ля отчета. Поля, описанные в этом предложении, будут добавлены только в доступные поля построителя отчета. Например, в следующем примере (листинг 13.6) поле Артикул будет добавлено в доступные поля для выбора в отбор построителя отчета. Листинг 13.6. Пример использования ключевого слова ГДЕ ВЫБРАТЬ ТоварыНаСкладах.Номенклатура КАК Номенклатура, ТоварыНаСкладах.Склад КАК Склад, ТоварыНаСкладах.Количество КАК Количество ИЗ РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах {ГДЕ ТоварыНаСкладах.Номенклатура.Код КАК Артикул) ИТОГИ ПО ОБЩИЕ, Склад, Номенклатура Ключевое слово УПОРЯДОЧИТЬ ПО Ключевое слово УПОРЯДОЧИТЬ ПО позволяет описать поля, которые будут доступны для выбора в качестве порядка построителя отчета. Если поля, описанные в этом предложении, совпадают с полями, перечисленными в соответствующем предло- жении запроса, и в предложении построителя отчета для них не заданы псевдонимы, — они будут автоматически добавлены в порядок построителя отчета с теми условия- ми, которые указаны в тексте запроса. Например, в следующем примере (листинг 13.7) поле Но- менклатура будет добавлено в доступные поля для выбора в порядок построителя отчета, и кроме этого, в доступных полях будет существовать возможность выбрать также и все поля, подчиненные полю Номенклатура. Листинг 13.7. Использование ключевого слова УПОРЯДОЧИТЬ ПО ВЫБРАТЬ ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОбороты.Склад КАК Склад, СУММА(ТоварыНаСкладахОбороты. КоличествоПриход) КАК КоличествоПриход, СУММА(ТоварыНаСкладахОбороты. КоличествоРасход) КАК КоличествоРасход, ТоварыНаСкладахОбороты. Номенклатура. Код КАК НоменклатураКод ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты( , , . ) КАК ТоварыНаСкладахОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОбороты. Склад, ТоварыНаСкладахОбороты. Номенклатура {УПОРЯДОЧИТЬ ПО Номенклатура.*} Ключевое слово ИТОГИ ПО Ключевое слово ИТОГИ ПО позволяет описать поля, которые будут доступны для выбора в качестве измерений строки и измерений колонки построителя отчета. Если поля, описанные в этом предложении, совпадают с полями, перечисленными в соответствующем предло- жении запроса, и в предложении построителя отчета для них не заданы псевдонимы, — они будут автоматически добавлены в измерения строки построителя отчета. Например, в следующем примере (листинг 13.8) поля Склад и Товар будут добавлены в доступные поля для вы- бора в измерения строки или измерения колонки по- строителя отчета. Листинг 13.8. Использование предложения ИТОГИ ПО ВЫБРАТЬ ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОбороты.Склад КАК Склад, СУММА(ТоварыНаСкладахОбороты.КоличествоПриход) КАК КоличествоПриход, СУММА(ТоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоРасход, ТоварыНаСкладахОбороты.Номенклатура.Код КАК НоменклатураКод ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты(, , , ) КАК ТоварыНаСкладахОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОбороты.Склад. ТоварыНаСкладахОбороты.Номенклатура ИТОГИ ПО {ИТОГИ ПО Склад КАК Склад, Номенклатура КАК Товар) ОБЩИЕ, Склад, Номенклатура Предложения языка запросов построителя отчета без ключевых слов Предложения языка запросов построителя отчета могут и не содержать ключевых слов. Такой способ используется для передачи построителю отчета параметров вирту- альных таблиц. Например, в следующем примере (лис- тинг 13.9) для отбора станут доступны поля НачалоПери- да, КонецПериода, Склад и поле Номенклатура с возможно- стью выбора подчиненных полей. Листинг 13.9. Указание параметров виртуальных таблиц "ВЫБРАТЬ ТоварыНаСкладахОбороты.Склад. ТоварыНаСкладахОбороты.Склад.Представление, | ТоварьНаСкладахОбороты.Номенклатура, ТоварыНаСкладахОбороты.Номенклатура.Представление, ТоварыНаСкладахОбороты.КоличествоПриход, | ТоварыНаСкладахОбороты.КоличествоРасход |ИЗ | РегистрНакопления.ТоварыНаСкладах.Обороты({&НачалоПериода}, &КонецПериода), , {Номенклатура.*, Склад}) | КАК ТоварыНаСкладахОбороты"; Условное включение таблиц в результирующий запрос С помощью конструкции {...} можно выделять не только отдельные параметры, но и целые части соединения, со- держащие таблицы. В этом случае построитель отчета бу- дет включать выделенную часть соединения в результи- рующий запрос только в том случае, если в настройках построителя отчета будут задействованы какие-либо
поля из выделенной таблицы соединения. Например, пусть имеется следующее описание левого соединения с вирту- альной таблицей РегистрНакопления.ТоварыНаСкладах.Остатки (листинг 13.10). Если пользователь захочет посмотреть только список но- менклатуры в порядке артикулов, будет сформирован следующий запрос (листинг 13.11). Однако если пользователь захочет посмотреть также и ос- татки номенклатуры, текст запроса значительно изменится и будет задействовано левое соединение с виртуальной таблицей остатков (листинг 13.12). Листинг 13.10. Текст исходного запроса "ВЫБРАТЬ {ВЫБРАТЬ СправочникНоменклатура.Ссылка КАК Товар, СправочникНоменклатура.Артикул КАК Артикул. ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток) СправочникНоменклатура.Ссылка. СлравочникНоменклатура.Представление, СправочникНоменклатура.Артикул, ТоварыНаСкладахОстатки.КоличествоОстаток ИЗ Справочник.Номенклатура КАК СправочникНоменклатура {ЛЕВОЕ СОЕДИЕНИЕ РегистрНакопления. ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки ПО ТоварыНаСкладахОстатки.Номенклатура = СправочникНоменклатура.Ссылка) {ГДЕ СправочникНоменклатура.Ссылка КАК Товар) ГДЕ СправочникНоменклатура.ЭтоГруппа = Ложь {УПОРЯДОЧИТЬ ПО СправочникНоменклатура.Артикул КАК Артикул, СправочникНоменклатура.Ссылка КАК Товар) {ИТОГИ ПО СправочникНоненклатура.Ссылка.* КАК Товар) ИТОГИ Сумма(ТоварыНаСкладахОстатки.КоличествоОстаток) ПО ОБЩИЕ АВТОУПОРЯДОЧИВАНИЕ" Листинг 13.11. Результирующий запрос без левого соединения ВЫБРАТЬ СправочникНоменклатура.Ссылка КАК Ссылка, СправочникНоменклатура.Представление КАК Представление, СправочникНоменклатура.Артикул КАК Артикул ИЗ Справочник.Номенклатура КАК СправочникНоменклатура ГДЕ (СправочникНоменклатура.ЭтоГруппа = ЛОЖЬ) УПОРЯДОЧИТЬ ПО СправочникНоменклатура.Артикул ИТОГИ ПО ОБЩИЕ АВТОУПОРЯДОЧИВАНИЕ Листинг 13.12. Результирующий запрос с левым соединением ВЫБРАТЬ СправочникНоменклатура.Ссылка КАК Ссылка, СправочникНоменклатура.Представление КАК Представление, СправочникНоменклатура.Артикул КАК Артикул. ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток ИЗ Справочник.Номенклатура КАК СправочникНоменклатура ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления. Тов арыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки ПО ТоварыНаСкладахОстатки.Номенклатура = СправочникНоменклатура.Ссылка ГДЕ (СправочникНоменклатура.ЭтоГруппа = ЛОЖЬ) УПОРЯДОЧИТЬ ПО СправочникНоменклатура.Артикул ИТОГИ СУММА(КоличествоОстаток) ПО ОБЩИЕ АВТОУПОРЯДОЧИВАНИЕ Использование повторяющихся псевдонимов в языке запросов построителя отчета В отличие от языка запросов язык запросов построителя отчета допускает использование повторяющихся псевдо- нимов. Повторяющиеся псевдонимы могут быть исполь- зованы для того, чтобы облегчить пользователю выбор полей, выводимых в отчет. Если несколько полей имеют одинаковые псевдонимы, то выбор пользователем этого псевдонима в качестве, например, выбранного поля будет равносилен тому, что он выбрал бы каждое из полей, имеющих этот псевдоним в выбранные поля. Например, в следующем запросе (листинг 13.13) пользо- вателю будет предложено выбрать в качестве выбранных полей Товар, Склад, Остатки и Обороты. Листинг 13.13. Пример использования повторяющихся псевдонимов ВЫБРАТЬ {ВЫБРАТЬ Номенклатура КАК Товар, СкладКомпании КАК Склад, КоличествоНачальныйОстаток КАК Остатки, КоличествоКонечныйОстаток КАК Остатки, КоличествоОборот КАК Обороты, КоличествоПриход КАК Обороты. КоличествоРасход КАК Обороты) ОстаткиТоваровКомпанмиОстаткиИОбороты.Номенклатура КАК Номенклатура, ОстаткиТоваровКомпанииОстаткиИОбороты.Номенклатура. Представление, ОстаткиТоваровКомпанииОстаткиИОбороты.СкладКомпании КАК СкладКомпании, ОстаткиТоваровКомпанимОстаткиИОбороты.СкладКомпании. Представление, СУММА(ОстаткиТоваровКомпанииОстаткиИОбороты. КоличествоНачальныйОстаток) КАК КоличествоНачальныйОстаток, СУММА(ОстаткиТоваровКомпанииОстаткиИОбороты. КоличествоКонечныйОстаток) КАК КоличествоКонечныйОстаток, СУММА(ОстаткиТоваровКомпанииОстаткиИОбороты. КоличествоОборот) КАК КоличествоОборот, СУММА(ОстаткиТоваровКомпанииОстаткиИОбороты. КоличествоПриход) КАК КоличествоПриход, СУММА(ОстаткиТоваровКомпанииОстаткиИОбороты. КоличествоРасход)
КАК КоличествоРасход ИЗ РегистрНакопления.ОстаткиТоваровКомпании.ОстаткиИОбороты КАК ОстаткиТоваровКоипанииОстаткиИОбороты СГРУППИРОВАТЬ ПО ОстаткиТоваровКомпанииОстаткиИОбороты.СкладКонпании, ОстаткиТоваровКомпанииОстаткиИОбороты.Номенклатура, ОстаткиТоваровКонпанииОстаткиИОбороты.Номенклатура. Представление, ОстаткиТоваровКонланииОстаткиИОбороты.СкладКомпании. Представление УПОРЯДОЧИТЬ ПО СкладКомпании. Номенклатура ИТОГИ СУММА(КоличествоНачальныйОстаток), СУММА(КоличествоКонечныйОстаток), СУММА(КоличествоОборот), СУММА(КоличествоПриход), СУММА(КоличествоРасход) ПО {ИТОГИ ПО Номенклатура КАК Товар, СкладКомпании КАК Склад} ОБЩИЕ. Номенклатура, СкладКомпании При этом если пользователь выберет в качестве выбран- ных полей Товар, Склад и Остатки (рис. 13.17), то в результат запроса будут выведены оба поля, имеющие псевдоним Остатки — КоличествоНачальныйОстаток и КоличествоКонеч- ныйОстаток: (рис. 13.18). Рис. 13.17. Выбранные поля _ П х В В В В в |склад _ ~ Главный склад Торговый тал Склад электротоваров Розничный магазин Ns 1 Розничный магазин № 2 Розничный магазин № 2 Розничный магазин № 2 Розничный магазин № 2 Розничный магазин № 2 Розничный магазин № 2 Итог__________________ (Товар Вилы Метла Лопата Мотоблок Грабли [Остатки |Остатки^ 12 878,000 6 069,000 2 961,000 998,000 2 825,000 25,000 10,000 5,000 4,000 6,000 Рис. 13.18. Сформированный отчет Однако при использовании стандартного макета, который формирует построитель отчета, в заголовок обеих колонок будет выведен псевдоним. Таким образом, пользователь не сможет понять назначение каждой из колонок. Поэтому нужно изменять макет, создаваемый построите- лем отчета по умолчанию. В нашем случае достаточно бу- дет назначить правильные заголовки колонок отчета. Для этого следует внести изменения в макет, сформирован- ный построителем отчета, заменив заголовки, сформиро- ванные автоматически, на те, которые будут понятны пользователю (листинг 13.14). Листинг 13.14. Изменение заголовков в макете Построитель.Выполнить(); // Прервать автоматическое формирование макета // построителем отчета Построитель.Макет = Неопределено: Макет = Построитель.Макет: ТекущаяОбласть = Неопределено: // Если пользователь выбрал поле Остатки, // заменить в макете надпись Остатки Если Построитель.ВыбранныеПоля.Найти("Остатки") <> Неопределено Тогда ТекущаяОбласть = Макет.НайтиТекстС"Остатки", ТекущаяОбласть, Макет.ОбластьО, Истина, Истина, Истина, Ложь); ТекущаяОбласть.Текст = "Начальный остаток"; ТекущаяОбласть = Макет.НайтиТекстСОстатки". ТекущаяОбласть, Макет.ОбластьО, Истина, Истина, Истина, Ложь); ТекущаяОбласть.Текст = "Конечный остаток": КонецЕсли; // Если пользователь выбрал поле Обороты, // заменить в макете надпись Обороты Если Построитель.ВыбранныеПоля.НайтиС'Обороты") <> Неопределено Тогда ТекущаяОбласть = Макет.НайтиТекстС"Обороты", ТекущаяОбласть, Макет.ОбластьО, Истина, Истина, Истина, Ложь); ТекущаяОбласть.Текст = "Оборот": ТекущаяОбласть = Макет.НайтиТекстС"Обороты". ТекущаяОбласть, Макет.ОбластьО, Истина, Истина, Истина, Ложь); ТекущаяОбласть.Текст = "Приход"; ТекущаяОбласть = Макет.НайтиТекстС"Обороты", ТекущаяОбласть, Макет.ОбластьО, Истина, Истина, Истина, Ложь); ТекущаяОбласть.Текст = "Расход"; КонецЕсли; // Установить измененный макет построителю Построитель.Макет = Макет; Построитель.ВывестиО; Заполнение настроек построителя отчета на основе сохраненных ранее настроек Настройки построителя отчета, созданные пользовате- лем, могут быть сохранены и использованы в дальней- шем.
Для получения настроек построителя отчета использует- ся метод ПолучитьНастройкиО. Этот метод возвращает зна- чение типа НастройкиПостроителяОтчета, которое может быть сериализовано, то есть сохранено методами Сохра- нитьЗначение и ЗначениеВФайл или помещено в объект Храни - лищеЗначения. В методе ПолучитьНастройкиО можно указать следует ли получать отбор, порядок, измерения и выбран- ные поля построителя отчета. Другими словами, раз- работчик может выбрать, какие именно настройки по- строителя отчета следует получить. Предположим, что настройки отчетов хранятся в регистре сведений, имею- щем следующую структуру (табл. 13.4). Таблица 13.4. Структура регистра сведений Имя Тип Измерение Отчет Строка, 100 Измерение ИмяНастройки Строка, 50 Ресурс Настройка ХранилищеЗначения В этом случае сохранение и загрузка настроек построите- ля отчета, используемого в обработке, может выглядеть следующим образом (листинг 13.15). Листинг 13.15. Фрагмент модуля формы обработки // Сохранить настройки построителя отчета в регистре сведений НастройкиПостроителя = Построитель.ПолучитьНастройки(); НаборЗаписей = РегистрыСведений.НастройкиОтчетов.СоздатьНаборЗаписей(); // Установить отбор НаборЗаписей.Отбор.Отчет.Установить( МетаданныеО .ПолноеИмяО, Истина); НаборЗаписей.Отбор.ИмяНастройки.Установить( ИияСохраняемойНастройки, Истина); // Добавить запись с настройками ЗаписьРегистра = НаборЗаписей. ДобавитьО; ЗаписьРегистра.Отчет = МетаданныеО. ПолноеИмяО; ЗаписьРегистра.ИмяНастройки = ИияСохраняемойНастройки; ХранилищеЗначения = Новый ХранилищеЗначения(НастройкиПостроителя); ЗаписьРегистра.Настройка = ХранилищеЗначения; НаборЗаписей.Записать(); //Получить настройки построителя отчета // Установить отбор НаборЗаписей = РегистрыСведений.НастройкиОтчетов.СоздатьНаборЗаписей(); НаборЗаписей.Отбор.Отчет.Установить( МетаданныеО .ПолноеИмяО, Истина); НаборЗаписей.Отбор.ИмяНастройки.Установить( ИняЗагружаемойНастройки. Истина); //Прочитать запись НаборЗаписей.Прочитать О; НастройкиПостроителя = НаборЗаписей[0].Настройка.Получить(); Построитель.УстановитьНастройки(НастройкиПостроителя); Для установки построителю отчета сохраненных ранее настроек используется метод УстановитьНастройкиО. Этот метод также позволяет указывать, следует ли устанавли- вать каждую из настроек построителя отчета или нет. Следует отметить, что настройки построителя отчета бу- дут установлены не в любом случае, а только тогда, когда текст запроса построителя отчета позволяет это сделать. Настройка построителя отчета интерактивными средствами Для того чтобы предоставить пользователю возможность настраивать построитель отчета, необходимо разместить в форме соответствующие элементы управления, связан- ные с настройками построителя отчета. Наиболее типичным вариантом использования построи- теля отчета является создание отчета или обработки, од- ним из реквизитов формы которых является построитель отчета (рис. 13.19). Действия» Реквизит Тип ОбработкаОбъект ВнешняяО бработкаП остроительОтчета! Поле!екстЗапроса Строка Построитель П остроительОтчета Т абличноеПолеСоставДоступныхП олей ТаблицаЗначений Рис. 13.19. Реквизиты формы обработки В этом случае в форме размещаются табличные поля, которые связываются с соответствующими настройками построителя отчета (рис. 13.20). Рис. 13.20. Название рисунка Поля настроек построителя отчета допускают интерак- тивное добавление, удаление и изменение порядка следо- вания элементов как при помощи командной панели, так и при помощи контекстного меню. Исключением является табличное поле, отображающее доступные поля построителя отчета. Единственными ин- терактивным действием, допускаемым для этого поля, является выбор полей в настройки отчета при помощи контекстного меню (рис. 13.21). Доступные поля Е Качество КоличествоКонечныйОстаток КоличествоНачальныйОстаток Ко личествоО борот Ё Ё Ё Количес КонецП< МетодД НачалоГ Номенк Период!- СерияН( Склад Добавить в условия Добавить в поля Добавить в порядок Добавить в строки Добавить в колонки Ё Характеристикам оменклатуры Рис. 13.21. Интерактивные действия с доступными полями
Менее типичным является случай, когда построитель от- чета создается конструктором. В этом случае табличные поля настроек, расположенные в форме, должны быть связаны с данными построителя средствами встроенного языка. Можно использовать как связанные с данными табличные поля, так и табличные поля, которые с данны- ми не связаны. Например, для табличных полей, отобра- жающих доступные поля, отбор и порядок построителя отчета, можно задать связь с реквизитами формы, имею- щими соответствующие типы значений: ПоляНастрйки, От- бор и Порядок. Для остальных настроек построителя отчета конфигуратор не предоставляет возможности назначить реквизиты нужных типов, поэтому необходимо использо- вать возможность работы непосредственно с элементами управления ТабличноеПоле. Для отображения в форме из- мерений строки, измерений колонки, выбранных полей и условного оформления построителя отчета следует расположить в форме табличные поля, не связанные с данными, и затем в процессе выполнения алгоритма при- своить им нужный тип значения и нужное значение (лис- тинг 13.16). Листинг 13.16. Пример связывания табличных полей с настройками построителя отчета Перем Построитель: // построитель отчета, создаваемый И конструктором // Процедура устанавливает связь настроек И построителя отчета с табличными полями. // расположенными в форме. И И Параметры: И Нет. И И Возвращаемое значение: И Нет. // Процедура КнопкаВыполнитьНажатие(Кнопка) ТекстЗапроса = "ВЫБРАТЬ ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОбороты.Склад КАК Склад, СУММА(ТоварыНаСкладахОбороты.КоличествоПриход) КАК КоличествоПриход, СУММА(ТоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты КАК ТоварыНаСкладахОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОбороты.Склад. ТоварыНаСкладахОбороты.Номенклатура ИТОГИ ПО ОБЩИЕ, Склад, Номенклатура" Построитель = Новый ПостроительОтчета(ТекстЗапроса); Построитель .ЗаполнитьНастройки (): // Показать доступные поля построителя ДоступныеПоля = Построитель.ДоступныеПоля; ЭлементыФормы .ДоступныеПоля. СоздатьКолонки (): И Показать отбор построителя Отбор = Построитель. Отбор: ЭлементыФормы.Отбор.Соз дат ьКолон ки(); И Показать порядок построителя Порядок = Построитель. Порядок; ЭлементыФормы. Порядок. СоздатьКолонки (): // Показать измерения строки построителя ПолеИзмеренияСтроки = ЭлементыФормы.ИзмеренияСтроки; ПолеИзнеренияСтроки.ТипЗначения = Новый ОписаниеТипов("ИзмеренияПостроителяОтчета"): ПолеИзмеренияСтроки.Значение = Построитель.ИзмеренияСтроки: ПолеИзмеренияСтроки.СоздатьКолонки(); // Показать измерения колонки построителя ПолеИзмеренияКолонки = ЭлементыФормы.ИзмеренияКолонки; ПолеИзмеренияКолонки.ТипЗначения = Новый ОписаниеТиповС'ИзнеренияПостроителяОтчета"): ПолеИзмеренияКолонки.Значение = Построитель.ИзмеренияКолонки; ПолеИзмеренияКолонки,СоздатьКолонки(); // Показать выбранные поля построителя ПолеВыбранныеПоля = ЭлементыФормы.ВыбранныеПоля; ПолеВыбранныеПоля.ТипЗначения = Новый ОписаниеТипов("ПоляПостроителяОтчета"); ПолеВыбранныеПоля.Значение = Построитель.ВыбранныеПоля; ПолеВыбранныеПоля.СоздатьКолонки(); // Показать условное оформление построителя ПолеОформление = ЭлементыФормы.УсловноеОформление; ПолеОформление.ТипЗначения = Новый ОписаниеТиповС'УсловноеОформление"); ПолеОформление.Значение = Построитель.УсловноеОформление: ПолеОформление.СоздатьКолонки(): КонецПроцедуры Изменение настроек при помощи полей ввода Можно предоставить пользователю возможность изме- нять настройки построителя отчета не с помощью таб- личных полей, расположенных в форме, а с помощью по- лей ввода. Это может понадобиться, например, в тех случаях, когда пользователю нужно иметь возможность настроить лишь некоторые, заранее известные настройки построителя. Например, начальную и конечную даты формирования отчета. В этом случае в форме можно раз- местить два поля ввода и связать их со значениями соот- ветствующих элементов отбора построителя отчета (лис- тинг 13.17). Листинг 13.17. Связь полей ввода с данными // Связать поля ввода с данными отбора построителя отчета ЭлементыФормы.ПолеВводаНачалоПериода.Данные = "Построитель.Отбор.НачалоПериода.Значение"; ЭлементыФормы.ПолеВводаКонецПериода.Данные = "Построитель.Отбор.КонецПериода.Значение"; Если все же нужно скрыть эти поля в табличном поле От- бор, следует использовать свойство расширения таблич- ного поля отбора НастройкаОтбора, которое предоставляет доступ к коллекции настроек отбора, с помощью которых можно управлять доступностью отдельных элементов отбора в табличном поле, отображающем отбор (лис- тинг 13.18). Листинг 13.18. Управление видимостью полей в табличном поле отбора // Скрыть поля отбора в табличном поле Отбор НастройкаОтбора = ЭлементыФормы.ТабличноеПолеОтбор.НастройкаОтбора; НастройкаОтбора.Добавить("НачалоПериода", Ложь): НастройкаОтбора.ДобавитьС’КонецПериода", Ложь);
Аналогичным образом можно управлять видимостью элементов порядка в табличном поле, связанном с поряд- ком построителя отчета. Для этого используется свойство расширения табличного поля порядка НастрокаПорядка и свойства объектов ЭлементУправленияПорядкон коллекции НастройкаПорядка. Настройка построителя отчета средствами встроенного языка Наряду с различными способами заполнения настроек построителя отчета есть возможность программного из- менения настроек, способа их отображения, состава по- лей. Это позволяет предоставить пользователю возмож- ность более точно настраивать построитель отчета или, наоборот, ограничить пользователя в выборе тех или иных настроек построителя. Допустим, что для первоначального заполнения настроек построителя отчета использовался обычный текст запро- са и метод ЗаполнитьНастройкиО (листинг 13.19). Листинг 13.19. Заполнение настроек построителя отчета Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад. ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММАСТоварыНаСкладахОстаткиИОбороты. КоличествоНачальныйОстаток) КАК КоличествоНачальныйОстаток, СУММА(ТоварыНаСкладахОстаткиИОбороты. КоличествоКонечныйОстаток) КАК КоличествоКонечныйОстаток, СУММАСТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход. СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура ИТОГИ СУММА(КоличествоНачальныйОстаток), СУММА(КоличествоКонечныйОстаток), СУММА(КоличествоПриход), СУММА(КоличествоРасход), СУММА(КоличествоОборот) ПО ОБЩИЕ, Склад. Ноненклатура" Построитель.ЗаполнитьНастройки(); Рассмотрим возможности, предоставляемые встроенным языком, для модификации настроек построителя отчета. Доступные поля Доступные поля построителя отчета представляют собой объект ПоляНастройки, который является коллекцией объ- ектов ПолеНастройки. Каждое поле настройки описывает одно из полей, которое может быть использовано для - выбора в порядок, отбор, измерения строки, измере- ния колонки и выбранные поля построителя отчета (рис. 13.22). Рис. 13.22. Доступные поля построителя отчета Объект ПоляНастройки обладает набором методов, которые позволяют добавлять, удалять отдельные поля настроек и менять порядок их следования в коллекции. Следует сра- зу оговориться, что при работе с построителем отчета нет смысла использовать метод Добавить О объекта ПоляНаст- ройки. Дело в том, что построитель отчета содержит опре- деленный набор данных о доступных полях, который соз- дается на основе анализа текста запроса и недоступен для изменения средствами встроенного языка. Поэтому поля, добавленные в коллекцию методом Добавить!), не могут быть полноценно использованы построителем отчета (на- пример, их нельзя будет интерактивно выбрать в изме- рения или выбранные поля). Добавление полей в кол- лекцию ПоляНастройки следует выполнять либо методом построителя отчета ЗаполнитьНастройкиО, либо используя язык запросов построителя отчета. В качестве отступления от темы можно сказать, что метод Добавить!) объекта ПоляНастройки может использоваться, когда объект ПоляНастройки применяется для модифика- ции объектов Порядок и Отбор. В этом случае, добавив в коллекцию нужные поля, можно на ее основе заполнить доступные поля для отбора и порядка. Какие действия можно выполнять с доступными по- лями? Прежде всего, можно удалить некоторые из доступных полей. Это приведет к тому, что поля, которые были уда- лены, нельзя будет выбрать интерактивно в настройки построителя отчета. Также эти поля нельзя будет доба- вить в настройки построителя отчета и программными средствами. Для этого используется метод Удалить!) объ- екта ПоляНастройки (листинг 13.20). Листинг 13.20. Пример удаления доступных полей // Запретить выбор некоторых доступных полей. ДоступныеПоля = Построитель.ДоступныеПоля; ДоступныеПоля.Удалить(ДоступныеПоля.Найти("МетодДополнения")); ДоступныеПоля.Удалить(ДоступныеПоля.Найти("Качество")); ДоступныеПоля.Удалить(ДоступныеПоля. Найти("ХарактеристикаНоменклатуры")); ДоступныеПоля.Удалить(ДоступныеПоля. Найти("СерияНоненклатуры")); Можно присвоить доступным полям представления, ко- торые будут удобны пользователю, так как построитель отчета при добавлении доступных полей использует в ка- честве их представления псевдонимы соответствующих полей запроса. Для этого используется свойство Представ - ление объекта ПолеНастройки (листинг 13.21).
Листинг 13.21. Изменение представлений доступных полей построителя отчета И Изменить представления оставшихся доступных полей ДоступныеПоля = Построитель.ДоступныеПоля; ДоступныеПоля. Найти("КоличествоКонечныйОстаток"). Представление = "Остаток конечный"; ДоступныеПоля.Найти("КоличествоНачальныйОстаток"). Представление = "Остаток начальный"; ДоступныеПоля.Найти("КоличествоОборот"). Представление = "Оборот"; ДоступныеПоля.Найти("КоличествоПриход"). Представление = "Приход": ДоступныеПоля.Найти("КоличествоРасход"). Представление = "Расход"; ДоступныеПоля.Найти("КонецПериода"). Представление = "Конец периода"; ДоступныеПоля. Найти ("НачалоПериода"). Представление = "Начало периода"; ДоступныеПоля.Найти("Номенклатура").Представление = "Товар"; Для полей, допускающих выбор подчиненных полей, можно запретить такую возможность. Для этого нужно очистить коллекцию полей настройки, находящуюся в свойстве Поля нужного поля настройки. Например, для поля «Качество» можно запретить выбор подчиненных полей (листинг 13.22). Листинг 13.22. Запрет выбора всех подчиненных полей ДоступныеПоля = Построитель.ДоступныеПоля; ПолеКачество = ДоступныеПоля.НайтиС’Качество"): ПолеКачество.Поля.Очистить(); Аналогичным образом можно запретить выбор некото- рых подчиненных полей: для этого следует удалить их из коллекции. Например, можно запретить выбор полей Владелец, Предопределенный и ПометкаУдаления для поля СерияНоменклатуры (листинг 13.23). Листинг 13.23. Запрет выбора некоторых подчиненных полей ДоступныеПоля = Построитель. ДоступныеПоля; ПолеСерия = ДоступныеПоля.НайтиС'СерияНоменклатуры"): КоллекцияПолей = ПолеСерия. Поля: КолпекцияПолей.Удалить(КоллекцияПолей.Найти("Владелец")); КоллекцияПолей. Удалить(КоллекцияПолей.Найти("Предопределенный")); КоллекцияПолей.Удалить(КоллекцияПолей.Найти("ПометкаУдаления") ): Также коллекция ПоляНастройки позволяет расположить доступные поля построителя отчета в нужном порядке. Для этого используется метод Сдвинуть () объекта ПоляНа- стройки (листинг 13.24). Листинг 13.24. Изменение порядка доступных полей РасположитьПоле("Номенклатура", 0); РасположитьПоле( "Склад", 1); РасположитьПоле("КоличествоНачальныйОстаток". 2); РасположитьПоле("КоличествоКонечныйОстаток", 3): РасположитьПолеС'КоличествоПриход", 4); РасположитьПоле("КоличествоРасход", 5); РасположитьПолеС’КоличествоОборот". 6); Расположит ьПоле (" Нач алоПериод а ”, 7); И Процедура перемещает доступное поле на указанную позицию. И И Параметры: И ИмяПоля - Строка - имя перемещаемого поля. И Позиция - Число - позиция, на которую должно быть // перемещено поле. И Нумерация позиций начинается с 0. // Возвращаемое значение: // Нет. // Процедура РасположитьПоле(ИмяПоля, Позиция); ДоступныеПоля = Построитель.ДоступныеПоля; Поле = ДоступныеПоля.Найти(ИмяПоля); Индекс = ДоступныеПоля.Индекс(Поле); ДоступныеПоля.Сдвинуть(Поле, Позиция - Индекс); КонецПроцедуры Каждое поле настройки содержит свойства, указываю- щие, может ли это поле быть выбрано в отбор, порядок, выбранные поля, измерения строки и измерения колонки построителя. Эти свойства заполняются построителем отчета автоматически, на основании того, как соответст- вующее поле описано в тексте запроса. Разработчик мо- жет дополнительно ограничить пользователя в выборе тех или иных полей, установив нужные свойства в значе- ние Ложь. Например, можно запретить выбор поля Количе- ствоОборот в отбор (листинг 13.25). Листинг 13.25. Запрет выбора доступного поля в отбор ДоступныеПоля = Построитель.ДоступныеПоля; ДоступныеПоля.Найти("КоличествоОборот").Отбор = Ложь; Нужно заметить, что не имеет смысла устанавливать описан- ные свойства в значение Истина, если построитель отчета при заполнении настроек установил их в значение Ложь, посколь- ку при добавлении (программном или интерактивном) по- лей в настройки построителя отчета будет выполняться до- полнительная проверка, которая все равно не даст добавить поле в ту настройку, для которой оно не предназначено. Можно управлять видимостью различных групп доступ- ных полей в табличном поле, связанном со свойством по- строителя отчета ДоступныеПоля. Для этого используются свойства расширения табличного поля для полей на- стройки ОтображатьИзнерения, ОтображатьОтбор, ОтображатьПо- ля и ОтображатьПорядок. Например, можно отобразить в табличном поле только те поля, которые доступны для выбора в измерения. По- скольку по умолчанию все эти свойства имеют значение Истина, достаточно «ненужным» свойствам присвоить зна- чение Ложь (листинг 13.26). Листинг 13.26. Управление отображением групп доступных полей ПолеДоступныеПоля = ЭлементыФормы.ТабличноеПолеДоступныеПоля; ПолеДоступныеПоля.ОтображатьОтбор = Ложь; ПолеДоступныеПоля.ОтображатьПоля = Ложь; ПолеДоступныеПоля.ОтображатьПорядок = Ложь; Следует учитывать, что по умолчанию свойства расшире- ния табличного поля для полей настройки установлены в значение Истина. Поэтому, если для какого-либо поля на- стройки свойства Измерение, Отбор, Поле и Порядок устано- вить в значение Ложь, это поле не будет отображено в таб- личном поле доступных полей, поскольку не будет являть- ся ни измерением, ни отбором, ни полем, ни порядком. Каждое поле настройки имеет свойство СписокЗначений. В этом свойстве перечисляются допустимые значения, которые могут быть использованы, при установке отбора по этому полю (то есть тогда, когда это поле выбирается в отбор построителя отчета). Список значений заполняется автоматически, при анализе текста запроса. Разработчик
имеет возможность удалить некоторые значения из этого списка, ограничив тем самым выбор пользователя при ус- тановке значений отбора. Например, можно разрешить пользователю задавать значения периодичности в пара- метре виртуальной таблицы только Регистратор и Месяц. Для этого нужно удалить все остальные значения из спи- ска значений (листинг 13.27). Листинг 13.27. Управление списком значений поля настройки // Ограничить пользователя в выборе периодичности. СписокПернодов = Построитель.ДоступныеПоля. Найти("Периодичность").СписокЗначений; СписокПериодов.Удалить(СписокПериодов.НайтиПоЗначению(О)); СписокПериодов.Удалить(СписокПериодов.НайтиПоЗначению(1)); СписокПериодов.Удалить(СписокПериодов.НайтиПоЗначению(З)); СписокПериодов.Удалить(СписокПериодов.НайтиПоЗначению(4)); СписокПериодов.Удалить(СписокПериодов.НайтиПоЗначению(Б)); СписокПериодов.Удалить(СписокПериодов.НайтиПоЗначению(7)); СписокПериодов.Удалить(СписокПериодов.НайтиПоЗначению(8)); СписокПериодов.Удалить(СписокПериодов.НайтиПоЗначению(9)); Порядок Порядок построителя отчета представляет собой универ- сальный объект Порядок и не имеет каких-либо особенно- стей работы, связанных именно с построителем отчета. Объект Порядок является коллекцией, содержащей объек- ты ЭлементПорядка, позволяющие описывать поля, по кото- рым будет производиться упорядочивание (в нашем слу- чае — упорядочивание результата запроса). Коллекция позволяет добавлять, удалять, менять порядок следова- ния элементов порядка и предоставляет возможность из- менять представление и направление упорядочивания для отдельных элементов порядка. В порядок можно добавить только те поля, которые при- сутствуют в доступных полях и для которых разрешен выбор в порядок построителя отчета. Для этого использу- ется метод Добавить() объекта Порядок. При добавлении нужно указать путь к данным. Если в доступных полях разрешен выбор подчиненных полей от данного поля, то «через точку» можно указать то подчиненное поле, по ко- торому будет выполняться упорядочивание. Также при добавлении полей порядка можно задать представление поля и направление упорядочивания (листинг 13.28). Для уже существующих элементов порядка можно задать представление, которое будет показано пользователю. Для этого используется свойство Представление объекта ЭлементПорядка (листинг 13.29). Листинг 13.28. Добавление полей порядка построителя отчета // Добавить новый элемент порядка. Порядок = Построитель.Порядок; Порядок.Добавит ь("Номенклатура.Код", "КодНоменклатуры", "Код номенклатуры", НалравлениеСортировки.Возр); Листинг 13.29. Задание представления полей порядка // Изменить представление элемента порядка СкладКомпании. Порядок = Построитель.Порядок; Для Каждого ЭлементПорядка из Порядок Цикл Если ЭлементПорядка.Представление = "Номенклатура" Тогда ЭлементПорядка.Представление = "Товар"; Прервать; КонецЕсли; КонецЦикла; Можно изменять порядок следования элементов поряд- ка. Для этого используется метод Сдвинуть!) объекта Поря- док (листинг 13.30). Листинг 13.30. Изменение порядка следования полей порядка // Изменить порядок следования элементов порядка. Для Счетчик = 0 по Порядок.КоличествоО - 1 Цикл ПолеПорядка = Порядок.Получить(Счетчик); Если ПолеПорядка.Представление = "Товар" Тогда РасположитьПоле(Счетчик, 1); ИначеЕсли ПолеПорядка.Представление = "Склад" Тогда РасположитьПоле(Счетчик, 0); КонецЕсли; КонецЦикла; // Процедура перемещает элемент порядка на указанную позицию. // // Параметры: // ИндексПоля - Число - индекс перемещаемого элемента. // Позиция - Число - позиция, на которую должен быть // перемещен элемент. // Нумерация позиций начинается с 0. // // Возвращаемое значение: // Нет. // Процедура РасположитьПоле(ИндексПоля, Позиция) ПоляПорядка = Построитель.Порядок; ПоляПорядка.Сдвинуть(ИндексПоля, Позиция - ИндексПоля); КонецПроцедуры Существующим элементам порядка можно изменить на- правление сортировки. Для этого используется свойство Направление объекта ЭлементПорядка (листинг 13.31). Листинг 13.31. Изменение направления сортировки Для Каждого ЭлементПорядка из Построитель.Порядок Цикл Если ЭлементПорядка.Представление = "Номенклатура" Тогда ЭлементПорядка.Направление = НаправлениеСортировки.Убыв; КонецЕсли; КонецЦикла; Методы ПолучитьДоступныеПоляО и УстановитьДоступныеПо- ля О объекта Порядок не имеют смысла при работе с по- строителем отчета, поскольку для порядка построителя отчета доступными полями будут являться доступные поля построителя отчета (рис. 13.23). Рис. 13.23. Доступные поля порядка построителя отчета Отбор Отбор построителя отчета представляет собой универ- сальный объект Отбор, который является коллекцией, со- держащей объекты ЭлементОтбора. С помощью этой коллек- ции описываются поля, по которым будет осуществляться отбор при выполнении запроса построителя отчета.
Коллекция позволяет добавлять, удалять, менять поря- док следования элементов отбора и предоставляет воз- можность изменять представление, вид сравнения, ис- пользование и другие свойства элементов отбора. Для добавления элементов отбора используется метод Доба- вить() объекта Отбор. Например, можно добавить в отбор нужные поля, сразу задав их представления (листинг 13.32). Листинг 13.32. Добавление полей отбора построителя отчета Отбор = Построитель. Отбор; Отбор.Добавить("НачалоПериода", , "Начало периода"). Использование = Истина; Отбор.Добавить("КонецПериода", , "Конец периода"). Использование = Истина; В остальном, работа с коллекцией осуществляется спосо- бами, аналогичными тем, которые были описаны для дос- тупных полей построителя отчета. Также следует заметить, что, как и для порядка построи- теля отчета, не имеет смысла использовать методы Полу- читьДоступныеПоляО и УстановитьДоступныеПоляО объекта Отбор, поскольку для отбора построителя отчета доступ- ными полями будут являться доступные поля построите- ля отчета (рис. 13.24). Рис. 13.24. Доступные поля отбора построителя отчета Измерения строки, измерения колонки Измерения строки, как и измерения колонки, представ- ляют собой объект ИзнеренияПостроителяОтчета. Этот объ- ект является коллекцией, содержащей объекты Измерение- ПостроителяОтчета. Каждое измерение построителя отчета описывает поле, которое будет выводиться в строки или колонки табличного документа. Коллекция позволяет добавлять, удалять, изменять поря- док следования измерений построителя отчета и предо- ставляет доступ к свойствам измерений. Для каждого измерения может быть задано представление, тип изме- рения и макеты, которые будут использованы при выводе значений этого поля. Например, можно задать вывод измерения Склад не в строках отчета, как это устанавливается по умолчанию, а в колонках, при этом задав иерархический порядок вы- вода измерения Номенклатура в строках. Для этого ис- пользуются методы Удалить() и Добавить() коллекции Из- меренияПостроителяОтчета и свойство ТипИзнерения объекта ИзмерениеПостроителяОтчета (листинг 13.33). Листинг 13.33. Вывод измерения Склад в колонках И Запретить вывод измерения Склад в строках отчета. ИзмеренияСтроки = Построитель.ИзмеренияСтроки; ИзмеренияСтроки. Удалить (ИзмеренияСтроки. Найти ("Склад")) ; И Изменить тип измерения Номенклатура. ИзмеренияСтроки.Найти("Номенклатура").ТипИзмерения = ТипИзмеренияПостроителяОтчета.Иерархия; // Добавить вывод измерения Склад в колонках отчета. ИзмеренияКолонки = Построитель.ИзмеренияКолонки; ИзмеренияКолонки.Добавить("СкладКомпании", "Склад", ТипИзмеренияПостроителяОтчета.Элементы): Следует заметить что, как и при работе с другими на- стройками построителя отчета, в измерения колонки и измерения строки могут быть добавлены только те поля, которые содержатся в доступных полях построителя от- чета и разрешены для выбора в измерения. Измерение построителя отчета содержит ряд свойств, связанных с выводом значений этого измерения в таб- личный документ. По умолчанию для вывода результата запроса в таблич- ный документ используется макет построителя отчета, который генерируется построителем автоматически и содержит набор областей со стандартными именами, в который будут выводиться, в том числе, и измерения по- строителя отчета. Однако каждому измерению может быть указана произвольная область макета для вывода или же непосредственно сам макет (табличный доку- мент), в который будет выводиться это измерение. Для этого используются свойства Макет, МакетИерархии, Макет - Подвала, МакетПодвалаИерархии, МакетыУровней и МакетыПодва- ловУровней объекта ИзмерениеПостроителяОтчета. Эти области будут иметь наивысший приоритет при формировании итогового документа. Подробнее о выводе результата запроса в табличный документ можно прочитать в раз- деле «Использование макетов табличных документов», с. 490. Выбранные поля Выбранные поля построителя отчета представляют собой объект ПоляПостроителяОтчета. Этот объект является кол- лекцией, содержащей объекты ПолеПостроителяОтчета. Каж- дое поле построителя отчета описывает поле, которое будет выводиться в результат запроса. Коллекция позво- ляет добавлять, удалять, изменять порядок следования выбранных полей, а также изменять представление вы- бранных полей. Способы работы с этой коллекцией аналогичны работе с доступными полям построителя отчета. Например, можно удалить ненужные поля, а оставшимся задать представления, понятные пользователю. Для этого ис- пользуются методы Удалить (), Найти О коллекции ПоляПо- строителяОтчета и свойство Представление объекта ПолеПо- строителяОтчета (листинг 13.34). Листинг 13.34. Задание представлений выбранных полей И Запретить вывод некоторых выбранных полей ВыбранныеПоля = Построитель.ВыбранныеПоля; ВыбранныеПоля.Удалит ь(ВыбранныеПоля. Найти("КоличествоНачальныйОстаток")); ВыбранныеПоля.Удалить(ВыбранныеПоля. Найти("КоличествоОборот")); ВыбранныеПоля.Удалить(ВыбранныеПоля. Найти("КоличествоПриход")): ВыбранныеПоля.Удалить(ВыбранныеПоля. Найти("КоличествоРасход")); // Изменить представление оставшихся выбранных полей ВыбранныеПоля.Найти("СкладКомпании”).Представление = "Склад"; ВыбранныеПоля.Найти("КоличествоКонечныйОстаток"). Представление = "Остаток конечный";
Можно изменять порядок следования выбранных полей построителя отчета (для этого используется метод Сдви- нуть О), однако следует помнить, что построитель отчета будет формировать макет таким образом, что сначала все- гда будут выведены группировки, затем поля, подчинен- ные группировочным полям, а затем уже все остальные поля. Например, в отчете, показывающем остатки но- менклатуры и ее код, первой колонкой всегда будет Но- менклатура, затем Код, а затем уже Остаток, независимо от того, какова последовательность выбранных полей в на- стройках построителя отчета (рис. 13.25). [ Номенклатура | Код Бытовая техника 00043 Инвентарь 00049 Обувь 00012 Женская обувь 00013 Кроссовки 00026 Кроссовки "ADIDAS" 00027 Кроссовки ’REEBOK" 00030 Кроссовки высокие нет кожа 00033 Кроссовки мужские, коже 00028 Мужская обувь 00016 Продукты 00003 Сборка компьютеров 00114 Тара 00055 Итог [Остаток 3 363,000 25,000 5 669,000 4690,000 754,000 481,000 231,000 21,000 21,000 225,000 3 506,000 205,000 30,000 12 870,000 Рис. 13.25. Отчет, формируемый на основании макета по умолчанию Поэтому, для того, чтобы получить отчет, в котором ко- лонка Код располагается на первой позиции, нужно вно- сить изменения в макет, формируемый построителем от- чета по умолчанию, либо использовать собственный макет для вывода результата запроса (рис. 13.26). ев ев в в в |Код [Номенклатура 00043 Бытовая темники 00049 Инвентарь 00012 Обувь 00013 Женская обувь 00026 Кроссовки 00027 Кроссовки "ADIDAS" 00030 Кроссовки ’REEBOK" 00033 Кроссовки высокие нат. кожа 00028 Кроссовки мужские, кожа •0016 Мужская обувь 00003 Продукты 00114 Сборка компьютеров 00055 Тара Итог [Остаток 3 363,000 25,000 5 669,000 4690,000 754,000 481,000 231,000 21,000 21,000 225,000 3 586,000 205,000 30,000 12 878,000 Рис. 13.26. Отчет, формируемый на основании измененного макета Выполнение запроса и вывод отчета После того как построителю отчета передан текст запроса и выполнены необходимые настройки, при помощи мето- да Вывести () можно выполнить запрос, сформированный построителем отчета, и вывести результат в табличный документ, поле табличного документа или диаграмму (рис. 13.27). Метод Вывести!) выполнит запрос, сформированный по- строителем отчета в случае, если отчет еще не выводился или если были изменены настройки построителя отчета. В остальных случаях метод Вывести () будет использовать для вывода результат запроса, полученный построителем ранее. Рис. 13.27. Вывод отчета При выводе в табличный документ и поле табличного до- кумента будет использован макет построителя отчета (подробнее можно прочитать в разделе «Макет построи- теля отчета», с. 431) и выполнено условное оформление в соответствии с настройками построителя (подробнее можно прочитать в разделе «Условное оформление», с. 437). Табличный документ или поле табличного доку- мента, в которое необходимо выводить отчет, может быть указано в явном виде в качестве параметра метода Вывес- ти!) (листинг 13.35). Листинг 13.35. Явное указание поля табличного документа для вывода отчета Построитель.Вывести(ЭлементыФормы.ПолеОтчета); При выводе в табличный документ параметр метода мож- но и не указывать; в этом случае отчет будет выведен в новый табличный документ, и этот табличный документ будет открыт для просмотра и редактирования. Подроб- нее о выводе в табличный документ можно прочитать в разделе «Использование макетов табличных докумен- тов», с. 490. При выводе построителя отчета в диаграмму диаграмма обязательно должна быть указана в параметре метода Вы- вести!) (листинг 13.36). Листинг 13.36. Вывод отчета в диаграмму Построитель.Вывести(ЭлементыФормы.Диаграмма); Подробнее о выводе отчета в диаграмму можно прочитать в разделе «Вывод в диаграмму», с. 456. При работе с построителем отчета может возникнуть не- обходимость использовать собственный алгоритм вывода результата запроса. В этом случае можно воспользовать- ся методом построителя отчета Выполнить(), который вы- полняет запрос, сформированный построителем отчета. Результат запроса может быть получен через свойство построителя отчета Результат (рис. 13.28). Рис. 13.28. Получение результата запроса В дополнение к этому и сам запрос, сформированный по- строителем отчета для исполнения, может быть получен методом ПолучитьЗапросО. Такая возможность может по- надобиться, если есть необходимость получения текста сформированного запроса или выполнение запроса долж-
Рис. 13.29. Получение запроса но выполняться в другом модуле конфигурации (напри- мер, на сервере) (рис. 13.29). Макет построителя отчета Построитель отчета автоматически генерирует макет для вывода результата запроса в табличный документ. Этот макет состоит из областей, имеющих фиксированные имена. Каждая область предназначена для отображения определенных данных результата запроса. Разработчик может изменять при необходимости, как отдельные об- ласти макета, так и весь макет целиком. Механизм генерации и оформления макета построителя отчета В процессе изменения настроек построитель отчета гене- рирует макет, который он будет использовать для вывода результата запроса. Этот макет доступен через свойство построителя отчета Макет. Разработчик может получить макет, сгенерированный построителем отчета, внести в него какие-либо измене- ния и вернуть его построителю отчета. Также разработ- чик может установить построителю отчета собственный макет, в который построитель выведет результат запроса. Как только свойству Макет построителя отчета будет при- своено какое-либо значение, отличное от Неопределено, он прекращает генерировать собственный макет и будет ис- пользовать тот макет, который передан ему через свойст- во Макет. Например, построителю отчета можно устано- вить в качестве макета табличный документ, который содержится в макете текущей обработки (листинг 13.37). Листинг 13.37. Установка внешнего макета построителю отчета И Вывести отчет в собственный макет Построитель. Макет = ПолучитьМакетС'СобственныйМакет"): Построитель.Выполнить!); Построитель. Вывести (); Если свойству Макет установить значение Неопределено, по- строитель отчета продолжит автоматическую генерацию макета (листинг 13.38). Кроме этого, макет, сгенерированный построителем отчета или установленный пользователем, может быть оформ- лен с использованием стандартных оформлений, поддер- живаемых платформой. Для этого построитель отчета ис- пользует макет оформления, содержащийся в свойстве МакетОфориления. Одновременно с тем, как макет оформ- ления устанавливается в свойство построителя отчета МакетОфориления, происходит оформление макета построи- теля отчета, генерируемого построителем по умолчанию. Дальнейшая генерация макета построителя отчета будет выполняться уже с учетом макета оформления. Например, можно оформить макет, используя стандартное оформле- ние Апельсин (листинг 13.39). Листинг 13.38. Использование собственного макета и макета построителя по умолчанию // Вывести отчет в собственный макет, // а затем - в макет по умолчанию Построитель.Макет = ПолучитьМакетС'СобственныйМакет"): Построитель.Выполнить(); Построитель.Вывести(); Построитель.Макет = Неопределено; Построитель.Выполнить(); Построитель.Вывести(); Листинг 13.39. Использование стандартного оформления Построитель.МакетОформления = ПолучитьМакетОформления(СтандартноеОформление.Апельсин); Если после этого текущий макет был изменен, можно за- ново оформить его, используя метод ОфорнитьМакетО объ- екта ПостроительОтчета. Метод ОфорнитьМакетО также следует использовать в том случае, когда нужно оформить макет, установленный по- строителю извне. В общем виде схема работы построителя отчета с макетом представлена на следующей схеме (рис. 13.30). Рис. 13.30. Схема работы построителя с макетом Неоформленный макет построителя отчета содержит набор областей, имеющих стандартные имена. После оформле-
ния к ним добавляется дополнительный набор областей, связанных с использованием возможностей оформления. Эти дополнительные области будут использованы по- строителем отчета вместо соответствующих областей не- оформленного отчета. При выводе конкретных данных результата запроса по- строитель отчета будет искать, в первую очередь, предна- значенную для вывода этих данных область макета, кото- рая могла быть добавлена в макет при его оформлении. Если такая область не будет найдена, построитель попы- тается найти соответствующую область неоформленного макета. Если же и она не будет найдена, данные просто не будут выведены в результирующий документ. Для линейного отчета и для кросс-отчета построитель ге- нерирует различные по своей структуре макеты, поэтому мы рассмотрим каждый из этих макетов отдельно. Макет линейного отчета Неоформленный макет Для вывода линейного отчета построитель генерирует макет, содержащий набор областей со стандартными име- нами. На рис. 13.31 показаны имена областей, на примере готового линейного отчета. Отчет по остаткам товаров Номенклатура КоличествоКонечныйОстаток Обувь Женская обувь Женская обувь: Итог 4690,000 Мужская обувь мужская осунь: Итог 225,000 Кроссовки Кроссовки "ADDAS" 481,000 Кроссовки "REEBOK” 231,000 Кроссовки высокие нат кожа 21,000 Кроссовки мужские, кожа 21,000 Кроссовки: Итог 754,000 Обувь: Итог 5 669,000 Бытовая техника Бытовая техника: Итог 3 363,000 Продукты Продукты: Итог 3 506,000 Сборка компьютеров Сборка компьютеров: Итог 205,000 Тара Тара: Итог 30,000 Инвентарь Инвентарь: Итог 25,000 Итог 12 «78,000 Номенклатура КоличествоКонечныйОстаток отчет сформирован пользователем Иванов 01.01.2004 Заголовок ШапкаТаблицы «имя измерения» Иерарх и я «имя измерения» Иерархия «имя измерения»Под вал Иерархия «имя измерения» Иерархи я «имя измерения»Под вал Иерархи я «имя измерения» Иерархи я «имя измерения» «имя измерения» «имя измерения» «имя измерения» «имя измерения»ПодвалИерархия «имя измерения»ПодвалИерархия «имя измерения»Иерархия «имя измерения»ПодвалИерархия «имя измерения» Иерархи я «имя измерения»Под вал Иерархия «имя измерения» Иерархи я «имя измерения»Г1одвалИерархия «имя измерения» Иерарх и я «имя измерения»ПодвалИерархия «имя измерения» Иерархия «имя измерения»ПодвалИерархия ОбиутеИтогм ПодвалТаблицы Подвал Рис. 13.31. Имена областей неоформленного отчета Некоторые имена областей имеют неизменяемые имена, другая часть областей получает имена, составляемые из имени измерения и некоторого стандартного суффикса. В приведенном примере для вывода поля Номенклатура по- строитель будет использовать области с именами: Номенкла- тураИерархия, Номенклатура и НоменклатураПодвалИерархия. Следует отметить, что для отображения подвала неиерар- хического измерения используется специальная область — «имя изиерения>Подвал, или в приведенном примере — Но- менклатураПодвал. Оформленный макет Рассмотрим, в чем заключается отличие оформленного макета от «простого». Внешний вид отчета, построенного на основе «простого» макета привязан к измерениям. Допустим, выполняется группировка по складу, а затем по номенклатуре, и области склада выводятся с серым фоном, а области номенк- латуры — с белым. Тогда результирующий табличный документ будет содержать сначала серые строки, а затем белые. Если теперь изменить порядок следования груп- пировок в запросе, то и внешний вид результирующего документа изменится: сначала будут следовать строки с белым фоном (группировка по номенклатуре), а затем — с серым. Такое изменение внешнего вида может ухудшать «чита- бельность» отчета и приводить к тому, что каждый раз при смене группировок пользователь будет получать «другой» отчет, к «устройству» которого ему надо привыкнуть. Чтобы избежать этого, механизм стандартного оформле- ния позволяет «привязывать» оформление измерений к логическим уровням результата запроса, выводимым в табличный документ. Что является уровнем? Для неиерархического измерения уровнем является группировка по этому измерению. Для иерархического измерения «первым» уровнем являются все группы этого измерения (любого уровня иерархии), а «вторым» уровнем — элементы. Таким образом, если выполняется группировка по эле- ментам склада, а затем — по иерархии номенклатуры, то результат запроса будет содержать три уровня: первый — элементы склада (неиерархическая группировка), вто- рой — группы номенклатуры всех уровней и третий — элементы номенклатуры. Таким образом, области, добавляемые в макет при оформ- лении, помимо указания имени измерения, содержат номер уровня, к которому они относятся. На рис. 13.32, на примере трех иерархических группировок (Качество, Склад и Номенклатура) показаны имена областей оформленного макета, используемого построителем отчета. Заголовок Отчет по остаткам товаров Качество 1 Склад/ Номенклатура КоличествоКонечныйОстаток Новый Оптовые склады Главный склад Обувь Женская обувь Женская обувь: Итог 2 537,080 Мужская обувь Мужская обувь: Итог 225,000 Кроссовки Кроссовки "ADDAS" 481,000 Кроссовки "REEBOK” 231,000 Кроссовки высокие нат кожа 21,000 Кроссовки мужские, кожа 21,000 Кроссовки: Итог 754,880 Обувь: Итог 3 516,880 Бытовая техника Бытовая техника: Итог 2 285,000 Продукты Продукты: Итог 45,000 Сборка компьютеров Сборка компьютеров: Итог 205,000 Тара Тара: Итог 15,000 Главный склад: Итог 6 006,000 Склад электротоваров Склад электротоваров: Итог 998,000 Оптовые склады Итог 7 064,880 Ротничные склады Ротничные склады: Итог 5 761,000 Новый: Итог 12 845,000 Брак Брак Итог 33,808 Итог 12 878,080 Качество ! Склад/ Номенклатура КоличествоКонечныйОстаток отчет сформирован пользователем Иванов 01.01 2004 ШапкаТаблицы «имя измерения» Уровень! «имя измерения» Уровень 2 «имя измерения» УровеяьЗ «имя измерения» Уровень 4 «имя измерения» Уровень 4 «имя измерения»ПодвалУровень4 «имя измерения» Уровень4 «имя измерения»ПодвалУровень4 «имя измерения» Уро в ень4 Детали Детали Детали Детали «имя измерения»ПодвалУровень4 «имя измерения»ПодвалУровень4 «имя измерения» Уровень4 «имя измерения»ПодвалУровень4 «имя измерения» УровеньД «имя измерения»ПодвалУровень4 «имя измерения» Уро в ень4 «имя измерения»ПодвалУровень4 «имя измерения» Уро в ень4 «имя измерения»ПодвалУровень4 «имя измерения»ПодвалУровеньЗ «имя измерения» Уро в еньЗ «имя измерения»ПодвалУровеяьЗ «имя измерения»Под в ал Уровень? «имя измерения»Уровень2 «имя измерения»ПодвалУровень2 «имя измерения»ПодвалУровень1 «имя измерения» Уровень! «имя измерения»ПодвалУроеень4 ОбциеИтопи ПодвалТаблицы Рис. 13.32. Имена областей оформленного макета
Сравнив этот пример с предыдущим, можно заметить, что области, добавляемые при оформлении, «перекрывают» собой не все области неоформленного макета, а только те, которые предназначены для вывода измерений. Приоритет использования областей неоформленного и оформленного макетов представлен на рис 13.33. Кроссовки Кроссовки "ADDAS" 481,000 Кроссовки "REEBOK" 231.000 Кроссовки высокие нат кожа 21,000 Кроссовки мужские, кожа 21,000 Кроссовки: Итог 754,000 «имя измерения* Иерархи я «имя измерения* «имя измерения* «имя измерения* «имя измерения* «имя измерения»Под вал Иерархия «имя измерения* Иерархия «имя измерения* «имя измерения* «имя измерения* «имя измерения* «имя измерения*Под вал Иерархия «имя измерения*Уровень«номер уровня* Детали Детали Детали Детали «имя измерения*ПодвалУровень<номер уровня* Рис. 13.33. Приоритет использования областей оформленного макета Кросс-отчет Для макетов, формируемых построителем отчета при вы- воде кросс-отчетов, также справедливо все, сказанное про «линейные» макеты. Отличие состоит лишь в составе и названии областей, используемых построителем. На рис. 13.34 и 13.35 рисунках в схематическом виде представлен кросс-отчет, в строках и колонках которого используются иерархические группировки. В ячейках таблицы указаны имена областей неоформленного маке- та, которые используются построителем отчета для выво- да данных. Заголовок <группировки>Иерархия Ресурсы Иерархия_______ Ресурсы РесурсыПрд вал Иерархия РесурсыИ тогПоКолонке ШапхаСтрок ___________________ <группировка>Иерархия_________ «группировка* _____________ «группировка^ од вал Иерархия Загого в ок Ито гаПо Колонке__ ПодвалТаблицы Подвал ЦК Ре Ре Pet Рис. 13.34. Левая «половина» неоформленного кросс-отчета «фуппировка* За головокИто гаПоСтроке РесурсыИерархия РесурсыИтогПоСтрокеИерархия Ресурсы Ресурсы И то гЯоСтроке РесурсыПод ва лИерархия Ре сурсыИтогПоСгрокеП о два лИерархия РесурсыИ то|ПоКолонке Обнулен тоги Рис 13.35. Правая «половина» неоформленного кросс-отчета Так же как и при выводе линейного отчета, для отображе- ния подвала неиерархической группировки используют- ся отдельные области — РесурсыПодвал и РесурсыИтогПо- СтрокеПодвал. Оформленный макет кросс-отчета также обеспечивает привязку областей к уровням. На рис. 13.36 и 13.37 ри- сунках показаны имена областей, «перекрывающих» об- ласти неоформленного макета кросс-отчета (). Дополнительно к этому, все области, относящиеся к вы- воду ресурсов, как для неоформленного, так и для оформленного кросс-отчета, могут быть определены и для отдельных группировок. При этом к указанному имени области добавляется префикс, являющийся име- нем группировки. Например, если существует груп- пировка Номенклатура, то для нее используются области НоменклатураРесурсыИерархия, НоменклатураРесурсы, Но- менклатураРесурсыИтогПоСтрокеИерархия, Номенклатура- РесурсыИтогПоСтроке и т. д. В оформленном макете используются области НоменклатураРесурсыУровень1, Но- менклатураРесурсыГруппировкаДетали, НоменклатураРесур- сыИтогПоСтрокеУровень1, НоменклатураРесурсыИтогПоСтро- ке и т. д. «группировка* Уровень «номер»_____РесурсыУровень«номер> _______ __________________________________Ресурсы Группиров каДетали___ «группировка*ПодвалУровень<номер> РесурсыПодвалУровень«номер> Pei Pec Pei Рис. 13.36. Левая «половина» оформленного кросс-отчета РесурсыУровеньсномер» РесурсыИюгПоСтрокеУровень«номер> РесурсыГруппировкаДетали Ресурсы И то гПоСтроке ГруппировкаДетали РесурсыПодвалУровень<номер> РесурсыИтогПоСтрокеПодвалУровень<номер> Рис. 13.37. Правая «половина» оформленного кросс-отчета Области, указанные для конкретных группировок, имеют больший приоритет использования, по сравнению с соот- ветствующими областями, не относящимися к конкрет- ным группировкам. Кроме того, как и в макете линейного отчета, в макете, содержащем одновременно области не- оформленного и оформленного макета кросс-отчета, при- оритетом использования будут обладать области оформ- ленного макета. Поэтому в макете кросс-отчета, выводящего группировки номенклатуры, построитель отчета сначала будет искать, например, область НоменклатураРесурсыУровень1, при ее отсутствии — РесурсыУровень1, при ее отсутствии — Но- менклатураРесурсыИерархия и при ее отсутствии — Ресур- сы Иерархия. Задание фиксированных макетов для вывода результата запроса Наряду с автоматической генерацией макета и установ- кой собственного макета построителя отчета существует возможность задать фиксированные макеты для вывода различных данных отчета. Во-первых, построитель отчета содержит ряд свойств, ко- торые позволяют назначить макеты различных областей отчета: ♦ МакетЗаголовкаОтчета; ♦ МакетШапкиТаблицы; ♦ МакетДетальныхЗаписей; ♦ МакетОбщихИтогов; ♦ МакетПодвалаТаблицы; ♦ МакетПодвалаОтчета. В эти свойства могут быть переданы либо имя области макета построителя отчета, либо сам макет (таблич- ный документ) для вывода этой области. Работа с этими
свойствами не влияет на процесс автоматической генера- ции макета построителя отчета. Однако результат запроса будет выводиться в области, указанные в этих свойствах, или же будут использованы области макета, определен- ные в этих свойствах. В случае если область с таким име- нем не обнаружена в макете построителя отчета, вывод будет осуществляться в область со стандартным именем. Например, можно задать фиксированный макет для вы- вода детальных записей (листинг 13.40). Листинг 13.40. Задание фиксированного макета для вывода детальных записей // Задать фиксированный макет детальных записей Построитель.МакетДетальныхЗаписей = Получи тьМакет("ЧерноБелыйМакет”). ПолучитьОбласть("ДетальныеЗаписи”); Также можно назначить область макета построителя от- чета, в которую будут выводиться детальные записи (лис- тинг 13.41). Листинг 13.41. Назначение области для вывода детальных записей // Назначить область для вывода детальных записей Построитель.Макет = ПолучитьМакетС'ЧерноБелыйМакет"); Построитель.МакетДетальныхЗаписей = "ДетальныеЗаписи"; Во-вторых, фиксированные макеты могут быть определены для каждого из измерений построителя отчета, содержа- щегося в коллекциях ИзиеренияСтроки или ИзмеренияКолонки. Для этого используются свойства объекта ИзиерениеПо- строителяОтчета: ♦ Макет, » МакетИерархии, ♦ МакетПодвала, » МакетПодвалаИерархии, ♦ макетыУровней, ♦ МакетыПодваловУровней. При выводе результата запроса будут использоваться ма- кеты, указанные в этих свойствах, или области макета по- строителя отчета (если в этих свойствах указаны имена областей). В случае если области с такими именами от- сутствуют в макете построителя отчета, будет выполнять- ся вывод в области со стандартными именами. Например, можно задать фиксированный макет для выво- да иерархических записей номенклатуры (листинг 13.42). Листинг 13.42. Задание макета для вывода иерархии номенклатуры //Задать макет для вывода иерархии номенклатуры Построитель.ИзиеренияСтроки.Найти("Номенклатура"). МакетИерархии = ПолучитьМакетС"ЧерноБелыйМакет"). ПолучитьОбласть("ИерархияНоменклатуры"); Также для вывода иерархических записей номенклатуры можно назначить область существующего макета (лис- тинг 13.43). Листинг 13.43. Назначение существующей области макета для вывода иерархии номенклатуры // Назначить область для вывода иерархии номенклатуры Построитель.Макет = ПолучитьМакетС'ЧерноБелыйМакет"); Построитель.ИзиеренияСтроки.Найти(“Номенклатура"). МакетИерархии = "ИерархияНоменклатуры": Макет оформления и оформление Макет оформления Макет оформления представляет собой табличный документ с областями, имеющими стандартные имена. Эти области будут использованы построителем отчета для оформле- ния определенных областей макета. Макет оформления может быть получен на основе одного из стандартных оформлений, поддерживаемых платформой, или создан разработчиком самостоятельно. Внешний вид макета оформления представлен на рис. 13.38. Этот макет получен на основе стандартного оформления Асфальт (листинг 13.44). Листинг 13.44. Отображение макета оформления Асфальт // Получить макет оформления Асфальт как табличный документ ПолучитьМакетОформления(СтандартноеОформление.Асфальт). Показать О; Заголовок Шапка таблицы 11 руппироака уровень 1 И ('Ресурсы итог уровень 1 1 _ [Ресурсы уровень 2 □ Рааувхытаг урааапь / |Г руппировш уровень 3 J [Ресурсы уровень 3 | [Ресурсы итог урооеньЗ | Группировка иерархия J [Ресурсы иерархия J [Ресурсы итог иерархия [ [Группировка J [Ресурсы | [Ресурсы итог | | Группировка детаты j |Ресурсы группировка детали | [Ресурсы итог группировка детали] [Детали J |Ресурсы детали | [Ресурсы итог детали [ [Группировке подвал J [Ресурсы подвал | [Ресурсы итог подвал ] [Группировка подвал иерархия J [Ресурсы подвал иерархия | [Ресурсы итог подвал иерархия | |Г руппировкв подвая уровень 3 J [Ресурсы подвал уровень 3 | [Ресурсы итог подвая ^ювень frppwMpo— мд— увввень t ! [Ресурсы подвая уровень 2 11 (туппировка подвал уровень 1 1 | Ресурсы итог поднял уровень 1] СЫ ОЬщиИ итог Ресурсы итог общий итог Подвал таблицы Рис. 13.38. Макет оформления Асфальт При модификации стандартных макетов оформления или при создании собственного следует учитывать, что не все оформительские свойства ячеек макета оформления будут применены к оформляемому макету. Не будут использованы следующие свойства области ячеек табличного документа: ♦ Формат, ♦ РазмещениеТекста, ♦ ГоризонтальноеПоложение, » ПоВыделеннымКолонкам, ♦ ОриентацияТекста, ♦ ВыделятьОтрицательные, ♦ АвтоОтметкаНезаполненного. Оформление макета При оформлении макета построителя отчета каждая об- ласть, содержащаяся в макете, оформляется с использо- ванием соответствующих областей макета оформления.
Оформление макета линейного отчета При оформлении макета линейного отчета используются следующие области макета оформления (табл. 13.5). При оформлении макета линейного отчета в него бу- дут добавлены оформленные области, перечисленные в табл. 13.6. Если области с такими именами уже сущест- вуют в макете, эти области будут оформлены с исполь- зованием соответствующих областей макета оформле- ния. Оформление макета кросс-отчета При оформлении макета кросс-отчета используются сле- дующие области макета оформления (табл. 13.7). При оформлении макета кросс-отчета в него будут добав- лены оформленные области, перечисленные в следующей таблице (табл. 13.8). Если области с такими именами уже существуют в макете, эти области будут оформлены с ис- пользованием соответствующих областей макета оформ- ления. Таблица 13.5. Оформление макета линейного отчета Области макета линейного отчета Области макета оформления Примечание Заголовок Заголовок ШапкаТаблицы ШапкаТаблицы «имя измерения>Иерархия ГруппировкаИерархия Если итоги в заголовке, то используются две области: ГруппировкаИерархия и РесурсыИтогИерархия «имя измерения» Группировка и Ресурсы «имяизмерения»Подвал Г руппировкаПодвал Если итоги в подвале, то используются две области: ГруппировкаПодвал и РесурсыИтогПодвал «имя измерения»ПодвалИерархия ГруппировкаПодвалИерархия Если итоги в подвале, то используются две области: ГруппировкаПодвалИерархия и РесурсыИтогПодвалИерархия ОбщиеИтоги ОбщиеИтоги ПодвалТаблицы ПодвалТаблицы Подвал Не оформляется Таблица 13.6. Области, добавляемые при оформлении макета линейного отчета Области макета линейного отчета Области макета оформления Примечание «имя измерения>Уровень1 ГруппировкаУровень! Если итоги в заголовке, то используются две области: ГруппировкаУровень! и РесурсыИтогУровень1 «имя измерения>Уровень2 Г руппировкаУровень2 Если итоги в заголовке, то используются две области: ГруппировкаУровень2 и РесурсыИтогУровень2 «имя измерения>УровеньЗ ГруппировкаУровеньЗ Если итоги в заголовке, то используются две области: ГруппировкаУровеньЗ и РесурсыИтогУровеньЗ Детали Детали и РесурсыДетали «имя измерения>ПодвалУровень1 ГруппировкаПодвалУровень1 Если итоги в подвале, то используются две области: ГруппировкаПодвалУровень! и РесурсыИтогПодвалУровенЫ «имя измерения>ПодвалУровень2 ГруппировкаПодвалУровень2 Если итоги в подвале, то используются две области: ГруппировкаПодвалУровень2 и РесурсыИтогПодвалУровень2 «имя измерения>ПодвалУровеньЗ ГруппировкаПодвалУровеньЗ Если итоги в подвале, то используются две области: ГруппировкаПодвалУровеньЗ и РесурсыИтогПодвалУровеньЗ
Таблица 13.7. Оформление макета кросс-отчета Области макета кросс-отчета Области макета оформления Заголовок Заголовок ШапкаСтрок ШапкаТаблицы ЗаголовокИтогаПоСтроке ШапкаТаблицы <группировка>Иерархия ГруппировкаИерархия <группировка> Группировка <группировка>Подвал ГруппировкаПодвал <группировка>ПодвалИерархия ГруппировкаПодвалИерархия РесурсыИерархия РесурсыИерархия Ресурсы Ресурсы РесурсыПодвал РесурсыПодвал РесурсыПодвалИерархия Ресурсы Подвал Иерархия РесурсыИтогПоСтрокеИерархия РесурсыИтогИерархия РесурсыИтогПоСтроке Ресурсы Итог РесурсыИтогПоСтрокеПодвал РесурсыИтогПодвал РесурсыИтогПоСтрокеПодвалИерархия РесурсыИтогПодвалИерархия ЗаголовокИтогаПоКолонке ОбщиеИтоги РесурсыИтогПоКолонке РесурсыОбщийИтог ОбщиеИтоги РесурсыИтогОбщийИтог ПодвалТаблицы ПодвалТаблицы Подвал Не оформляется Таблица 13.8. Области, добавляемые при оформлении макета кросс-отчета Области макета кросс-отчета Области макета оформления <группировка>Уровень1 ГруппировкаУровень! <группировка>Уровень2 ГруппировкаУровень2 <группировка>УровеньЗ Г руппировкаУровеньЗ <группировка>ПодвалУровень1 ГруппировкаПодвалУровень! <группировка>ПодвалУровень2 ГруппировкаПодвалУровень2 <группировка>ПодвалУровеньЗ ГруппировкаПодвалУровеньЗ РесурсыУровень! РесурсыУровень! РесурсыУровень2 РесурсыУровень2 РесурсыУровеньЗ РесурсыУровеньЗ РесурсыГруппировкаДетали РесурсыГруппировкаДетали РесурсыПодвалУровень! РесурсыПодвалУровень! РесурсыПодвалУровень2 РесурсыПодвалУровень2 РесурсыПодвалУровеньЗ РесурсыПодвалУровеньЗ Ресурсы Ито гП оСтро кеУ ро вен ь 1 РесурсыИтогУровень! РесурсыИтогПоСтрокеУровень2 РесурсыИтогУровень2 РесурсыИтогПоСтрокеУ ровен ьЗ Ресурсы ИтогУровеньЗ
Области макета кросс-отчета Области макета оформления Ресурсы ИтогПоСтрокеГруппировкаДетали Ресурсы ИтогГруппировкаДетали Ресурсы ИтогПоСтрокеПодвалУ ровен ь1 РесурсыИтогПодвалУровень! РесурсыИтогПоСтрокеПодвалУровень2 РесурсыИтогПодвалУровень2 РесурсыИтогПоСтрокеПодвалУровеньЗ Ресурсы ИтогПодвалУровеньЗ <группировка>РесурсыУровень1 РесурсыУровень! <группировка>РесурсыУровень2 РесурсыУровень2 <группировка>РесурсыУровеньЗ РесурсыУровеньЗ <группировка>РесурсыГруппировкаДетали РесурсыГруппировкаДетали <группировка>РесурсыПодвалУровень1 РесурсыПодвалУровень! <группировка>РесурсыПодвалУровень2 РесурсыПодвалУровень2 <группировка>РесурсыПодвалУровеньЗ РесурсыПодвалУровеньЗ <группировка>РесурсыИтогПоСтрокеУровень1 РесурсыИтогУровень! <группировка>РесурсыИтогПоСтрокеУровень2 РесурсыИтогУровень2 <группировка>РесурсыИтогПоСтрокеУровеньЗ Ресурсы Ито гУ ро вен ь 3 <группировка>РесурсыИтогПоСтрокеГруппировкаДетали Ресурсы ИтогГруппировкаДетали <грулпировка>РесурсыИтогПоСтрокеПодвалУровень1 РесурсыИтогПодвалУровень! <группировка>РесурсыИтогПоСтрокеПодвалУровень2 РесурсыИтогПодвалУровень2 <группировка>РесурсыИтогПоСтрокеПодвалУровеньЗ РесурсыИтогПодвалУровеньЗ Условное оформление Механизм условного оформления построителя отчета по- зволяет оформлять отчет, выводимый в табличный доку- мент или поле табличного документа, в зависимости от значений полей отчета. Можно настроить такие свойства ячеек табличного документа, как цвет текста, цвет фона, шрифт, формат значения, выделение отрицательных чи- сел и др. Например, желтым фоном выделить количество товаров, расход которых меньшее 10 штук, а красным текстом вы- делить строки, в которых расход товаров из группы про- дукты меньше 100 штук. ловия отборов, при выполнении которых будет происхо- дить оформление, и набор настроек оформления, которые будут применяться к оформляемой области (рис. 13.39). Интерактивная настройка условного оформления Для того чтобы пользователь мог производить настройку условного оформления, в форме следует расположить табличное поле и связать его со свойством построителя отчета УсловноеОформление (если построитель отчета явля- ется реквизитом формы) (рис. 13.40). П остроительОтчета УсловноеО кормление УсловноеОформление Элементу слоеногоО Формления Область Отбор О бластьО Формления Э лементОбластиО Форм ления Оформление Отбор ЭлементОтбора Н астройкаОформления ЭлементН астройкиО Форм ления Рис 13.39. Коллекция значений УсловноеОформление Условное оформление задается коллекцией Условное- Оформление, состоящей из объектов ЭлеиентУсловногоОфори- ления. Каждый элемент условного оформления позволяет описать набор областей, которые будут оформляться, ус- Рис. 13.40. Условное оформление — связь с данными Если построитель отчета создается программно, следует установить нужный тип и значение элемента управления табличное поле, отображающего условное оформление. Фрагмент кода, выполняющего программную связь на- стройки построителя с табличным полем, представлен в разделе «Настройка построителя отчета интерактивны- ми средствами», с. 424.
Программная настройка условного оформления Состав полей, которые будут доступны для использова- ния в условном оформлении, определяется, как и для ос- тальных настроек построителя отчета, доступными поля- ми построителя отчета по следующим правилам: ♦ для выбора в качестве области условного оформления будут доступны поля, разрешенные для выбора в каче- стве полей или в качестве измерений построителя отчета; ♦ для задания условий отбора будут доступны поля, разре- шенные для выбора в качестве полей построителя отчета. Условное оформление построителя отчета доступно че- рез свойство построителя УсловноеОформление, которое со- держит коллекцию УсловноеОформление. Эта коллекция об- ладает методами, позволяющими добавлять, удалять и изменять порядок следования объектов ЭлементУсловного- Оформления, из которых состоит эта коллекция. Задача разработчика состоит в том, чтобы добавить в эту коллекцию необходимое количество элементов условно- го оформления. Каждый элемент условного оформления обладает определенным набором свойств (рис. 13.41). УсловноеОформление Заголовок Имя Использование Область Отбор Оформление Рис. 13.41. Свойства элемента условного оформления Заголовок — позволяет задать наименование элемента ус- ловного оформления, понятное для пользователя. Напри- мер, «Выделять малое количество продаж красным». За- головки удобно использовать, если в отчете формируется некоторый набор вариантов условного оформления и пользователю предлагается выбрать один или некоторые из них. В этом случае табличное поле, отображающее ус- ловное оформление построителя отчета, может содер- жать только два поля: Использование и Заголовок. Имя — позволяет обращаться к элементам условного оформ- ления по имени из встроенного языка. Использование — признак использования данного элемента условного оформления. Область, Отбор и Оформление — это три свойства, которые и определяют, собственно, изменения, которые должны быть выполнены в табличном документе данным элемен- том условного оформления. Область — это то, что будет оформлено, отбор — это условие, при котором будет вы- полнено это оформление, а оформление — это то, как нужно оформить указанную область. Например, область — поле Склад, отбор — КоличествоРас- ход меньше 100, оформление — серый фон. При добавлении элементов условного оформления в кол- лекцию важно помнить, что по умолчанию свойство Ис- пользование у элемента условного оформления сброшено, поэтому его нужно устанавливать в явном виде. Напри- мер, добавление элемента условного оформления в кол- лекцию может быть выполнено при помощи следующего кода (листинг 13.45). При добавлении нескольких элементов условного оформ- ления следует учитывать, что оформление будет выпол- няться в том порядке, в котором следуют элементы коллекции. Чтобы добавить новый элемент в нужную по- зицию коллекции, можно использовать метод Вставить!), а для изменения позиции существующего элемента — ме- тод Сдвинуть!). В методе Вставить!) указывается позиция, в которую необходимо вставить элемент условного оформ- ления, а в методе Сдвинуть!) — сам элемент условного оформления, который требуется сдвинуть, и количество позиций, на которые он должен быть сдвинут. Листинг 13.45. Добавление элемента условного оформления // Установить условное оформление отчета НоваяНастройкаОформления = Построитель.УсловноеОформление.Добавить!"КрасныйЦвет"); НоваяНастройкаОформления.Заголовок = "Малый расход красным"; НоваяНастройкаОформления.Использование = Истина: Область оформления Область представляет собой объект ОбластьОфориления. Это коллекция значений, которая состоит из объектов Элемент- ОбластиОформления (рис. 13.42). У ловное О формление Заголовок Имя Исполь5ование Область Отбор Оформление Область Оформления Заголовок ПутьКДанным ТипОбласти Рис. 13.42. Коллекция значений ОбластьОформления Каждый элемент области оформления содержит следую- щие свойства: Заголовок — название данной области для пользователя; ПутьКДанныи — имя поля результата запроса или имя груп- пировки, к которой будет применено оформление; ТипОбласти — принимает значения системного перечисле- ния ТипОбластиОфориления: Группировка или Поле. Отличие этих двух типов областей проще всего продемонстриро- вать на примере. В первом случае заданы два условия: ♦ группировка Номенклатура выделяется серым фоном, если КоличествоРасход меньше 15; ♦ группировка Склад выделяется серым фоном, если Коли- чествоРасход меньше 100 (рис. 13.43). Во втором случае те же самые условия применяются не к группировкам, а к полям Номенклатура и Склад (рис. 13.44). Использование различного сочетания элементов области оформления позволяет оформлять различные логические области отчета. Оформление отчета целиком Чтобы оформить все области отчета, удовлетворяющие некоторому условию, необходимо коллекцию область оформления оставить пустой. Например, так будет выглядеть оформление отчета с ус- ловием, что значение поля КоличествоРасход меньше 130 (рис. 13.45).
_ □ X [Номенклатура Инвентарь Метла Лопата Мотоблок Грабли Обувь Бытовая техника Кухонные электроприборы Холодильники, моротильные камеры Вентиляторы, пылесосы, кондиционеры Телевизоры Телевизор "JVC* Продукты Сборка компьютеров Комплектующие Клавиатура Мывь Системный блок Монитор Итог ] Главный склад Торговый зал Склад электротоваров Розничный магазин № 2 Итог 25,000 25,000 6,000 5.000 6,000 6,000 4,000 4,880 ю.ооо чо.оот 186.000 186,000 71,000 139,000 216,000 32,000 32,000 30,000 38,000 27,000 107.000 134,000 6,000 6,000 6J000 6,000 35,000 104,000 139,000 17,000 17,000 17,000 17,000 5,000 5,080 5,000 5,080 5,000 5,080 2,000 2,000 309,000 104,000 138,000 25,000 577,000 Рис. 13.43. Оформление группировок Рис. 13.44. Оформление полей Оформление поля отчета Чтобы оформить только определенное поле отчета, необ- ходимо, чтобы элемент области оформления имел тип Поле (табл. 13.9). Например, так будет выглядеть оформление поля Количе- ствоРасход с условием, что значение поля КоличествоРас- ход меньше 130 (рис. 13.46). Таблица 13.9. Состав коллекции ОбластьОформления ПутьКДанным ТипОбласти КоличествоРасход Поле Оформление группировки отчета Чтобы оформить целиком группировку, необходимо, что- бы элемент области оформления имел тип Группировка (табл. 13.10). Например, так будет выглядеть оформление группировки Склад с условием, что значение поля КоличествоРасход меньше 130 (рис. 13.47). Рис 13.45. Пример оформления всего отчета
_ОХ Е Е В EJ В в [Склад Оптовые склады Главный склад Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Розничные склады Торговый пл Торговый зал Торговый зал Торговый зал Торговьй зал Торговый зал Торговый зал Торговый зал Торговый зал Розничный магазин Не 2 Розничный магазин № 2 Розничный магазин № 2 Розничный магазин № 2 Розничный магазин № 2 Итог | Номенклатура Комбайн кухонный BINATONE FP 67 Кофеварка 0RAUN KF22R Вентилятор BINATONE ALPINE 160вт, налольньй Вентилятор ЛРОМС (Тай в ), Вентилятор настольный Комбайн MOULINEX А774С Вентилятор оконный Вентилятор OPBWTA.STERLNG.Bn Кондиционер БК-2300 Пылесос “Электросила" Барбарис (конфеты) Причуда (вафли) Принц (печенье) Ассорти (конфеты) Сердечко (печенье) Фруктовые (вафли) Грильяж (конфеты) Миика (конфеты) Метла Лопата Мотоблок Грабли |КоличествоРаскод~] 448,080 309,000 139,000 13,000 6,000 32 ДЮ 24,000 18 ДЮ 13.000 9,000 13ДЮ 5 ДЮ 5 ДЮ 129,000 104,008 зо дю 25 ДЮ 4 ДЮ 10.000 5 ДЮ 5 ДЮ 11 ДЮ 14 ДЮ 25,000 5ДЮ 6 ДЮ 4 ДЮ 10ДЮ 577,000 Например, так будет выглядеть оформление поля Количе- ствоРасход в группировке Склад с условием, что значение поля КоличествоРасход меньше 130 (рис. 13.48). Рис. 13.46. Пример оформления поля [Склад Оптовые склады Главный склад Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Склад электротоваров Ротничные склады Торговый тал Торговый зал Торговый зал Торговый зал Торговый зал Торговый зал Торговый зал Торговый зал Торговый зал Розничный магазин Не 2 Розничный магазин № 2 Розничный магазин № 2 Розничный магазин № 2 Розничный магазин №2 Итог [Номенклатура Комбайн кухонный BINATONE FP 67 Кофеварка 0RAUN KF22R Вентилятор BINATONE ALPWE 160вт, напольный . Вентилятор ЛРОМС (Тайв.). Вентилятор настольный Комбайн MOULNEX А774С Вентилятор оконный Вентилятор OPbUTA.STERLING.Fffl Кондиционер БК-2300 Пылесос “Электросила" Барбарис (конфеты) Причуде (вафли) Принц (печенье) Ассорти (конфеты) Сердечко (печенье) Фруктовые (вафли) Грильяж (конфеты) Миика (конфеты) Метла Попета Мотоблок Грабли [КоличествоРаскод"] 448,000 309,000 139,000 13,000 Б ДЮ 32,000 24.000 19,000 13.000 9,000 13,000 5,000 5.000 129,8М 104*090 зо.ооо 25,000 4.000 10,000 5,000 5,000 11,000 14.000 25,9М 5,000 6.000 4.000 10,000 577,000 Таблица 13.10. Состав коллекции ОбластьОформления ПутьКДанным ТипОбласти Склад Группировка Рис. 13.48. Пример оформления поля в группировке Рис. 13.47. Пример оформления группировки Оформление области детальных записей Чтобы оформить область детальных записей, необходи- мо, чтобы элемент области оформления имел тип Группи- ровка и пустое свойство ПутьКДанным (табл. 13.12). Таблица 13.12. Состав коллекции ОбластьОформления ПутьКДанным ТипОбласти Группировка Например, так будет выглядеть оформление детальных записей с условием, что значение поля КоличествоРасход меньше 130 (рис. 13.49). Оформление поля в группировке отчета Чтобы оформить определенное поле в группировке, необ- ходимо, чтобы коллекция ОбластьОформления содержала два элемента: элемент, имеющий тип Группировка, и элемент, имеющий тип Поле (табл. 13.11). Таблица 13.11. Состав коллекции ОбластьОформления ПутьКДанным ТипОбласти Склад Группировка КоличествоРасход Поле Рис. 13.49. Пример оформления детальных записей
Для того чтобы задать область оформления, нужно в коллек- цию ОбластьОформления добавить необходимое количество эле- ментов, описывающие те области, которые будут оформлять- ся. Обратите внимание, что оформляемая область для одного элемента условного оформления может описываться не- сколькими элементами области оформления (например, оформляться будут несколько различных полей отчета). Например, чтобы оформить поле КоличествоРасход, мож- но выполнить следующий код (листинг 13.46). Листинг 13.46. Пример оформления поля // Установить условное офорнление отчета НоваяНастройкаОформления = Построитель.УсловноеОформление.Добавить("КрасныйЦвет"); НоваяНастройкаОформления.Заголовок = "Малый расход красным"; НоваяНастройкаОформления.Использование = Истина; НоваяОбласть = НоваяНастройкаОформления.Область. ДобавитьСКоличествоРасход"); НоваяОбласть.ТипОбласти = ТипОбластиОформления.Поле; Отбор оформления Свойство Отбор элемента условного оформления пред- ставляет универсальный объект Отбор, работа с которым подробно рассматривалась в разделе «Отбор», с. 428. Сле- дует лишь отметить, что можно использовать несколько элементов отбора, при этом условия, задаваемые каждым из элементов, будут объединяться по И. Также следует помнить, что свойство Использование у добавляемых эле- ментов отбора по умолчанию сброшено, поэтому его нуж- но устанавливать в явном виде. Например, можно добавить условие, что оформление бу- дет применяться в случае, когда значение поля Количес- твоРасход меньше 15 (листинг 13.47). Листинг 13.47. Пример задания отбора условного оформления // Установить условное оформление отчета НоваяНастройкаОформления = Построитель.УсловноеОформление.ДобавитьС"КрасныйЦвет"); НоваяНастройкаОформления.Заголовок = "Малый расход красным"; НоваяНастройкаОформления.Использование = Истина: НоваяОбласть = НоваяНастройкаОформления.Область. ДобавитьСКоличествоРасход"): НоваяОбласть.ТипОбласти = ТипОбластиОформления.Поле; НовыйОтбор = НоваяНастройкаОформления.Отбор. ДобавитьСКоличествоРасход”); НовыйОтбор.ВидСравнения = ВидСравнения.Меньше; НовыйОтбор.Значение = 15: НовыйОтбор.Использование = Истина; Настройка оформления Свойство Оформление представляет собой объект Настрой- каОформления. Этот объект является фиксированной кол- лекцией, то есть эта коллекция содержит определенное количество элементов, которые создаются системой; раз- работчик не имеет возможности добавлять или удалять элементы фиксированной коллекции, он может только изменять некоторые свойства имеющихся элементов кол- лекции (рис. 13.50). Каждый объект этой коллекции, — ЭлементНастройкиОформле- ния, — имеет имя, по которому возможно обращение к данно- му элементу. Имя и ТипЗначения — это свойства, которые разра- ботчик может только прочитать. Остальные свойства эле- ментов настройки оформления доступны для изменения. Условное© формление Заголовок Имя Использование Область Отбор Оформление Отбор ОбластьОформления Заголовок ПутъКДанным ТипОбласти НастройкаОформления Заголовок Значение Имя Использование ТипЗначения ЦветТекста ЦветФона Шрифт Формат Г оризонтальное Положение Вертикальное Положение ОриентацияТекста Отступ Лвтоотступ Выделять Отрицательное Текст Рис. 13.50. Коллекция значений НастройкаОформления Заголовок — задает название элемента настройки оформ- ления. Значение — содержит значение, которым будет оформлять- ся выбранная область. Для каждого элемента настройки оформления значение имеет свой тип, который хранится в свойстве ТипЗначения. Имена элементов настроек совпада- ют с соответствующими свойствами области ячеек таблич- ного документа, поэтому при установке значений следует руководствоваться описаниями этих свойств (табл. 13.13). Настройка оформления также может использовать не- сколько элементов (например, выделение другим цветом и жирным шрифтом). Для этого у соответствующих эле- ментов настройки оформления нужно установить свойст- во Использование (по умолчанию оно сброшено), и задать свойство Значение. Например, можно добавить выделение значения поля красным цветом (листинг 13.48). Листинг 13.48. Пример задания оформления // Установить условное оформление отчета НоваяНастройкаОформления = Построитель.УсловноеОформление. ДобавитьС"КрасныйЦвет"): НоваяНастройкаОформления.Заголовок = "Малый расход красным"; НоваяНастройкаОформления.Использование = Истина: НоваяОбласть = НоваяНастройкаОформления.Область.ДобавитьС"КоличествоРасход"); НоваяОбласть.ТипОбласти = ТипОбластиОформления.Поле; НовыйОтбор = НоваяНастройкаОформления.Отбор. ДобавитьСКоличествоРасход"): НовыйОтбор.ВидСравнения = ВидСравнения.Меньше; НовыйОтбор.Значение = 15: НовыйОтбор.Использование = Истина; НоваяНастройкаОформления.Оформление.ЦветТекста.Значение = ЫеЬЦвета.Красный; НоваяНастройкаОформления.Оформление.ЦветТекста.Использование = Истина;
Таблица 13.13. Значения элементов настройки оформления Элемент настройки оформления Тип Значения Описание значения ЦветТекста ЦветФона Цвет Содержит цвет текста в ячейках области. Объект Цвет может быть получен, например, как значение системных наборов значений ЫЕВЦвета, НтпсЫзЦвета, или создан с помощью конструктора Шрифт Шрифт Содержит шрифт ячеек области. Объект Шрифт может быть создан, например, с помощью конструктора Формат Строка Содержит строку, задающую формат вывода данных в ячейках таблицы Г оризонтальноеПоложение Г оризонтальноеПоложение Содержит способ горизонтального выравнивания текста в области. Является значением соответствующего системного перечисления: Авто, Лево, ПоШирине, Право, Центр ВертикальноеПоложение ВертикальноеПоложение Определяет способ вертикального выравнивания текста в ячейках области. Является значением соответствующего системного перечисления: Верх, Низ, Центр ОриентацияТ екста Число Содержит угол наклона текста по отношению к горизонтальному положению в градусах Отступ Число Отступ текста от края ячейки в символах Автоотступ Число Содержит отступ текста от края ячейки в символах в зависимости от уровня группировки ВыделятьОтрицательное Булево Содержит признак выделения текста ячеек, содержащего отрицательные числа, специальным цветом стиля ЦветОтрицательногоЧисла Текст Строка Содержит значение текста ячеек области. Этот элемент условного оформления будет применен даже в том случае, если ячейка, в которую выводится значение поля, содержит некоторое значение (свойство СодержитЗначение равно Истина) Также следует заметить, что, как и для порядка и отбора построителя отчета, не имеет смысла использовать методы ПолучитьДоступныеПоляО и УстановитьДоступныеПоляО объек- тов УсловноеОформление, ОбластьОформления и Отбор (свойство Отбор элемента условного оформления), поскольку для них доступными полями будут являться доступные поля построителя отчета (рис. 13.51). ление отчета, следует учитывать последовательность вы- полнения этих операций. Оформление макета построителя отчета выполняется либо в момент присвоения значения свойству МакетОформления (если используется макет построителя, генерируемый по умолчанию), либо при выполнении метода ОформитьМакетО, если используется макет, назначаемый разработчиком. Рис. 13.51. Доступные поля условного оформления Совместное использование оформления и условного оформления отчетов Если одновременно используется как оформление отчета с помощью макетов оформления, так и условное оформ- Рис. 13.52. Оформление и условное оформление построителя отчета
Таким образом, при выводе результата запроса в таблич- ный документ построитель отчета будет использовать уже оформленный макет, на основании которого и фор- мируется табличный документ. Условное оформление также задается до вывода резуль- тата отчета в табличный документ, однако применяется непосредственно к самому табличному документу, кото- рый формируется на основе оформленного ранее макета (рис. 13.52). По этой причине условное оформление всегда будет «пе- рекрывать» оформление, полученное за счет макета по- строителя отчета. Вывод в табличный документ Размещение измерений Свойство построителя отчета РазмещениеИзмеренийВСтроках по- зволяет управлять тем, сколько колонок будет создано в ре- зультирующем табличном документе для отображения изме- рений и каким образом будут размещены значения в этих колонках. Это свойство может принимать три значения: ♦ Вместе; ♦ Отдельно; ♦ ОтдельноИТолькоВИтогах. В случае если выбрано значение Отдельно (листинг 13.49), результирующий табличный документ будет иметь, на- пример, следующий вид (рис. 13.53). Листинг 13.49. Размещение измерений отдельно // Размещать измерения в разных колонках Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений. Отдельно; В данном примере каждое из измерений, по которому вы- полняется группировка, будет выведено в отдельную ко- лонку, причем в каждой строке отчета будет выведено значение этого измерения. В случае если выбрано значение ОтдельноИТолькоВИтогах (листинг 13.50), результирующий табличный документ будет иметь, например, следующий вид (рис. 13.54). Листинг 13.50. Размещение измерений отдельно и только в итогах // Размещать измерения в разных колонках и только в итогах Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.ОтдельноИТолькоВИтогах; В данном примере каждое из измерений, по которому вы- полняется группировка, также будет выведено в отдельную колонку, однако значения измерений будут выведены только в строках, в которых выводятся итоги по группировке. В случае если выбрано значение Вместе (листинг 13.51), результирующий табличный документ будет иметь, на- пример, следующий вид (рис. 13.55). Листинг 13.51. Размещение измерений вместе // Размещать измерения в одной колонке Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Рис 13.53. Размещение измерений отдельно Рис. 13.54. Размещение измерений отдельно и только в итогах
Рис. 13.55. Размещение измерений вместе В данном примере оба измерения, по которым выполня- ется группировка, будут выведены в одной колонке ре- зультирующего отчета. Аналогичным образом, при выводе кросс-отчета можно управлять размещением измерений в колонках результи- рующего табличного документа. Для этого используется свойство РазмещениеИзмеренийВКолонках построителя отчета. Размещение итогов Свойство построителя отчета РазмещениеИтоговВСтроках по- зволяет управлять тем, в каких строках результирующего отчета будут расположены итоги по группировкам. Это свойство может принимать четыре значения: ♦ Заголовок; ♦ ЗаголовокИПодвал; ♦ Подвал; ♦ ТолькоПодвал. В случае если выбрано значение Заголовок (листинг 13.52), результирующий табличный документ будет иметь, на- пример, следующий вид (рис. 13.56). В данном примере для каждой группировки итоги будут выведены в заголовке группировки вместе со значением самой группировки. Листинг 13.52. Размещение итогов в заголовках группировок // Размещать итоги в заголовках группировок Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Построитель.РазмещениеИтоговВСтроках = ТипРазмещенияИтогов.Заголовок; Рис. 13.56. Размещение итогов в заголовках группировок В случае если выбрано значение ЗаголовокИПодвал (лис- тинг 13.53), результирующий табличный документ будет иметь, например, следующий вид (рис. 13.57). Листинг 13.53. Размещение итогов в заголовках и подвале группировок И Размещать итоги в заголовках и подвалах группировок Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе: Построитель.РазмещениеИтоговВСтроках = ТипРазмещенияИтогов.ЗаголовокИПодвал; Рис. 13.57. Размещение итогов в заголовках и подвале группировок В данном примере для каждой группировки итоги будут выведены как в заголовке, так и в подвале группировки вместе со значением самой группировки. В случае если выбрано значение Подвал (листинг 13.54), результирующий табличный документ будет иметь, на- пример, следующий вид (рис. 13.58). Рис. 13.58. Размещение итогов в подвале группировок
Листинг 13.54. Размещение итогов в подвале группировок // Размещать итоги в подвалах группировок Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Построитель.РазмещениеИтоговВСтроках = ТипРазмещенияИтогов.Подвал: В данном примере для каждой группировки итоги будут выведены только в подвале группировки, в то время как значение группировки будет выведено как в заголовке, так и в подвале группировки. В случае если выбрано значение ТолькоПодвал (листинг 13.55), результирующий табличный документ будет иметь, на- пример, следующий вид (рис. 13.59). Листинг 13.55. Размещение итогов только в подвале // Размещать итоги только в подвалах группировок Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Построитель.РазмещениеИтоговВСтроках = ТипРазмещенияИтогов.ТолькоПодвал; Построитель.Выполнить(); РезультирующийДокумент = Новый ТабличныйДокунент; Построитель.Вывести(РезультирующийДокумент); // Изменить расположение маркеров горизонтальных секций РезультирующийДокумент.ИтогиСнизу = Истина; РезультирующийДокумент. Показать О; Рис. 13.59. Размещение итогов только в подвале В данном примере для каждой группировки итоги будут выведены только в подвале группировки, вместе со значе- нием этой группировки. В этом случае нужно учесть, что заголовки группировок не выводятся, поэтому нужно изменить установленное по умолчанию, расположение маркеров горизонтальных секций в результирующем табличном документе на рас- положение их внизу группировки (листинг 13.56). Листинг 13.56. Изменение расположения маркеров горизонтальных секций // Изменить расположение маркеров горизонтальных секций РезультирующийДокумент. ИтогиСнизу = Истина; Аналогичным образом, при выводе кросс-отчета можно управлять размещением измерений в колонках результи- рующего табличного документа. Для этого используется свойство РазмещениеИтоговВКолонках построителя отчета. Размещение реквизитов измерений Под реквизитами измерений понимаются поля, кото- рые получаются в запросе «через точку» от полей изме- рений. Свойство построителя отчета РазмещениеРеквизитовИзмере- нийВСтроках позволяет управлять тем, сколько колонок бу- дет создано в результирующем табличном документе для отображения реквизитов измерений и каким образом бу- дут размещены значения в этих колонках. Это свойство может принимать три значения: ♦ Вместе; ♦ ВместеСИзмерениями; ♦ Отдельно. В случае если выбрано значение Отдельно (листинг 13.57), результирующий табличный документ будет иметь, на- пример, следующий вид (рис. 13.60). Листинг 13.57. Расположение реквизитов отдельно И Размещать реквизиты измерений в отдельных колонках. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе: Построитель.РазмещениеИтоговВСтроках = ТипРазмещенияИтогов.Заголовок; Построитель.РазмещениеРеквизитовИзмеренийВСтроках = ТипРазмещенияРеквизитовИзмерений.Отдельно; В данном примере реквизиты измерений — код склада и код номенклатуры, — выводятся в отдельных колонках после колонки, содержащей значения измерений. Если изменить тип вывода измерений в строках (лис- тинг 13.58), то можно увидеть, что построитель форми- рует макет таким образом, что реквизиты измерения выводятся в колонке, следующей непосредственно за измерением, к которому они относятся (рис. 13.61). Листинг 13.58. Размещение реквизитов отдельно // Размещать реквизиты измерений в отдельных колонках. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений. Отдельно; Построитель.РазмещениеИтоговВСтроках = ТипРазмещенияИтогов.Заголовок; Построитель.РазмещениеРеквизитовИзмеренийВСтроках = ТипРазмещенияРеквизитовИзмерений.Отдельно; В случае если выбрано значение Вместе (листинг 13.59), результирующий табличный документ будет иметь, на- пример, следующий вид (рис. 13.62). Листинг 13.59. Размещение реквизитов вместе // Размещать реквизиты измерений в одной колонке. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Построитель.РазмещениеИтоговВСтроках = ТипРазмещенияИтогов.Заголовок; Построитель.РазмещениеРеквизитовИзмеренийВСтроках = ТипРазмещенияРеквизитовИзмерений.Вместе;
НовыйЗ * _ П X [Склад/ Код [Код [Начальный [Оборот [ [Конечный [номенклатура [склада [номенклатуры [остаток [ [остаток Оптовые склады 00006 7 067,000 7 067,000 Главный склад 00003 6 069,000 6 069,000 Тара 00055 15,000 15,000 Обувь 00012 3 519,000 3 519,000 Женская обувь 00013 2 540,800 2 540,800 Мужская обувь 00016 225,000 225,000 Кроссовки 00026 754,600 754,600 Кроссовки "ADIDAS" 00027 481,000 481,000 Кроссовки "REEBOK" 00030 231.000 231,000 Кроссовки высокие нат кожа 00033 21,000 21,000 Кроссовки мужские, кожа 00028 21,000 21,000 Бытовая техника 00043 2 285,000 2 285,000 Продукты 00003 45,000 45,000 Сборка компьютеров 00114 205,000 285,000 Склад электротоваров 00010 998,000 998,000 Ротничные склады 00069 5 611,000 5 011,000 Итог 12 078,000 12 078,000 Рис. 13.60. Расположение реквизитов отдельно Рис. 13.61. Размещение реквизитов отдельно НовыйЭ Е в Е в Е Е в Б В Lb LE Е I Склад/ [Номенклатура_________________________ Оптовые склады Г лавный склад Тара Обувь Женская обувь Мужская обувь Кроссовки Кроссовки "ADDAS" Кроссовки "REEBOK" Кроссовки высокие нат кожа Кроссовки мужские, кожа Бытовая техника Продукты Сборка компьютеров Склад электротоваров Ротничные склады Итог__________________________________ ТКод склада / (Начальный |код номенклатуры [остаток 00008 00003 00055 00012 00013 00016 00026 00027 00030 00033 00028 00043 00003 00114 00010 00008 [Оборот [Конечный J___________[остаток 7 067,044 6 000,004 15,000 3 519,000 2 540,800 225,000 754,000 481,000 231,000 21,000 21,000 2 285,000 45,000 285,000 998,000 5 611,000 12 878,008 7 067,004 6 069,000 15,000 3 519,000 2 540,000 225,000 754,000 481,000 231.000 21,000 21,000 2 205,000 46,000 205,000 998,000 5 811,000 12 678,000 □ X Рис. 13.62. Размещение реквизитов вместе В данном примере реквизиты измерений — код склада и код номенклатуры — выводятся в одной колонке после колонки, содержащей значения измерений. В случае если выбрано значение ВместеСИзмерениями (лис- тинг 13.60), результирующий табличный документ будет иметь, например, следующий вид (рис. 13.63). Листинг 13.60. Размещение реквизитов вместе с измерениями // Размещать реквизиты измерений в одной колонке. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Построитель.РазмещениеИтоговВСтроках = ТипРазмещенияИтогов.Заголовок; Построитель.РазмещениеРеквизитовИзмеренийВСтроках = ТипРазмещенияРеквизитовИзмерений.ВместеСИзмерениями:
В данном примере реквизиты измерений — код склада и код номенклатуры — выводятся в той же колонке, что и соответствующие им измерения, дополняя представле- ние значения измерения. Рис. 13.63. Размещение реквизитов вместе с измерениями Примеры и особенности использования построителя отчета Установка отбора Отбор построителя отчета допускает перечисление по- вторяющихся полей. При этом следует учитывать, что ус- ловия, указываемые в отборе построителя отчета, будут объединяться по И. Поэтому, для того чтобы узнать, например, количество поступившей обуви и бытовой техники на главный склад, не следует задавать в отборе подобное условие (рис. 13.64). |й] [01 И Поле_________ Номенклатура Номенклатура Склад Равно Тип сравнения В иерархии В иерархии Г л-збмый ст лад Рис. 13.64. Пример неправильного выбора условий отбора В тексте результирующего запроса все эти условия будут объединены по «И» (листинг 13.61). Листинг 13.61. Текст результирующего запроса ВЫБРАТЬ ТоварыНаСкладахОбороты.Номенклатура КАК Товар. ТоварыНаСкладахОбороты.Номенклатура.Представление КАК НоменклатураПредставление. ТоварыНаСкладахОбороты.КоличествоПриход КАК Приход ИЗ РегистрНакопления.ТоварыНаСкладах.ОборотыС . . . Номенклатура В ИЕРАРХИИС&Параметр!) И Номенклатура В ИЕРАРХИИ(&Параметр2) И Склад = &ПараметрЗ) КАК ТоварыНаСкладахОбороты ИТОГИ ПО ОБЩИЕ АВТОУПОРЯДОЧИВАНИЕ Поскольку один и тот же товар не может одновременно находиться как в группе Обувь, так и в группе Бытовая тех- ника, в результате запроса не будет содержаться ни одной записи. В данном случае указанное условие должно быть задано следующим образом (рис. 13.65). Рис. 13.65. Пример правильного выбора условий отбора Результирующий запрос будет выглядеть следующим об- разом (листинг 13.62). Листинг 13.62. Текст результирующего запроса ВЫБРАТЬ ТоварыНаСкладахОбороты.Номенклатура КАК Товар. ТоварыНаСкладахОбороты.Номенклатура.Представление КАК НоменклатураПредставление, ТоварыНаСкладахОбороты.КоличествоПриход КАК Приход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты!, , , Номенклатура В ИЕРАРХИИ(&Параметр1) И Склад = &Параметр2) КАК ТоварыНаСкладахОбороты ИТОГИ ПО ОБЩИЕ АВТОУПОРЯДОЧИВАНИЕ И в итоге будет получен требуемый результат: количест- во поступивших товаров, находящихся либо в группе Обувь, либо в группе Бытовая техника. Вывод дополнительной информации в отчет В случае когда необходимо вывести в отчет, формируе- мый построителем отчета, дополнительную информацию, следует внести необходимые изменения в макет, форми- руемый построителем отчета. Например, к отчету нужно добавить дату его формирова- ния в заголовке и фамилию пользователя, сформировавше- го отчет, в подвале отчета. Для этого, перед выполнением и выводом отчета, следует получить макет, автоматически ге- нерируемый построителем отчета, внести в него необходи- мые изменения и установить обратно построителю (лис- тинг 13.63). Листинг 13.63. Пример вывода дополнительной информации в отчет // Продолжить автоматическое формирование макета. Построитель.Макет = Неопределено: МакетПостроителя = Построитель.Макет; // Получить области заголовка и подвала. ОбластьЗаголовока = МакетПостроителя.ОбластьСЗаголовок"); ОбластьПодвала = МакетПостроителя.Область("Подвал"); // Вывести текст во вторую и третью строки области заголовка МакетПостроителя. Область("Р"+ Строка(0бластьЗаголовока.Верх + 1) + "С2").Текст = "Остатки товаров на складах";
МакетПостроителя. 06nacTb("R"+ Строка(0бластьЗаголовока.Верх + 2) + "С2").Текст = “по состоянию на " + ТекущаяДатаО; // Вывести текст в строку подвала МакетПостроителя. Область("Р"+ Строка(ОбластьПодвала.Верх) + "С2”).Текст = “отчет сформирован пользователем " + ИмяПользователяО; // Установить построителю измененный макет. Построитель.Макет = МакетПостроителя; Построитель.ВыполнитьО; Построитель.ВывестиО: В результате дополнительная информация в заголовке и подвале отчета будет выводиться при любых настрой- ках, выбранных пользователем (рис. 13.66 и 13.67). Остатки товаров на складах по состоянию на 22.10 200412:20:51___________ [Склад / IOctitok Номенклатура j Оптовые склады 7 067,000 Г лавный склад Б 069,004 Тара 15,000 Обувь 3 519,000 Женская обувь 2 540,000 Мужская обувь 225,000 Кроссовки 754,000 Кроссовки “ADIDAS" 481,000 Кроссовки "REEBOK" 231,000 Кроссо вкивысокиенат 21,000 кожа Кроссовки мужские, кожа 21,000 Бытовая техника 2 205,010 Продукты 46,000 Сборка компьютеров 205,000 Склад электротоваров 998,000 Розничные склады 5 811,000 Итог 12 878,000 отчет сформирован пользователем Федоров (администратор) Рис. 13.66. Пример сформированного линейного отчета Рис. 13.67. Пример сформированного кросс-отчета Изменение ширины колонок, выводимых в отчет и настройка формата Построитель отчета при автоматической генерации маке- та устанавливает ширину колонок, в которые будут выво- диться ресурсы, исходя из размерности полей, указанной в конфигураторе. Однако на реальных данных такая ши- рина колонок может быть избыточной, и возникает жела- ние уменьшить ее для того, чтобы отчеты (особенно кросс-отчеты) выглядели более компактно. Для этого следует получить макет отчета, автоматически генерируемого построителем отчета, и настроить в нем ширину нужных колонок. Кроме этого можно изменить и другие параметры макета. Например, формат отдельных ячеек и областей и положение текста в ячейках (лис- тинг 13.64). Листинг 13.64. Пример установки ширины колонок, выводимых в отчет Построитель.Текст = “ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление. ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты. КоличествоКонечныйОстаток) КАК Остаток ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, Т оварыНаСкладахОстат киИОбороты.Номен клатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММА(Остаток) ПО ОБЩИЕ, Склад ИЕРАРХИЯ. Номенклатура ИЕРАРХИЯ” Построитель.ЗаполнитьНастройкиО; // Размещать измерения в одной колонке. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; // Получить макет построителя отчета по умолчанию. Построитель.Макет = Неопределено; МакетПостроителя = Построитель.Макет; // Изменить макет. Если (Построитель.ИзиеренияСтроки.КоличествоО <> 0) И (Построитель.ИзмеренияКолонки.КоличествоО <> 0) Тогда // Формируется кросс-отчет. // Задать ширину колонок для вывода ресурсов. МакетПостроителя.ОбластьС'Ресурсы").ШиринаКолонки = 10; МакетПостроителя.Облает ь("РесурсыИтогПоСтроке"). ШиринаКолонки = 10; // Задать формат областей для вывода ресурсов. МакетПостроителя.Область("Ресурсы”).Формат = "ЧДЦ=2"; МакетПостроителя.Область("РесурсыИтогПоСтроке").Формат = “ЧДЦ=2“; МакетПостроителя.ОбластьС'РесурсыИтогПоКолонке").Формат = "ЧДЦ=2"; МакетПостроителя.ОбластьС'ОбщиеИтоги").Формат = "ЧДЦ=2“; // Задать положение заголовков ресурсов. МакетПостроителя.Область("Склад").ГоризонтальноеПоложение = ГоризонтальноеПоложение.Право: МакетПостроителя.Область("ЗаголовокИтогаПоСтроке"). ГоризонтальноеПоложение = ГоризонтальноеПоложение.Право; Иначе
И Формируется линейный отчет. ТекущаяОбласть = Неопределено; ШиринаКолонкиНеУстановлена = Истина; Пока Истина Цикл ТекущаяОбласть = МакетПостроителя.НайтиТекстС"Остаток". ТекущаяОбласть, МакетПостроителя.Область(), Истина, Истина. Истина, Ложь); Если ТекущаяОбласть <> Неопределено Тогда Если ТекущаяОбласть.Параметр = "Остаток" Тогда // Задать ширину колонок и формат ячеек для вывода // ресурсов Если ШиринаКолонкиНеУстановлена Тогда ТекущаяОбласть.ШиринаКолонки = 10; ШиринаКолонкиНеУстановлена = Ложь; КонецЕсли; ТекущаяОбласть.Формат = "ЧДЦ=2"; Иначе // Задать положение заголовока ресурсов ТекущаяОбласть.ГоризонтальноеПоложение = Гори з он т аль н оеПоложен ие.Прав о; КонецЕсли; Иначе Прервать; КонецЕсли; КонецЦикла; КонецЕсли; // Установить построителю измененный макет. Построитель.Макет = МакетПостроителя; // Оформить макет. Построитель.МакетОфориления - ПолучитьМакетОформления(СтандартноеОформление.Лед); Построитель.Оформит ьМакет(); Построитель.МакетОформления = Неопределено; // Выполнить запрос и вывести отчет. Построитель. Выполнить(); Построитель. ВывестиС); В результате приведенных выше действий линейный от- чет, формируемый на основе стандартного макета по- строителя отчета (рис. 13.68), приобретет вид, показан- ный на рис. 13.69. Кросс-отчет, формируемый построителем по умолчанию (рис. 13.70), будет выглядеть более компактным и более «читабельным» (рис. 13.71). Рис. 13.68. Внешний вид линейного отчета до преобразования Рис. 13.69. Внешний вид линейного отчета после преобразования Рис. 13.70. Внешний вид кросс-отчета до преобразования Рис 13.71. Внешний вид кросс-отчета после преобразования
Следует обратить внимание на несколько особенностей работы с макетом построителя отчета. Прежде всего, при получении макета отчета, формируе- мого по умолчанию, нужно быть уверенным, что построи- тель в данный момент осуществляет генерацию макета. Для этого используется следующая конструкция (лис- тинг 13.65). Листинг 13.65. Фрагмент получения макета построителя отчета // Получить макет построителя отчета по умолчанию. Построитель.Макет = Неопределено; МакетПостроителя = Построитель.Макет; Если перед получением макета построителя не возобнов- лять автоматическую генерацию макета, то при повтор- ном выводе отчета будет получен не макет по умолчанию, а тот макет, который был установлен построителю при первоначальном выводе отчета. Поэтому, например, если первоначально выводился линейный отчет, а после этого пользователь решил вывести кросс-отчет, — будет полу- чен плачевный результат. Кросс-отчет будет выведен в макет линейного отчета. Кроме этого, если используется изменение макета по- строителя и последующее его оформление, также следует быть уверенным в том, что при получении макета по умолчанию будет получен неоформленный макет. Для этого, после оформления макета, свойству построителя МакетОформления присваивается значение Неопределено (лис- тинг 13.66). Листинг 13.66. Фрагмент оформления макета // Оформить макет. Построитель.МакетОформления = ПолучитьМакетОформления(СтандартноеОформление.Лед); Построитель.ОформитьМакетС); Построитель.МакетОформления = Неопределено; Это гарантирует, что в дальнейшем, когда мы возобновим генерацию макета по умолчанию, он не будет генериро- ваться с учетом макета оформления. В противном случае будет получен оформленный макет по умолчанию, кото- рый содержит другие имена областей для вывода данных отчета. Передача значений параметров в запрос построителя отчета В процессе создания различных отчетов возникает необхо- димость в установке фиксированных значений параметров запроса построителя отчета. В зависимости от решаемых задач это может быть выполнено двумя способами. Во-первых, может использоваться установка значения параметра самого запроса, текст которого передан построи- телю. В этом случае параметр описывается по правилам языка запроса, и для установки его значения использует- ся свойство построителя отчета Параметры. В следующем примере запрос содержит параметр ЯСклад, значение которого устанавливается перед выполнением запроса (листинг 13.67). Листинг 13.67. Пример передачи значения параметра в запрос построителя отчета Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММАСТоварыНаСкладахОстаткиИОбороты. КоличествоКонечныйОстаток) КАК Остаток ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОборотыС . . . , Склад = &Склад) КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММАСОстаток) ПО ОБЩИЕ. Склад ИЕРАРХИЯ. Номенклатура ИЕРАРХИЯ" Построитель.ЗаполнитьНастройки(); // Размещать измерения в одной колонке. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Построитель.Параметры.Вставить!"Склад", ВыбранныйСклад); // Выполнить запрос и вывести отчет. Построитель.Выполнит ь О; Построитель.Вывести(); Во-вторых, может использоваться передача параметра по- строителю отчета. В этом случае передаваемый параметр заключается в фигурные скобки {...} и может быть выбран в отбор построителя отчета. Для установки значения пара- метра в этом случае следует использовать отбор построи- теля отчета, в который добавлять поле с соответствующи- ми свойствами. В следующем примере построителю отчета из запроса передается параметр Склад, и перед выполне- нием запроса в отбор добавляется соответствующее поле, описывающее этот параметр (листинг 13.68). Листинг 13.68. Пример передачи значения параметра построителю отчета Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад. Тов арыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММАСТ оварыНаСкладахОстаткиИОбороты. КоличествоКонечныйОстаток.) КАК Остаток ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОборотыС .... {Склад}) КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление
|ИТОГИ СУММА(Остаток) ПО ОБЩИЕ, Склад ИЕРАРХИЯ, Номенклатура ИЕРАРХИЯ" И Размещать измерения в одной колонке. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; ОтборПоСкладу = Построитель.Отбор.Добавить("Склад"); ОтборПоСкладу.Использование = Истина; ОтборПоСкладу.ВидСравнения = ВидСравнения.Равно; ОтборПоСкладу.Значение = ВыбранныйСклад; И Выполнить запрос и вывести отчет. Построитель.Выполнить(); Построитель.Вывести О; В этом случае текст итогового запроса, который будет вы- полнен построителем, выглядит следующим образом (лис- тинг 13.69). Листинг 13.69. Пример результирующего запроса ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление КАК СкладПредставление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура. ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление КАК НоменклатураПредставление, СУММА(ТоварыНаСкладахОстаткиИОбороты. КоличествоКонечныйОстаток) КАК Остаток ИЗ РегистрНакопления.ТоварыНаСкладах.0статкиИ0бороты(, , , , Склад = &Параметр1) КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММА(Остаток) ПО ОБЩИЕ. Склад ИЕРАРХИЯ, Номенклатура ИЕРАРХИЯ Особенности оформления при разной иерархии Построитель отчета различным образом оформляет иерар- хические измерения для различных ссылочных полей. Если поле содержит ссылку на справочник, с иерархией групп и элементов — область иерархической группиров- ки будет выделена цветом. Если же поле ссылается на справочник с иерархией элементов, то область иерархи- ческой группировки не будет выделена. Например, при формировании оформленного отчета о количестве долж- ностей в подразделениях согласно кадровому плану (лис- тинг 13.70), оформленный отчет будет выглядеть следую- щим образом (рис. 13.72). Так происходит потому, что справочник Подразделения, по которому строится иерархическая группировка, имеет иерархию элементов. Листинг 13.70. Пример формируемого отчета Построитель.Текст = "ВЫБРАТЬ | КадровыйПлан.Подразделение КАК Подразделение, | КадровыйПлан. Подразделение. Представление, СУММА(КадровыйПлан.Количество) КАК Должности |ИЗ РегистрСведений.КадровыйПлан КАК КадровыйПлан СГРУППИРОВАТЬ ПО КадровыйПлан.Подразделение, КадровыйПлан.Подразделение.Представление ИТОГИ СУММА(Должности) ПО ОБЩИЕ. Подразделение ИЕРАРХИЯ АВТОУПОРЯДОЧИВАНИЕ" Построитель.ЗаполнитьНастройки(): // Размещать измерения в одной колонке. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе: // Оформить макет Построитель.МакетОформления = ПолучитьМакетОформления(СтандартноеОформление.Лед); И Выполнить запрос и вывести отчет. Построитель.Выполнить(); Построитель.Вывести(); Рис. 13.72. Пример оформленного отчета Чтобы вывести такой отчет с выделением областей иерар- хической группировки, можно заменить тип измерения построителя отчета Подразделение на ТолькоИерархия и до- бавить еще одно измерение построителя отчета Подразде- ление с типом Элементы (листинг 13.71). Листинг 13.71. Пример формируемого отчета Построитель.ЗаполнитьНастройки(); // Размещать измерения в одной колонке. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; // Оформить макет Построитель.МакетОформления = ПолучитьМакетОформления(СтандартноеОформление.Лед); // Изменить группировки Построитель.ИзиеренияСтроки.Найти("Подразделение"). ТипИзмерения = ТипИз меренияПостроителяОтчета.ТолькоИерархия; Построитель.ИзиеренияСтроки.Добавить("Подразделение", , ТипИзмеренияПостроителяОтчета.Элементы): И Выполнить запрос и вывести отчет. Построитель.Выполнить(); Построитель.Вывести();
После выполнения этого кода отчет будет выведен с вы- деленными областями первого уровня (рис. 13.73). Рис. 13.73. Пример оформленного отчета Изменение полей для некоторых группировок Порой возникают ситуации, когда значения ресурсов в итоговом отчете необходимо отображать не для всех группировок, а только для группировок, расположенных ниже некоторой группировки. Такая ситуация может воз- никнуть, например, при выводе отчета о движении де- нежных средств по контрагентам (листинг 13.72). Листинг 13.72. Пример запроса о движении денежных средств по контрагентам "ВЫБРАТЬ ДвиженияДенежныхСредствОбороты.Контрагент КАК Контрагент, ДвиженияДенежныхСредствОбороты.Контрагент.Представление, ДвиженияДенежныхСредствОбороты.ПриходРасход КАК ПриходРасход, ДвиженияДенежныхСредствОбороты.БанковскийСчетКасса. ВалютаДенежныхСредств КАК БанковскийСчетКассаВалютаДенежныхСредств, ДвиженияДенежныхСредствОбороты.БанковскийСчетКасса. ВалютаДенежныхСредств.Представление, СУММА(Дв ижен ияДенежныхСредст вОбороты.Сум м аОборот) КАК СуммаОборот, СУММА!Дв ижени яДенежныхСредст вОбороты.Сум м аУпрОборот) КАК СуммаУпрОборот ИЗ РегистрНакопления.ДвиженияДенежныхСредств.Обороты КАК ДвиженияДенежныхСредствОбороты СГРУППИРОВАТЬ ПО ДвиженияДенежныхСредствОбороты.Контрагент. ДвиженияДенежныхСредствОбороты.ПриходРасход, ДвиженияДенежныхСредствОбороты.БанковскийСчетКасса. ВалютаДенежныхСредств, ДвиженияДенежныхСредствОбороты.БанковскийСчетКасса. ВалютаДенежныхСредств.Представление, ДвиженияДенежныхСредствОбороты.Контрагент.Представление ИТОГИ СУММА(СуммаОборот), СУША(СуммаУпрОборот) ПО ОБЩИЕ, Контрагент, ПриходРасход, БанковскийСчетКассаВалютаДенежныхСредств АВТОУПОРЯДОЧИВАНИЕ" Если не предпринимать никаких дополнительных дейст- вий, то результат такого запроса будет выглядеть следую- щим образом (рис. 13.74). Очевидно, что значения ресурса СуммаОборот не имеют смысла в группировках выше, чем группировка по валю- те. Например, для контрагента Пластинформ приход в сум- ме 125 465,78 не несет никакой полезной информации, поскольку складываются суммы в разных валютах. Рис. 13.74. Сформированный отчет Поэтому необходимо запретить вывод ресурса СуммаОбо- рот в группировках, расположенных выше группировки БанковскийСчетКассаВалютаДенежныхСредств. Для этого нужно получить макет построителя отчета и в областях, которые содержат имена группировок, рас- положенных в отборе построителя отчета выше, чем нуж- ная нам группировка, удалить параметр области (лис- тинг 13.73). Листинг 13.73. Отмена вывода итогов в определенных группировках // Размещать измерения в одной колонке. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Построитель.Макет = Неопределено; МакетПостроителя = Построитель.Макет; И Удалить поле СуммаОборот из всех областей группировок И выше группировки ВалютаДенежныхСредств Для Каждого ТекущееИзмерениеСтроки Из Построитель. ИзмеренияСтроки Цикл Если ТекущееИзмерениеСтроки.ПутьКДанным = "БанковскийСчетКассаВалютаДенежныхСредств" Тогда Прервать: Иначе И Найти области с именем группировки или И с именем группировки и словом Иерархия ИменаОбластей = Новый Массив; ИменаОбластей.Добавить(ТекущееИзмерениеСтроки.Имя); ИменаОбластей.Добав ить( ТекущееИзмерениеСтроки.Имя + "Иерархия"); ИменаОбластей.Добавить("ОбщиеИтоги"); Для Каждого ИмяИзмерения Из ИменаОбластей Цикл Область = МакетПостроителя.Области.Найти(ИмяИзмерения) ; Если Область <> Неопределено Тогда ТекущаяОбласть = Неопределено; Пока Истина Цикл
И Найти ячейку, в которой находится // параметр - СумнаОборот ТекущаяОбласть = МакетПостроителя.НайтиТекстС "СумнаОборот". ТекущаяОбласть, Область. Истина, Истина. Истина. Ложь); Если ТекущаяОбласть <> Неопределено Тогда Если ТекущаяОбласть.Параметр = "СумнаОборот" Тогда И Удалить параметр из области ТекущаяОбласть. Параметр = ; КонецЕсли; Иначе Прервать; КонецЕсли; КонецЦикла; КонецЕсли; КонецЦикла; КонецЕсли; КонецЦикла; Построитель.Макет = МакетПостроителя; И Выполнить запрос и вывести отчет. Построитель. Выполнить (); Построитель.Вывести(); В результате выполнения этого кода итоговый отчет при- мет требуемый вид (рис. 13.75). Рис. 13.75. Внешний вид полученного отчета Особенности использования построителя отчета для отбора по значению субконто Все отчеты, создаваемые для целей анализа данных бух- галтерского учета, можно разделить на две большие груп- пы: специализированные и универсальные. Деление это довольно условное, и критерием отнесения к первой или второй группе служит возможность настройки отчета. К специализированным относятся те отчеты, которые предназначены для анализа одного участка учета и, как следствие, обладают минимальными возможностями на- стройки пользователем. К этой группе можно отнести ин- вентарные ведомости, кассовую книгу, расшифровку де- биторской и кредиторской задолженности и другие. Универсальные бухгалтерские отчеты представлены в лю- бом типовом решении комплектом стандартной отчетно- сти: оборотки, карточки и анализы счетов, ведомости и ордера. Формы этих отчетов стандартизированы не столько законами, сколько сложившейся четырехсотлет- ней практикой использования двойной записи. И все эти отчеты (или многие из них) могут быть сформированы по любому счету используемого плана счетов, с различными отборами и группировками, которые во многом зависят от того счета (раздела) учета, который выбран для анализа. Специализированные отчеты, предоставляющие пользо- вателю минимальные возможности настройки, могут быть легко разработаны с использованием объекта встроенно- го языка Запрос. Язык запросов и передаваемые в запрос параметры позволят точно описать условия извлечения данных из информационной базы. Как правило, такие от- четы имеют несложные пользовательские диалоги, содер- жащие поля для выбора периода и, может быть, несколько полей для описания дополнительных фильтров извлече- ния данных. Чем больше возможностей настройки мы предоставляем пользователю, тем сложнее разработать диалог, описать текст (а может быть, и динамическое формирование тек- ста) запроса и макет. Примером может служить отчет по проводкам. Самый простой его вариант позволит пользо- вателю указать в диалоге интервал дат. Для формирова ния такого отчета потребуется несложный запрос, приве- денный в листинге 13.74. Листинг 13.74. Пример запроса из отчета по проводкам ВЫБРАТЬ ДвиженияССубконто.Период КАК Период, ДвиженияССубконто.СчетДт, ДвиженияССубконто.СчетКт, ДвиженияССубконто.Сунна КАК Сунна, ДвиженияССубконто.Содержание ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии. ДвиженияССубконто! &НачПериода. &КонПериода, ) КАК ДвиженияССубконто УПОРЯДОЧИТЬ ПО Период ИТОГИ СУММА(Сумма) ПО ОБЩИЕ Реализовать более сложную задачу — добавить пользова телю возможность отбора по счетам — не составит особо го труда. Серьезно усложнит решение задачи необходи- мость отбора по значениям субконто. Субконто может быть любого (по сути любого, хотя чаще всего любого ссылочного) типа данных. Максимальное количество субконто хоть и ограничено настройками плана счетов, но для различных счетов оно может быть различным в рамках настроек.
Усложняет задачу также и сервис, который требует поль- зователь: установка отборов как по конкретным значени- ям, так и по спискам и группам значений. Резко услож- няется задача, если требуется разработать механизм, независящий от конкретной информационной базы, ко- гда заранее неизвестно имя, структура и количество реги- стров бухгалтерии, и может изменяться организация ана- литического учета. Использование объекта Построитель отчета позволяет су- щественно сократить время на разработку сложных на- страиваемых отчетов. Построитель отчета может взять на себя: ♦ создание сложного диалога; ♦ исполнение запроса, модифицированного самим по- строителем в соответствии с пожеланиями пользовате- ля, высказанными им в диалоге формы; ♦ создание макета и подготовку результирующего таб- личного документа. Однако использование построителя отчета при разра- ботке бухгалтерских отчетов имеет определенные огра- ничения. Во-первых, формы бухгалтерской отчетности сформиро- вались за все время использования двойной записи. И все пользователи, а бухгалтера в особенности, люди консер- вативные и считают, удобным отчетом — отчет привыч- ный. Потому что в новом отчете они «... ничего не видят». Поэтому, как правило, при создании бухгалтерских отче- тов используется или фиксированный макет построителя отчета, или возможность формирования табличного до- кумента построителем не используется вообще (построи- тель отчета используется только для формирования и вы- полнения запроса, а для вывода результата в табличный документ пишется специальная процедура). В последнем случае от построителя требуется лишь выполнить запрос и «отдать» результат запроса. Во-вторых, для хранения значений субконто использу- ются поля составного типа. Причем в составной тип вхо- дят все типы, описанные в свойстве Тип значения характе- ристик плана видов характеристик, используемого для хранения видов субконто. Рассмотрим более подробно последнюю особенность на примере отчета по проводкам. Итак, предоставим воз- можность пользователю устанавливать отбор проводок по значениям счета и субконто этого счета. Счет добавим в диалог в виде поля ввода, и будем передавать в построи- тель отчета в виде параметра, а для отбора по субконто воспользуемся построителем отчета. Отчет можно разра- ботать с помощью конструктора выходных форм, но оста- нутся нерешенными задачи: ♦ пользователь должен иметь возможность выбирать столько субконто, сколько прикреплено к выбранному им счету; ♦ при выборе значения субконто не должен открываться стандартный диалог выбора типа (субконто имеет со- ставной тип данных), а сразу должен осуществляться выбор значения типа субконто выбранного ранее счета. Для решения этих задач мы используем возможности по- строителя отчета. Итак, текст запроса, написанного с использованием кон- структора, приведен в листинге 13.75. Листинг 13.75. Текст запроса для отчета по проводкам ВЫБРАТЬ ДвиженияССубконто.Период КАК Период. ДвиженияССубконто.СчетДт, ДвиженияССубконто.СчетКт, ДвиженияССубконто.Сумма КАК Сумма, ДвиженияССубконто.Содержание ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии. ДвиженияССубконто( &НачПериода, &КонПериода, Счет В ИЕРАРХИИ (&Счет) {Субконто1.*, Субконто2.*} ) КАК ДвиженияССубконто УПОРЯДОЧИТЬ ПО Период ИТОГИ СУММА(Сумма) ПО ОБЩИЕ Текст включает всего одно предложение, использую- щее расширение языка запроса построителя отчета (лис- тинг 13.76). Листинг 13.76. Предложение, использующее расширение языка запроса построителя отчета {Субконто!.*, Субконто2.*} В фигурные скобки взято выражение для отбора по субконто. Мы не будем использовать в отчете метод по- строителя отчета ЗаполнитьНастройкиО, поэтому долж- ны выделить параметры виртуальной таблицы, кото- рые будут использоваться в отборе построителя отчета. Остальные параметры будут вводиться пользователем в полях ввода. Однако не на всех счетах плана счетов задействованы оба вида субконто. Выбранный пользователем счет может во обще не иметь субконто или иметь только одно. Поэтому приведенную выше строку (см. листинг 13.76) придется формировать динамически при обходе субконто выбран- ного счета (листинг 13.77). Листинг 13.77. Текст запроса для отчета по проводкам Процедура ОтчетПоПроводкамПостроителемИнициализацияО Построитель.Текст = "ВЫБРАТЬ ДвиженияССубконто.Период КАК Период, ДвиженияССубконто.СчетДт, ДвиженияССубконто.СчетКт, ДвиженияССубконто.Сумма КАК Сумма. ДвиженияССубконто.Содержан ие ИЗ РегистрБухгалтерии.ОсновнойРегистрБухгалтерии. ДвиженияССубконто( &НачПериода, &КонПериода. Счет В ИЕРАРХИИ (&Счет) " + ТекстОтбораПоСубконто + " ) КАК ДвиженияССубконто УПОРЯДОЧИТЬ ПО Период ИТОГИ СУММА(Сумма) ПО ОБЩИЕ"; КонецПроцедуры
Вторая задача — обеспечить пользователю удобный вы- бор значения субконто. Мы решили использовать для этого свойство построителя отчета Отбор. Если ничего специально не описывать, то выбор субконто будет вы- глядеть следующим образом: пользователь добавит в поле отбор новую строку (рис. 13.76), при этом ему будет пред- ложен диалог, содержащий имена Субконто1 и Субконто2 (если на счете 2 субконто) (рис. 13.77). Тип сравнения Равно значение Рис. 13.76. Добавление новой строки в отбор Рис. 13.77. Диалог выбора поля Пользователь выберет в этом диалоге одно из значений (рис. 13.78). Рис. 13.78. Поле отбора выбрано После этого, для выбора значения субконто, ему придется сначала вспомнить, какой вид субконто прикреплен на выбранный им счет первым, потом выбрать нужное ему значение из списка (рис. 13.79). Рис. 13.79. Диалог выбора типа Только после этого пользователь сможет выбрать значе- ние субконто. Слишком сложно! Чтобы ему помочь, нам придется написать процедуру, ко- торая будет обрабатывать событие выбора счета в диалоге (листинг 13.78). Листинг 13.78. Пример обработки события выбора счета в диалоге Если Счет.Пустая() Тогда Возврат: КонецЕсли: Пока Построитель. Отбор. КоличествоО > 0 Цикл Построитель.Отбор.Удалить(О); КонецЦикла; ТекстОтбораПоСубконто = Если Счет.ВидыСубконто.КоличествоО > 0 Тогда Для Каждого ВидСубконто Из Счет.ВидыСубконто Цикл ТекстОтбораПоСубконто = ТекстОтбораПоСубконто + ", Субконто" + ВидСубконто.НонерСтроки + " *'. КонецЦикла; ТекстОтбораПоСубконто = Прав(ТекстОтбораПоСубконто. СтрДлина(ТекстОтбораПоСубконто) -1); ТекстОтбораПоСубконто = ”{” + ТекстОтбораПоСубконто + ОтчетПоПроводкамПостроителенИнициализацияО; Для Каждого ВидСубконто Из Счет.ВидыСубконто Цикл Поле = Построитель. ДоступныеПоля. Найти("Субконто" + ВидСубконто.НонерСтроки): Поле.ТипЗначения = ВидСубконто.ВидСубконто.ТипЗначения: Поле.Представление = ВидСубконто.ВидСубконто. Наименование; Если Построитель.Отбор.Найти("Субконто" + ВидСубконто.НомерСтроки) = Неопределено Тогда Построитель.Отбор. Добавить("Субконто" + ВидСубконто.НомерСтроки); КонецЕсли: КонецЦикла; КонецЕсли; Прокомментируем процедуру. Мы будем предоставлять возможность выбора субконто, только если выбран счет (небольшое ограничение в методических целях). Мы будем не только назначать типы и имена полям отбо- ра, мы еще хотим сразу заполнить свойство отбор воз- можными элементами. Но для этого его сначала надо очистить. Если на счете ведется аналитический учет, мы должны «собрать» переменную, которая дополнит текст запроса инструкцией для построителя. После чего обязательно заново вызываем процедуру, устанавливающую свойство построителя отчета Текст, теперь уже с условиями отбора по субконто. Это нужно делать после любого изменения текста запроса. А если при этом хочется сохранить на- стройки построителя, сделанные до изменения текста, имеет смысл воспользоваться методами построителя от- чета ПолучитьНастройкиО и УстановитьНастройкиО. После того как построитель получил из текста информа- цию о доступных для отбора полях, мы должны назна- чить типы этим полям. Для этого в цикле по табличной части ВидыСубконто выбранного счета, мы позициониру- емся на одном из доступных полей, устанавливаем для него тип значения и наименование, как у вида субконто счета. Кроме того, добавляем его в свойство построителя Отбор. Наша задача решена. Используя аналогичный подход, может быть решена задача управления группировками отчета в строках и колонках и другие подобные задачи. Вывод представлений ссылочных значений Результат работы построителя отчета может быть ис- пользован как для вывода данных в отчет, так и для даль- нейшей обработки полученных данных. По этой причине при формировании итогового запроса построитель отчета не добавляет в него представления для ссылочных полей, которые существовали в исходном тексте запроса.
Для тех же ссылочных полей, которые были добавлены в запрос в результате изменения настроек построителя отчета, поля представлений будут добавлены автомати- чески. Поэтому если результат работы построителя отчета пред- полагается использовать для дальнейшей обработки, в которой не требуются представления ссылочных полей запроса, можно использовать, например, следующий код (листинг 13.79). Листинг 13.79. Пример запроса Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, СУММА(ТоварыНаСкладахОстаткиИОбороты. КоличествоКонечныйОстаток) КАК Остаток"; Если же результат работы этого запроса предназначен для вывода, например, в табличный документ, следует получать поля представлений для всех ссылочных полей запроса (листинг 13.80). Листинг 13.80. Пример запроса с получением представлений ссылочных полей Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад. ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты. КоличествоКонечныйОстаток) КАК Остаток"; В противном случае вывод отчета может существенно - замедлиться (особенно на больших объемах данных), так как построитель отчета будет выполнять дополни- тельные запросы для получения представлений. Вывод в диаграмму Результат построителя отчета может быть выведен в диа- грамму. При этом существует два ограничения, которые следует учитывать: ♦ может быть выведен только один ресурс; ♦ может быть выведено не более двух измерений. Рассмотрим, каким образом может быть выведен в диа- грамму результат запроса, получающего приход, расход и оборот товаров на складах. Для этого используется ме- тод Вывести() построителя отчета, в котором первым па- раметром указывается диаграмма, в которую должен быть осуществлен вывод (листинг 13.81). Результат вы- вода представленного отчета в диаграмму показан на рис. 13.80. Листинг 13.81. Пример вывода отчета в диаграмму Построитель = Новый ПостроительОтчетаО; Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММА(КоличествоПриход), СУММА(КоличествоОборот), СУММА(КоличествоРасход) ПО ОБЩИЕ. Номенклатура ИЕРАРХИЯ" Построитель. ЗаполнитьНастройкиО; ЭлементыФормы.Диаграмма!.ОбластьЗаголовка.Текст = "Приход товаров”; Построитель. ВыполнитьО; Построитель.Вывести(ЭлементыФормы.Диаграмма!); Рис. 13.80. Вывод отчета в диаграмму Данный пример наглядно иллюстрирует некоторые осо- бенности вывода результата построителя отчета в диа- грамму. Во-первых, если отчет содержит иерархические итоги (в данном случае по полю Номенклатура), то в диаграмму будут выведены значения только для первого уровня ие- рархии (в нашем случае это группы первого уровня спра- вочника Номенклатура). Во-вторых, первое измерение, содержащееся в предложе- нии ИТОГИ, всегда будет выведено в серии диаграммы. В-третьих, если в запросе указано несколько ресурсов, по умолчанию будет выведен только первый из пере- численных ресурсов (в данном случае — КоличествоПри- ход). Для того чтобы указать в явном виде ресурс, который не- обходимо выводить в диаграмму (листинг 13.82), нужно указать его имя вторым параметром в методе Вывести () построителя отчета (рис. 13.81).
Листинг 13.82. Указание выводимого ресурса ЭлементыФормы.Диаграмма!.ОбластьЗаголовка.Текст = "Оборот товаров"; Построитель.ВылолнитьО; Построитель.Вывести(ЭлементыФормы.Диаграмма!, “КоличествоОборот"); Рис. 13.81. Вывод в диаграмму указанного ресурса В случае когда в диаграмму выводятся два измерения (листинг 13.83), первое будет расположено в сериях, а второе — в точках диаграммы (рис. 13.82). Листинг 13.83. Вывод двух измерений в диаграмму Построитель = Новый ПостроительОтчетаО; Построитель. Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура. ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММА(КоличествоПриход), СУММА(КоличествоОборот), СУММА(КоличествоРасход) ПО ОБЩИЕ, Номенклатура ИЕРАРХИЯ, Склад"; Построитель.ЗаполнитьНастройки(); ЭлементыФормы.Диаграмма!.ОбластьЗаголов ка.Текст = "Приход товаров"; Построитель.Выполнить(); Построитель.Вывести(ЭлементыФормы.Диаграмма!, "КоличествоПриход"): Следует учитывать, что при выводе двух измерений в диаграммы, которые содержат только одну точку, будет выведено первое значение «второго» измерения. Напри- мер, если в предыдущем примере изменить тип диаграм- мы на Круговая, то будет выведено количество товара, по- ступившего на главный склад (рис. 13.83). Рис. 13.83. Вывод в круговую диаграмму Вывод в сводную таблицу Для вывода результата построителя отчета в сводную таблицу (рис. 13.84) достаточно указать построитель Рис. 13.82. Вывод двух ресурсов в диаграмму
отчета в качестве источника данных сводной таблицы (листинг 13.84). Листинг 13.84. Пример вывода в сводную таблицу Построитель = Новый ПостроительОтчетаО; Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление. ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура. ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление. ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММА(КоличествоПриход), СУММА(КоличествоОборот), СУММА(КоличествоРасход) ПО ОБЩИЕ, Номенклатура ИЕРАРХИЯ, Склад Иерархия”; Построитель .ЗаполнитьНастройкиО; Таблица = ЭлементыФормы.ПолеТабличногоДокумента!. ВстроенныеТ аблицы.СводнаяТаблица!; Таблица.МакетОфориления = ПолучитьМакетОформления(СтандартноеОформление.Лед); Таблица.ИсточникДанных = Построитель; Таблица.Строки.ДобавитьС"Номенклатура"); Таблица.Колонки.ДобавитьС"Склад"); Таблица. Данные. Добавить ("КоличествоПриход"): Обратите внимание, что при работе со сводной таблицей запрос построителя отчета формируется и выполняется автоматически, но лишь при изменении состава измере- ний, присутствующих в сводной таблице. Вывод в сводную диаграмму Вывод результата построителя в сводную диаграмму (рис. 13.85) аналогичен тому, как выводится результат за- проса в сводную таблицу. Построитель отчета должен быть указан в качестве источника данных для сводной диаграммы (листинг 13.85). Листинг 13.85. Вывод отчета в сводную диаграмму Построитель = Новый ПостроительОтчетаО: Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход | ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты |СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление |ИТОГИ СУММА(КоличествоПриход), СУММА(КоличествоОборот), СУММА(КоличествоРасход) ПО ОБЩИЕ. | Номенклатура ИЕРАРХИЯ, Склад Иерархия"; Построитель.ЗаполнитьНастройки(); Диаграмма - ЭлементыФормы.СводнаяДиаграмма!; Диаграмма.ОбластьЗаголовка.Текст = "Приход товаров"; Диаграмма.ИсточникДанных = Построитель: Диаграмма.Серии.Добав и т ь("Номен кл атура"); Диаграмма.Точки.ДобавитьС"Склад"); Диаграмма.Ресурсы.Добавить("КоличествоПриход"); Рис. 13.84. Вывод в сводную таблицу
Рис. 13.85. Вывод отчета в сводную диаграмму Работа с расшифровкой Построитель отчета позволяет использовать механизм расшифровки при выводе результатов отчета в поле таб- личного документа и диаграмму. При выводе результата построитель может автоматиче- ски заполнить расшифровку ячеек табличного документа несколькими способами. Кроме этого, существует воз- можность настроить расшифровку построителя отчета на основе имеющейся расшифровки и отбора построителя отчета. В общем виде работа механизма расшифровки выглядит следующим образом (рис. 13.86). Рис. 13.86. Схема работы механизма расшифровки Построитель отчета 1 при выводе результата в поле таблично- го документа заполняет расшифровку указанным способом. При двойном щелчке в ячейке табличного документа плат- форма генерирует событие Обработка расшифровки. В обра- ботчике этого события будет доступно значение расшиф- ровки, соответствующее выбранной ячейке табличного документа. В этом же обработчике можно использовать метод Кастро- итьРасшифровкуО построителя отчета 1 для того, чтобы на- строить другой построитель отчета (построитель отчета 2) или тот же самый построитель отчета (построитель отчета 1). Настройка расшифровки заключается в том, что в на- страиваемом построителе устанавливается отбор по зна- чениям измерений, содержащимся в расшифровке, и кроме этого, устанавливается отбор, содержащийся в построи- теле на момент вызова этого метода. После этого настраиваемый построитель отчета может быть выполнен и результат выведен, например, в то же поле табличного документа. Таким образом, механизм расшифровки позволяет ис- пользовать один и тот же текст запроса (или разные за- просы) для формирования новых отчетов, детализирую- щих или уточняющих данные текущего отчета. Автоматическое заполнение расшифровки при использовании макета по умолчанию Построитель отчета поддерживает возможность автома- тического заполнения расшифровки в итоговом таблич- ном документе или диаграмме. Для этого используется свойство построителя отчета ЗаполнениеРасшифровки. Оно может принимать три значения: ♦ НеЗаполнять; ♦ ЗначенияГруппировок; * Расшифровка. Если установлено значение НеЗаполнять, то построитель оставит расшифровки незаполненными. Если установлено значение ЗначенияГруппировок, то рас- шифровки некоторых ячеек, в которые выводятся зна- чения группировок, будут заполнены значениями со- ответствующих группировок, выводимых в эти ячейки. Например, будет доступна расшифровка ячеек, содержа- щих значения номенклатуры (рис. 13.87). При двойном щелчке на этой ячейке будет открыта фор- ма этого элемента справочника Номенклатура (если ис- пользуется стандартная обработка расшифровки).
Рис. 13.87. Доступность расшифровки ячеек, содержащих значения номенклатуры Для ячеек, содержащих значения ресурсов, расшифровка в этом случае заполнена не будет (рис. 13.88). Рис. 13.88. Расшифровка для ячеек, содержащих значения ресурсов, недоступна Если установлено значение Расшифровка, то расшифровки всех ячеек, содержащих значения группировок и ресур- сов, будут заполнены структурой, содержащей значения всех группировок. Например, для приведенного выше примера это будут значения группировок Склад и Номенк- латура (рис. 13.89). Рис. 13.89. Структура расшифровки Такой состав расшифровки не может уже быть по умол- чанию обработан платформой и требует специальной об- работки на встроенном языке. Автоматическое заполнение расшифровки при использовании назначаемого макета В случае когда для формирования итогового докумен- та используется макет, назначаемый разработчиком, по- строитель также может автоматически заполнить рас- шифровки в формируемом табличном документе. Для этого для ячеек макета, для которых должна заполняться расшифровка, должны быть указаны стандартные имена параметра расшифровки. Если вид расшифровки построителя отчета установлен Расшифровка, тогда имя параметра расшифровки в макете должно быть Расшифровка. Если вид расшифровки построителя отчета установлен ЗначенияГруппировок, тогда имена параметров расшифров- ки в макете должны совпадать с именами группировок. Пример использования построителя отчета для получения уточненных данных по расшифровке Для того чтобы проиллюстрировать возможности ис- пользования расшифровок при работе с построителем от- чета, рассмотрим простой пример. В этом примере будет использован один построитель отчета, который будет вы- водить отчет об остатках номенклатуры на складе. При вызове расшифровки в итоговом табличном документе этот построитель отчета будет настраиваться в соответст- вии с расшифровкой и выводить подробный отчет об остат- ках и движениях выбранной номенклатуры по складам. Общая схема использования расшифровки в этом случае будет выглядеть следующим образом (рис. 13.90). Рис. 13.90. Схема работы с расшифровкой Для того чтобы создать такой отчет, добавим реквизит формы Построитель с типом ПостроительОтчета, разместим в форме обработки поле табличного документа, в которое будет выводиться результат отчета, и установим у этого поля свойство Только просмотр в значение Истина, чтобы был доступен механизм расшифровки. В обработчике события При открытии формы зададим текст запроса (листинг 13.86). Листинг 13.86. Обработчик При открытии И Обработчик события ПриОткрытии формы И Выполняет заполнение текста запроса построителя отчета. // Процедура ПриОткрытии!) Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура. Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты. КоличествоНачальныйОстаток) КАК НачальныйОстаток, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК Приход,
СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК Расход, СУММА(ТоварыНаСкладахОстаткиИОбороты. КоличествоКонечныйОстаток) КАК КонечныйОстаток, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК Оборот ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО Т оварыНаСкладахОстат киИОбороты.Склад. ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура. Представление ИТОГИ СУММА(Приход), СУММА(Оборот), СУММА(Расход). СУММА(НачальныйОстаток), СУММА(КонечныйОстаток) ПО ОБЩИЕ, Склад ИЕРАРХИЯ. Номенклатура ИЕРАРХИЯ"; КонецПроцедуры Затем в процедуре, обрабатывающей нажатие кнопки Вы- полнить в панели ОсновныеДействияФормы, зададим вид за- полнения расшифровок, изменим настройки построителя отчета по умолчанию и выведем результат в поле таблич- ного документа, расположенное в форме (листинг 13.87). Листинг 13.87. Обработчик нажатия кнопки Выполнить // Обработчик события Нажатие кнопки Выполнить // командной панели ОсновныеДействияФормы // Настраивает, выполняет запрос и выводит результат И в поле табличного документа формы. // Процедура КнопкаВыполнитьНажатие(Элемент) Построитель .ЗаполнитьНастройкиО; // Заполнять расшифровки значениями группировок. Построитель.ЗаполнениеРасшифровки = ВидЗаполненияРасшифровкиПостроителяОтчета. Расшифровка; // Размещать измерения в одной колонке. Построитель.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе: // Запретить вывод измерения склад и всех ресурсов, // кроме КонечныйОстаток. Построитель.ВыбранныеПоля. Удалить(Построитель.ВыбранныеПоля.Найти("Склад”)); Построитель.ВыбранныеПоля. УдалитьСПостроитель.ВыбранныеПоля. НайтиС’НачальныйОстаток")); Построитель.ВыбранныеПоля. Удалить(Построитель.ВыбранныеПоля.Найти("Приход")); Построитель.ВыбранныеПоля. Удалить(Построитель.ВыбранныеПоля.Найти("Расход")); Построитель.ВыбранныеПоля. Удалить(Построитель.ВыбранныеПоля.Найти("Оборот")); И Запретить группировку по измерению Склад. Построитель.ИзмеренияСтроки. Удалит ь(Построитель.ИзмеренияСтроки.Найти("Склад")); // Задать заголовок отчета. Построитель.ТекстЗаголовка = "Остатки товаров"; Построитель.Выполнит ь(); И Вывести результат в поле табличного документа в форме. ЭлементыФормы.ПолеТабличногоДокумента1.Очистить(); ЭлементыФормы.ПолеТабличногоДокумента1.ТекущаяОбласть = ЭлементыФормы.ПолеТабличногоДокумента1.Область("R1C1"); Построитель.Вывести(ЭлементыФормы. ПолеТабличногоДокумента1); КонецПроцедуры Теперь создадим обработчик события Обработка расшифровки поля табличного документа. В этом обработчике запол- ним настройки построителя отчета по умолчанию, на- строим расшифровку в соответствии с имеющейся рас- шифровкой и отбором построителя, который установлен в данный момент, изменим некоторые настройки построи- теля по умолчанию и выведем результат в поле табличного документа, расположенное в форме (листинг 13.88). Листинг 13.88. Обработчик события Обработка расшифровки // Обработчик события ОбработкаРасшифровки // поля табличного документа ПолеТабличногоДокумента1 // Настраивает, выполняет запрос и выводит результат // в поле табличного документа формы. // Процедура ПолеТабличногоДокумента10бработкаРасшифровки( Элемент, Расшифровка, СтандартнаяОбработка) // Запретить стандартную обработку расшифровки. СтандартнаяОбработка = Ложь; Построитель. ЗаполнитьНастройкиО; // Настроить расшифровку построителя, используя имеющуюся // расшифровку и установленный отбор. Построитель.НастроитьРасшифровку(Построитель. Расшифровка); // Запретить вывод измерения Номенклатура и группировку // по этому измерению. Построитель.ВыбранныеПоля. Удалить(Построитель.ВыбранныеПоля. НайтиС'Номенклатура")); Построитель.ИзмеренияСтроки. Удалить(Построитель.ИзмеренияСтроки. НайтиС'Номенклатура")); // Установить заголовок отчета. Построитель.ТекстЗаголовка = "Ведомость по товару " + Построитель.Отбор. Найти("Номенклатура").Значение: Построитель.Выполнить(); // Вывести результат в поле табличного документа в форме. ЭлементыФормы.ПолеТабличногоДокумента1.Очистить(); ЭлементыФормы.ПолеТабличногоДокумента1.ТекущаяОбласть = ЭлементыФормы. ПолеТабличногоДокумента1. Область("R1C1"); Построитель.Вывести(ЭлементыФормы.ПолеТабличногоДокумента1); КонецПроцедуры Теперь, для облегчения работы пользователя с этим отче- том, реализуем в простейшем виде «историю» выполняе- мых отчетов, позволяющую переходить от одного сфор- мированного ранее отчета к другому. Для этого добавим в текст модуля описание двух масси- вов, которые будут хранить историю движения по выве- денным отчетам назад и вперед (листинг 13.89).
Листинг 13.89. Массивы для хранения истории Перем ИсторияВперед, ИсторияНазад; // Массивы структур. ИсторияВперед = Новый Массив; ИсторияНазад = Новый Массив: В обработчик расшифровки добавим строки, запоминаю- щие текущее состояние отчета в массиве ИсторияНазад, для того, чтобы, получив подробный отчет, пользователь мог вернуться к исходному отчету, из которого он вызы- вал расшифровку. Текущее состояние запоминается в виде структуры, со- держащей настройки построителя отчета, табличный до- кумент, отображаемый в форме, и текущую (выделен- ную) область этого табличного документа (листинг 13.90). Листинг 13.90. Сохранение истории расшифровки // Обработчик события ОбработкаРасшифровки // поля табличного документа ПолеТабличногоДокумента1 // Настраивает, выполняет запрос и выводит результат // в поле табличного документа формы. // Процедура ПолеТабличногоДокумента10бработкаРасшифровки( Элемент, Расшифровка, СтандартнаяОбработка) // Запретить стандартную обработку расшифровки. СтандартнаяОбработка = Ложь; // Очистить движения вперед ИсторияВперед.ОчиститьО; ЭлементыФормы.ОсновныеДействияФормы.Кнопки.КнопкаВперед. Доступность = Ложь; // Запомнить текущее состояние для движения назад ИсторияНазад.ДобавитьС Новый СтруктураС'Настройки, Отчет. ТекущаяОбласть". Построитель .ПолучитьНастройкиО, ЭлементыФормы.ПолеТабличногоДокумента!. ПолучитьОбластьО, ЭлементыФормы.ПолеТабличногоДокумента!. ТекущаяОбласть)); ЭлементыФормы.ОсновныеДействияФормы.Кнопки.КнопкаНазад. Доступность = Истина; Построитель .ЗаполнитьНастройкиО: // Настроить расшифровку построителя, используя имеющуюся // расшифровку и установленный отбор. Построитель.НастроитьРасшифровкуСПостроитель. Расшифровка): // Запретить вывод измерения Номенклатура и группировку // по этому измерению. Построитель.ВыбранныеПоля. Удалить(Построитель.ВыбранныеПоля. Найти("Номенклатура")): Построитель.ИзмеренияСтроки. Удалить(Построитель.ИзмеренияСтроки. Найти("Номенклатура")); // Установить заголовок отчета. Построитель.ТекстЗаголовка = "Ведомость по товару " + Построитель.Отбор. Найти("Номенклатура").Значение: Построитель.Выполнить(); // Вывести результат в поле табличного документа в форме. ЭлементыФормы.ПолеТабличногоДокумента1.0чистить(); ЭлементыФормы.ПолеТабличногоДокумента!.ТекущаяОбласть = ЭлементыФормы.ПолеТабличногоДокумента!. Облает bC'RlCl"); Построитель.Вывести(ЭлементыФормы. ПолеТабличногоДокумента!): КонецПроцедуры Теперь, для завершения отчета, осталось в командную па- нель ОсновныеДействияФормы добавить две кнопки: Назад и Вперед. Обработчик события нажатия кнопки Вперед будет вы- глядеть следующим образом (листинг 13.91). Листинг 13.91. Обработчик нажатия кнопки Вперед // Действие кнопки Вперед командной // панели ОсновныеДействияФормы // Отображает предыдущее состояние расшифровки отчета. // Процедура ОсновныеДействияФормыКнопкаВперед(Кнопка) // Запомнить текущее состояние для движения назад. ИсторияНазад.Добавить( Новый СтруктураС'Настройки, Отчет, ТекущаяОбласть", Построитель .ПолучитьНастройкиО. ЭлементыФормы.ПолеТабличногоДокумента!. ПолучитьОбластьО, ЭлементыФормы.ПолеТабличногоДокумента!. ТекущаяОбласть)); ЭлементыФормы.ОсновныеДействияФормы.Кнопки.КнопкаНазад. Доступность = Истина; // Отобразить новое состояние отчета. ПрошлаяИстория = ИсторияВперед[ИсторияВперед.ВГраница()]; Построитель. УстановитьНастройки(ПрошлаяИстория["Настройки”]): ЭлементыФормы.ПолеТабличногоДокумента!.Очистить(); ЭлементыФормы.ПолеТабличногоДокумента!.ТекущаяОбласть = ЭлементыФормы.ПолеТабличногоДокумента!. Область("R1C1"); ЭлементыФормы.ПолеТабличногоДокумента!. Вывести(ПрошлаяИстория["Отчет"]); ЭлементыФормы.ПолеТабличногоДокумента!.ТекущаяОбласть = ПрошлаяИстория["ТекущаяОбласть"] ; // Удалить отображенное состояние из движений вперед. ИсторияВперед.Удалить(ИсторияВперед.ВТраница()); Если ИсторияВперед.ВГраницаО = -1 Тогда ЭлементыФормы.ОсновныеДействияФормы.Кнопки.КнопкаВперед. Доступность = Ложь; КонецЕсли; КонецПроцедуры Обработчик нажатия кнопки Назад будет выглядеть с точ- ностью «до наоборот» (листинг 13.92). Листинг 13.92. Обработчик нажатия кнопки Назад // Действие кнопки Назад командной панели // ОсновныеДействияФормы // отображает предыдущее состояние отчета. // Процедура ОсновныеДействияФормыКнопкаНазад(Кнопка) // Запомнить текущее состояние для движения вперед. ИсторияВперед.Добавить( Новый СтруктураС'Настройки, Отчет. ТекущаяОбласть", Построитель .ПолучитьНастройкиО, ЭлементыФормы.ПолеТабличногоДокумента!. ПолучитьОбластьО, ЭлементыФормы.ПолеТабличногоДокумента!. ТекущаяОбласть)); ЭлементыФормы.ОсновныеДействияФормы.Кнопки.КнопкаВперед. Доступность = Истина: // Отобразить новое состояние отчета. ПредыдущаяИстория = ИсторияНазад[ИсторияНазад.ВГраница()]; Построитель. УстановитьНастройки(ПредыдущаяИстория["Настройки"]); ЭлементыФормы. ПолеТабличногоДокумента!. ОчиститьО; ЭлементыФормы.ПолеТабличногоДокумента!.ТекущаяОбласть = ЭлементыФормы.ПолеТабличногоДокумента!. Область("К1С1"); ЭлементыФормы.ПолеТабличногоДокумента!. Вывеет и(ПредыдущаяИст ория["Отчет"]);
ЭлементыФормы.ПолеТабличногоДокунента1.Текущая0бласть = ПредыдущаяИстория["ТекущаяОбласть"]; // Удалить отображенное состояние из движений назад. ИсторияНазад.Удалит ь(ИсторияНазад.ВГраница()); Если ИсторияНазад.ВГраницаО = -1 Тогда ЭлементыФормы.ОсновныеДействияФормы.Кнопки.КнопкаНазад. Доступность = Ложь: КонецЕсли: КонецПроцедуры Рис. 13.91. Отчет по остаткам товаров Созданный отчет будет работать следующим образом. При нажатии на кнопку Выполнить пользователь получит отчет по остаткам товаров (рис. 13.91). При вызове расшифровки в какой-либо строке отчета, пользователь будет получать подробный отчет о движе- ниях выбранного товара по всем складам (рис. 13.92). Кнопки Вперед и Назад позволяют пользователю осущест- влять навигацию между исходным отчетом по остаткам и полученной расшифровкой. Особенности заполнения расшифровок при выводе в диаграмму При выводе результата отчета в диаграмму построитель отчета автоматически заполняет расшифровки диаграм- мы, если ему установлены соответствующие режимы. Если свойство ЗаполнениеРасшифровки построителя отчета установлено в значение ЗначенияГруппировок, то расшиф- ровки серий и точек диаграммы будут заполнены значе- ниями соответствующих группировок (рис. 13.93). Если свойство ЗаполнениеРасшифровки построителя отчета установлено в значение Расшифровка, то расшифровки точек, серий и значений диаграммы будут заполнены структурами, содержащими значения всех группировок (рис. 13.94). Обработка полученных значений расшифровки может быть выполнена в обработчике события Обработка расшиф- ровки диаграммы. Рис. 13.92. Отчет о движениях товара по складам Рис. 13.93. Заполнение расшифровок диаграммы
Рис. 13.94. Заполнение расшифровки точек, серий и значений Использование произвольного источника данных До сих пор мы рассматривали ситуацию, когда построи- тель отчета «самостоятельно» получал данные из базы данных на основании установленного текста запроса и за- данных настроек. Однако довольно часто могут возникать задачи, когда требуется строить отчеты для данных, которые затрудни- тельно или невозможно получить при помощи языка за- просов (например, если данные получаются из некоторо- го внешнего источника, а не из базы данных). Построитель отчета может работать и с уже готовыми данными, содержащимися в различных объектах встроен- ного языка. Для этого построитель отчета содержит свой- ство ИсточникДанных, через которое, собственно, и получает нужные данные. Объекты, предоставляющие эти данные, могут иметь раз- личную структуру. Чтобы построитель отчета «понимал» данные, которые ему предоставляются для использова- ния, применяется специальный «буферный» универсаль- ный объект — ОписаниеИсточникаДанных, который «объясня- ет» построителю, какие данные ему следует использовать (рис. 13.95). Рис. 13.95. Источник данных построителя отчета После того как построителю отчета установлено свойство ИсточникДанных, построитель переходит в режим работы с внешним источником данных. В этом режиме текст за- проса (если он был установлен) игнорируется, и построи- тель предоставляет всю свою функциональность для ра- боты уже теми данными, которые содержатся в источнике данных. При использовании в качестве источника данных ре- зультата запроса следует учитывать, что если построите- лю отчета назначается иерархический источник данных, то построитель будет обрабатывать только данные, нахо- дящиеся на верхнем уровне иерархии. Поэтому в запро- се, результат которого впоследствии будет назначен ис- точником данных, не следует использовать, например, итоги. Существует несколько особенностей при работе построи- теля отчета в этом режиме: ♦ внешний источник данных может содержать только поля примитивных типов и поля — ссылки на таблицы информационной базы; ♦ построитель отчета не позволяет выводить иерархи- ческую группировку, если источник данных содержит иерархические данные (например, ссылки на иерархи- ческий справочник); ♦ у построителя отчета нельзя получить запрос, который будет использован для получения данных из информа- ционной базы; ♦ в настройках построителя отчета нельзя предоставить пользователю возможность выбора произвольных по- лей через точку от ссылочного поля. Можно только указать на конкретное поле, являющееся реквизитом другого поля, описав путь к нему в свойстве ПутьКДаннын колонки описания источника данных. В остальном работа построителя отчета с произвольным источником данных не отличается от работы построителя отчета с запросом. Установка источника данных Для того чтобы построителю отчета установить источник данных, необходимо его свойству ИсточникДанных присво- ить определенный объект ОписаниеИсточникаДанных.
Объект ОписаниеИсточникаДанных может быть создан с помо- щью конструктора, в качестве параметра которого может быть передан источник данных, для которого создается описание (листинг 13.93). Листинг 13.93. Назначение источника данных ПостроительОтчета.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаЗначенийДанные); Помимо собственно источника данных, объект ОписаниеИ- сточникаДанных в свойстве Колонки содержит описание по- лей источника данных (объект КолонкиОписанияИсточника- Данных). При создании описания источника данных конструкто- ром выполняется автоматическое заполнение описаний полей источника данных, содержащихся в этом объек- те. Однако разработчику может потребоваться настройка ко- лонок, отличная от той, которая устанавливается автома- тически. В этом случае он может отредактировать коллек- цию значений КолонкиОписанияИсточникаДанных в соответствии со своими потребностями. Каждый элемент этой коллекции — КолонкаОписанияИсточ- никаДанных, — содержит набор свойств, описывающих одну колонку источника данных: ♦ Имя - содержит имя колонки в источнике данных; ♦ ПутьКДанным — содержит описание зависимости колонок друг от друга. Колонка, чей путь к данным получен че- рез точку от пути к данным другого поля, считается ре- квизитом другой колонки. Если поле содержит через точку слово Представление, то данное поле считается представлением для колонки, от пути к данным которо- го получается представление. Например, если колонка Номенклатура имеет путь к данным Номенклатура, а ко- лонка Код имеет путь к данным Номенклатура.Код, то данная колонка будет считаться реквизитом колонки Номенклатура. Колонка с путем к данным Номенклату- ра.Представление будет считаться представлением для колонки Номенклатура; ♦ Поле — признак того, что данная колонка может быть ис- пользована в качестве поля отчета; ♦ Порядок — признак того, что по данной колонке можно выполнять упорядочивание; ♦ Отбор — признак того, что на данную колонку можно на- кладывать отбор; ♦ Измерение — признак того, что данная колонка может быть использована как группировка отчета; ♦ Итог — строка, содержащая выражение для расчета ито- га. Для построителя отчета выражение данной строки соответствует выражению для вычисления итога, ис- пользуемому в языке запросов. Например, может понадобиться возможность группи- ровки по некоторым полям. Для этого следует устано- вить для соответствующих колонок источника данных свойство Измерение и указать, в какой колонке будут вы- водиться итоги по группировкам. При этом следует помнить, что все изменения в описании источника дан- ных должны быть выполнены до его назначения по- строителю отчета. Например, для того чтобы иметь возможность группи- ровки по полям Номенклатура и Склад и выводить сумму значений поля КоличествоРасход в этой же колонке, мож- но использовать следующий код (листинг 13.94). Листинг 13.94. Пример настройки источника данных ДанныеИсточника = Новый ОписаниеИсточникаДанных(ТаблицаЗначенийДанные); ДанныеИсточника.Колонки.Номенклатура.Измерение = Истина: ДанныеИсточника.Колонки.Склад.Измерение = Истина; ДанныеИсточника.Колонки.КоличествоРасход.Итог = "СУММА(КоличествоРасход)"; Построитель.ИсточникДанных = ДанныеИсточника; Текстовый документ Текстовый документ 1С:Предприятия позволяет пред- ставлять различную информацию (в том числе и резуль- таты отчетов) в виде текстов. Текстовый документ может быть прочитан из текстового файла, сохранен в текстовый файл. Он может быть разме- щен в форме или в макете, работа с ним возможна средст- вами встроенного языка (рис. 13.96). По большому счету, текстовый документ позволяет вы- полнять три логические группы действий: ♦ чтение с диска и запись на диск текстовых файлов, по- лучение и установка текста, содержащегося в докумен- те как единого целого; ♦ работа с отдельными строками текстового документа: получение, добавление, удаление, замена; ♦ создание текстового макета и использование его для формирования результирующего текстового документа. Рис. 13.96. Схема использования текстового документа
Чтение и запись текстовых файлов Для выполнения чтения и записи текстовых файлов ис- пользуются следующие методы текстового документа. Конструктор позволяет создать новый текстовый доку- мент. Методы Прочитать () и Записать О позволяют соответствен- но читать и записывать текстовые файлы с/на диск. При этом в параметрах методов обязательно должен быть ука- зан путь к файлу и может быть указана кодировка, в кото- рой необходимо выполнить чтение/запись. Метод УстановитьТипФайлаО также позволяет задать коди- ровку файла, в который будет сохранен текстовый доку- мент. Методы ПолучитьТекстО и УстановитьТекстО позволяют опе- рировать с содержимым текстового документа как с еди- ным целым, имеющим тип Строка. Метод Показать () позволяет открыть содержимое тексто- вого документа для просмотра и редактирования в тек- стовом редакторе. Свойство ТолькоПроснотр!) позволяет управлять возмож- ностью редактирования содержимого текстового доку- мента при открытии его в текстовом редакторе. Прежде всего, следует сказать о том, что при работе с тек- стовыми документами поддерживается четыре вида ко- дировки: ♦ UTF-8 — кодировка, в которой символы кодируются несколькими байтами (их количество меняется в зави- симости от кодируемого символа); в начале файла сто- ит специальный маркер для кодировки UTF-8 — три байта, которые в шестнадцатеричной кодировке выгля- дят как EF ВВ BF; ♦ UTF-16 — кодировка, в которой символы кодируются последовательностями из двух байт; в начале файла стоит специальный маркер для кодировки UTF-16; ♦ ANSI — кодировка, в которой для представления каж- дого символа используется 1 байт. Для представления символов используется кодовая страница ANSI, соот- ветствующая текущим региональным настройкам Win- dows. Данный вид кодировки текста часто называют Windows-кодировкой; ♦ OEM — кодировка, в которой для представления каж- дого символа используется 1 байт. Для представления символов используется кодовая страница OEM, соот- ветствующая текущим региональным настройкам Windows. Данный вид кодировки текста часто называ- ют DOS-кодировкой. В 1С:Предприятии тип Строка означает UNICODE -строку. Аналогичным образом, все текстовые данные в ^Пред- приятии представляются в UNICODE (в максимально универсальном виде). Только вне системы, как правило, в файлах, тексты существуют в закодированном виде (ср!257, ср!251, UTF-8, UTF-16 и т. п.). При чтении текстового файла можно задать кодировку файла, который будет считан. Кодировка задается с по- мощью системного перечисления КодировкаТекста (лис- тинг 13.95). Листинг 13.95. Задание кодировки Текст Док = Новый ТекстовыйДокунентО; ТекстДок.Прочитать("С:\Price.txt". КодировкаТекста.UTF16); В случае если в явном виде указано использование коди- ровки UTF8 или UTF16, при чтении файла будет снача- ла выполняться попытка чтения соответствующего мар- кера, расположенного в начале файла. В случае если такой маркер обнаружен не будет, система будет счи- тать, что файл имеет другой формат, и будет вызвано ис- ключение. Если указана кодировка ANSI или OEM, то будет выпол- няться чтение всего содержимого файла до его оконча- ния. При этом каждый прочитанный из файла байт будет рассматриваться как код соответствующего символа. Признаком конца файла является символ EOF (end-of- file), который имеет шестнадцатеричный код 1А. При выполнении метода Прочитать!) кодировка может быть и не указана. В этом случае система сначала попыта- ется прочитать файл в кодировке UTF8. Если окажется, что файл имеет другой формат, она попытается прочи- тать его в кодировке UTF16. Если эта кодировка также окажется неверной, файл будет прочитан в кодировке ANSI. Следует учитывать, что если метод Прочитать!) приме- нить не к текстовому файлу, а к двоичному, то ошибки выдано не будет, и файл будет прочитан. Однако такое действие не принесет никакого осмысленного результа- та. Двоичный файл состоит из последовательности бай- тов, представляющих не только коды существующих символов, но и все другие коды. Так как в начале двоич- ного файла не будет найден маркер кодировки UTF, этот файл будет прочитан в кодировке ANSI. При этом каж- дый байт двоичного файла будет трансформирован в не- который символ в соответствии с кодировкой. Набор та- ких символов не имеет практического смысла. Кроме этого, чтение файла закончится тогда, когда встретится символ EOF. В текстовых файлах этот символ всегда расположен в конце файла. В двоичных файлах анало- гичный символ может располагаться внутри файла или вообще отсутствовать. Если EOF отсутствует — файл будет прочитан до конца. Если же EOF расположен внутри файла — будет прочитана только часть файла, до этого символа. После того как файл прочитан, его можно открыть для просмотра и редактирования (метод Показать!)), или по- лучить текст, содержащийся в файле для дальнейшей об- работки (метод ПолучитьТекстО). Например, чтобы просмотреть текстовый файл, содержа- щий прайс-лист поставщика, можно использовать сле- дующий код (листинг 13.96). Листинг 13.96. Просмотр текстового документа ТекстДок = Новый ТекстовыйДокунентО; Т екстДок.Прочитат ь!"С:\Ргтсе.txt"): ТекстДок.ТолькоПроснотр = Истина; ТекстДок.Показать!); При выполнении метода Показать!) можно задать заголо- вок окна, который будет отображаться, а также имя фай- ла, в который будет предложено сохранить измененный текстовый документ (листинг 13.97).
Листинг 13.97. Задание имени сохраняемого файла ТекстДок = Новый ТекстовыйДокументО: ТекстДок.Прочитать("С:\Ргтсе.txt"); ТекстДок.Показать("Прайс-лист поставщика". "C:\Price_New.txt"): Если пользователю предоставляется возможность редакти- рования открываемого текстового файла, следует учиты- вать следующую особенность: для обеспечения привычного поведения открытого файла при вызове метода ПоказатьО обязательно должен быть указан путь для сохранения изме- ненного файла. Тогда если пользователь модифицировал документ, то при закрытии окна редактора будет задай во- прос о необходимости сохранения измененного файла. Если при вызове метода Показать () путь не указан, то окно редактора, содержащего модифицированный документ, будет закрываться без вопросов, и изменения, выполнен- ные пользователем, будут потеряны. Другой пример: чтобы получить текст прайс-листа для дальнейшей обработки, можно использовать такой код (листинг 13.98). Листинг 13.98. Получение текста из текстового документа ТекстДок = Новый ТекстовыйДокументО: ТекстДок. Прочитат ьС'САРгтсе. txt"): ТекстДляОбработки = ТекстДок. ПолучитьТекстО; Запись текстового документа в файл в простейшем слу- чае может быть выполнена с использованием уже готово- го текста. Если указанный файл не существует, он будет создан. Если указанный файл существует, он будет заме- щен (листинг 13.99). Листинг 13.99. Пример записи текстового документа ТекстДокумента = ТекстДляОбработки: ТекстДок = Новый ТекстовыйДокументО: ТекстДок.Установит ьТекст(ТекстДокумента); ТекстДок. Записать ("С: ХСписокТоваров. txt”, КодировкаТекста-ANSI); Работа с отдельными строками текстового документа Помимо работы с содержимым текстового документа как с единым целым, текстовый документ может быть пред- ставлен в виде совокупности строк, содержащихся в нем. В этом случае становится возможным произвольный порядок заполнения текстового документа, а также удале- ние или замещение отдельных строк текстового документа. Для добавления строк в документ используются методы ДобавитьСтрокуО, ВставитьСтрокуО и ЗаменитьСтрокуО. Этим методам должна быть передана собственно сама добав- ляемая строка, имеющая тип Строка, а также, для вставки и замены указан номер результирующей строки текстово- го документа. При добавлении строки (листинг 13.100) новая строка добавляется в конец текстового документа (рис. 13.97). Листинг 13.100. Добавление строки в текстовый документ ТекстДок = Новый ТекстовыйДокументО: ТекстДок. Прочитать ("С: \Р гт се. txt"): ТекстДок.ДобавитьСтрокуС"Новая строка"); Рис. 13.97. Добавление строки в текстовый документ Если новая строка вставляется в текстовый документ и ее номер меньше либо равен количеству строк текстового документа (листинг 13.101), то она будет размещена в текстовом документе соответственно указанному номеру (рис. 13.98). Листинг 13.101. Вставка строки в текстовый документ ТекстДок = Новый ТекстовыйДокументО; ТекстДок.Прочитать("C:\Price.txt"): Текст Док. ВставитьСтроку(4, "Новая строка''): Рис. 13.98. Вставка строки в текстовый документ Если для вставляемой строки указан номер, равный нулю или единице, — новая строка будет вставлена перед пер- вой существующей строкой текстового документа. Если для вставляемой строки указан номер, равный или больший количеству строк в текстовом документе, новая строка будет вставлена перед последней существующей строкой текстового документа. Замена строк текстового документа выполняется с помо- щью метода ЗаменитьСтрокуО (листинг 13.102). В парамет- рах этого метода обязательно должен быть указан номер заменяемой строки и сама строка, которая будет исполь- зована вместо существующей (рис. 13.99). Если в доку- менте нет строки с таким номером, содержимое докумен- та не изменяется. Листинг 13.102. Замена строки текстового документа ТекстДок = Новый ТекстовыйДокументО: ТекстДок.Прочитать("С:\Price.txt"): ТекстДок.ЗаменитьСтроку(2, "новая строка''): Рис. 13.99, Замена строки текстового документа Для удаления строк документа используются методы Уда - литьСтрокуО и ОчиститьО- Метод УдалитьСтрокуО удаляет из текстового документа строку, с указанным номером. Если в документе нет строки с таким номером — содер- жимое документа не изменяется. Метод ОчиститьО удаля- ет все строки из текстового документа.
Метод КоличествоСтрокО позволяет определить, какое ко- личество строк содержится в текстовом документе. Для получения отдельной строки документа использу- ется метод ПолучитьСтрокуО, в параметре которого указы- вается номер строки, которую требуется получить. Как правило, этот метод используется при обходе строк тек- стового документа (листинг 13.103). Листинг 13.103. Обход строк текстового документа ТекстДок = Новый ТекстовыйДокументО: ТекстДок.Прочитать("С:\Р г1 се.txt"): КоличествоСтрокДокумента = Текст Док. КоличествоСтрокО; Для НомерСтроки = 1 По КоличествоСтрокДокумента Цикл ОчереднаяСтрока = ТекстДок.ПолучитьСтроку(НомерСтроки); КонецЦикла; Использование макетов текстовых документов Помимо непосредственного формирования содержимого текстового документа и записи его в документ целиком или по строкам, существует возможность заполнения текстовых документов на основе макетов. Макет тексто- вого документа описывает неизменяемые части текстово- го документа, содержащие оформление, и поля, в которые могут быть добавлены данные. Рис. 13.100. Схема формирования текстового документа на основе макета Процесс заполнения текстового документа на основе ма- кета заключается в считывании определенных областей макета, циклическом заполнении их данными и последо- вательном выводе полученных частей документа в ре- зультирующий текстовый документ (рис. 13.100). Формат макета текстового документа Макет текстового документа представляет собой тексто- вый документ, в котором использованы служебные стро- ки, начинающиеся с символа «#». После управляющего символа следуют ключевые слова, которые описывают те или иные элементы макета. Также в макете текстового документа используются слу- жебные символы «[» и «]», которые определяют располо- жение изменяемых полей макета. Весь макет текстового документа состоит из областей. Одна область объединяет в себе несколько последова- тельно расположенных строк. Области должны следовать друг за другом и не могут пересекаться или включаться друг в друга. Для описания области используются ключевые слова Об- ласть и КонецОбласти. После ключевого слова Область ука- зывается имя области (листинг 13.104). Листинг 13.104. Пример описания области ^Область Шапка ^КонецОбласти Ключевое слово КонецОбласти указывать не обязательно — объявление начала области означает окончание предыду- щей области. Каждая область может быть представлена в нескольких вариантах — на разных языках. Для этого в объявлении области, через пробел после имени области, указывается код языка, для которого должна быть использована эта область (листинг 13.105). Листинг 13.105. Пример описания вариантов области ^Область Шапка RU ^КонецОбласти ^Область Шапка EN ^КонецОбласти В данном примере описаны два варианта области Шапка: для языка с кодом RU и для языка с кодом EN. Код языка, указываемый в области, должен соответствовать одному из кодов объектов конфигурации Язык (Общие - Языки). Указание кода языка в области позволяет использовать при формировании результирующего документа те или иные варианты области. Если не предпринимать специальных действий, то при получении области текстового макета будет получен вариант области с тем кодом языка, который соответст- вует коду языка, назначенному для текущего пользова- теля. Таким образом, если текущему пользователю на- значен язык с кодом RU, то будет получена область Шапка RU.
Если текущему пользователю язык не назначен, то будет использован код языка, который указан в свойстве Основ - ной язык конфигурации. Если код языка пользователя (или основного языка кон- фигурации) не совпадает ни с одним из кодов, которые указаны для вариантов данной области макета, система будет пытаться найти вариант этой области, для которого код языка не указан. Например, пусть существуют сле- дующие варианты области Шапка (листинг 13.106). Листинг 13.106. Пример нескольких вариантов области ^Область Шапка RU #КонецОбласти ^Область Шапка #КонецОбласти ^Область Шапка EN #КонецОбласти Если текущему пользователю задан язык с кодом КА, то будет получен вариант области Шапка (без кода языка). Если такая область найдена не будет, система вызовет ис- ключение. Наряду с описанным механизмом получения вариантов областей макета, разработчик самостоятельно может ука- зывать, область с каким кодом языка должна быть полу- чена. Для этого используется свойство текстового доку- мента КодЯзыкаМакета. Это свойство может принимать значения типа Строка и Неопределено. По умолчанию это свойство имеет значе- ние Неопределено. В этом случае действует механика, опи- санная выше. Если задать этому свойству конкретный код языка, то при получении областей текстового макета будет получен вариант области с кодом, соответствующим значению свойства КодЯзыкаМакета. При этом если варианта области с таким кодом нет, будет получен вариант области, не со- держащий кода языка. Если такой вариант области тоже отсутствует, будет вызвано исключение. В любой момент разработчик может вернуться к механи- ке получения вариантов областей в зависимости от языка текущего пользователя — для этого достаточно устано- вить свойству КодЯзыкаМакета значение Неопределено. Каждая область состоит из двух логических частей: слу- жебная часть и текстовая часть. Эти части не имеют фик- сированных границ. Служебная часть области В служебную часть входят строки, начиная от объяв- ления области, которые содержат ключевые слова. Да- лее, до конца области следует текстовая часть (лис- тинг 13.107). Листинг 13.107. Служебная часть области ^Область Строка #Попе Остаток ^Формат "ЧЦ=10: ЧДЦ=3; ЧРД=." [Склад ]|[Номенклатура ]|[ Остаток]| |«Номенклатура >| ^онецОбласти В приведенном примере вторая и третья строки представ- ляют собой служебную часть области. Наличие служеб- ной части — не обязательно, она может и отсутствовать. Служебная часть области может содержать описания фор- матов полей и описание замены символов. Замена символов обычно используется, если в оформле- нии строк макета должен входить символ «#». Если опи- сание замены символов используется, оно располагается в начале области и описывается ключевым словом Замена- Символа (листинг 13.108). Листинг 13.108. Замена символа ^Область Шапка RU #ЗаменаСимвола "0" Отчет 0 Склад 0 Номенклатура 0 Остаток 0 #КонецОбласти В данном примере, при выводе области в результирую- щий текстовый документ, символы @ будут заменены на символ #. Если бы замена символов не использовалась, то строка, содержащая символы @, была бы воспринята как управляющая. После описания замены символов могут располагаться описания форматов полей. В общем виде каждое поле может быть описано несколькими ключевыми словами (листинг 13.109). Листинг 13.109. Описание поля ^Область Строка #Поле Остаток ^Выравнивание Право #3абивать Истина ^Формат "ЧЦ=10; ЧДЦ=3; ЧРД=." |[Склад ]|[Номенклатура ]|[ Остаток]| |«Номенклатура >| #КонецОбласти Ключевое слово Поле указывает, что далее будут следо- вать управляющие конструкции, описывающие формат поля, с указанным именем. Ключевое слово Выравнивание служит для указания вари- анта выравнивания значения поля в пределах отведенно- го для него места. Возможные варианты: Лево, Право, Центр, ПоШирине. Ключевое слово Формат служит для указания форматной строки, которая будет использоваться при выводе значе- ния поля. Ключевое слово Забивать служит для указания необходи- мости забивки области, отведенной для поля, символами «#», если содержимое поля не помещается в отведенное место. Возможные варианты: Истина, Ложь. Текстовая часть области Текстовая часть области собственно содержит оформле- ние, которое будет использовано при выводе в результи- рующий текстовый документ, и указание изменяемых полей, которые описываются их именами. Область, ко- торая будет занята полем, ограничивается символами «[» и «]». Например, в предыдущем примере в текстовой части описаны три поля с именами Склад, Номенклатура и Остаток.
Расположение имени поля внутри области определяет выравнивание выводимого в это поле значения. Если имя поля прижато к левой скобке, считается, что поле имеет левое выравнивание, а если к правой скобке, то правое выравнивание. Если пробелы есть слева и справа от име- ни поля, оно будет центрироваться в пределах отведен- ных под него знакомест. В случае если имя одного или нескольких полей не поме- щаются в отводимое для них количество знакомест, име- на полей перечисляются в этой же строке после ключево- го слова Поля (листинг 13.110). Листинг 13.110. Использование ключевого слова Поля ^Область Строка #Поле Остаток ^Формат "ЧЦ=10: ЧДЦ=3: ЧРД=.” I[ 11[ 11[ 11 #Поля Склад Номенклатура Остаток #КонецОбласти Такое описание будет аналогично описанию, приведенно- му в листинге 13.111. Листинг 13.111. Описание полей макета ^Область Строка #Поле Остаток ^Формат "ЧЦ=10: ЧДЦ=3; ЧРД=." |[Склад ] | [Номенклатура ] | [ Остаток]| #КонецОбласти При описании местоположения полей можно указывать возможность переноса длинных значений поля на другие строки. Для этого используются ограничители положе- ния поля вида «{», «}» и «<», «>». Ограничители {ИмяПоля} указывают, что автоперенос тек- ста, хранящегося в поле ИмяПоля, возможен на эту строку, и ограничивают область для не поместившегося ранее в поле текста. При этом даже если в этой строке нет необ- ходимости выводить ни одно из полей, строка все равно будет выведена. Ограничители <ИмяПоля> указывают, что автоперенос тек- ста, хранящегося в поле ИмяПоля, возможен, и ограничи- вают область для не поместившегося на предшествующей строке в поле ИмяПоля текста. При этом если все поля, имеющиеся в строке, указаны в угловых скобках, но ни одно из них не потребовалось для вывода текста, строка не будет выведена. В случае если при выводе текста из поля в строку, в которой поле размещено в угловых скоб- ках, текст все равно не уместится, такая строка будет раз- множена до тех пор, пока не удастся вывести весь текст из поля (листинг 13.112). Листинг 13.112. Описание полей макета ^Область Строка #Поле Остаток ^Выравнивание Право #3абивать Истина ^Формат "ЧЦ=10: ЧДЦ=3; ЧРД=." I[Склад ] [ Остаток] [Номенклатура ]| {Номенклатура }| «Номенклатура >| #КонецОбласти В приведенном примере поле значение поля Номенклатура будет выведено вместе с полями Склад и Остаток. После этой строки будет выведена еще одна строка. Если значе- ние поля Номенклатура не поместилось в первой строке, его вывод будет продолжен во второй строке. Если значе- ние поля Номенклатура не поместилось и во вторую стро- ку, будет выведено еще необходимое количество строк до тех пор, пока значение поля Номенклатура не будет выве- дено полностью. Процедура формирования текстового документа Для формирования текстового документа на основе маке- та используются следующие методы и свойства текстово- го документа. Метод ПолучитьОбластьО позволяет получить область ма- кета текстового документа по имени. Полученная область также имеет тип ТекстовыйДокуиент (листинг 13.113). Листинг 13.113. Получение области ОбластьШапка = Макет.ПолучитьОбластьСШапка"); Свойство Параметры позволяет получить доступ к коллек- ции параметров области макета текстового документа (объект ПараметрыМакетаТекстовогоДокумента). Имена пара- метров совпадают с именами полей, описанных в данной области макета текстового документа. Задача разработчи- ка состоит в том, чтобы присвоить параметрам требуемые значения. Наиболее удобным способом присвоения значения пара- метрам является использование метода Заполнить О объек- та ПараметрыМакетаТекстовогоДокумента. Этому методу может быть передан произвольный объект, и для совпадающих свойств переданного объекта и имен параметров макета текстового документа метод выполнит присвоение значе- ний. Например, если переменная Выборка содержит выбор- ку из результата запроса, то заполнение параметров макета текстового документа (ОбластьСтроки) может выглядеть следующим образом (листинг 13.114). Листинг 13.114. Пример заполнения параметров области Пока Выборка.Следующий() Цикл ОбластьСтроки = Макет.ПолучитьОбластьС"Строка"); ОбластьСтроки.Параметры.Заполнить(Выборка): ИтоговыйДокумент.Вывести(ОбластьСтроки); КонецЦикла; Аналогичного результата можно достигнуть, если вы- полнять присвоение значений каждому параметру в от- дельности (например, если псевдонимы полей запроса не совпадают с именами параметров макета текстового доку- мента) (листинг 13.115). Листинг 13.115. Пример заполнения параметров области Пока Выборка.Следующий() Цикл ОбластьСтроки = Макет.ПолучитьОбластьС'Строка"); ОбластьСтроки.Параметры.Склад = Выборка.СкладПредставление; ОбластьСтроки.Параметры.Номенклатура = Выборка. НоменклатураПредставление; ОбластьСтроки.Параметры.Остаток = Выборка.КоличествоОстаток; ИтоговыйДокумент.Вывести(ОбластьСтроки); КонецЦикла; Метод Вывести() позволяет вывести секцию макета тексто- вого документа, заполненную данными, в результирую-
щий текстовый документ. В параметре метода указывает- ся сама секция (тип ТекстовыйДокунент), подготовленная для вывода. Обратите внимание, что этот метод необхо- димо применять не к секции макета, а к результирующе- му текстовому документу. В качестве примера, иллюстрирующего полную процеду- ру формирования текстового документа на основе макета, можно рассмотреть вывод отчета об остатках товаров в текстовый документ. Предположим, что в конфигурации создан макет, содержащий следующий текстовый доку- мент (листинг 13.116). Листинг 13.116. Макет текстового документа Область Шапка RU Отчет I Склад | Номенклатура | Остаток | #КонецОбласти Область Шапка EN Report I Warehouse | Product | Quantity | #КонецОбласти Область Строка Ооле Остаток ^Формат "ЧЦ=10; ЧДЦ=3; ЧРД=." |[Склад ]|[Номенклатура ]|[ Остаток]| | «Номенклатура >| КонецОбласти Область Подвал ^КонецОбласти Тогда процедура, получающая остатки товаров и выводя- щая их в текстовый документ, может выглядеть следую- щим образом (листинг 13.117). Листинг 13.117. Пример процедуры, формирующей текстовый документ на основе макета // Получить данные из базы данных Запрос = новый Запрос; Запрос. Текст = "ВЫБРАТЬ ТоварыНаСкладахОстатки.Склад.Представление КАК Склад, ТоварыНаСкладахОстатки.Номенклатура.Представление КАК Номенклатура, ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки АВТОУПОРЯДОЧИВАНИЕ"; Выборка = Запрос.ВыполнитьО.ВыбратьО; // Создать новый текстовый документ, в который будет осуществляться вывод ИтоговыйДокумент = Новый ТекстовыйДокунент(); // Получить макет текстового документа Макет = ПолучитьМакетС’ТекстовыйМакет"); // Установить код языка макета, если в этом есть необходимость //Макет.КодЯзыкаМакета = "EN"; // Вывести область Шапка ИтоговыйДокумент.Вывести(Макет.ПолучитьОбласть("Шапка")); //В цикле перебрать выборку из результата запроса // и для каждого элемента выборки получить область макета, И заполнить ее данными выборки и вывести Пока Выборка.Следующий() Цикл ОбластьСтроки = Макет.ПолучитьОбластьС'Строка"); ОбластьСтроки.Параметры.Заполнить(Выборка); ИтоговыйДокумент.Вывести(ОбластьСтроки); КонецЦикла; // Вывести область Подвал ИтоговыйДокумент.Вывести(Макет.ПолучитьОбласть("Подвал")); // Открыть итоговый текстовый документ для просмотра ИтоговыйДокумент.Показать(); В заключение хочется заметить, что макет текстового до- кумента может храниться не только в макете конфигура- ции, но и во внешнем текстовом файле. Сравнение текстовых документов Система 1С:Предприятие позволяет выполнять автома- тическое сравнение двух текстовых документов. Следует оговориться, что механизм сравнения файлов позволяет сравнивать файлы не только как текстовые документы, но и как табличные документы, и как бинарные файлы. Возможность сравнения двух файлов как текстовых до- кументов может быть полезной в тех случаях, когда тре- буется знать сам факт того, что файлы отличаются, на- пример, чтобы определить, отличается ли новый прайс- лист, присланный поставщиком, от того, который имеет- ся, и нужно ли его обрабатывать. Также сравнение тек- стовых документов может использоваться, когда, напри- мер, необходимо визуально проанализировать отличия в двух больших текстовых документах. Для решения таких задач можно было бы прочитать оба файла в текстовые документы и далее создать некий алго- ритм, который бы выполнял сравнение полученных тек- стов. Однако существует более простой способ сравнения тек- стовых документов, который можно использовать как ин- терактивно, так и средствами встроенного языка. Для интерактивного сравнения файлов можно воспользо- ваться командой Файл | Сравнить файлы. Будет открыто окно сравнения файлов, в котором можно задать сравниваемые файлы и установить параметры сравнения (рис. 13.101). Сравнить файлы X Сравнить [cASamplet txt Hl"'l I OK | С |cASample2txt Hl'"l I Отмена { Как | Щ Текстовый документ| Справка | 0 Игнорировать пустое пространство ЕЗ Учитывать регистр Рис. 13.101. Сравнение файлов Этот же механизм доступен и из встроенного языка. Для этого следует воспользоваться общим объектом Сравне- ниеФайлов. Свойства ПервыйФайл и ВторойФайл служат для задания пу- тей к сравниваемым файлам. Свойство СпособСравнения позволяет задать способ сравне- ния файлов и принимает значения системного перечисле- ния СпособСравненияФайлов:
♦ как бинарных файлов (Двоичное); ♦ как текстовых документов (ТекстовыйДокунент); ♦ как табличных документов (ТабличныйДокунент). Свойства ИгнорироватьПустоеПространство и УчитыватьРегистр задают настройки сравнения. Если свойство Игнорировать- ПустоеПространство установлено в значение Истина, то про- белы при сравнении файлов как текстовых документов учитываться не будут. Если свойство УчитыватьРегистр ус- тановлено в значение Истина, то прописная и строчная бу- квы будут считаться различными символами. Реультаты выполнения методов ПоказатьРазличияО и По- казатьРазличияМодальноО аналогичны интерактивному ре- зультату выполнения сравнения. Если файлы совпа- дают, будет выдано сообщение об этом. Если файлы отличаются, будет открыто окно для просмотра разли- чий в файлах. Метод Сравнить() позволяет получить результат сравне- ния файлов в виде булева значения без открытия инте- рактивных форм. Если файлы совпадают — будет возвра- щено значение Истина, если отличаются — значение Ложь. Например, сравнение двух файлов может быть выполне- но с помощью следующего кода (листинг 13.118). Листинг 13.118. Пример сравнения текстовых файлов Сравнение = Новый СравнениеФайловО: Сравнение.ПервыйФайл = "C:\Samplel.txt”; Сравнение. ВторойФайл = “C:\Saniple2.txt"; Сравнение.СпособСравнения = СпособСравненияФайлов.ТекстовыйДокунент; Сравнение.ИгнорироватьПустоеПространство = Истина; Сравнение.УчитыватьРегистр = Ложь; РезультатСравнения = Сравнение.Сравнить!); ПРИМЕЧАНИЕ Следует заметить, что не во всех случаях система сможет выполнить сравнение текстовых файлов как текстовых до- кументов. Перед сравнением система последовательно выполняет попытку чтения файлов в кодировках UTF-8, UTF-16 и ANSI. Если файлы прочитаны в кодировках UTF-8, UTF-16 или если при чтении в кодировке ANSI файлы не содержат 0, то система выполнит их сравнение как тексто- вых документов. Если попытки чтения были неудачными (или при чтении в кодировке ANSI были обрнаружены символы 0), то система выполнит сравнение этих файлов как бинарных. Табличный документ Табличный документ 1С:Предприятия является од- ним из основных средств для создания различных вы- ходных форм и представления итоговых данных. Он может быть получен из файла табличного документа, сохранен в файлы различных форматов. Табличный документ может быть размещен в форме или в макете, работа с ним возможна средствами встроенного языка (рис. 13.102). Рис. 13.102. Схема использования табличного документа Он может содержать вложенные таблицы, картинки, раз- личные элементы управления, может использоваться для ввода данных. Табличный документ поддерживает меха- низм расшифровок для получения связанных отчетов, от- крытия форм и иных действий. Общие свойства табличного документа Можно сказать, что табличный документ состоит из строк и колонок, на пересечении которых располагаются ячейки. Общее оформление табличного документа опре- деляется несколькими свойствами. Прежде всего, это свойства ОтображатьЗаголовки и Отобра- жатьСетку. По умолчанию при создании нового табличного документа эти свойства имеют значение Истина (лис- тинг 13.119), поэтому табличный документ имеет вид, представленный на рис. 13.103. Листинг 13.119. Отображение заголовков и сетки табличного документа ТабДок = Новый ТабличныйДокунент!); ТабДок. Показать О; Рис. 13.103. Отображение заголовков и сетки При необходимости разработчик может управлять ото- бражением как заголовков, так и сетки документа (лис- тинг 13.120). Внешний вид табличного документа с заго- ловками представлен на рис. 13.104.
Листинг 13.120. Отображение заголовков табличного документа ТабДок = Новый ТабличныйДокументО; ТабДок.ОтображатьСетку = Ложь: ТабДок.ПоказатьО: Пример отображения только сетки табличного документа представлен в листинге 13.121. Внешний вид документа с сеткой показан на рис. 13.105. Листинг 13.121. Отображение сетки табличного документа ТабДок = Новый ТабличныйДокументО; ТабДок.ОтображатьЗаголовки = Ложь; ТабДок.ПоказатьО; Рис. 13.105. Отображение сетки Если оба свойства, ОтображатьЗаголовки и ОтображатьСетку, установить в значение Ложь (листинг 13.122), то табличный документ будет иметь вид, представленный на рис. 13.106. Листинг 13.122. Табличный документ без отображения заголовков и сетки ТабДок = Новый ТабличныйДокументО; ТабДок.ОтображатьЗаголовки = Ложь; ТабДок. ОтображатьСетку = Ложь; ТабДок.ПоказатьО; Таблица - □ х Рис. 13.106. Табличный документ без заголовков и сетки Если заголовки табличного документа отображаются, раз- работчик может управлять цветом текста и цветом фона заголовков. Для этого используются свойства табличного документа ЦветТекстаЗаголовков и ЦветФонаЗаголовков, кото- рые имеют значения типа Цвет. По умолчанию эти свойст- ва имеют значения, соответствующие цветам текста фор- мы и фона формы из стиля, используемого в качестве основного для конфигурации (свойство Основной стиль). Табличный документ позволяет фиксировать первые стро- ки и колонки. Такую возможность удобно использовать для просмотра больших таблиц. В этом случае можно зафикси- ровать, например, шапку таблицы, и при вертикальной про- крутке документа она всегда будет присутствовать в верх- ней части видимой области документа. Для того чтобы задать количество фиксируемых строк или колонок, используются свойства табличного доку- мента ФиксацияСверху и ФиксацияСлева. Они принимают зна- чения типа Число, которое указывает количество фикси- руемых строк или колонок. Например, можно зафиксировать три строки и четыре ко- лонки документа (листинг 13.123). В этом случае при го- ризонтальной и вертикальной прокрутке документа пер- вые четыре колонки и первые три строки всегда будут присутствовать в окне документа (рис. 13.107). Листинг 13.123. Использование горизонтальной и вертикальной фиксации в табличном документе ТабДок = Новый ТабличныйДокументО; ТабДок.ОтображатьСетку = Ложь; ТабДок.ФиксацияСверху = 3; ТабДок.ФиксацияСлева = 4; ТабДок.ПоказатьО; Для оформления табличного документа может использо- ваться фоновый рисунок. Этот рисунок будет распо- лагаться «под» текстом документа и может быть как за- фиксирован (то есть при любой прокрутке документа, фоновый рисунок перемещаться не будет), так и не за- фиксирован. При этом фоновый рисунок при прокрутке документа будет перемещаться вместе с ячейками таб- личного документа. Для задания фонового рисунка используется свойство табличного документа ФоноваяКартинка, имеющее тип Кар- тинка. Для управления фиксацией фоновой картинки ис- пользуется свойство ФиксированныйФон, имеющее тип Буле- во. По умолчанию фон не зафиксирован (свойство имеет значение Ложь). Пример добавления картинки и фиксации фона таблич- ного документа приведен в листинге 13.124. Листинг 13.124. Использование фиксированной фоновой картинки в табличном документе ТабДок = Новый ТабличныйДокументО; Картинка = Новый Картинка("С:\Ртс1.рпд"); ТабДок.ФоноваяКартинка = Картинка; ТабДок.ФиксированныйФон = Истина: ТабДок.ПоказатьО: Табличный документ может быть отображен на экране в ок- не редактора табличных документов. При этом можно управлять видом отображения: цветной или черно-белый. Черно-белый вид отображения может использоваться для того, чтобы оценить, например, внешний вид цветного до- кумента, распечатанного на черно-белом принтере. Для управления видом отображения табличного доку- мента используется свойство ЧерноБелыйПросмотр. По умол- чанию это свойство имеет значение Ложь, то есть документ отображается в цветном виде. Ячейки и области текстового документа могут быть за- щищены от редактирования, так же как и весь документ.
Для того чтобы защитить весь документ, следует исполь- зовать свойство ТолькоПросмотр. Если его установить в зна- чение Истина, то в этом случае можно будет редактировать только те ячейки, для которых свойство Защита не уста- новлено. По умолчанию для всех ячеек текстового доку- мента свойство Защита имеет значение Истина, а для самого документа — Ложь. Также, независимо от свойств отдельных ячеек, можно запретить редактирование и копирование табличного до- кумента. Для этого следует свойство Защита документа ус- тановить в значение Истина. В том случае, если редактирование табличного документа разрешено, можно задать направление перехода после редактирования значения очередной ячейки. Для этого используется свойство НаправлениеПерехода, которое при- нимает значения системного перечисления ТипНаправления- ПереходаТабличногоДокумента. По умолчанию значение это- го свойства равно ПоКолонкам, но разработчик может за- дать также значения ПоСтрокан и БезПерехода. В последнем случае после того, как нажата клавиша Ввод, положение текущей области табличного документа изменяться не будет. Табличный документ может быть прочитан из файла таб- личного документа. Для этого используется метод Прочи- татьО. В качестве параметра передается строка, содержа- щая путь к файлу табличного документа. Для отображения табличного документа в окне редакто- ра табличных документов используется метод ПоказатьО. В качестве параметров этого метода передается заголовок окна, который будет установлен при открытии докумен- та, путь к сохраняемому файлу и признак активизации открываемого окна. Для обеспечения привычного поведения открытого фай- ла при вызове метода Показать () обязательно должен быть указан путь для сохранения измененного файла. Тогда если пользователь модифицировал документ, то при за- крытии окна редактора будет задан вопрос о необходимо- сти сохранения измененного файла. Если при вызове метода Показать () путь не указан, то окно редактора, содержащего модифицированный документ, будет закрываться без вопросов и изменения, выполнен- ные пользователем, будут потеряны. Признак активизации по умолчанию имеет значение Истина, таким образом, окно, содержащее открытый таб- личный документ, становится активным, открывается «поверх» существующих окон. Если установить его в зна- чение Ложь, то активным будет оставаться то окно, из ко- торого была вызвана обработка (листинг 13.125). Листинг 13.125. Открытие табличного документа без активизации окна ТабДок = Новый ТабличныйДокументО; Т абДок.Прочитат ь("С:\Pr1се.mxl"); ТабДок.Показать("Прайст-лист поставщика", "C:\Price_New.mxl" , Ложь); Открытое окно табличного документа может быть скры- то, — для этого используется метод СкрытьО табличного документа. Скрытое окно может быть снова отображено с помощью метода ПоказатьО. Запись табличного документа в файл можно выполнить с помощью метода ЗаписатьО. При этом необходимо ука- зать путь к записываемому файлу, а также можно указать и формат создаваемого файла. По умолчанию файл будет записан в формате табличного документа 1 С: Предпри- ятия 8.0 (*.mxl), но также поддерживаются и другие фор- маты файлов. Формат файла задается с помощью систем- ного перечисления ТипФайлаТабличногоДокумента (табл. 13.14). Таблица 13.14. Значения системного перечисления ТипФайлаТабличногоДокумента Значение Описание HTML Файл в формате HTML последней версии, поддерживаемой 1 С:Предприятием 8.0 HTML3 Формат файла HTML версии 3 HTML4 Формат файла HTML версии 4 MXL Файл табличного документа 1 С: Предприятия MXL7 Файл табличного документа ЮПредприятия версии 7.7 TXT Текстовый файл XLS Файл в формате MS Excel 95 Для табличного документа, открытого для просмотра, мо- гут быть установлены различные свойства, влияющие на его отображение, например отображение заголовков, сет- ки документа, отображение групп, отображение име- нованных строк/колонок и т. д. Для того чтобы при по- вторном открытии документа эти свойства также были применены к документу, используется установка свойст- ва документа СохранятьСвойстваОтображения в значение Ис- тина. По умолчанию это свойство имеет значение Ложь. Положение окна открытого табличного документа и его размеры могут быть запомнены для того, чтобы в послед- ствии открыть этот же или другой документ в окне того же размера, расположенном в той же области экрана. Для этого используется свойство табличного документа Имя- СохраненияПоложенияОкна. По умолчанию это свойство име- ет значение пустой строки. Если свойству ИмяСохранения- ПоложенияОкна присвоить значение, отличное от значения типа Строка по умолчанию, то при закрытии окна таблич- ного документа положение окна будет запомнено и может использоваться в дальнейшем при повторном открытии, например, этого же документа. Для этого перед открыти- ем (перед выполнением метода ПоказатьО), свойству Имя- СохраненияПоложенияОкна открываемого табличного доку- мента должно быть присвоено то же самое имя. Например, для того чтобы табличный документ, отобра- жаемый в ходе выполнения отчета, открывался всегда с теми же размерами и тем же положением, которое было последний раз перед его закрытием, следует использовать установку имени сохранения положения окна перед по- казом документа (листинг 13.126). Листинг 13.126. Использование имени сохранения положения окна ТабДок - Новый ТабличныйДокументО: ТабДок.ИмяСохраненияПоложенияОкна = "ОтчетАнализПродаж"; Т абДок.Показ ат ь("Отчет”, "C:\SaleRep.mxl");
В результате после первого показа и закрытия документа положение его окна будет сохранено с именем ОтчетАна- лизПродаж, а при повторном открытии будет использова- но положение окна, соответствующее значению свойства ИмяСохраненияПоложенияОкна — то есть то же самое поло- жение. Если, например, сохраненный файл отчета нужно откры- вать с тем же положением окна, что и в самом отчете, пе- ред показом нужно установить соответствующее значе- ние свойства ИмяСохраненияПоложенияОкна (листинг 13.127). Листинг 13.127. Использование сохраненного положения окна при открытии другого табличного документа ТабДок = Новый ТабличныйДокументО: ТабДок.Прочитать("С:\SaleRep.mxl"); ТабДок.ИмяСохраненияПоложенияОкна = “ОтчетАнализПродаж"; ТабДок.ПоказатьО: Табличный документ имеет два свойства, которые в про- цессе редактирования или заполнения документа позво- ляют определить размеры области табличного документа, которая содержит или может содержать данные. Это свойства ВысотаТаблицы и ШиринаТаблицы. Оба этих свойства доступны только для чтения и содержат соответственно количество строк и количество колонок в таблице. По умолчанию (при создании нового табличного доку- мента) оба эти свойства имеют значение 0. В процессе ре- дактирования или заполнения табличного документа они изменяют свои значения так, чтобы показывать реальное количество строк или колонок документа, которые запол- нены данными. При интерактивном редактировании табличного доку- мента область ячеек табличного документа, ограниченная значениями ВысотаТаблицы и ШиринаТаблицы, выделяется пунк- тирными линиями (рис. 13.108). Рис, 13.108. Высота и ширина таблицы При очистке значений строк или колонок, значения свойств ВысотаТаблицы и ШиринаТаблицы не изменяются (рис. 13.109). Рис. 13.109. Высота и ширина таблицы В приведенном примере данные пятой колонки были очищены, однако ширина таблицы осталась равной 5. Для того чтобы свойство ШиринаТаблицы приняло значение 4 (в соответствии с реально заполненными ячейками), не- обходимо удалить пятый столбец; в противном случае бу- дет считаться, что этот столбец принадлежит таблице, так как может содержать, например, некоторое оформле- ние, необходимое для документа. Области табличного документа Основной логической частью табличного документа, с которой осуществляется работа, является область ячеек табличного документа, или сокращенно просто область. Область может представлять собой как отдельную ячей- ку документа, так и совокупность нескольких ячеек, соот- ветствующую определенным правилам. В качестве облас- ти может выступать: ♦ одна или несколько соседних строк; ♦ одна или несколько соседних колонок; ♦ группа ячеек, находящихся на пересечении одной или нескольких соседних строк с одной или несколькими соседними колонками. Для обращения к области ячеек табличного документа используется метод табличного документа Область(). Этот метод позволяет обращаться к конкретным областям таб- личного документа, причем поддерживается обращение в нескольких вариантах. Обращение к области ячеек Обращение по номерам строк и колонок В этом варианте в параметрах метода перечисляются но- мера строк и колонок, которые образуют нужную область (листинг 13.128). Листинг 13.128. Синтаксис получения области по номерам строк и колонок Область(<номер первой строки>, <нонер первой колонки>, <номер последней строки>, <номер последней колонки>) Пример указания прямоугольной области на пересечении 2-4 строк и 2-4 колонок представлен в листинге 13.129. Область, получаемая в результате выполнения этого при- мера, показана на рис. 13.110. Листинг 13.129. Получение прямоугольной области табличного документа ТабДок = Новый ТабличныйДокументО; ТабДок.ОтображатьСетку = Ложь: НоваяОбласть = ТабДок.Область(2, 2, 4, 4); НоваяОбласть.Имя = "НоваяОбласть": Рис. 13.110. Прямоугольная область
Пример указания области, состоящей только из 2-4 строк, представлен в листинге 13.130. Область, получаемая в ре- зультате выполнения этого примера, показана на рис. 13.111. Листинг 13.130. Получение области, состоящей из строк табличного документа ТабДок = Новый ТабличныйДокументО; ТабДок.ОтображатьСетку = Ложь; НоваяОбласть = ТабДок.0бласть(2. , 4); НоваяОбласть.Имя = "НоваяОбласть"; Рис. 13.111. Область строк Пример указания области, состоящей только из 2-4 ко- лонок, представлен в листинге 13.131. Область, получае- мая в результате выполнения этого примера, показана на рис. 13.112. Листинг 13.131. Получение области, состоящей из колонок табличного документа ТабДок = Новый ТабличныйДокументО; ТабДок.ОтображатьСетку = Ложь; НоваяОбласть = ТабДок.Область( ,2. ,4); НоваяОбласть.Имя = "НоваяОбласть"; Рис. 13.112. Область колонок Пример указания области, состоящей из одной ячейки, представлен в листинге 13.132. Область, получаемая в ре- зультате выполнения этого примера, показана на рис. 13.113. Листинг 13.132. Получение области, состоящей из одной ячейки табличного документа ТабДок = Новый ТабличныйДокументО; ТабДок.ОтображатьСетку = Ложь; НоваяОбласть = ТабДок.Область(2, 4); НоваяОбласть.Имя = "Новая область"; Рис. 13.113. Область, состоящая из одной ячейки Обращение по адресу Обращение к области может быть выполнено также и по адресу области (листинг 13.133). Адрес области указывается координатами левого верхнего и правого нижнего углов области в формате R1C1: R2C2. Чис- ло после R обозначает номер строки, число после С — номер колонки, символом «:» (двоеточие) разделяются координа- ты левого верхнего и правого нижнего угла области. Листинг 13.133. Синтаксис получения области по адресу Область(<адрес области>) Пример обращения к прямоугольной области на пересе- чении 2-4-й строк и 2-4-й колонок показан в листин- ге 13.134. Листинг 13.134. Получение прямоугольной области табличного документа ТабДок = Новый ТабличныйДокументО; НоваяОбласть = ТабДок. Область ("R2C2:R4C4"); Пример обращения к области, состоящей из 2-4-й стро- ки, показан в листинге 13.135. Листинг 13.135. Получение области, состоящей из строк табличного документа ТабДок = Новый ТабличныйДокументО; НоваяОбласть = ТабДок.Область("R2:R4"); Пример обращения к области, состоящей из 2-4-й коло- нок, показан в листинге 13.136. Листинг 13.136. Получение области, состоящей из колонок табличного документа ТабДок = Новый ТабличныйДокументО; НоваяОбласть = ТабДок.Область("С2:04"): Пример обращения к области, состоящей из одной ячей- ки, которая находится на пересечении второй строки и четвертой колонки, представлен в листинге 13.137. Листинг 13.137. Получение области, состоящей из одной ячейки табличного документа ТабДок = Новый ТабличныйДокументО; НоваяОбласть = ТабДок.Область("R2C4"); Обращение по имени Любая область табличного документа может иметь уни- кальное имя. Имя области может быть задано при визу- альном редактировании документа в редакторе таблич- ных документов или программно. По умолчанию любая область имеет имя, совпадающее с ее адресом. Однако разработчик имеет возможность присвоить области соб- ственное, уникальное в пределах данного табличного до- кумента имя. Для этого используется свойство области ячеек табличного документа Имя. Для управления отображением именованных областей служат две команды редактора табличных документов. Команда Таблица ► Имена ► Отображение именованных строк/ко- лонок позволяет отобразить имена областей, которые явля- ются совокупностью соседних строк или соседних коло- нок. Команда Таблица ► Имена ► Отображать именованные ячейки позволяет отобразить имена прямоугольных областей таб- личного документа. Из встроенного языка управление ото- бражением имен областей недоступно. Пример обращения к области по имени представлен в листинге 13.138. Листинг 13.138. Получение области табличного документа по имени ТабДок = ПолучитьМакетС'Макет”): НоваяОбласть = ТабДок.Область("НоваяОбласть");
Области, для которых заданы имена, отличные от имен по умолчанию, входят в коллекцию именованных областей табличного документа. Доступ к этой коллекции возмо- жен через свойство табличного документа Области. Обход коллекции именованных областей возможен с помощью итератора Для Каждого ... Из ... Цикл. Пример перечисления всех именованных областей, содержащихся в табличном документе, представлен в листинге 13.139. Листинг 13.139. Перебор именованных областей табличного документа ТабДок = ПолучитьМакетС"Макет"); ИменованныеОбласти = ТабДок.Облаети; Для Каждого Область из ИменованныеОбласти Цикл Сообщить(Область.Имя): КонецЦикла; Кроме этого, для коллекции именованных областей дос- тупны методы получения индекса области (ИндексО), по- лучения количества именованных областей (Количест- воО), поиска по имени области (НайтиО) и получения об- ласти по индексу (ПолучитьО). ВНИМАНИЕ Следует заметить, что в коллекцию именованных областей табличного документа входят также и рисунки табличного документа, для которых заданы имена, отличные от имен по умолчанию. О рисунках более подробно рассказывается в разделе «Рисунки табличного документа», с. 484. Обращение к пересечению областей Помимо явного указания области по имени или в виде ад- реса, можно обращаться к пересечению двух областей. В этом случае синтаксис вызова метода Область О выгля- дит следующим образом (листинг 13.140). Листинг 13.140. Синтаксис получения области как пересечения именованных областей Область(<имя области 1>|<имя области 2>) В качестве имени области может быть использовано имя по умолчанию (адрес) или имя, назначенное разработ- чиком. Например, если в табличном документе определены две области, — ГоризонтальнаяОбласть и ВертикальнаяОбласть (рис. 13.114), то обратиться к их пересечению можно так, как это показано в листинге 13.141. Рис. 13.114. Именованные области Листинг 13.141. Получение области табличного документа на пересечении двух областей ТабДок = ПолучитьМакет("Макет”); НоваяОбласть = ТабДок.Область( "ГоризонтальнаяОбласть|ВертикальнаяОбласть"); Общие свойства областей Область ячеек табличного документа обладает набором свойств и методов, которые позволяют оформить ее и по- лучить характеристики области. Свойство Пня позволяет получать и изменять имя области. Свойство ТипОбласти предназначено для чтения и содер- жит значения системного перечисления ТипОбластиЯчеек- ТабличногоДокунента. Если область представляет собой совокупность строк или колонок, то ТипОбласти будет содержать соответственно значения Строки или Колонки. Если область прямоугольная, то в этом свойстве будет значение Прямоугольник. Если область представляет собой весь табличный документ, то тогда значение свойства ТипОбласти будет равно Таблица. Для определения координат имеющейся области служат свойства Верх, Лево, Низ и Право. Они доступны только для чтения и содержат номера, соответственно, первой стро- ки, первой колонки, последней строки и последней ко- лонки области. Если область состоит из строк, то тогда свойства Лево и Право будут иметь значение 0. Если об- ласть состоит из колонок, то в этом случае свойства Верх и Низ будут равны нулю. Оформление областей Скрытие областей Области, состоящие из строк или колонок, могут быть скрыты при отображении табличного документа в окне редактора табличных документов. Для этого использует- ся свойство Видимость, значение которого необходимо установить в Ложь. По умолчанию для всех областей таб- личного документа свойство Видимость имеет значение Истина. Например, скрыть 2-4-й колонки можно с помощью кода, представленного в листинге 13.142. Листинг 13.142. Скрытие колонок табличного документа ТабДок = Новый ТабличныйДокументО; ТабДок.ОтображатьСетку = Ложь; НоваяОбласть = ТабДок.Облаеть( , 2, ,4); НоваяОбласть.Видимость = Ложь: ТабДок.ПоказатьО; В результате табличный документ будет иметь вид, пред- ставленный на рис. 13.115. Защита областей Области табличного документа могут быть защищены, для этого используется свойство Защита. Использование этого свойства имеет смысл только вместе со свойством самого табличного документа Защита. Если у табличного документа свойство Защита установлено в значение Истина, то в этом случае в окне редактора табличных документов пользователю будет недоступно редактирование тех об-
ластей табличного документа, для которых свойство Защи - та также установлено в значение Истина. По умолчанию свойство Защита имеет значение Истина для всех областей табличного документа. Высота строк Свойства ВысотаСтроки и АвтоВысотаСтроки позволяют за- дать различные варианты расчета высоты строк, участ- вующих в области табличного документа. В зависимости от значения свойства АвтоВысотаСтроки свойство ВысотаСтроки определяет либо собственно фикси- рованную высоту строки (АвтоВысотаСтроки = Ложь), либо максимальную высоту строки (АвтоВысотаСтроки = Истина). Высота строки задается в пунктах. Если свойство ВысотаСтроки имеет значение 0, то свойство АвтоВысотаСтроки имеет значение Истина, и изменить его присвоением другого значения невозможно. Это значит, что высота строки будет установлена автоматически, в за- висимости от текста, который содержится в области. Если свойству ВысотаСтроки присвоить значение, отличное от 0, то свойство АвтоВысотаСтроки автоматически будет ус- тановлено в значение Ложь. Это значит, что высота строки будет фиксированная и равная указанной величине. В этой ситуации свойство АвтоВысотаСтроки можно устано- вить в значение Истина, и тогда свойство ВысотаСтроки будет использоваться как максимальная высота строки. Други- ми словами, высота строки будет переменная, от значе- ния по умолчанию до указанного в свойстве ВысотаСтроки. Если свойству ВысотаСтроки присвоить значение 0, то свой- ство АвтоВысотаСтроки автоматически будет установлено в значение Истина. Ширина колонок Табличный документ может иметь строки с различной шириной колонок. Такая возможность используется для создания форм отчетности, содержащих, по сути, не- сколько различных таблиц с различной шириной коло- нок в каждой из них. Для установки ширины колонок используется свойство области ячеек табличного документа ШиринаКолонки. Если это свойство применяется к прямоугольной области или области колонок (листинг 13.143), то новая ширина коло- нок будет установлена для всех колонок, участвующих в указанной области (рис. 13.116). Листинг 13.143. Установка ширины колонок табличного документа ТабДок = Новый ТабличныйДокументО; ТабДок.Область(2, 2, 4, 4).ШиринаКолонки = 15; ТабДок. ПоказатьО; Если ширину колонок задать для области, состоящей из строк, то новая ширина колонок будет установлена для всего табличного документа. Для того чтобы установить другую ширину колонок только в некоторых строках, необходимо предварительно создать новый формат строк (метод СоздатьФорматСтрокО) и затем заново получить требуемую область (лис- тинг 13.144). После этого можно будет задать для этой об- ласти требуемую ширину колонок (рис. 13.117). Листинг 13.144. Установка ширины колонок для выбранной области табличного документа ТабДок = Новый ТабличныйДокументО; Область = ТабДок.Область(2. 2, 4, 4): Область. СоздатьФорматСтрокО; Область = ТабДок.0бласть(2. 2, 4, 4); Область.ШиринаКолонки = 15; ТабДок. Показать О; ’= Таблица Г~| X Рис. 13.117. Установка формата строк Цвет фона и узор Для области табличного документа может быть задан цвет фона, а также узор и цвет узора. Причем если об- ласть включает в себя несколько ячеек документа, то эти свойства будут установлены для каждой ячейки, входя- щей в область. Для задания цвета фона и цвета узора используются соответ- ственно свойства ЦветФона и ЦветУзора, принимающие значе- ние типа Цвет. Для задания узора используется свойство Узор, которое принимает значения системного перечисления ТипУ- зораТабличногоДокумента. Это системное перечисление позво- ляет определить 17 различных узоров (рис. 13.118). Рис. 13.118. Значения и внешний вид узоров Кроме этого, возможны значения БезУзора и Сплошной. Зна- чение БезУзора позволяет не использовать узор вообще и является значением по умолчанию, а использование зна- чения Сплошной с заданным цветом узора аналогично уста- новке фона области с этим цветом.
Объединение ячеек Несколько ячеек, входящих в область табличного доку- мента, могут быть объединены в одну ячейку. Для этого используется метод области ячеек табличного документа Объединить!). Пример объединения ячеек представлен в листинге 13.145. Листинг 13.145. Пример объединения ячеек области табличного документа ТабДок = Новый ТабличныйДокументО; Область = ТабДок.Область(2, 2, 4, 4); Область.Объединить(): ТабДок.ПоказатьО: Результат выполненного объединения показан на рис. 13.119. Рис. 13.119. Объединение ячеек области Если к области, состоящей из объединенных ячеек, при- менить метод Разъединить!), то в области будет сформиро- вано то же количество ячеек, что и до объединения. Группировка Области табличного документа, представляющие собой строки или колонки, могут быть сгруппированы. Для это- го используется метод Сгруппировать (). Обратное действие выполняется с помощью метода Разгруппировать О. Группировка строк или колонок табличного документа позволяет при просмотре документа скрывать/раскры- вать строки/колонки, детализирующие основную строку/ колонку. Эта возможность используется, например, при выводе отчетов с группировками, например, остатков то- варов по складам. Тогда строки, относящиеся к остаткам товаров на одном и том же складе, можно сгруппировать, что сделает отчет более «читабельным». При просмотре отчета пользователь сможет сворачивать/разворачи- вать отдельные группировки или все группировки одного уровня. Пример группировки 2-4-й строк табличного документа представлен в листинге 13.146. Листинг 13.146. Пример группировки строк табличного документа ТабДок = Новый ТабличныйДокументО: ТабДок.0бласть(2, , 4).Сгруппировать!): ТабДок.Показать!); Внешний вид табличного документа, получающийся в ре- зультате выполнения этого кода, показан на рис. 13.120. Рис. 13.120. Группировка строк Маркеры уровней (1 и 2) позволяют сворачивать/разво- рачивать все группировки, находящиеся на данном уров- не, в то время как маркеры отдельных группировок позволяют сворачивать/разворачивать отдельные груп- пировки. Метод Разгруппировать!) позволяет, соответственно, раз- группировать строки или колонки области ячеек таблич- ного документа. Границы Для области табличного документа может быть задано отображение границ области целиком и отдельных яче- ек, входящих в область. Для этого используются свой- ства ГраницаСверху, ГраницаСлева, ГраницаСнизу и Граница- Справа. Эти свойства имеют тип Линия. Если они применяются к области, содержащей несколько ячеек, то соответствующее свойство будет установлено у каж- дой ячейки, входящей в область. Цвет границы задается с помощью свойства ЦветГраницы, принимающего значе- ния типа Цвет. Также для задания границ области можно использовать метод Обвести!), которому передаются объекты типа Линия, описывающие левую, верхнюю, правую и нижнюю грани- цы области. В этом случае оформление будет применено только к внешним границам ячеек, находящимся на гра- нице области. Метод Обвести!), так же как и прямое указание границ, может быть применен как к прямоугольным областям, так и к областям, состоящим из строк или колонок. ВНИМАНИЕ При использовании конструктора объекта Линия следует помнить, что для линии ячейки табличного документа может быть задан отступ линии от краев ячейки, а тол- щина двойной линии может быть задана только равной единице. Пример оформления областей табличного документа ли- ниями представлен в листинге 13.147. Листинг 13.147. Пример оформления областей табличного документа линиями ТабДок = Новый ТабличныйДокумент!); ТабДок.ОтображатьСетку = Ложь: ЛинияСОтступон = Новый Линия! ТипЛинииЯчейкиТабличногоДокунента.Двойная, 1, Истина): ЛинияБезОтступа = Новый Линия! ТипЛинииЯчейкиТабличногоДокумента.Двойная, 1); Область = ТабДок.Область(2. 4, 3, 5): Область.ГраницаСверху = ЛинияСОтступон; Область. ГраницаСлева = ЛинияСОтступон: Область.ГраницаСнизу = ЛинияСОтступон: Область.ГраницаСправа = ЛинияСОтступон: Область = ТабДок.0бласть!5, 2, б, 3): Область.Обвести!ЛинияБезОтступа, ЛинияБезОтступа, ЛинияБезОтступа, ЛинияБезОтступа): ТабДок.Показать!); Внешний вид табличного документа, получающийся в ре- зультате выполнения этого кода, показан на рис. 13.121.
Рис. 13.121. Оформление областей линиями Примечание Область ячеек табличного документа может иметь при- мечание, которое будет отображаться при наведении курсора на маркер, расположенный в правом верхнем углу ячейки. Примечание представляет собой объект РисунокТабличногоДокумента, имеющий тип Текст. О ри- сунках табличного документа подробно рассказывает- ся в разделе «Рисунки табличного документа», с. 484. Здесь же скажем только, что существует возможность установить текст примечания для области ячеек, полу- чив из свойства Примечание области объект РисунокТаб- личногоДокумента и обратившись к его свойству Текст (листинг 13.148). Листинг 13.148. Установка текста примечания для области ячеек табличного документа ТабДок = Новый ТабличныйДокументО; ТабДок.Область(2, 2, 4, 4).Примечание.Текст = "Текст примечания области": ТабДок.ПоказатьО; В результате, если текст примечания был установлен для области, содержащей одну ячейку, соответствую- щий маркер будет установлен у этой ячейки. Если же текст примечания был установлен для области, содер- жащей несколько ячеек, примечание будет установлено у левой верхней ячейки этой области (рис. 13.122). Очистка Метод ОчиститьО табличного документа позволяет очи- стить весь табличный документ и переводит его в состоя- ние, которое табличный документ имеет после его созда- ния конструктором. Этот метод может использоваться, когда необходимо повторно использовать тот же самый экземпляр объекта табличного документа без его пере- создания. Метод ОчиститьО есть также и у области ячеек таблич- ного документа. Для области ячеек метод ОчиститьО имеет три параметра, которые позволяют уточнять, что именно должно быть очищено: текст, форматирование, рамки. Все три параметра имею тип значения Булево; по умолчанию очищается только текст, содержащийся в области ячеек табличного документа. Свойства области, относящиеся к тексту Забегая вперед скажем, что табличный документ может использоваться не только для непосредственного запол- нения, но может формироваться на основе шаблона и ис- пользоваться для ввода данных. Поэтому собственно со- держимое областей может задаваться непосредственно как текст, а может быть вычислено тем или иным спосо- бом. В зависимости от этого область может иметь различ- ное заполнение, что подробно рассматривается в главе «Значения в табличном документе», с. 519. Текст и шрифт В самом простом случае область содержит текст, который доступен для чтения и изменения через свойство Текст. Следует учитывать, что это свойство применимо только для прямоугольных областей. При этом если область со- держит несколько ячеек, то свойство Текст будет установ- лено для каждой из ячеек, входящих в область. Для области табличного документа может быть задан шрифт текста (свойство Шрифт), содержащегося в этой об- ласти. Шрифт также задается один для всех ячеек, содержа- щихся в области. Вертикальное и горизонтальное выравнивание Свойства ВертикальноеПоложение и ГоризонтальноеПоложение позволяют задавать положение текста внутри области. Свойство ВертикальноеПоложение принимает значения сис- темного перечисления ВертикальноеПоложение — Верх, Низ, Центр (по умолчанию Низ), а свойство ГоризонтальноеПоло- жение принимает значения системного перечисления Гори- зонтальноеПоложение — Авто, Лево, ПоШирине, Право, Центр (по умолчанию Авто). Значение Авто выравнивает числовые значения по правой границе, остальные — по левой. Зна- чение ПоШирине располагает текст таким образом, чтобы за- нимать всю ширину области табличного документа. Если область состоит из нескольких ячеек, то эти свойства применяются к каждой ячейке области. При использовании горизонтального выравнивания может также применяться свойство ПоВыделеннынКолонкан. Если это свойство установлено в значение Истина, то горизонтальное выравнивание будет выполняться по следующему правилу. Если справа от текущей ячейки, содержащей текст, нахо- дится ячейка с текстом, выравнивание будет применено только к текущей ячейке. Если справа от текущей ячейки находится одна или не- сколько пустых ячеек, то выравнивание будет применено к области, начинающейся с текущей ячейки и заканчи- вающейся перед последней непустой ячейкой справа. В качестве примера рассмотрим использование этого свойства при выравнивании текста в области, показанной на рис. 13.123. Рис. 13.123. Исходная область табличного документа
Если в этом случае к области применить горизонтальное выравнивание по центру и установить свойство ПоВыде- леннымКолонкам (листинг 13.149), то надпись «первая» будет выровнена в пределах второй колонки, надпись «вторая» будет выровнена в пределах 3-5 колонок, а над- пись «третья» будет выровнена в пределах 6-7 колонок (рис. 13.124). Листинг 13.149. Использование выравнивания по выделенным колонкам ТабДок = ПолучитьМакет!"Макет"); Область = ТабДок.Область(2, 2, 2, 7); Область.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр; Область.ПоВыделеннымКолонкам = Истина; ТабДок.ПоказатьО: ♦ Забивать — видимая часть текста будет ограничена ле- вой и правой границами ячейки, все символы видимой части будут отображаться как #. Такой способ отобра- жения может применяться для предотвращения непра- вильного восприятия длинных чисел; ♦ Переносить — текст будет переноситься на следующие строки ячейки. Для того чтобы текст был отображен в ячейке целиком, необходимо, чтобы свойство Высота- Строки было установлено в значение 0 (при этом свойство АвтоВысотаСтроки будет установлено в значение Истина). Примеры использования различного размещения текста представлены на рис. 13.126. Рис. 13.124. Результат выравнивания по выделенным колонкам i5= Таблица _ Г~1 X Рис. 13.126. Размещение текста Ориентация Текст в области табличного документа может распола- гаться под разными углами наклона относительно гори- зонтального положения. Для задания угла наклона используется свойство ОриентацияТекста. Угол наклона за- дается в градусах. Если угол наклона равен 0 — текст бу- дет расположен горизонтально. Угол наклона 90 соответ- ствует расположению текста снизу вверх, угол наклона 270 — сверху вниз, а угол наклона 180 соответствует рас- положению текста «вверх ногами» (рис. 13.125). Отступ Свойство Отступ задает отступ текста от правого или лево- го края ячейки в средних символах шрифта. Отступ будет применен в зависимости от горизонтального положения, указанного для этой области. Размещение Свойство РазмещениеТекста позволяет задать тип размеще- ния для текста, который не помещается целиком в ячей- ку. Возможные варианты задаются значениями системно- го перечисления ТипРазмещенияТекстаТабличногоДокунента: ♦ Авто — текст будет показан в соседних по горизонтали ячейках, если в них нет текста; ♦ Обрезать — видимая часть текста будет ограничена ле- вой и правой границами ячейки; Цвет Для задания цвета текста, содержащегося в области таб- личного документа, используется свойство ЦветТекста, ко- торое принимает значения типа Цвет. Если область состо- ит из нескольких ячеек, то свойство будет применено к каждой ячейке области. Выделение отрицательных Свойство ВыделятьОтрицательные позволяет выделить спе- циальным цветом текст, содержащийся в области. Выде- ление будет осуществляться для тех текстов, которые на- чинаются с символа «-» (минус). При выделении таких текстов будет использоваться цвет Отрицательное число стиля, используемого конфигурацией. Работа с областями табличного документа Тип области В процессе выполнения различных действий с областями табличного документа необходимо знать, какую форму имеет та или иная область. Для этого можно использо- вать свойство области ячеек табличного документа ТипОб- ласти. Это свойство предназначено только для чтения и содержит значения системного перечисления ТипОбласти- ЯчеекТабличногоДокумента. Тип области может принимать значения Колонки, Строки, Прямоугольник и Таблица. Если область является областью строк или колонок таблич- ного документа, то тип области будет соответственно Строки или Колонки. Если область прямоугольная, то тип области будет Прямоугольник. Тип области Таблица означает, что об- ласть представляет собой весь табличный документ. Такая область может быть получена, например, в результате вы- полнения метода Область!) без параметров (листинг 13.150). Листинг 13.150. Получение области с типом Таблица ТабДок = Новый ТабличныйДокументО; ОбластьВесьДокумент = ТабДок.Область!); Сообщить(ОбластьВесьДокумент.ТипОбласти);
Текущая область У табличного документа всегда есть текущая область. По умолчанию при создании табличного документа, текущей областью становится область с адресом R1C1. В режиме просмотра эта область выделяется жирной рамкой (рис. 13.127). Рис. 13.127. Текущая область по умолчанию Коллекция выделенных областей всегда содержит одну область табличного документа — это текущая область. Для добавления областей в коллекцию используется ме- тод Добавить О, которому передается область ячеек или рисунок табличного документа (листинг 13.152). При этом добавленная область становится текущей для таб- личного документа (рис. 13.129). В коллекции выделен- ных областей текущая область всегда имеет индекс 0. Листинг 13.152. Выделение нескольких областей ТабДок = Новый ТабличныйДокументО; Т абДок.ВыделенныеОбласти. ДобавитьС ТабДок.Область(2, 2. 3. 3)): ТабДок.ВыделенныеОбласти. Добавить( ТабДок.0бласть(1, 5. 4, 5)); ТабДок.ПоказатьО: Текущая область может быть изменена интерактивно или программно. Для программного определения и измене- ния текущей области табличного документа использует- ся свойство документа ТекущаяОбласть (листинг 13.151). Например, текущей может быть назначена область, состоящая из нескольких ячеек табличного документа (рис. 13.128). Листинг 13.151. Назначение текущей области табличного документа ТабДок = Новый ТабличныйДокументО; ТабДок.ТекущаяОбласть = ТабДок.Область(2, 2. 4. 4); ТабДок.ПоказатьО; Рис. 13.129. Выделение нескольких областей Рис. 13.128. Текущая область, состоящая из нескольких ячеек Белым цветом выделяется ячейка, с которой было начато интерактивное выделение данной области. Эта информа- ция носит чисто визуальный характер. Если текущая об- ласть определяется программно, то белым цветом будет вы- делена ячейка, находящаяся в левом верхнем углу области. Выделенные области Табличный документ позволяет выделять одновременно несколько областей. В интерактивном режиме это выпол- няется с помощью мыши при нажатой клавише Control. Для программного выделения нескольких областей ис- пользуется коллекция выделенных областей табличного документа, которая доступна через свойство документа ВыделенныеОбласти. В этом свойстве содержится объект ВыделенныеОбластиТаб- личногоДокумента. Этот объект представляет собой коллек- цию объектов двух типов: ОбластьЯчеекТабличногоДокумента и РисунокТабличногоДокунента, то есть коллекция может со- держать одновременно значения как одного, так и друго- го типа. Принцип работы с этой коллекцией не зависит от типа элемента, поэтому здесь мы рассмотрим работу с этой коллекцией на примере области ячеек табличного документа (про рисунки табличного документа подробно рассказывается в главе «Рисунки табличного документа», с. 484). Коллекция выделенных областей табличного документа содержит методы, позволяющие вставлять, сдвигать, уда- лять, получать по индексу и подсчитывать количество выделенных областей. Кроме этого, коллекция содержит метод ОчиститьО, кото- рый удаляет все области из коллекции выделенных об- ластей. При этом текущей областью становится область с адресом R1C1, и она же включается в коллекцию выделен- ных областей. Копирование области Область ячеек табличного документа может быть ско- пирована в другую область документа. Для этого исполь- зуется метод документа ВставитьОбластьО. В качестве параметров метода передается область-источник, об- ласть-приемник, направление смещения при вставке и признак заполнения параметров в области-приемнике. Если указано использование сдвига по горизонтали (лис- тинг 13.153), то область-источник будет скопирована на место области-приемника, а область приемник и ячейки, расположенные правее, будут сдвинуты вправо (рис. 13.130). Листинг 13.153. Вставка области со сдвигом по горизонтали ТабДок = ПолучитьМакет("Макет"); ОбластьИсточник = ТабДок.Область(2, 2); ОбластьПриемник = ТабДок.Область(3. 3): ТабДок.ВставитьОбласть(ОбластьИсточник, ОбластьПриемник, ТипСмещенияТабличногоДокумента. ПоГоризонтали); ТабДок.ПоказатьО; Рис. 13.130. Вставка области со сдвигом по горизонтали
Если указано использование сдвига по вертикали (лис- тинг 13.154), то область-источник будет скопирована на место области-приемника, а область-приемник и ячейки, расположенные ниже, будут сдвинуты вниз (рис. 13.131). Листинг 13.154. Вставка области со сдвигом по вертикали ТаВДок = ПолучитьМакет("Макет"): ОбластьИсточник = ТабДок.0бласть(2, 2): ОбластьПриенник = ТабДок.ОбластьСЗ, 3): ТабДок.ВставитьОбласть(ОбластьИсточник. ОбластьПриенник, Т ипСмещенияТ абличногоДокумента.ПоВертикали); ТабДок.ПоказатьО; Рис. 13.131. Вставка области со сдвигом по вертикали Если указан тип сдвига БезСдвига (это значение использу- ется по умолчанию) (листинг 13.155), то фактически вы- полняется замещение области-приемника копией облас- ти-источника (рис. 13.132). Листинг 13.155. Вставка области без сдвига ТабДок = ПолучитьМакетС"Макет"): ОбластьИсточник = ТабДок.0бласть(2. 2): ОбластьПриенник = ТабДок.Область(3. 3): ТабДок.ВставитьОбласть(ОбластьИсточник, ОбластьПриенник): ТабДок.ПоказатьО; При выполнении вставки области ячеек табличного доку- мента размеры области-источника и области-приемника должны совпадать, иначе будет выдана ошибка. ПРИМЕЧАНИЕ При указании типа сдвига следует учитывать, что если вставляется область строк, то не имеет смысла задавать тип сдвига равным ПоГоризонтали, а при вставке области ко- лонок не имеет смысла задавать тип сдвига равным ПоВер- тикали. Удаление области Область табличного документа может быть удалена. Для этого используется метод табличного документа Удалить - Область О, которому передается удаляемая область, а также вариант смещения строк или колонок табличного доку- мента. Вариант смещения задается значением системного перечисления ТипСнещенияТабличногоДокумента. Для значений ПоГоризонтали (рис. 13.134) и ПоВертикали (рис. 13.135) выполняется соответствующий сдвиг ячеек документа для заполнения удаляемой области. Рис. 13.134. Удаление области со сдвигом по горизонтали Рис. 13.132. Вставка области без сдвига Рис. 13.135. Удаление области со сдвигом по вертикали Если область-приемник не указана, то копирование вы- полняется в область, расположенную сразу за областью- источником в соответствии с типом сдвига (по вертикали или по горизонтали). Если тип сдвига также не указан (листинг 13.156), то будет выполняться вставка в об- ласть, расположенную справа сразу за областью-источни- ком без сдвига (рис. 13.133). Рис. 13.133. Вставка без указания области-приемника и сдвига Листинг 13.156. Вставка области без указания области приемника ТабДок = ПолучитьМакетС "Макет"); ОбластьИсточник = ТабДок.0бласть(2, 2); ОбластьПриенник = ТабДок.Область(3, 3): ТабДок. ВставитьОбласть(ОбластьИсточник): ТабДок.ПоказатьО: Значение БезСмещения, по сути, означает очистку указан- ной области, так как сдвиг ячеек документа не произво- дится (рис. 13.136). По умолчанию удаление области выполняется без сме- щения. Очистка Метод ОчиститьО позволяет очистить весь табличный до- кумент и переводит его в состояние, которое табличный документ имеет после его создания конструктором. Этот метод может использоваться, когда необходимо повторно использовать тот же самый экземпляр объекта таблично- го документа без его пересоздания.
Поиск текста Табличный документ позволяет выполнять поиск опре- деленного текста в табличном документе. Для этого ис- пользуется метод табличного документа НайтиТекстО, ко- торый содержит следующие параметры: ♦ Строка — имеет тип Строка и представляет собой текст, который необходимо найти в табличном документе. ♦ Начало — имеет тип ОбластьЯчеекТабличногоДокунента. Пред- ставляет собой область, после которой начинается поиск. Если этот параметр не указан, то поиск будет выполнен с начала табличного документа (начиная с области R1C1). ♦ Где — имеет тип ОбластьЯчеекТабличногоДокунента. Пред- ставляет собой область, в пределах которой осуществ- ляется поиск текста. Если этот параметр не указан, то поиск будет осуществляться во всем табличном доку- менте. ♦ Искать по строкам — имеет тип Булево. Определяет способ поиска — по строкам или по колонкам. Значение по умолчанию — Истина, что означает поиск по строкам. При этом поиск будет осуществляться в соответствии со значением параметра Искать вперед. Например, поиск по строкам вперед означает следую- щую последовательность перехода (рис. 13.137). Первая строка области поиска Последняя строка области поиска Рис. 13.137. Поиск по строкам вперед Последовательность перехода при поиске по строкам назад показана на рис. 13.138. Первая строка Г области поиска L Последняя строка Г области поиска L Рис. 13.138. Поиск по строкам назад ♦ Ячейка целиком — имеет тип Булево. Значение по умолча- нию — Ложь, это означает, что будет искаться вхождение указанной подстроки в текст области. Значение Истина означает, что будет найдено только полное соответст- вие указанной строки тексту области. ♦ Искать вперед — имеет тип Булево и определяет направле- ние поиска. Значение по умолчанию — Истина — искать вперед. Значение Ложь означает поиск назад. ♦ Игнорировать регистр — имеет тип Булево. Значение по умолчанию Ложь, это означает, что при поиске регистр будет игнорироваться. Значение Истина означает поиск с учетом регистра. Таким образом, по умолчанию метод осуществляет поиск первого вхождения указанной подстроки в текст какой- либо области, причем поиск выполняется во всем доку- менте, начиная с ячейки R1C1, по строкам вперед, без уче- та регистра (листинг 13.157). Листинг 13.157. Пример поиска текста в табличном документе ТабДок = ПолучитьМакет("Макет"); НайденнаяОбласть = ТабДок.НайтиТекст("Остатки"); В случае успешного завершения поиска метод возвраща- ет найденную область табличного документа (или рису- нок табличного документа, если текст найден в нем). Если текст не найден, возвращается значение Неопреде- лено. Рисунки табличного документа Помимо данных, размещенных непосредственно в ячей- ках, табличный документ может содержать рисунки. Коллекция рисунков табличного документа доступна через его свойство Рисунки. Элементами этой коллекции являются объекты РисунокТабличногоДокунента, каждый из которых описывает отдельный рисунок, содержащийся в табличном документе. Существует 12 типов рисунков, которые могут быть раз- мещены в табличном документе и которые описываются значениями системного перечисления ТипРисункаТаблично- гоДокумента (табл. 13.15). Добавление рисунков в табличный документ может быть выполнено с помощью метода Добавить () коллекции рисун- ков табличного документа. При этом обязательно должен быть указан тип добавляемого рисунка. Метод ДобавитьО возвращает добавленный рисунок, после чего устанавлива- ются требуемые свойства рисунка (листинг 13.158). Листинг 13.158. Добавление рисунка в табличный документ ТабДок = Новый ТабличныйДокунент; НовыйРисунок = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Картинка); Коллекция рисунков табличного документа обладает так- же методами, позволяющими очищать коллекцию, уда- лять, получать рисунки по индексу и определять количе- ство рисунков табличного документа. Общие свойства рисунков табличного документа Объект РисунокТабличногоДокунента имеет набор свойств, которые позволяют работать с теми или иными типами рисунков. Не все из существующих свойств могут быть использованы с любым типом рисунка, однако существу- I ет ряд свойств, которые, за небольшим исключением, ис- пользуются с рисунками любого типа. Имя и тип Прежде всего, это свойства Имя и ТипРисунка. Все рисунки, I добавляемые в табличный документ, получают имена по I
Таблица 13.14. Типы рисунков табличного документа Значение Описание Г руппа Рисунок, представляющий собой группу рисунков Диаграмма Рисунок, предназначенный для отображения в табличном документе объекта Диаграмма ДиаграммаГанта Рисунок, предназначенный для отображения в табличном документе объекта ДиаграммаГанта СводнаяДиаграмна Рисунок, предназначенный для отображения в табличном документе объекта СводнаяДиаграмна Дендрограмма Рисунок, предназначенный для отображения в табличном документе объекта Дендрограмма Г еографическаяСхема Рисунок, предназначенный для отображения в табличном документе объекта ПолеГ еографическойСхемы Картинка Рисунок, отображающий картинку Объект Рисунок, предназначенный для отображения в табличном документе объекта ActiveX Прямая Рисунок, являющийся прямой линией Прямоугольник Рисунок, являющийся прямоугольником Текст Рисунок, содержащий текст Эллипс Рисунок, являющийся эллипсом умолчанию DI, D2 и т. д. При необходимости разработчик может назначить собственное имя рисунку. При этом ри- сунок будет включен в коллекцию именованных областей табличного документа (свойство табличного документа Области) (листинг 13.159). Листинг 13.159. Назначение имени рисунку ТабДок = Новый ТабличныйДокунент; НовыйРисунок = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Картинка); Сообщить (НовыйРисунок. Иня); НовыйРисунок.Иня = "Логотип"; Сообщить(ТабДок.Области.Логотип.Иня); Сообщить(ТабДок.Рисунки.Логотип.Иня); Свойство ТипРисунка принимает значения системного пе- речисления ТипРисункаТабличногоДокунента и задается при добавлении рисунка в табличный документ. В дальней- шем значение этого свойства может быть только прочитано. Размеры рисунка Каждый рисунок, добавляемый в табличный документ, ограничивается прямоугольной областью, размеры кото- рой задаются с помощью свойств Верх, Высота, Лево и Шири- на. Все эти свойства принимают значения типа Число. Свойство Верх задает расстояние от верхней стороны таб- личного документа до границы рисунка, от которой будет отсчитываться высота в миллиметрах. Свойство Высота задает высоту рисунка в миллиметрах. Свойство Лево за- дает расстояние от левой стороны табличного документа до границы рисунка, от которой будет отсчитываться ши- рина в миллиметрах, а свойство Ширина задает ширину ри- сунка в миллиметрах. По умолчанию, для нового рисунка значения всех пере- численных свойств равны нулю, поэтому их нужно зада- вать в явном виде (листинг 13.160). В результате выполнения приведенного кода, будет до- бавлен рисунок (рис. 13.139). Листинг 13.160. Установка размеров рисунка ТабДок = Новый ТабличныйДокунент; НовыйРисунок = ТабДок. Рисунки. Добавить(ТипРисункаТабличногоДокумента.Текст); НовыйРисунок.Текст = "Текст рисунка"; НовыйРисунок.Верх = 10: НовыйРисунок.Лево = 10; НовыйРисунок.Высота = 5; НовыйРисунок.Ширина = 30; ТабДок.ПоказатьО; Следует отметить, что при положительных значениях ширины и высоты рисунка высота рисунка будет отсчи- тываться вниз от верхней границы рисунка, а ширина — вправо от левой границы рисунка. Если же свойствам ши- рина и высота присваиваются отрицательные значения, то высота будет отсчитываться вверх от «верхней» грани- цы рисунка, а ширина — влево от «правой» границы ри- сунка. Поэтому приведенный на рис. 13.139 табличный доку- мент также может быть получен с помощью следующего кода (листинг 13.161). Листинг 13.161. Использование отрицательных значений ширины и высоты рисунка ТабДок = Новый ТабличныйДокунент; НовыйРисунок = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Текст); НовыйРисунок.Текст = "Текст рисунка"; НовыйРисунок.Верх = 15; НовыйРисунок.Лево = 40: НовыйРисунок.Высота = -5; НовыйРисунок.Ширина = -30: ТабДок.ПоказатьО;
ПРИМЕЧАНИЕ Для рисунков типа Группа применимы только те свойства, которые были перечислены: Имя, ТипРисунка, Верх, Высо- та, Лево и Ширина. Свойства, описываемые далее, не при- менимы к рисункам типа Группа. Ограничивающая линия Для всех типов рисунков может быть использовано свой- ство Линия. Это свойство задает тип линии, которая будет ограничивать рисунок. Исключение составляют лишь ри- сунки типов Прямая и Эллипс: для них это свойство задает тип линии, которой рисуется отображаемая фигура, а са- ми рисунки этих типов не содержат ограничивающей ли- нии. Свойство Линия принимает значения типа Линия, которые, как правило, создаются с помощью конструктора объекта Линия (листинг 13.162). При этом следует учитывать, что в конструкторе должен быть использован тип линии ТипЛи- нииРисункаТабличногоДокунента. В противном случае будет выдано сообщение о несоответствии типов при установке значения свойства линия. Листинг 13.162. Пример использования свойства Линия ТабДок = Новый ТабличныйДокумент; НовыйРисунок = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Эллипс); НовыйРисунок.Верх = 10: НовыйРисунок.Лево = 10: НовыйРисунок.Высота = 5: НовыйРисунок.Ширина = 30; НовыйРисунок.Линия = Новый Линия(ТипЛинииРисункаТабличногоДокунента.Точечная); ТабДок.ПоказатьО; В результате выполнения приведенного кода будет до- бавлен эллипс рисунок (рис. 13.140). Рис. 13.140. Использование свойства Линия По умолчанию после добавления нового рисунка в его свойстве Линия установлена линия типа Сплошная с толщи- ной равной 1. Цвет линии задается с помощью свойства ЦветЛинии, кото- рое принимает значение типа Цвет. По умолчанию для но- вого рисунка цвет линии задается черным с помощью аб- солютных значений составляющих цвета. Свойства ГраницаСверху, ГраницаСлева, ГраницаСнизу и Грани- цаСправа имеют тип Булево и определяют отображение со- ответствующих линий, ограничивающих рисунок. Эти свойства неприменимы для рисунков типов Пряная и Эл- липс, так как такие рисунки не имеют ограничивающих линий. По умолчанию в этих свойствах установлены значения Истина, поэтому для того, чтобы скрыть какие-либо огра- ничивающие линии рисунка (рис. 13.141), следует уста- новить соответствующее свойство в значение Ложь (лис- тинг 13.163). Листинг 13.163. Пример скрытия границы рисунка ТабДок = Новый ТабличныйДокумент: НовыйРисунок = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Прямоугольник); НовыйРисунок.Верх = 10: НовыйРисунок.Лево = 10; НовыйРисунок.Высота = 5: НовыйРисунок.Ширина = 30; НовыйРисунок.ГраницаСверху = Ложь; ТабДок.ПоказатьО; Рис. 13.141. Скрытие верхней границы рисунка Заполнение рисунка Для всех рисунков, кроме рисунка типа Прямая, может быть задан заполняющий узор, цвет узора и цвет фона рисунка. Узор задается с помощью свойства рисунка табличного документа Узор, которое принимает значения системного перечисления ТипУзораТабличногоДокумента (эти значения описаны на с. 478) (листинг 13.164). Листинг 13.164. Использование узора рисунка табличного документа ТабДок = Новый ТабличныйДокумент; НовыйРисунок = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Прямоугольник); НовыйРисунок.Верх = 10; НовыйРисунок.Лево = 10; НовыйРисунок.Высота = 5; НовыйРисунок.Ширина = 30; НовыйРисунок.Узор = ТипУзораТабличногоДокумента.Узор5; ТабДок.ПоказатьО; В результате выполнения приведенного кода в таблич- ный документ будет вставлен прямоугольник, заполнен- ный узором (рис. 13.142). Рис. 13.142. Использование узора рисунка Цвет узора и цвет фона рисунка задается с помощью свойств ЦветУзора и ЦветФона, которые принимают значения типа Цвет. По умолчанию для новых рисунков цвет узора задается черным, а цвет фона — белым с помощью абсо- лютных значений составляющих цвета. Для рисунков, яв- ляющихся примечаниями, по умолчанию цвет фона зада- ется равным фону подсказки из стиля, используемого конфигурацией (свойство Основной стиль конфигурации). Защита рисунка Для рисунка, так же как и для области ячеек табличного документа, может быть задано свойство Защита. Исполь- зование этого свойства имеет смысл только вместе со
свойством самого табличного документа Защита. Если у табличного документа свойство Защита установлено в значение Истина, то в этом случае в окне редактора таблич- ных документов пользователю будет недоступно редакти- рование тех рисунков табличного документа, для кото- рых свойство Защита также установлено в значение Истина. По умолчанию свойство Защита имеет значение Истина для всех рисунков табличного документа. Рисунки типа Текст Рисунки табличного документа, имеющие тип Текст, ис- пользуются для отображения текста и значений различ- ного типа в табличном документе. Кроме этого, они используются для отображения примечаний к ячейкам табличного документа. Есть три основных отличия в использовании рисунка типа Текст «самого по себе», и в качестве примечания. Первое отличие заключается в том, что для добавления рисунка типа Текст в табличный документ используется метод Добавить!) коллекции рисунков табличного доку- мента (листинг 13.165). Листинг 13.165. Добавление рисунка типа Текст ТабДок = Новый ТабличныйДокумент; РисунокТекст = ТабДок. Рисунки. Добавить(ТипРисункаТабличногоДокумента. Текст); Примечания в табличный документ добавлять не нужно. После создания табличного документа каждая его ячейка уже содержит примечание, доступ к которому можно по- лучить через свойство области ячеек табличного доку- мента Примечание. При установке примечанию свойства Текст, отличного от пустой строки (листинг 13.166), это примечание будет отображено в табличном документе (рис. 13.143). Если свойству Текст рисунка, который явля- ется примечанием, присвоить значение пустой строки, то отображение примечания будет прекращено. Листинг 13.166. Установка примечания ТабДок = Новый ТабличныйДокумент; ТабДок.0бласть(2, 2).Примечание.Текст = "Текст примечания": Второе отличие заключается в том, что примечания не отображаются в коллекции рисунков табличного доку- мента. Поэтому если доступ к обычному рисунку типа Текст можно получить через коллекцию рисунков таблич- ного документа или через коллекцию именованных об- ластей табличного документа (листинг 13.160), то доступ к примечанию осуществляется только через область таб- личного документа, которой «принадлежит» данное при- мечание (листинг 13.166). Третье отличие заключается в том, что рисунок типа Текст, используемый в качестве примечания, может ото- бражать только текст, в то время как обычный рисунок типа Текст может отображать текст, а также может отобра- жать значения других типов, которые задаются при помо- щи параметра рисунка. Особенности использования рисунка типа Текст для ото- бражения значений подробно рассмотрены в разделе «Зна- чения в табличном документе», с. . Здесь же мы остано- вимся только на общих свойствах рисунка типа Текст, ко- торые используются как в том, так и в другом случае. Прежде всего, это свойства Текст, ЦветТекста и Шрифт. Свойство Текст задает собственно сам текст, который бу- дет отображен в рисунке. Свойство ЦветТекста описывает цвет, которым будет ото- бражен указанный текст. По умолчанию для обычных ри- сунков типа Текст это черный цвет, заданный абсолютны- ми значениями составляющих цвета, а для рисунков, являющихся примечаниями, это цвет текста подсказки из стиля, используемого конфигурацией. Свойство Шрифт имеет значение типа Шрифт и задает вид шрифта, используемого для отображения указанного тек- ста. По умолчанию используется шрифт Arial 8. Свойства РазнещениеТекста, ВертикальноеПоложение, Горизон- тальноеПоложение, ОриентацияТекста, Отступ и ВыделятьОтрица- тельные аналогичны одноименным свойствам области ячеек табличного документа, о которых более подробно можно прочитать в разделе «Свойства области, относящиеся к тексту», с.. Свойство АвтоРазиер позволяет использовать возможность автоматического задания размеров рисунка на основе текста, содержащегося в рисунке. Для обычных рисунков по умолчанию это свойство уста- новлено в значение Ложь, что подразумевает указание раз- меров рисунка в явном виде (свойства Высота и Ширина). Для рисунков, являющихся примечаниями, по умолча- нию свойство АвтоРазиер установлено в значение Истина, что означает, что размер примечания будет определяться автоматически. Если необходимо явное указание разме- ров примечания (рис. 13.144), следует свойство АвтоРазиер установить в значение Ложь и задать нужные значения свойств Высота и Ширина (листинг 13.167). Листинг 13.167. Установка размеров примечания ТабДок = Новый ТабличныйДокумент; Прииечание = ТабДок.0бласть(2, 2).Прииечание; Прииечание.Текст = "Текст примечания”; Примечание.АвтоРазиер = Ложь; Примечание.Ширина = 50; Примечание.Высота = 50: ТабДок.ПоказатьО: Рис. 13.144. Установка размеров примечания
Рисунки типа Картинка Рисунки типа Картинка используют два специальных свой- ства, которые не используются рисунками других типов. Это свойства Картинка и РазиерКартинки. Свойство Картинка имеет тип Картинка и позволяет указать собственно ту картинку, которая будет отображена в ри- сунке. Свойство РазиерКартинки имеет тип системного перечисле- ния РазиерКартинки и позволяет указать способ отображе- ния картинки в рисунке. Поддерживаются следующие значения этого перечисления (табл. 13.16). Таблица 13.16. Значения системного перечисления РазмерКартинки Значение Описание АвтоРазмер Если область, в которой отображается картинка, больше чем размеры картин- ки, используется режим РеальныйРазмер, в противном случае используется ре- жим Пропорционально Пропорционально Картинка растягивается или сжимается таким образом, чтобы занять всю высоту или ширину отведенной для нее облас- ти, сохраняя при этом соотношение вы- соты и ширины оригинальной картинки Растянуть Растянуть или сжать картинку таким образом, чтобы она занимала всю об- ласть, отведенную для ее отображения РеальныйРазмер Сохранять реальные размеры картинки. Если область, в которой отображается картинка, меньше ее размеров, из сере- дины картинки вырезается прямоуголь- ник нужного размера Черепица Картинка, сохраняя свои оригинальные размеры, будет периодически повто- ряться, заполняя всю отведенную для нее область Например, для добавления рисунка типа Картинка в таб- личный документ можно использовать следующий код (листинг 13.168). Листинг 13.168. Добавление рисунка типа Картинка ТабДок = Новый ТабличныйДокунент; РисунокКартинка = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Картинка); РисунокКартинка.Картинка = Новый Картинка("С:/1_одо.11Г'): РисунокКартинка.Верх = 10; РисунокКартинка.Лево = 10: РисунокКартинка.Высота = 45; РисунокКартинка.Ширина = 60; РисунокКартинка.РазмерКартинки = РазмерКартинки.АвтоРазмер; РисунокКартинка.ГраницаСверху = Ложь; РисунокКартинка.ГраницаСлева = Ложь; РисунокКартинка.ГраницаСнизу = Ложь; РисунокКартинка.ГраницаСправа = Ложь; ТабДок.ПоказатьО; В результате выполнение приведенного кода будет соз- дан следующий табличный документ (рис. 13.145). Рис. 13.145. Добавление рисунка типа Картинка Рисунки, содержащие объекты Помимо рисунков табличного документа, отображающих текст, картинки, те или иные геометрические фигуры, су- ществуют рисунки, предназначенные для отображения различных объектов и предоставляющие доступ к самим отображаемым объектам. Такими рисунками являются рисунки типа Диаграмма, ДиаграммаГанта, СводнаяДиаграмна, Дендрограмма, ГеографическаяСхема и Объект. Все перечисленные типы рисунков, кроме рисунка типа Объект, могут быть добавлены в табличный документ средствами встроенного языка (метод Добавить() коллек- ции рисунков табличного документа). Рисунок типа Объ- ект может быть добавлен в табличный документ только интерактивно, так как при добавлении такого рисунка будет предложено выбрать один из зарегистрированных в операционной системе ActiveX объектов. ПРИМЕЧАНИЕ Следует заметить, что не все ActiveX объекты, зарегистри- рованные в операционной системе, могут быть размещены в табличном документе. Также список ActiveX объектов, предлагаемых для размещения в табличном документе, будет отличаться от списка ActiveX объектов, предлагае- мых для размещения, например, в форме. Это объясняется различным функциональным назначением формы и таб- личного документа. Алгоритм работы со всеми перечисленными типами ри- сунков одинаков. Сначала нужно добавить рисунок в таб- личный документ, затем получить объект, отображаемый в рисунке и после этого выполнить необходимые дейст- вия по настройке отображаемого объекта. Например, для того чтобы отобразить в табличном доку- менте результаты отчета в виде диаграммы (рис. 13.146), можно выполнить код, представленный в листинге 13.169. Листинг 13.169. Пример вывода результатов отчета в диаграмму, расположенную в табличном документе Построитель = Новый ПостроительОтчетаО; Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Ноненклатура.Представление,
Рис. 13.146. Использование рисунка типа Диаграмма СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУММАСТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММА(КоличествоПриход), СУММА(КоличествоОборот), СУММА(КоличествоРасход) ПО ОБЩИЕ, Номенклатура ИЕРАРХИЯ" Построитель .ЭаполнитьНастройки (); ТабДок = Новый ТабличныйДокумент: И Добавить рисунок типа Диаграмма и задать его размеры РисунокДиаграмма = ТабДок. Рисунки. Добавить(ТипРисункаТабличногоДокумента.Диаграмма); РисунокДиаграмма. Верх = 5: РисунокДиаграмма.Лево = 5: РисунокДиаграмма. Ширина = 150; РисунокДиаграмма.Высота = 70; И Получить объект Диаграмма, отображаемый в рисунке Диаграмма = РисунокДиаграмма.Объект; Диаграмма.ОбластьЭаголовка.Текст = "Приход товаров"; Построитель. Выполнить (); Построитель .Вывести(Диаграмма); ТабДок.ПоказатьО; Рисунки типа Прямая В заключение рассказа о рисунках табличного документа, остановимся на некоторых особенностях, связанных с ис- пользованием рисунка типа Прямая в табличном докумен- те. Прямая всегда рисуется из «левого верхнего» угла рисунка в «правый нижний». Таким образом, изменяя ширину и высоту рисунка (листинг 13.170), мы можем нарисовать практически любую прямую, имеющую угол наклона от 270 градусов (вертикально, Ширина = 0), до 360 градусов (горизонтально, Высота = 0) (рис. 13.147). Листинг 13.170. Пример рисования линии ТабДок = Новый ТабличныйДокумент; Для ВысотаПрямой = 0 По 50 Цикл Прямая = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Прямая); Прямая.Лево = 5; Прямая.Верх = 5; Прямая.Ширина = 50; Прямая.Высота = ВысотаПрямой; ВысотаПрямой = ВысотаПрямой + 4; КонецЦикла; Для ШиринаПряной = 0 По 50 Цикл Прямая = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Прямая); Прямая.Лево = 5; Прямая.Верх = 5; Прямая.Ширина = ШиринаПряной; Прямая.Высота = 50; ШиринаПряной = ШиринаПряной + 4; КонецЦикла; ТабДок.ОтображатьСетку = Ложь; ТабДок.ПоказатьО; Рис. 13.147. Пример рисования линии Но как же быть, если требуется нарисовать прямую, имеющую угол наклона от 180 до 270 градусов? Для этого можно использовать задание отрицательных значений высоты или ширины рисунка (листинг 13.171). Отрица- тельное значение высоты позволяет отразить рисунок
вертикально, а отрицательное значение ширины — отра- зить рисунок горизонтально (рис. 13.148). Листинг 13.171. Пример рисования линий ТабДок = Новый ТабличныйДокумент; ПрямаяОбычная = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Прямая): ПрямаяОбычная.Линия = Новый Линия(ТипЛинииРисункаТабличногоДокумента. Сплошная. 2); ПрямаяОбычная.Верх = 30; ПрямаяОбычная.Лево = 55: ПрямаяОбычная.Ширина = 50; ПрямаяОбычная.Высота = 25; ПрянаяОтображениеВертикально = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Прямая); ПрянаяОтображениеВертикально.Линия = Новый Линия(ТипЛинииРисункаТабличногоДокумента. Пунктир); ПрянаяОтображениеВертикально.Верх = 30; ПрянаяОтображениеВертикально.Лево = 55: ПрянаяОтображениеВертикально.Ширина = 50; ПрянаяОтображениеВертикально.Высота = -25; ПрянаяОтображениеГоризонтально = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокунента.Прямая); ПрянаяОтображениеВертикально.Линия = Новый ЛинияСТипЛинииРисункаТабличногоДокумента. Точечная); ПрянаяОтображениеГоризонтально.Верх = 30; ПрянаяОтображениеГоризонтально.Лево = 55; ПрянаяОтображениеГоризонтально.Ширина = -50; ПрянаяОтображениеГоризонтально.Высота = 25; Надпись 1 = ТабДок. Рисунки. Добавить(ТипРисункаТабличногоДокунента.Текст); Надпись1.Текст = "Исходная пряная"; Надпись].. АвтоРазиер = Истина; Надпись].Верх = 50; Надпись!.Лево = 70; Надпись2 = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Текст); Надпись2.Текст = "Отражение вверх"; Надпись2.АвтоРазиер = Истина; Надпись2.Верх = 5; Надпись2.Лево = 70: НадписьЗ = ТабДок.Рисунки. Добавить(ТипРисункаТабличногоДокумента.Текст); НадписьЗ.Текст = "Отражение влево"; НадпнсьЗ.АвтоРазиер = Истина; НадписьЗ.Верх = 50; НадписьЗ.Лево = 14; ТабДок.ОтображатьСетку = Ложь; ТабДок.ПоказатьО; Использование макетов табличных документов Помимо непосредственного заполнения табличных доку- ментов данными, существует возможность формирования табличного документа на основе макета. Макет таблично- го документа описывает неизменяемые части табличного документа, содержащие оформление, и области, в кото- рые могут быть выведены данные. Процесс заполнения табличного документа на основе ма- кета заключается в считывании определенных областей макета, циклическом заполнении их данными и последо- вательном выводе полученных частей документа в ре- зультирующий табличныйдокумент (рис. 13.149). Рис. 13.149. Схема использования макета табличного документа Кроме этого, в процессе формирования результирующего табличного документа можно использовать возможность автоматической установки некоторых свойств документа, таких, например, как группировки и отступы. Формат макета табличного документа Макет табличного документа представляет собой таблич- ный документ, у которого свойство Макет установлено в значение Истина. Изменение этого свойства возможно только интерактивным способом, так как создание макета выполняется средствами визуального конструирования в редакторе табличных документов.
После того как табличному документу установлено свой- ство Макет, для областей и рисунков табличного докумен- та становится доступной возможность указать, чем будет заполняться та или иная область (рисунок) макета. Для этого используются свойства Заполнение области и ри- сунка табличного документа (следует заметить, что для рисунков свойство Заполнение может быть использовано, только если рисунок имеет тип Текст). Свойство заполне- ние принимает значения системного перечисления ТипЗа- полненияОбластиТабличногоДокунента. Возможны три значе- ния: ♦ Текст — при выводе области/рисунка в табличный до- кумент будет выведен текст, содержащийся в свойстве Текст области/рисунка; ♦ Параметр — при выводе области/рисунка в табличный документ будет выведено значение параметра, имя ко- торого указано в свойстве Параметр области/рисунка; ♦ Шаблон — при выводе области/рисунка в табличный до- кумент будет выведен текст в соответствии с шаблоном, который описан в свойстве Текст области/рисунка. Макет представляет собой строку, содержащую имена па- раметров. Для указания имени параметра используются символы «[» и «]» (листинг 13.172). Листинг 13.172. Пример шаблона Налогоплательщик: [НазваниеОрганизации] В приведенном примере НазваниеОрганизации — это имя параметра, значение которого будет выведено в таблич- ный документ после строки «Налогоплательщик:». Как правило, в макете табличного документа определяет- ся набор именованных областей, соответствующих логи- ческим частям будущего табличного документа. Напри- мер, если на основе шаблона будет формироваться отчет, содержащий табличные данные, то, скорее всего, макет такого отчета будет содержать области «Шапка», «Стро- ка» и «Подвал». Процедура формирования табличного документа Для того чтобы заполнить значения параметров области макета необходимыми данными, эта область должна быть получена в виде табличного документа. Для этого исполь- зуется метод табличного документа ПолучитьОбластьО, ко- торому в качестве параметра передается имя области. После этого к параметрам области можно обратиться с помо- щью свойства табличного документа Параметры. Обраще- ние возможно по имени параметра (листинг 13.173). Листинг 13.173. Обращение к параметрам области макета по имени ТабМакет = Получит ьМакет( "Макет"): ОбластьШапки = ТабМакет.ПолучитьОбласть("Шапка"); ОбластьШапки.Параметры.НачалоПериода = НачапьнаяДата; ОбластьШапки.Параметры.КонецПериода = КонечнаяДата; Свойство Параметры содержит коллекцию параметров таб- личного документа. Помимо обращения по имени, кол- лекция содержит метод Заполнить О, который позволяет заполнить значения всех параметров, содержащихся в об- ласти, значениями одноименных свойств переданного ей объекта. Такой способ заполнения параметров удобно ис- пользовать, например, при выводе в табличный документ результата запроса. Например, пусть создан следующий макет (рис. 13.150). Рис. 13.150. Макет Тогда фрагмент кода, выводящий данные запроса в таб- личный документ, формируемый на основе этого макета, может выглядеть следующим образом (листинг 13.174). Листинг 13.174. Пример заполнения значения параметров области макета Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладахОбороты.Номенклатура.Представление КАК Номенклатура, ТоварыНаСкладахОбороты.КоличествоРасход КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты КАК ТоварыНаСкладахОбороты АВТОУПОРЯДОЧИВАНИЕ" Выборка = Запрос.ВыполнитьО.ВыбратьО; И Получить макет ТабМакет = ПолучитьМакет("Макет"); И Получить область макета для вывода данных запроса СекцияСтрока = ТабМакет.ПолучитьОбласть("Строка"); Пока Выборка.СледующийО Цикл // Заполнить значения параметров области СекцияСтрока.Параметры.Заполнить(Выборка): КонецЦикла; После того как значения параметров области заданы, таб- личный документ, содержащий область макета, может быть выведен в результирующий табличный документ. Для этого могут быть использованы два метода таблично- го документа: Вывести() и Присоединить О. Метод Вывести () выводит переданный ему табличный до- кумент в результирующий табличный документ, добав- ляя его со следующей строки вслед за самой нижней вы- веденной строкой, начиная с первой колонки. Метод Присоединить () также выводит переданный ему таб- личный документ в результирующий табличный доку- мент, но помещает его в следующей колонке правее самой правой выведенной колонки, начиная со строки, с кото- рой выводился предыдущий табличный документ. Как правило, метод Вывести О используется для формиро- вания линейных отчетов, когда области макета являются областями строк и должны выводиться последовательно, друг за другом. Например, пусть существует макет, у которого определе- на область строк Строка, содержащая параметр Название (рис. 13.151).
Рис. 13.151. Макет Тогда результирующий табличный документ, для фор- мирования которого использовался метод Вывести О (листинг 13.175), будет выглядеть следующим образом (рис. 13.152). Листинг 13.175. Пример использования метода ВывестиО ТабДок = Новый ТабличныйДокумент; ТабМакет = ПолучитьМакетС'Макет"); ОбластьСтрока = ТабМакет.ПолучитьОбластьС'Строка"); ОбластьСтрока.Параметры.Название = "Первая область"; ТабДок.Вывести(ОбластьСтрока); ОбластьСтрока.Параметры.Название = "Вторая область": ТабДок.Вывести(ОбластьСтрока); ОбластьСтрока.Параметры.Название = "Третья область": ТабДок.Вывести(ОбластьСтрока); ТабДок.ПоказатьО; Рис. 13.152. Результирующий табличный документ Теперь предположим, что используется макет, в котором определена прямоугольная область Строка с параметром Название (рис. 13.153). Рис. 13.153. Макет Для вывода этой области макета будем использовать как метод ВывестиО, так и метод Присоединить О (листинг 13.176). Листинг 13.176. Пример использования метода Присоединит^) ТабДок = Новый ТабличныйДокумент; ТабМакет = ПолучитьМакетС'Макет"): ОбластьСтрока = ТабМакет.ПолучитьОбласть("Строка"); ОбластьСтрока.Параметры.Название = "Первая область"; ТабДок.Вывести(ОбластьСтрока); ОбластьСтрока.Параметры.Название = "Вторая область"; ТабДок.Вывести(ОбластьСтрока); ОбластьСтрока.Параметры.Название = "Третья область"; Т абДок.Присоединить(ОбластьСтрока); ОбластьСтрока.Параметры.Название = "Четвертая область"; Т абДок.Присоединить(ОбластьСтрока); ТабДок.ПоказатьО; В этом случае результирующий табличный документ бу- дет выглядеть так, как показано на рис. 13.154. Рис. 13.154. Результирующий табличный документ Метод Присоединить () используется, как правило, при соз- дании кросс-отчетов, для вывода колонок отчета. Коли- чество выводимых колонок отчета может изменяться в зависимости от состава данных отчета и заданных пара- метров. Поэтому обычно создается прямоугольная об- ласть макета, которая присоединяется к заголовку строки нужное количество раз при формировании результирую- щего табличного документа. Методы ВывестиО и Присоединить О содержат четыре пара- метра, смысл которых одинаков для обоих методов. Параметр Таблица является обязательным и содержит тот самый табличный документ, который должен быть добав- лен в результирующий табличный документ. Параметр Уровень используется для автоматической груп- пировки строк/колонок результирующего табличного до- кумента. Соседние строки/колонки с одинаковым уров- нем будут отнесены к одной группе. При использовании метода ВывестиО указывается уровень для группировки строк, а при использовании метода Присоединить О — уро- вень для группировки колонок. Для автоматической группировки строк/колонок резуль- тирующего табличного документа используются методы НачатьАвтогруппировкуСтрокО, ЗакончитьАвтогруппировкуСтрокО, НачатьАвтогруппировкуКолонокО и ЗакончитьАвтогруппировку- КолонокО. Обычно возможность автогруппировки строк/колонок ре- зультирующего табличного документа используется при выводе иерархических результатов запроса. Тогда в качест- ве номера уровня задается уровень записи выборки резуль- тата запроса, данные которой выводятся в область макета. Пусть, например, существует макет, показанный на рис. 13.155. Рис. 13.155. Макет Тогда, указав при формировании результирующего таб- личного документа уровни группировок и необходимость автоматической группировки строк (листинг 13.177), можно получить отчет, содержащий группировки товаров по складам (рис. 13.156). Параметр Имя группы задает название группы, к которой относятся выводимые строки. Это название будет отобра- жено во всплывающей подсказке при наведении курсора на маркер группы. Использование таких подсказок может быть полезным в многоуровневых отчетах для повыше- ния их читабельности.
Листинг 13.177. Пример использования автогруппировки строк Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладахОбороты.Склад.Представление КАК Склад. ТоварыНаСкладахОбороты.Номенклатура.Представление КАК Номенклатура. СУММА(ТоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты КАК ТоварыНаСкладахОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОбороты.Склад. ТоварыНаСкладахОбороты.Номенклатура. ТоварыНаСкладахОбороты.Склад.Представление, ТоварыНаСкладахОбороты.Номенклатура.Представление ИТОГИ СУММА(КоличествоРасход) ПО Склад, Номенклатура Выборка = Запрос.ВыполнитьО. Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); ТабДок = Новый Табличныйдокумент; ТабМакет = ПолучитьМакет("Макет"); ОбластьСклад = ТабМакет.ПолучитьОбластьС’Склад"); ОбластьНоменклатура = ТабМакет.ПолучитьОбласть("Номенклатура"); ТабДок.НачатьАвтогруппировкуСтрок(); Пока Выборка.Следующий() Цикл ОбластьСклад.Параметры.Заполнить( Выборка); ТабДок.Вывести(ОбластьСклад, Выборка.Уровень()); ВыборкаНоменклатура = Выборка. Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); Пока ВыборкаНоменклатура.Следующий() Цикл ОбластьНоменклатура.Параметры. Заполнить(ВыборкаНоменклатура); ТабДок.Вывести(ОбластьНоменклатура, ВыборкаНоменклатура.Уровень О); КонецЦикла; КонецЦикла; ТабДок. ЗакончитьАвтогруппировкуСтрокО; ТабДок. ПоказатьО; Рис. 13.156. Сформированный отчет ПРИМЕЧАНИЕ Обратите внимание, что на рис. 13.156 в строках, которые входят в группировку первого уровня, имя склада выведе- но с отступом от левого края ячейки. Так происходит потому, что для этой ячейки в макете табличного докумен- та установлено свойство АвтоОтступ, которое задает количе- ство символов отступа от левого края области в зависимо- сти от уровня группировки. В данном случае значение свойства равно 3, это означает, что для строк первого уров- ня группировки будет использован отступ в 3 символа, для строк второго уровня группировки — 6 символов и т. д. Например, если взять за основу пример, приведенный в листинге 13.177 и несколько видоизменить его (лис- тинг 13.178) по при сворачивании/разворачивании груп- пировок будет выдаваться соответствующая подсказка (рис. 13.157). Листинг 13.178. Пример использования имен групп Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладахОбороты.Склад.Представление КАК Склад, ТоварыНаСкладахОбороты.Номенклатура.Представление КАК Номенклатура, СУММА(ТоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоРасход | ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты КАК ТоварыНаСкладахОбороты |СГРУППИРОВАТЬ ПО ТоварыНаСкладахОбороты.Склад. ТоварыНаСкладахОбороты.Номенклатура, ТоварыНаСкладахОбороты.Склад.Представление, ТоварыНаСкладахОбороты.Номенклатура.Представление |ИТОГИ СУММА(КоличествоРасход) | ПО | Склад. Номенклатура Выборка = Запрос.ВыполнитьО. Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); ТабДок = Новый Табличныйдокумент: ТабМакет = ПолучитьМакет("Макет"); ОбластьСклад = ТабМакет.ПолучитьОбластьС’Склад"); ОбластьНоменклатура = ТабМакет.ПолучитьОбласть("Номенклатура"); ТабДок. Начат ьАвтогруппировкуСтрокО; Пока Выборка.Следующий() Цикл ОбластьСклад.Параметры.Заполнить( Выборка); ТабДок.Вывести(ОбластьСклад, Выборка.Уровен ь()); ВыборкаНоменклатура = Выборка. Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); Пока ВыборкаНоменклатура.СледующийО Цикл ОбластьНоменклатура.Параметры. Заполнить(ВыборкаНоменклатура); ТабДок.Вывести(ОбластьНоменклатура, ВыборкаНоменклатура.Уровень(), "Номенклатура на складе " + Выборка.Склад); КонецЦикла; КонецЦикла: ТабДок. ЗакончитьАвтогруппировкуСтрокО; ТабДок.ПоказатьО: Параметр Открыта определяет вид, в котором будет выво- диться создаваемая группа. Если параметр имеет значе-
иие Истина, группа будет выводиться в развернутом виде (по умолчанию). Если параметр имеет значение Ложь, группа будет выводиться в свернутом виде. Рис. 13.157. Использование имен групп Например, если в примере, приведенном в листинге 13.177, использовать этот параметр при выводе группировки Но- менклатура (листинг 13.179), то результирующий документ будет содержать свернутые группировки (рис. 13.158). Листинг 13.179. Пример управления видом создаваемых группировок Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладахОбороты.Склад.Представление КАК Склад, ТоварыНаСкладахОбороты.Номенклатура.Представление КАК Номенклатура, СУММАСТоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты КАК ТоварыНаСкладахОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОбороты.Склад, Т оварыНаСкладахОбороты.Номенклатура, ТоварыНаСкладахОбороты.Склад.Представление, ТоварыНаСкладахОбороты.Номенклатура.Представление ИТОГИ СУММА(КоличествоРасход) ПО Склад, Номенклатура Выборка = Запрос.ВыполнитьО. Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); ТабДок = Новый ТабличныйДокунент: ТабМакет = ПолучитьМакет("Макет”); ОбластьСклад = ТабМакет.ПолучитьОбласть("Склад"); ОбластьНоменклатура = ТабМакет.ПолучитьОбласть("Номенклатура"); ТабДок. НачатьАвтогруплировкуСтрокО; Пока Выборка.СледующийО Цикл ОбластьСклад.Параметры.Заполнить( Выборка); ТабДок.Вывести(ОбластьСклад, Выборка.Уровень()); ВыборкаНоменклатура = Выборка. Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); Пока ВыборкаНоменклатура.СледующийО Цикл ОбластьНоменклатура.Параметры. Заполнить(ВыборкаНоменклатура); Т абДок.Вывести(Облает ьНоменклатура, ВыборкаНоменклатура.Уровень(), Ложь); КонецЦикла; КонецЦикла; ТабДок. ЗакончитьАвтогруппировкуСтрокО; ТабДок.ПоказатьО; | Таблица □ х 1 ИЕ 1 | ..2- 3 .. 4 ж Е 1 Главный склад 309,006. В 33 Торговьы зал 104, ОМ В 42 Склад электротоваров 139,000' В 53 Ротничныи магатин № 2 25,ОМ Ж. 58 I Рис 13.158. Результирующий документ Аналогичного результата можно достигнуть с помощью методов табличного документа ПоказатьУровеньГруппиро- вокСтрокО и ПоказатьУровеньГруппировокКолонокО. Эти мето- ды имеют один обязательный параметр Уровень, который задает номер уровня, до которого необходимо раскрыть группировки. Например, в примере, приведенном в листинге 13.169, можно было бы использовать конструкцию: ТабДок.ПоказатьУровеньГруппировокСтрок(О): Табличный документ содержит методы, которые позво- ляют определить количество уровней группировки, ис- пользованных в документе. Это методы КоличествоУровней- ГруппировокСтрокО и КоличествоУровнейГруппировокКолонокО. Использование этих методов может понадобиться, на- пример, если требуется организовать собственную ко- мандную панель для управления группировками таблич- ного документа. Тогда результаты, возвращаемые этими методами, позволят организовать цикл обхода всех уров- ней группировок. Наряду с автоматической группировкой строк/колонок результирующего документа можно группировать строки/ колонки и «вручную». Для этого используются методы табличного документа НачатьГруппуСтрокО, ЗакончитьГруп- пуСтрокО, НачатьГруппуКолонокО и ЗакончитьГруппуКолонокО. Эти методы имеют два необязательных параметра: Иня группы и Открыта ли группа. Если, например, говорить про группировку строк, то в слу- чае использования методов НачатьГруппуСтрокО и Закон- читьГруппуСтрокО в одну группу будут объединены строки, выведенные в результирующий табличный документ ме- жду вызовами этих методов. Также можно создавать и вложенные группировки. Например, в результате выполнения примера, приведен- ного в листинге 13.180, будет получен следующий таб- личный документ (рис. 13.159). Листинг 13.180. Пример использования группировки строк табличного документа ТабМакет = ПолучитьМакет("Макет"); ОбластьСтрока = ТабМакет.ПолучитьОбласть("Строка"); ТабДок = Новый ТабличныйДокунент; // Вывести одну строку верхнего уровня ОбластьСтрока.Параметры.Наз вание = "Строка верхнего уровня"; ТабДок.Вывести(ОбластьСтрока):
ТабДок.НачатьГруппуСтрокО; И Вывести три строки группы первого уровня ОбластьСтрока.Параметры.Название = "Группировка первого уровня”; ТабДок.Вывести(ОбластьСтрока); ТабДок.Вывести(ОбластьСтрока); ТабДок.Вывести(ОбластьСтрока); ТабДок.Начат ьГруппуСтрок(); И Вывести две строки группы второго уровня Облает ьСтрока.Параметры.Название = "Группировка второго уровня": ТабДок.Вывести(ОбластьСтрока); ТабДок.Вывести(ОбластьСтрока); ТабДок.ЗакончитьГруппуСтрокО; // закончить группировку строк // второго уровня ТабДок.ЗакончитьГруппуСтрокО; // закончить группировку строк // первого уровня ТабДок.ПоказатьО; Рис. 13.159. Результирующий табличный документ Табличный документ позволяет управлять расположением маркеров секций, сворачивающих горизонтальные и вер- тикальные группировки табличного документа. Для этого используются свойства ИтогиСнизу и ИтогиСправа. Эти свойства принимают значения типа Булево и по умол- чанию для нового документа установлены в значение Ложь, то есть для горизонтальных секций маркеры будут располагаться сверху, а для вертикальных — слева. Свойство табличного документа ОтображатьГруппировки по- зволяет управлять отображением существующих группи- ровок. По умолчанию это свойство для нового документа установлено в значение Истина, это означает, что группи- ровки будут отображены. Свойства ЦветТекстаГруппировки и ЦветФонаГруппи- ровки позволяют задавать цвет текста и фона области, отображающей группировки табличного документа. Например, если в предыдущий пример (см. листинг 13.180) добавить следующие строки (листинг 13.181), то резуль- тирующий табличный документ примет вид, показанный нарис. 13.160. Листинг 13.181. Управление цветом фона и текста области группировок ТабДок.ЦветФонаГруппировки = ЫеЬЦвета.Черный; ТабДок.ЦветТекстаГруппировки = ЫеЬЦвета.Белый; Рис 13.160. Управление цветом фона и текста области группировок Получение строк макета на разных языках При получении различных областей макета можно ука- зать язык, на котором должны быть получены строки, со- держащиеся в макете. Если в конфигурации определено несколько языков (Общие - Языки), то система предоставляет возможность задать значение любой строки, содержащейся в конфигурации, на каждом из языков, определенных в конфигурации. Та- ким образом, если макет содержит текстовые строки, то в общем случае их значения могут быть указаны отдельно, для каждого языка. Предположим, что существует макет (рис. 13.161), в ко- тором определена область Строка, содержащая строку на разных языках. Рис. 13.161. Макет Для языка Русский (код ru) указано значение Сотрудник, а для языка Английский (код еп) указано значение Employee (рис. 13.162). Рис. 13.162. Строка на разных языках При формировании результирующего табличного доку- мента на основе такого макета указанная строка может быть получена как на русском языке, так и на англий- ском. Для этого используется свойство табличного доку- мента КодЯзыкаМакета (листинг 13.182). После того как об- ласть макета получена в виде табличного документа, ей следует установить нужный код языка (в нашем случае еп или ru). Тогда при выводе этой области с результирую- щим табличным документом для строк на разных языках, которые содержатся в выводимом документе, будет полу- чено их значение на языке, код которого совпадает с ко- дом, указанным в свойстве КодЯзыкаМакета. Листинг 13.182. Получение области на указанном языке ТабМакет = ПолучитьМакетС'Макет"); ТабДок = Новый ТабличныйДокумент; ОбластьСтрока = ТабМакет.ПолучитьОбластьС'Строка"); // Вывести строки, содержащиеся в области, на русской языке ОбластьСтрока.КодЯзыкаМакета = "ru"; ТабДок.Вывести(ОбластьСтрока): // Вывести строки, содержащиеся в области, на английском языке ОбластьСтрока.КодЯзыкаМакета = "еп"; ТабДок.Вывести(ОбластьСтрока); ТабДок.ПоказатьО;
Результирующий табличный документ будет выглядеть так, как показано на рис. 13.163. Рис. 13.163. Результирующий табличный документ В том случае, если свойству КодЯзыкаМакета указан код языка, отсутствующий в конфигурации, будет выведена пустая строка. По умолчанию свойство КодЯзыкаМакета имеет значение Неопределено. В этом случае при выводе областей макета в табличный документ будет использо- ван код языка макета, соответствующий языку, назначен- ному для текущего пользователя. Если текущему пользо- вателю язык не назначен, будет использован код языка, ус- тановленного для свойства конфигурации Основной язык. Использование расшифровки в табличном документе Табличный документ предоставляет возможность исполь- зовать расшифровку для получения детальной информа- ции при нажатии на определенные ячейки результирую- щего табличного документа. ПРИМЕЧАНИЕ Следует заметить, что расшифровка может быть использо- вана как непосредственно в табличном документе, так и в табличном документе, размещенном в форме (объект ПолеТабличногоДокумента). Однако возможности исполь- зования расшифровки непосредственно в табличном доку- менте ограничены, по сравнению с полем табличного доку- мента. Об использовании расшифровки в поле табличного документа рассказывается в разделе «Расшифровка в поле табличного документа» на с. 517. Для того чтобы существовала возможность использова- ния расшифровки, должны быть выполнены условия: ♦ ячейкам/рисункам табличного документа, для которых должна выполняться расшифровка, должны быть зада- ны имена параметров расшифровки (свойство Параметр- Расшфровки области ячеек табличного документа или рисунка табличного документа); ♦ в процессе вывода областей макета в результирующий табличный документ параметрам расшифровки долж- ны быть присвоены значения, отличные от Неопределено; ♦ результирующий табличный документ должен обеспе- чивать запрет редактирования тех ячеек/рисунков, для которых предполагается использовать расшифровку. Для этого используется обычно либо свойство Только- Просмотр, либо свойство Защита табличного документа. Если все перечисленные условия выполнены, то при на- ведении курсора на область/рисунок табличного доку- мента, допускающий расшифровку, курсор принимает вид креста с расположенной на нем лупой, что говорит о том, что данная ячейка допускает расшифровку. При двойном щелчке мышью на такой ячейке будет выпол- нено стандартное действие со значением, находящимся в параметре расшифровки данной ячейки: ♦ для значений примитивных типов будет отображено их значение в отдельном окне; ♦ для ссылочных значений будет открыта основная фор- ма объекта, используемая для редактирования данных объекта. Таким образом, непосредственно в табличном документе расшифровка используется, как правило, для того, чтобы предоставить возможность просмотра и редактирования данных ссылочных объектов, представления которых со- держатся в результирующем табличном документе. Выполнение расшифровки возможно не только по двой- ному, но и по одинарному щелчку мышью на ячейке. Для этого используется свойство области/рисунка табличного документа Гиперссылка. Если это свойство установлено в значение Истина, то при наведении курсора на такую ячейку он будет принимать форму ладони, и описанные выше дей- ствия будут выполняться по одинарному щелчку мыши. Также область ячеек табличного документа обладает свой- ством ИспользованиеРасшифровки, которое принимает значе- ния системного перечисления ИспользованиеРасшифровки- ТабличногоДокуиента (табл. 13.17). Свойства: Ячейки Ячейки ► Основные: Макет: Заполнение Параметр ► Значения: ► Положение: Параметр Парам, расшифровки Использование расшифровки СкладПредставление РасшифровкаСклада Ячейка (формление: Е Рис. 13.164. Макет табличного документа
Таблица 13.17. Значения системного перечисления ИспользованиеРасшифровкиТабличногоДокумента Значение Описание БезОбработки Курсор не меняет свой внешний вид, и расшифровка не выполняется Ячейка Расшифровка вызывается только для ячейки, содержащей значение параметра расшифровки Строка Расшифровка выполняется для всех ячеек строки, следующих за ячейкой, содержа- щей значение параметра расшифровки В качестве примера использования расшифровки рас- смотрим формирование отчета по расходу номенклатуры на складах, в котором при нажатии на склад или номенк- латуру будет открываться форма соответствующего эле- мента (для справочников Склады и Номенклатура указано ре- дактирование в диалоге). Используем макет, показанный на рис. 13.164. В этом ма- кете для ячеек, в которые выводится представление скла- да, указано имя параметра расшифровки Расшифровка- Склада, а для ячеек, в которые выводится представление номенклатуры, указано имя параметра расшифровки Рас- шифровкаНоменклатуры. Для формирования отчета используем код, представлен- ный в листинге 13.183. В этом фрагменте перед выводом областей макета в ре- зультирующий табличный документ присваиваются зна- чения параметрам расшифровки, содержащимся в этих областях. Перед показом результирующего табличного документа ему устанавливается свойство ТолькоПросмотр. В результате будет сформирован табличный документ, в котором при двойном щелчке, например, по ячейке, со- держащей представление склада, будет открываться фор- ма для просмотра и редактирования данных этого склада (рис. 13.165). Листинг 13.183. Пример использования расшифровки Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладахОбороты.Склад КАК Склад. ТоварыНаСкладахОбороты.Склад.Представление КАК СкладПредставление, ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОбороты.Номенклатура.Представление КАК НоменклатураПредставление, СУММАСТоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты КАК ТоварыНаСкладахОбороты СГРУППИРОВАТЬ ПО Т оварыНаСкладахОбороты.Склад, ТоварыНаСкладахОбороты.Номенклатура ИТОГИ СУММА(КоличествоРасход) ПО Склад, Номенклатура" Выборка = Запрос.ВыполнитьО. Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); ТабДок = Новый ТабличныйДокунент; ТабМакет = ПолучитьМакетС'Макет"); ОбластьСклад = ТабМакет.ПолучитьОбласть("Склад"); ОбластьНоменклатура = ТабМакет.ПолучитьОбласть("Номенклатура"); ТабДок. НачатьАвтогруппировкуСтрокО: Пока Выборка.Следующий() Цикл ОбластьСклад.Параметры.Заполнить( Выборка); // Установить расшифровку поля Склад группировки Склад ОбластьСклад.Параметры.РасшифровкаСклада = Выборка.Склад; ТабДок.Вывести(ОбластьСклад. Выборка.Уровень()); ВыборкаНоменклатура = Выборка. Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); Рис 13.165. Сформированный отчет
Пока ВыборкаНоменклатура.СледующийО Цикл ОбластьНоменклатура.Параметры. Заполнить(ВыборкаНоменклатура); // Установить расшифровку полей Склад и Номенклатура // группировки Номенклатура ОбластьНоменклатура.Параметры.РасшифровкаСклада = ВыборкаНоменклатура.Склад; ОбластьНоменклатура.Параметры.РасшифровкаНоменклатуры = ВыборкаНоменклатура.Номенклатура; ТабДок.Вывести(ОбластьНоменклатура, ВыборкаНоменклатура.Уровень()); КонецЦикла; КонецЦикла; ТабДок.ЗакончитьАвтогруппировкуСтрок(); // Установить режим просмотра документа ТабДок.ТолькоПросмотр = Истина; ТабДок.ПоказатьО; Печать табличного документа Табличный документ может быть распечатан на принте- ре, причем система предоставляет возможность настрой- ки различных параметров печати не только интерактив- ными средствами (в диалоге настройки печати), но и средствами встроенного языка. Для того чтобы распечатать табличный документ, ис- пользуется метод табличного документа Напечатать О. Этот метод содержит один параметр, имеющий тип Буле- во, который позволяет выводить или скрывать диалог на- стройки печати. По умолчанию параметр имеет значение Истина, и диалог настройки печати не отображается перед печатью табличного документа. Для того чтобы предоста- вить пользователю возможность вручную настраивать параметры печати, в параметр метода Напечатать О должно быть передано значение Ложь (листинг 13.184). Листинг 13.184. Печать табличного документа с использованием диалога печати ТабДок = ПолучитьМакетС'Макет"): ТабДок.Напечатать(Ложь); ВНИМАНИЕ Следует учитывать, что если свойства табличного докумен- та ВысотаТаблицы и ШиринаТаблицы равны нулю (под- робнее смотри на с. 475), то при попытке печати такого до- кумента будет выдано сообщение: Нет информации для вывода на печать, и печать будет отменена. По умолчанию печать будет осуществляться на принтер, который установлен в операционной системе как принтер по умолчанию. Для того чтобы указать определенный принтер, на который должна осуществляться печать, ис- пользуется свойство табличного документа ИмяПринтера (листинг 13.185). Листинг 13.185. Печать на указанный принтер ТабДок = ПолучитьМакетС’Макет"); ТабДок.ИмяПринтера = "HP LaserJet 6L"; ТабДок.НапечататьО; Если принтер с указанным именем не установлен в опе- рационной системе, или если имя принтера не указано, печать будет осуществляться на принтер по умолчанию. Перед печатью табличного документа ему может быть ус- тановлен ряд параметров, аналогичных тем параметрам, которые задаются в диалоге настройки печати. Для этого используются следующие свойства табличного доку- мента: ОриентацияСтраницы — задает ориентацию страницы. При- нимает значения системного перечисления ОриентацияСт- раницы: Ландшафт или Портрет. По умолчанию используется значение Портрет. ПолеСверху, ПолеСлева, ПолеСнизу, ПолеСправа — эти свойства задают ширину полей отступа при печати в миллиметрах. По умолчанию для всех свойств используется значе- ние 10. ОбластьПечати — задает область табличного документа, ко- торая будет выводиться на печать. Содержит значение типа ОбластьЯчеекТабличногоДокуиента или Неопределено. Значение Неопределено — это значение по умолчанию. В этом случае на печать будет выведена область таблич- ного документа, ограниченная свойствами ШиринаТаблицы и ВысотаТаблицы табличного документа. Если это свойство содержит прямоугольную область табличного докумен- та — то будет напечатана указанная область. Если свойст- во содержит область строк, то будет напечатана часть этой области, ограниченная справа значением свойства табличного документа ШиринаТаблицы. Если свойство со- держит область колонок, то будет напечатана часть этой области, ограниченная снизу значением свойства таблич- ного документа ВысотаТаблицы. КоличествоЭкзеипляров — задает количество экземпляров табличного документа, которые будут выведены на пе- чать. Принимает значения типа Число и Неопределено. Не- определено — значение по умолчанию. В этом случае ко- личество экземпляров будет определяться настройками принтера, на который осуществляется печать. Экземпляров на странице — задает количество страниц, на которые будет разбит текст табличного документа, напе- чатанный на одном листе бумаги. Может принимать чи- словые значения 0, 1 и 2 и значение Неопределено. Значе- ние 1 означает, что на одном листе будет напечатана одна страница. Значение 2 означает, что табличный документ, печатаемый на одном листе бумаги, будет разбит на две страницы по вертикали. Значение 0 задает автоматиче- ское определение количества страниц на листе. Значение Неопределено означает, что количество экземпляров на странице будет определяться настройками принтера, на который осуществляется печать. Разбор по копиям — позволяет управлять последовательно- стью печати страниц многострочного табличного доку- мента при выводе на печать нескольких экземпляров до- кумента. Если свойство установлено в значение Истина, то печать будет выполняться в следующей последовательности: Экземпляр! Страница! Экземпляр! Страница2 Экземпляр! Страницам Зкземпляр2 Страница! Зкземпляр2 Страница2 Экземпляр2 Страницам ЭкземплярМ Страница! ЭкземплярМ Страница2 ЭкземплярМ Страницам
Если свойство установлено в значение Ложь, то печать бу- дет выполняться в следующей последовательности: Экземпляр! Страница! Экземпляр? Страница! ЭкземплярЛ Страница! Экземпляр! Страница? Экземпляр? Страница? ЭкзенплярН Страница? Экземпляр! Страницам Экземпляр? Страницам ЭкземплярМ Страницам Значение Неопределено означает, что последовательность вывода страниц на печать будет определяться настройка- ми принтера, на который осуществляется печать. Свойства МасштабПечати и АвтоМасштаб позволяют управ- лять масштабом печатаемого документа. Свойство Авто- Масштаб принимает значения типа Булево. Если значение свойства АвтоМасштаб установлено в Истина, то в случае если по ширине табличный документ занимает более од- ной страницы, его масштаб будет уменьшен таким обра- зом, чтобы документ помещался на одну страницу по ши- рине. Значение Ложь означает, что масштаб печати будет определяться свойством МасштабПечати. Свойство МасштабПечати принимает числовые значения и значение Неопределено. Это свойство задает масштаб пе- чатаемого табличного документа в процентах. Значение Неопределено — значение по умолчанию. Оно означает, что масштаб будет определяться настройками принтера, на который осуществляется печать. Свойство ЧерноБелаяПечать позволяет печатать документ в черно-белом режиме. По умолчанию это свойство имеет значение Неопределено, это означает, что режим печати бу- дет определяться настройками того принтера, на который осуществляется печать. Значение Ложь означает, что будет выполняться печать в цветном режиме, значение Истина означает, что печать будет выполняться в черно-белом ре- жиме. При печати табличного документа можно определить строки/колонки, которые будут печататься на каждом новом листе. Для этого используются свойства таблич- ного документа ПовторятьПриПечатиСтроки и ПовторятьПри- ПечатиКолонки. Эти свойства содержат значения типа ОбластьЯчеекТабличногоДокуиента. Наиболее распространен- ным случаем использования этих свойств является по- вторение на каждом новом листе шапки таблицы в случае, когда таблица располагается на нескольких страницах. Табличный документ позволяет использовать при печати колонтитулы. Колонтитулы представляют собой специ- альные области, вставляемые в верхнюю и нижнюю часть каждой страницы документа. В колонтитулы обычно по- мещается информация о номере страницы, названии до- кумента, названии глав или разделов документа и т. д. В табличном документе верхний и нижний колонтитулы описываются объектами КолонтитулТабличногоДокунента. Для доступа к верхнему колонтитулу используется свой- ство табличного документа ВерхнийКолонтитул, для доступа к нижнему — НижнийКолонтитул. Колонтитул состоит из трех логических частей: левой, центральной и правой. Каждая из этих частей может со- держать значение типа Строка, которое и будет напечатано на каждом листе документа. Для доступа к этим частям колонтитула используются свойства ТекстСлева, ТекстВЦентре и ТекстСправа колонтиту- ла табличного документа. Эти свойства принимают зна- чения типа Строка и могут содержать ряд управляющих конструкций (табл. 13.18). Таблица 13.18. Управляющие конструкции колонтитула табличного документа Конструкция Описание [&НомерСтраницы] При печати вместо данной управляющей конструкции будет выведен номер страницы [ &СтраницВсего] При печати вместо дайной управляющей конструкции будет выведено количество страниц в документе [&Дата] При печати вместо данной управляющей конструкции будет выведена текущая дата [&Время] При печати вместо данной управляющей конструкции будет выведено текущее время Помимо собственно текста колонтитула, могут быть зада- ны различные свойства, определяющие внешний вид ко- лонтитулов. Свойство ВертикальноеПоложение определяет способ вырав- нивания текста колонтитула по вертикали в пределах от- веденной для него области (Верх, Низ, Центр). Значение по умолчанию — Вниз. Размеры верхнего и нижнего колонти- тулов задаются свойствами табличного документа Размер- КолонтитулаСверху и РазнерКолонтитулаСнизу. Размеры зада- ются в миллиметрах и по умолчанию имеют значение 10. Свойство НачальнаяСтраница принимает значения типа Чис- ло и определяет помер страницы, начиная с которого бу- дет выводиться колонтитул. По умолчанию имеет значе- ние 0. Свойство Шрифт позволяет установить шрифт для вывода колонтитула. Принимает значения типа Шрифт. Свойство Выводить определяет необходимость вывода ко- лонтитула. По умолчанию это свойство имеет значение Ложь, это означает, что колонтитулы не выводятся. Пример задания колонтитулов документа показан в лис- тинге 13.186. Листинг 13.186. Пример использования колонтитулов ТабДок = Новый Табличныйдокумент; ВерхнийКолонтитул = ТабДок.ВерхнийКолонтитул: ВерхнийКолонтитул.Выводить = Истина; ВерхнийКолонтитул.ТекстСлева = "Отчет составлен Е&Дата] в [&Время]"; НижнийКолонтитул = ТабДок.НижнийКолонтитул: НижнийКолонтитул.Выводить = Истина; НижнийКолонтитул.ТекстВЦентре = "Страница [&НонерСтраницы] из [&СтраницВсего]": Т абДок.Напечатат ь():
Параметры печати табличного документа могут быть за- помнены для того, чтобы впоследствии распечатать этот же или другой документ аналогичным образом. Для этого используется свойство табличного документа ИняПарамет- ровПечати. По умолчанию это свойство имеет значение пустой строки. Если свойству ИмяПаранетровПечати присво- ить значение, отличное от значения типа Строка по умол- чанию, то после печати табличного документа настройки печати будут запомнены, и могут использоваться в даль- нейшем при повторной печати, например, этого же доку- мента. Для этого перед печатью (перед выполнением метода Напечатать ()), свойству ИмяПаранетровПечати печа- таемого табличного документа должно быть присвоено то же самое имя. Это свойство используется таким же образом, как и свой- ство табличного документа ИняСохраненияПоложенияОкна (пример использования можно посмотреть па с. 474). В процессе формирования результирующего табличного документа на основе макета могут использоваться мето- ды ВывестиВертикальныйРазделительСтраницО и ВывестиГори- зонтальныйРазделительСтраницО. Эти методы выводят в ре- зультирующий документ соответственно вертикальный и горизонтальный разделители страниц. Например, эти ме- тоды могут быть использованы при печати документов, формы которых изначально подразумевают размещение информации на двух страницах. Метод табличного документа КоличествоСтраницО возвра- щает количество страниц в документе с учетом текущих настроек печати. Использование этого метода может быть полезным перед печатью результирующего таблич- ного документа для информирования пользователя о ко- личестве страниц, которые будут напечатаны. При формировании результирующего табличного доку- мента может возникнуть задача создания определенного оформления каждого печатаемого листа документа. На- пример, каждый лист документа, выводимый на печать, должен содержать однотипную шапку и однотипный под- вал, в котором может быть указана итоговая информация по данным, выведенным на этом листе. В этом случае по- сле вывода шапки нужно вывести в табличный документ столько строк, чтобы на текущем печатаемом листе по- местилась еще и область подвала. Для решения подобных задач предназначены методы табличного документа Про- веритьВыводО и ПроверитьПрисоединениеО. Метод ПроверитьВыводО, примененный к результирующе- му табличному документу, позволяет определить, помес- тится ли па одном листе (по высоте) результирующий табличный документ (при текущих настройках печати), если в него вывести документы, переданные в параметре этого метода. Аналогичным образом, метод ПроверитьПрисоединениеО, при- мененный к результирующему табличному документу, позволяет определить, поместится ли на одном листе (по ширине) результирующий табличный документ (при те- кущих настройках печати), если к нему присоединить до- кументы, переданные в параметре этого метода. Параметр этих методов может принимать значения типа ТабличныйДокумент или Массив. Если необходимо проверить добавление/присоединение одного табличного докумен- та, то этот документ и передается в параметре указанных методов. Если необходимо проверить добавление/при- соединение нескольких табличных документов, то в этом случае в параметр метода передается массив, состоящий из добавляемых/присоединяемых документов. Указанные методы возвращают значение типа Булево. Значе- ние Истина говорит о том, что результирующий табличный документ помещается на одну страницу. Значение Ложь го- ворит о том, что документ не поместится на одну страницу. Для примера рассмотрим формирование результирующе- го табличного документа на основе шаблона, в котором определены три области: Шапка, Строка и Подвал (рис. 13.166). Рис. 13.166. Шаблон табличного документа Требуется, чтобы каждая страница результирующего таб- личного документа начиналась с области Шапка, содер- жала некоторое число областей Строка и закапчивалась областью Подвал, причем каждая страница должна быть максимально заполнена данными и не содержать пустых областей внизу страницы. Пример формирования документа по указанным прави- лам показан в листинге 13.187. Листинг 13.187. Пример использования метода ПроверитьВыводО ТабМакет = ПолучитьМакетС’Макет"): ОбластьШапка = ТабМакет.ПолучитьОбластьС'Шапка”); ОбластьСтрока = ТабМакет.ПолучитьОбластьС'Строка”); ОбластьПодвал = ТабМакет.ПолучитьОбласть("Подвал"): // Сформировать массив областей для проверки СтрокаСПодвалом = Новый Массив; СтрокаСПодвалом.Добавить(ОбластьСтрока): СтрокаСПодвалом.Добавить(ОбластьПодвал): ТабДок = Новый ТабличныйДокументО; // заполнение параметров области Шапка ТабДок.Вывести(ОбластьШапка): // Цикл обхода данных, выводимых в результирующий документ Пока Выборка.СледующийО Цикл Если ТабДок.ПроверитьВывод(СТрокаСПодвалом) Тогда ... // заполнение значений параметров области Строка ТабДок.Вывести(ОбластьСтрока); Иначе ... // заполнение значений параметров области Подвал ТабДок.Вывести(ОбластьПодвал); ТабДок. ВывестиГоризонтальныйРазделительСтраницО; ... // заполнение параметров области Шапка ТабДок.Вывести(ОбластьШапка); ... // заполнение параметров области Строка ТабДок.Вывести(ОбластьСтрока); КонецЕсли; КонецЦикла; ... // заполнение параметров области Подвал ТабДок.Вывести(ОбластьПодвал): ТабДок.НапечататьО;
Сначала формируется массив, состоящий из двух облас- тей макета: Строка и Подвал. В цикле вывода области Стро- ка в результирующий табличный документ выполняется проверка, поместится ли результирующий табличный до- кумент на одну страницу, если к нему добавить области Строка и Подвал. В том случае, если документ помещается, выводится область Строка и осуществляется переход к следующему шагу цикла. Если документ не помещает- ся, выводится область Подвал и формируется следующая страница документа: выводится горизонтальный разде- литель страниц, область Шапка и область Строка. Свойства областей и рисунков табличного документа, управляющие печатью Свойства и методы табличного документа, перечислен- ные в предыдущем разделе, необходимо применять непо- средственно к тому документу, который будет напечатан, то есть если результирующий табличный документ фор- мируется на основе макета, то оформлять нужно именно результирующий табличный документ, а не макет или об- ласти макета. Свойства же областей и рисунков табличного документа, управляющие печатью, могут быть применены как к об- ластям/рисункам результирующего табличного документа, так и к областям/рисункам макета или областей макета. При выводе областей макета в результирующий таблич- ный документ значения этих свойств будут сохранены. Рисунки табличного документа имеют свойство Выводить - НаПечать, которое позволяет управлять выводом рисунка табличного документа на печать. Оно принимает значе- ния типа Булево. Если свойство имеет значение Истина (значение по умолчанию для новых рисунков), рисунок будет напечатан. Для рисунков, которые являются примечаниями, управ- ление выводом на печать также осуществляется с помо- щью этого свойства, однако оно будет использоваться только в том случае, если у табличного документа инте- рактивно включен режим отображения примечаний (Таб- лица | Отображать прииечания). В противном случае, незави- симо от значения свойства ВыводитьНаПечать, примечания не будут напечатаны. Область ячеек табличного документа обладает свойством ВнестеСоСледующин, которое позволяет объединять строки или колонки области таким образом, чтобы при разделе- нии на страницы они всегда оказывались на одной стра- нице. Следует учитывать, что это свойство применимо только к областям строк или областям колонок. По умол- чанию свойство имеет значение Ложь; для того чтобы объе- динение было выполнено, его необходимо установить в значение Истина. Также область ячеек табличного документа имеет свойст- ва КонецСтраницы и НачалоСтраницы. Эти свойства прини- мают значения типа Булево и применимы только для об- ластей строк/колонок. Значение свойства КонецСтраницы равное Истина, говорит о том, что данная область является последней на странице. Значение свойства НачалоСтраницы, равное Истина, говорит о том, что данную область необходимо выводить с повой страницы. Сводная таблица Табличный документ может содержать сводные таблицы, которые позволяют программно и интерактивно пред- ставлять многомерные данные в удобном для анализа виде (рис. 13.167). Рис. 13.167. Сводная таблица Коллекция сводных таблиц, содержащихся в табличном документе, доступна через свойство ВстроенныеТаблицы таб- личного документа. Элементами этой коллекции являют- ся объекты СводнаяТаблица, каждый из которых описывает одну сводную таблицу. Добавление сводной таблицы в табличный документ может быть выполнено интерактивно или средствами встро- енного языка, с помощью метода Добавить () коллекции встроенных таблиц табличного документа. В этот метод обязательно передается тип создаваемой таблицы, при- чем это может быть только единственный тип Сводная- Таблица. Также вторым параметром в метод может быть передана область табличного документа, которая будет использована для расположения сводной таблицы (лис- тинг 13.188). Эта область необходима лишь для того, чтобы определить, где будет располагаться левый верх- ний угол сводной таблицы, поэтому в качестве области достаточно передать одну ячейку табличного документа (рис. 13.168). Листинг 13.188. Пример добавления сводной таблицы в табличный документ ТабДок = Новый ТабличныйДокунент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.0бласть(2, 2)); ТабДок.ПоказатьО; Рис. 13.168. Добавление сводной таблицы в табличный документ Добавляемые сводные таблицы получают имена по умол- чанию. Первая таблица получает имя СводнаяТаблица1, вторая — СводнаяТаблица2 и т. д.
Обращение к сводным таблицам, расположенным в таб- личном документе, возможно по имени. Разработчик мо- жет использовать имя по умолчанию или присвоить таб- лице собственное имя. Для этого используется свойство сводной таблицы Имя. Логически сводная таблица представляет собой совокуп- ность строк и колонок, на пересечении которых отобра- жаются данные, соответствующие указанным значениям строки и колонки (рис. 13.169). Рис. 13.169. Элементы сводной таблицы Источником данных, отображаемых сводной таблицей, может служить либо результат запроса, либо построитель отчета. Для установки источника данных используется свойство сводной таблицы ИсточникДанных (листинг 13.189). Листинг 13.189. Пример установки источника данных сводной таблицы Построитель = Новый ПостроительОтчетаО; Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Код КАК КодСклада, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУММАСТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММА(КоличествоПриход), СУММА(КоличествоОборот), СУММА(КоличествоРасход) ПО ОБЩИЕ. Номенклатура ИЕРАРХИЯ, Склад Иерархия": Построитель.ЗаполнитьНастройкиС); ТабДок = Новый Табличныйдокумент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.0бласть(2, 2)); Таблица.ИсточникДанных = Построитель; После того как источник данных установлен, следует оп- ределить поля, которые будут содержаться в строках, ко- лонках и данных сводной таблицы. Все поля, которые доступны для выбора в строки колон- ки или данные сводной таблицы, содержатся в коллекции полей сводной таблицы, доступной через свойство Поля. Эта коллекция заполняется автоматически, при назначе- нии источника данных сводной таблицы. Как программ- ное, так и интерактивное добавление полей в строки/ко- лонки и данные сводной таблицы будет определяться свойствами, установленными для каждого из полей в этой коллекции. В коллекцию полей сводной таблицы включаются поля источника данных, являющиеся измерениями и ресурса- ми. Каждое поле сводной таблицы обладает свойствами Измерение и Ресурс, которые устанавливаются в значение Истина, если соответственно поле является измерением или ресурсом. Например, для запроса, приведенного в листинге 13.189, будет сформирована следующая коллекция полей свод- ной таблицы (табл. 13.19). Таблица 13.19. Пример полей сводной таблицы Имя поля Измерение Ресурс КоличествоОборот Ложь Истина КоличествоПриход Ложь Истина КоличествоРасход Ложь Истина Номенклатура Истина Ложь Склад Истина Ложь Поля, у которых свойство Измерение имеет значение Исти- на, могут быть добавлены в строки или колонки сводной таблицы. Поля, у которых свойство Ресурс имеет значе- ние Истина, могут быть добавлены в данные сводной таб- лицы. Кроме свойств Имя, Измерение и Ресурс каждое поле сводной таблицы содержит свойство ТипЗначения, которое описы- вает тип значений, которые содержит данное поле, а так- же свойство Реквизиты. Свойство Реквизиты имеет смысл только для полей, яв- ляющихся измерениями, и содержит коллекцию полей сводной таблицы, которые описывают все поля, которые могут быть получены «через точку» от данного поля. Вы- деление реквизитов измерений в отдельную коллекцию позволяет использовать различные способы отображения данных, то есть реквизит измерения может быть отобра- жен и как реквизит, и как отдельное измерение. Поля сводной таблицы При интерактивном редактировании сводной таблицы состав коллекции полей сводной таблицы, содержащейся в свойстве Поля, отображается в окне полей сводной таб- лицы (рис. 13.170), которое может быть открыто средст- вами встроенного языка. Для этого нужно установить свойство ОтображатьПоля сводной таблицы в значение Исти- на (листинг 13.190).
Рис 13.170. Окно полей сводной таблицы Листинг 13.190. Пример отображения окна полей сводной таблицы Построитель = Новый ПостроительОтчетаО: Построитель.Текст = // си. листинг 13.191 Построитель.ЗаполнитьНастройкиО; ТабДок = Новый ТабличныйДокунент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.0бласть(2, 2)): Таблица.ИсточникДанных = Построитель; Таблица.ОтображатьПоля = Истина; ТабДок.ПоказатьО; Сводная таблица различным образом заполняет коллек- цию полей в свойстве Поля при использовании в качестве источника данных результата запроса и построителя от- чета. Если в качестве источника данных используется резуль- тат запроса, то в поля сводной таблицы будут добавлены измерения и ресурсы из результата запроса, а также рек- визиты измерений, если они присутствуют в выбранных полях запроса (листинг 13.191). При этом для интер- активного и программного добавления будут доступны только сами добавленные поля, а реквизиты измерений будут доступны для добавления только в качестве рекви- зитов (рис. 13.171). Листинг 13.191. Пример формирования полей сводной таблицы, когда в качестве источника данных используется результат запроса Запрос = Новый Запрос: Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Код КАК КодСклада, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад. ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММА(КоличествоПриход). СУММА(КоличествоОборот). СУММА(КоличествоРасход) ПО ОБЩИЕ, Номенклатура Иерархия. Склад Иерархия" ТабДок = Новый ТабличныйДокунент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.0бласть(2, 2)); Таблица.ИсточникДанных = Запрос.ВыполнитьО; Таблица.ОтображатьПоля = Истина; ТабДок.ПоказатьО; Рис. 13.171. Поля сводной таблицы Если в качестве источника данных используется построи- тель отчета, то в поля сводной таблицы будут добавлены измерения и ресурсы построителя отчета (листинг 13.192). При этом если измерение иерархическое, то для него будет предоставлена возможность выбора всех подчиненных по- лей в измерения, а также возможность выбора всех подчи- ненных полей в качестве реквизитов этого измерения. Так- же будут предоставлены варианты выбора этого измерения без иерархии и выбора только иерархии (рис. 13.172). Листинг 13.192. Пример формирования полей сводной таблицы, когда в качестве источника данных используется построитель отчета Построитель = Новый ПостроительОтчетаО; Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Код КАК КодСклада, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, | ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, | ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММАСТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУШАСТоварыНаСкладахОстаткиИОбороты. КоличествоОборот) КАК КоличествоОборот,
СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММА(КоличествоПриход), СУММА(КоличествоОборот). СУММА(КоличествоРасход) ПО ОБЩИЕ, Номенклатура Иерархия, Склад Иерархия" Построитель.ЗаполнитьНастройки(); ТабДок = Новый ТабличныйДокумент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.Область(2. 2)); Таблица.ИсточникДанных = Построитель; Таблица.ОтображатьПоля = Истина; ТабДок.ПоказатьО; Поля сводной таблицы X □ L. Склад - Ц. (Без иерархии) (Только иерархия) ....t , Пометка удаления L. г^е допре де В Ц. Родитель -1 , Это группа г- Ц. Код г-Ц Наименование Е- Ц. Тип цен розничной торговли Ё Ц. Подразделение Е Ц. Вид склада \ i....Ц. Номер секции : Ц. Расчет розничных цен по торговой наценке = Й- я Реквизиты • — ПометкаУдаления ....— Предопределенный Е — Родитель ; —— ЭтоГруппа | — Код = .... — Наименование ....— Комментарий Е- — ТипЦенРозничнойТорговли В- — Подразделение \ Е — ВидСклада - — НомерСекции — РасчетРозничныхЦенПоТорговойНаценке КоличествоПриход I—В КоличествоОборот - В КоличествоРасход Поместить в строки | Рис. 13.172. Поля сводной таблицы Коллекция полей сводной таблицы, содержащаяся в свой- стве Поля, не может быть модифицирована средствами встроенного языка. Поэтому разработчик не имеет воз- можности каким-либо образом ограничивать пользовате- ля в использовании полей сводной таблицы, которые соз- даются при назначении источника данных. Отсюда следует вывод, что в случае, когда требуется соз- дание несложной сводной таблицы, для которой заранее известен состав полей, предпочтительнее использовать запрос в качестве источника данных. Если же нужно пре- доставить пользователю максимум возможностей по самостоятельному формированию сводной таблицы, следует использовать в качестве источника данных построитель отчета. В этом случае, к тому же, при изменении состава из- мерений текст запроса, содержащийся в построителе отче- та, будет сформирован и выполнен заново. Если источник данных — результат запроса, то изменение состава измере- ний сводной таблице не будет приводить к повторному вы- полнению запроса. В отличие от построителя отчета ре- зультат запроса является статическим источником данных. Строки, колонки и данные сводной таблицы Для того чтобы сводная таблица отобразила какие-либо данные, назначения источника данных недостаточно. Не- обходимо еще указать, какие поля сводной таблицы бу- дут находиться в строках, колонках и данных сводной таблицы. Это может быть выполнено как интерактивны- ми средствами (путем перетаскивания полей из окна по- лей сводной таблицы в соответствующие области свод- ной таблицы), так и средствами встроенного языка. Сводная таблица содержит три свойства, которые описыва- ют расположение полей: Строки, Колонки и Данные. Каждое из этих свойств, так же как и свойство Поля, является коллекци- ей полей сводной таблицы. Для добавления полей в коллек- цию используется метод ДобавитьО (листинг 13.193). При этом следует учитывать, что добавление полей в строки/колонки и данные сводной таблицы ведет к перерисовке таблицы. Поэтому для ускорения процесса добавления полей можно на то время, пока выполняется добавление, выключать об- новление сводной таблицы (свойство Обновление устанавли- вается в значение Ложь). После того как все необходимые поля будут добавлены, можно снова включить автоматиче- ское обновление сводной таблицы. При этом таблица будет перерисована один раз, в соответствии с последним со- ставом полей в строках/колонках и данных (рис. 13.173). ПРИМЕЧАНИЕ При необходимости обновление сводной таблицы может быть выполнено принудительно с помощью метода Обно- вить О сводной таблицы. Листинг 13.193. Пример добавления полей сводной таблицы в строки/колонки и данные Построитель = Новый ПостроительОтчетаО; Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Код КАК КодСклада, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУММАСТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура. ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление
ft; Таблица _ О X 1 2 3 4 5 6 7 В 68 1 п 2 Склад Данные 3 Оптовые склады Розничные склады Ко личест воПриход КоличествоРасход 4 Номенклатура Количество! Количество₽ Ко личест в оГ| Ко личест в of ! 5 Тара 30, 30 6 Инвентарь 50 25 50 25 7 Обувь 3 705 186 2150 5 855 186 8 Бытовая техника 3 478 210 951 3 573 210 9 Продукты 90' 35 3 645 104 3 735 139' 10 Сборка компьютеров 225 17 225 17 11 Итог 7 528 448 5 940 129 13 468 577 12 1Q SC2 Рис. 13.173. Сводная таблица |ИТ0ГИ СУММА(КоличествоПриход). СУММА(КоличествоОборот), СУММА(КоличествоРасход) ПО ОБЩИЕ. | Номенклатура Иерархия, Склад Иерархия" Построитель.ЗаполнитьНастройки(); ТабДок = Новый Табличныйдокумент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.0бласть(2. 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Таблица.Строки.Добавить("Номенклатура"); Таблица.Колонки.Добавить("Склад"); Таблица.Данные.ДобавитьС"КоличествоПриход"): Таблица.Данные.Добавить("КоличествоРасход"); Таблица.Обновление = Истина; ТабДок.Показать(); Иерархия измерений Сводная таблица предоставляет возможность разворачи- вать иерархию измерений, которые выведены в строки или колонки таблицы. Это возможно в том случае, если измерения иерархические и были выведены в сводную таблицу с помощью построителя отчета или с помощью запроса, содержащего итоги по иерархии. Разворачивание уровней иерархии возможно как инте- рактивно, так и программно. Интерактивно оно выполня- ется двойным щелчком на заголовке строки или колонки таблицы. Для программного управления разворачива- нием уровней иерархии используется свойство Количест- воОткрытыхУровней поля сводной таблицы. Если свойство КоличествоОткрытыхУровней поля имеет зна- чение 0, это означает, что поле не добавлено ни в строки, ни в колонки сводной таблицы. После того как поле до- бавляется в строки/колонки таблицы, значение его свой- ства КоличествоОткрытыхУровней автоматически устанавли- вается равным 1 (см. рис. 13.173). Разработчик может Рис. 13.174. Сводная таблица
задать другое значение этого свойства, например, чтобы раскрыть все уровни иерархии измерения (рис. 13.174). Для определения максимального количества уровней иерархии измерения используется метод поля сводной таблицы КоличествоУровней() (листинг 13.194). Листинг 13.194. Пример указания количества открытых уровней Построитель = Новый ПостроительОтчетаО; Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Код КАК КодСклада, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура. ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление, СУММАСТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУММАСТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот, СУММАСТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Номенклатура. ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Номенклатура.Представление ИТОГИ СУММА(КоличествоПриход), СУММА(КоличествоОборот), СУММА(КоличествоРасход) ПО ОБЩИЕ. Номенклатура Иерархия, Склад Иерархия" Построитель.ЗаполнитьНастройки(); ТабДок = Новый ТабличныйДокунент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.Область(2, 2)); Таблица.ИсточникДанных = Построитель: Таблица.Обновление = Ложь: Таблица. Строки. Добавить (“Номенклатура"); Таблица.Колонки.Добавить("Склад"); Таблица.Данные.Добавить("КоличествоПриход"); Таблица.Строки.Номенклатура.КоличествоОткрытыхУровней = Таблица.Строки.Номенклатура.КоличествоУровней(); Таблица.Обновление = Истина; ТабДок.ПоказатьО; Следует учитывать, что изменение свойства Количество- ОткрытыхУровней влияет не только на вид отображения дан- ных поля сводной таблицы, но и на сам факт нахождения поля в коллекции строк/колонок. Например, если для поля Номенклатура значение этого свойства изменяется с 0 на какое-либо корректное значение (листинг 13.195), то поле Номенклатура будет автоматически включено в коллекцию строк сводной таблицы (рис. 13.175). Листинг 13.195. Изменение количества открытых уровней поля Построитель = Новый ПостроительОтчетаО; Построитель. Текст = И см. листинг 13.194 Построитель.ЗаполнитьНастройки(); ТабДок = Новый ТабличныйДокунент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.Область(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Таблица.Поля.Номенклатура.КоличествоОткрытыхУровней = 2; Таблица.Колонки.Добавить("Склад"); Табли ца.Дан ные.Добав и т ь("Количест воПриход"); Таблица.Обновление = Истина; ТабДок.ПоказатьО; Рис. 13.175. Сводная таблица
Если поле сводной таблицы включено в состав строк/ ко- лонок и для его свойства КоличествоОткрытыхУровней уста- навливается значение 0, то это поле будет автоматически удалено из коллекции строк/колонок. Если выполняется попытка установить некорректное зна- чение количества открытых уровней поля, то будет уста- новлено ближайшее корректное значение: 0 или возвра- щаемое методом КоличествоУровнейО. Оформление сводной таблицы Сводная таблица может быть оформлена на основе маке- та оформления. Для этого используется свойство свод- ной таблицы МакетОфорнления. Это свойство принимает значения типа Табличныйдокумент или СтандартноеОфориление. Таким образом разработчик может использовать для оформления сводной таблицы как стандартные оформле- ния, поддерживаемые платформой, так и собственные ма- кеты оформления (более подробно про работу с макетами оформления рассказано в разделе «Макет оформления и оформление», с. 434). Например, для оформления сводной таблицы (рис. 13.176) может быть использовано стандартное оформление Лед (листинг 13.196). Сводная таблица содержит целый ряд свойств, которые позволяют разработчику средствами встроенного языка управлять внешним видом сводной таблицы. Листинг 13.196. Использование оформления сводной таблицы Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // см. листинг 13.194 Построитель.ЗаполнитьНастройки(); ТабДок = Новый Табличныйдокумент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"). ТабДок.0бласть(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Таблица. Строки. ДобавитьС "Номенклатура"); Таблица.Колонки.Добавить("Склад"); Таблица.Данные.Добавить("КоличествоПриход"); Таблица.МакетОформления = СтандартноеОфориление.Лед; Таблица.Обновление = Истина: ТабДок.ПоказатьО; Прежде всего, это свойство АвтоФиксация, которое позво- ляет фиксировать заголовки строк и колонок сводной таблицы таким образом, что при прокрутке они остаются на месте, а прокручивается только область данных. По умолчанию автофиксация выключена (АвтоФиксация = Ложь). Свойство ОтображатьЛинии позволяет управлять отображе- нием линий в области данных сводной таблицы. Это свойство принимает значения системного перечисления ТипОтображенияЛинийСводнойТаблицы и по умолчанию имеет значение Авто, что означает автоматическое определение необходимости отображения линий. Другое значение этого перечисления — Всегда - означает, что линии в об- ласти данных будут отображаться всегда. Свойство ОтображатьПодписиИтогов позволяет вывести ря- дом с представлением значения итоговой записи строки или колонки слово «Итог» (рис. 13.177). По умолчанию отображение подписей итогов выключено (ОтображатьПод- писиИтогов = Ложь). Свойства ПоложениеИтоговСтрок и ПоложениеИтоговКолонок по- зволяют указывать местоположение итоговых записей в строках и колонках сводной таблицы при развернутой иерархии. Свойство ПоложениеИтоговСтрок принимает значения сис- темного перечисления ПоложениеИтоговСтрокСводнойТаблицы и может принимать два значения: Верх или Низ. По умол- чанию устанавливается значение Верх (см. рис. 13.176). Если свойству установить значение Низ (листинг 13.197), то итоговые записи будут располагаться внизу группи- ровки (рис. 13.178). Листинг 13.197. Установка положения итогов строк Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // см. листинг 13.194 Построитель. ЗаполнитьНастройкиО; Рис. 13.176. Стандартное оформление Лед
Рис. 13.178. Положение итогов строк сводной таблицы ТабДок = Новый ТабличныйДокумент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.0бласть(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Таблица.Строки.ДобавитьС"Номенклатура"); Таблица.Колонки.ДобавитьС"Склад"); Таблица.Данные.ДобавитьС"КоличествоПриход"); Таблица.МакетОформления = СтандартноеОформление.Лед; Таблица.ПоложениеИтоговСтрок = ПоложениеИтоговСтрокСводнойТ аблицы.Низ; Таблица.Обновление = Истина; ТабДок.ПоказатьО; Свойство ПоложениеИтоговКолонок принимает значения сис- темного перечисления ПоложениеИтоговКолонокСводнойТабли- цы и может принимать два значения: Лево или Право. По умолчанию устанавливается значение Лево. Свойства РазмещениеИзмеренийВСтроках и РазмещениеИзмере- нийВКолонках позволяют выбирать варианты совместного отображения нескольких измерений в строках или не- скольких измерений в колонках. Они принимают значе- ния системного перечисления ТипРазмещенияИзмерений. Для сводной таблицы использование этого системного пере- числения имеет особенность, заключающуюся в том, что значения Отдельно и ОтдельноИТолькоВИтогах вызывают оди- наковое отображение сводной таблицы, как при значении ОтдельноИТолькоВИтогах. По умолчанию устанавливается значение Отдельно (лис- тинг 13.198), это означает, что каждое из измерений будет расположено, например, в отдельной колонке заголовка строк (рис. 13.179). Листинг 13.198. Пример размещения измерений отдельно Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // см. листинг 13.194 Построитель.ЗаполнитьНастройки(); ТабДок = Новый ТабличныйДокумент; Таблица « ТабДок.ВстроенныеТаблицы. Добавить(ТипС"СводнаяТаблица"), ТабДок.0бласть(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь;
Таблица.Строки.ДобавитьС"Склад"): Таблица.Строки.Добавить("Ноиенклатура"): Таблица.Данные.ДобавитьС"КоличествоПриход"); Таблица.МакетОформления = СтандартноеОфориление.Лед; Таблица.Обновление = Истина; ТабДок.ПоказатьО; Рис 13.179. Размещение измерений отдельно Если установлено значение Вместе (листинг 13.199), то все измерения будут расположены, например, в одной ко- лонке заголовка строк (рис. 13.180). Рис 13.180. Размещение измерений вместе Листинг 13.199. Пример размещения измерений вместе Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // см. листинг 13.194 Построитель. ЗаполнитьНастройки О; ТабДок = Новый ТабличныйДокунент; Таблица = ТабДок. ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.0бласть(2, 2)): Таблица. ИсточникДанных = Построитель: Таблица. Обновление = Ложь; Таблица. Строки. ДобавитьС "Склад”); Таблица. Строки. ДобавитьС "Номенклатура"): Таблица.Данные. ДобавитьС "КоличествоПриход”): Таблица. РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Таблица.МакетОформления = СтандартноеОформление.Лед; Таблица. Обновление = Истина; ТабДок.ПоказатьО: Управление отображением реквизитов измерений Как уже говорилось выше, реквизиты измерений (поля «через точку» от измерений) могут быть выведены в свод- ной таблице как отдельные измерения, или как реквизи- ты некоторого измерения. Для вывода реквизита (например, поля Код) как отдельного измерения (рис. 13.181) он должен быть добавлен в коллек- цию строк/колонок сводной таблицы (листинг 13.200). Листинг 13.200. Пример вывода реквизита как отдельного измерения Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // см. листинг 13.194 Построитель.ЗаполнитьНастройки(); ТабДок = Новый ТабличныйДокунент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.0бласть(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Таблица.Строки.Добавить("Номенклатура"): Таблица.Строки.ДобавитьС"Номенклатура.Код"); Таблица.Колонки.ДобавитьС"Склад"): Т аблица.Данные.ДобавитьС"КоличествоПриход"); Таблица.МакетОформления « СтандартноеОформление.Лед; Таблица.Обновление = Истина; ТабДок.ПоказатьО; В этом случае отображение измерения и его реквизита будет определяться свойствами РазмещениеИзмеренийВСтро- ках (РазмещениеИзмеренийВКолонках). Для того чтобы вывести реквизит именно как реквизит измерения (рис. 13.182), необходимо добавлять его в кол- лекцию реквизитов сводной таблицы (листинг 13.201). Коллекция реквизитов доступна через свойство Реквизиты сводной таблицы и также является коллекцией полей сводной таблицы. Обратите внимание, что коллекция реквизитов — одна. В нее добавляются как реквизиты измерений строк, так и реквизиты измерений колонок (листинг 13.202). Сводная таблица в состоянии самостоятельно опреде- лить, «чьим» реквизитом является то или иное поле (рис. 13.183). В случае когда реквизиты добавляются в коллекцию рек- визитов сводной таблицы, за совместное отображение изме- рений и реквизитов в строках/колонках сводной таблицы отвечают свойства РазмещениеРеквизитовИзмеренийВСтроках и РазмещениеРеквизитовИзмеренийВКолонках. Эти свойства прини- мают значение системного перечисления ТипРазмещенияРек- визитовИзмерений. По умолчанию эти свойства имеют зна- чение Отдельно (листинг 13.203), это говорит о том, что реквизиты будут отображены отдельно от измерений, при- чем каждый реквизит в собственной колонке, например, за- головка строк (рис. 13.184).
Рис. 13.181. Вывод реквизита как измерения Рис. 13.182. Вывод реквизита измерения Листинг 13.201. Пример вывода реквизита измерения Построитель = Новый ПостроительОтчетаО: Построитель.Текст = // см. листинг 13.194 Построитель.ЗаполнитьНастройкиС); ТабДок = Новый Табличныйдокумент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.0бласть(2, 2)): Таблица.ИсточникДанных = Построитель: Таблица.Обновление = Ложь: Таблица.Строки.ДобавитьС"Номенклатура"): Таблица.Реквизиты.ДобавитьС"Номенклатура.Код"); Таблица.Колонки.ДобавитьС"Склад"): Таблица.Данные.ДобавитьС"КоличествоПриход"); Таблица.МакетОформления = СтандартноеОформление.Лед: Таблица.Обновление = Истина; ТабДок. ПоказатьО:
Таблица _ □ X Рис. 13.183. Вывод реквизитов измерений Листинг 13.202. Пример вывода реквизитов измерений Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // сн. листинг 13.194 Таблица.Данные.Добавить("КоличествоПриход"); Таблица.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Таблица.МакетОформления = СтандартноеОформление.Лед: Таблица.Обновление = Истина; Построитель.ЗаполнитьНастройки(); ТабДок = Новый ТабличныйДокумент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.Область(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Т аблица.Строки.Добавить("Номенклатура"); Таблица.Колонки.Добавить("Склад"): Таблица.Реквизиты .Добавить("Номенклатура.Код"); Таблица.Реквизиты.Добавить("Склад.Код"): Таблица.Данные.ДобавитьС"КоличествоПриход"); Таблица.МакетОформления = СтандартноеОформление.Лед; Таблица.Обновление = Истина: ТабДок.ПоказатьО; Листинг 13.203. Пример размещения реквизитов измерений отдельно Построитель = Новый ПостроительОтчетаО; Построитель.Текст = И см. листинг 13.194 Построитель. ЗаполнитьНастройки О; ТабДок = Новый ТабличныйДокумент: Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.Область(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь: Таблица. Строки. Добавить ("Склад"); Таблица.Строки .ДобавитьС "Номенклатура"); Таблица. Реквизиты .Добавить ("Номенклатура .Код ”); Таблица.Реквизиты. Добавить ("Склад.Код"); ТабДок.ПоказатьО; Рис. 13.184. Размещение реквизитов измерений отдельно Если указывается значение Вместе (листинг 13.204), то это означает, что реквизиты будут размещены отдельно от измерений, но в одной колонке (рис. 13.185), напри- мер, заголовка строк (при условии, что сами измерения располагаются вместе; если измерения располагаются отдельно, то и реквизиты будут расположены отдель- но). Листинг 13.204. Пример размещения реквизитов вместе Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // см. листинг 13.194
Построитель .ЗаполнитьНастройкиО; ТабДок = Новый ТабличныйДокунент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"). ТабДок.0бласть(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Таблица.Строки.ДобавитьС"Склад"); Таблица. Строки .Добавить ("Номенклатура''); Т аблица.Реквизиты.ДобавитьС"Ноненклатура.Код"); Т аблица.Реквизиты.ДобавитьС"Склад.Код"); Таблица.Данные.Добавить("КоличествоПриход"); Таблица.РазмещениеИзмеренийВСтроках = ТипРазмещенияИзмерений.Вместе; Таблица.РазмещениеРеквизитовИзмеренийВСтроках = ТипРазмещенияРеквизитовИзмерений.Вместе; Таблица.МакетОформления = СтандартноеОформление.Лед: Таблица.Обновление = Истина; ТабДок.ПоказатьО; Рис. 13.185. Размещение реквизитов вместе Если указывается значение ВместеСИзмерениями, (лис- тинг 13.205) то это означает, что реквизиты будут разме- щены в тех же колонках, что и соответствующие им изме- рения (рис. 13.186). Листинг 13.205. Пример размещения реквизитов вместе с измерениями Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // см. листинг 13.194 Построитель .ЗаполнитьНастройкиО; ТабДок = Новый ТабличныйДокунент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"). ТабДок.0бласть(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Т аблица.Строки.Добавить("Номенклатура"): Таблица.Колонки.ДобавитьС"Склад"); Таблица.Реквизиты.Добавить("Номенклатура.Код"); Таблица.Реквизиты.Добавить("Склад.Код"); Таблица.Данные.Добав и т ь("Коли чест воПриход"); Таблица.РазмещениеРеквизитовИзмеренийВСтроках = ТипРазмещенияРеквизитовИзмерений. ВместеСИзмерениями; Таблица.РазмещениеРеквизитовИзмеренийВКолонках = ТипРазмещенияРеквизитовИзмерекий. ВместеСИз мерения ми; Таблица.МакетОформления = СтандартноеОформление.Лед; Таблица.Обновление = Истина: ТабДок.ПоказатьО; Управление отображением ресурсов Как уже говорилось, коллекция полей сводной таблицы, содержащаяся в свойстве Поля таблицы, описывает прави- ла, по которым те или иные поля могут быть добавлены в строки/колонки и данные сводной таблицы. Однако сводная таблица позволяет добавлять в строки/колонки Рис. 13.186. Размещение реквизитов вместе с измерениями
Рис. 13.187. Вывод нескольких ресурсов Рис. 13.188. Добавление данных в строки сводной таблицы не только поля, но и коллекции полей сводной таблицы, а точнее коллекцию полей данных. Рассмотрим следующую ситуацию. Допустим, в сводную таблицу выводится три ресурса (листинг 13.206). В этом случае «чтение» такой таблицы может быть неудобным для пользователя (рис. 13.187), особенно если он начнет разворачивать иерархию складов — таблица станет слиш- ком широкой. Так происходит потому, что по умолчанию ресурсы свод- ной таблицы выводятся в области данных в одну строку по горизонтали. Очевидно, что в этом случае более пред- почтительным был бы вывод ресурсов не в одной строке, а в одной колонке, друг под другом. Для того чтобы создать такое отображение данных (рис. 13.188), используется добавление коллекции полей данных сводной таблицы в коллекцию строк таблицы (листинг 13.207). Коллекция полей данных сводной таблицы может быть единственным элементом коллекции строк сводной таб- лицы (листинг 13.208). В этом случае таблица будет со- держать итоговые значения ресурсов по значениям изме- рений, выведенных в колонках таблицы (рис. 13.189).
Рис. 13.189. Сводная таблица Листинг 13.206. Вывод нескольких ресурсов в сводную таблицу Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // си. листинг 13.194 Листинг 13.208. Пример вывода только данных в строки сводной таблицы Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // см. листинг 13.194 Построитель.ЗаполнитьНастройки(); ТабДок = Новый ТабличныйДокумент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тил("СводнаяТаблица"). ТабДок.Область(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Таблица.Строки.Добавить("Номенклатура”); Т аблица.Колонки.ДобавитьС"Склад"); Таблица.Данные.Добавить("КоличествоПриход"); Таблица.Данные.Добавить("КоличествоОборот"); Таблица.Данные.Добавить("КоличествоРасход"); Таблица.МакетОформления = СтандартноеОформление.Лед; Таблица.Обновление = Истина; ТабДок.ПоказатьО: Листинг 13.207. Добавление данных в строки сводной таблицы Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // см. листинг 13.194 Построитель.ЗаполнитьНастройки(); ТабДок = Новый ТабличныйДокумент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"). ТабДок.Область(2. 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Табли ца.Строки.Добавит ь("Номенклатура"); Таблица.Колонки.Добавить("Склад"); Таблица.Данные.Добавить("КоличествоПриход"); Таблица.Данные.ДобавитьС"КоличествоОборот"); Таблица.Данные.ДобавитьС"КоличествоРасход"); Таблица.Строки.Добавить(Таблица.Данные): Таблица.МакетОформления = СтандартноеОформление.Лед; Таблица.Обновление = Истина: ТабДок.ПоказатьО; Построитель.ЗаполнитьНастройки(); ТабДок = Новый ТабличныйДокумент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"). ТабДок.0бласть(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Таблица.Колонки.Добавить("Склад"): Т аблица.Данные.ДобавитьС"КоличествоПриход"): Т аблица.Данные.Добавить("КоличествоОборот"): Т аблица.Данные.Добавить("КоличествоРасход"); Таблица.Строки.Добавить СТаблица.Данные); Таблица.МакетОформления = СтандартноеОформление.Лед; Таблица.Обновление = Истина; ТабДок.ПоказатьО; Оформление областей сводной таблицы Для оформления сводной таблицы, помимо шаблонов, можно использовать непосредственный доступ к облас- тям заголовков строк, колонок и к области данных. Для этого используются свойства сводной таблицы ОбластьЗа- головковСтрок, ОбластьЗаголовковКолонок и ОбластьДанных. Эти свойства возвращают значения типа ОбластьЯчеекТаблично- гоДокумента, к которым может быть применено оформле- ние, описанное в разделе «Оформление областей», с. 477. Пример оформления сводной таблицы приведен в лис- тинге 13.209, а на рис. 13.190 показан результат этого оформления. Листинг 13.209. Пример оформления областей заголовков строк/колонок и области данных Построитель = Новый ПостроительОтчетаО; Построитель.Текст = // см. листинг 13.194 Построитель.ЗаполнитьНастройкиО;
ТабДок = Новый ТабличныйДокунент; Таблица = ТабДок.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ТабДок.0бласть(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Таблица.Строки.Добавить("Ноненклатура"); Таблица.Колонки.Добавить("Склад"); Таблица.Данные.Добавить("КоличествоПриход"); ШрифтНаклонный = Новый Шрифт( , , , Истина); ЗаголовкиИолонок = Таблица.ОбластьЗаголовковКолонок; ЗаголовкиКолонок ЦветФона = ИеЬЦвета.Пшеничный: ЗаголовкиИолонок.Шрифт = ШрифтНаклонный; ЗаголовкиСтрок = Таблица.ОбластьЗаголовковСтрок; ЗаголовкиСтрок.ЦветФона = ИеЬЦвета.Пшеничный; ЗаголовкиСтрок.Шрифт = ШрифтНаклонный; Таблица.ОбластьДанных.ЦветФона = ИеЬЦвета.СветлоЖелтый; Таблица.Обновление = Истина; ТабДок.ПоказатьО; Рис 13.190. Пример оформления областей заголовков строк/колонок и области данных Использование табличного документа в форме Табличный документ располагается в форме с помощью элемента управления ПолеТабличногоДокумента При этом к функциональности табличного документа, которая была описана выше, добавляются возможности, связанные с наличием контекста формы и модуля формы ♦ использование элементов управления в табличном до- кументе; ♦ обработка событий, возникающих при манипулирова- нии табличным документом, в частности: обработка расшифровки; обработка нажатий в табличном документе. Элемент управления ПолеТабличногоДокумента содержит в се- бе табличный документ которым он управляет, причем контекст табличного документа дополняет контекст поля табличного документа. Поэтому к свойствам и методам табличного документа можно обращаться как к свойст- вам и методам поля табличного документа. Например, для того, чтобы сформировать итоговый таб- личный документ в форме на основании макета (рис. 13.191), следует обращаться к соответствующим свойствам и ме- тодам поля табличного документа (листинг 13.210). Листинг 13.210 Пример формирования табличного документа в форме Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладахОбороты.Склад КАК Склад, ТоварыНаСкладахОбороты.Склад.Представление КАК СкладПредставление, ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура. ТоварыНаСкладахОбороты.Номенклатура.Представление КАК НоменклатураПредставление, СУММА(ТоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты КАК ТоварыНаСкладахОбороты СГРУППИРОВАТЬ ПО Т оварыНаСклад ахОбороты.Склад, ТоварыНаСкладахОбороты.Ноненклатура ИТОГИ СУММА(КоличествоРасход) ПО Склад, Ноненклатура Выборка = Запрос ВыполнитьО.Выбрать(ОбходРезультатаЗапроса. ПоГруппировкам), ТабМакет = ПолучитьМакет("Макет"); ОбластьСклад = ТабМакет.ПолучитьОбласть("Склад"); ОбластьНоменклатура = ТабМакет.ПолучитьОбласть("Ноненклатура"); ЭленентыФорны.ПолеТабличногоДокумента. НачатьАвтогруппировкуСтрокО, Пока Выборка СледующийО Цикл ОбластьСклад.Параметры.Заполнить( Выборка); // Установить расшифровку поля Склад группировки Склад ОбластьСклад.Параметры.РасшифровкаСклада = Выборка.Склад; ЭлементыФормы.ПолеТабличногоДокумента.Вывести(ОбластьСклад, Выборка.УровеньО); ВыборкаНоменклатура = Выборка. Выбрать(ОбходРезультатаЗапроса.ПоГ руппировкан); Пока ВыборкаНоменклатура.Следующий() Цикл ОбластьНоменклатура.Параметры. Заполнить(ВыборкаНоменклатура); И Установить расшифровку полей Склад и Номенклатура // группировки Номенклатура ОбластьНоменклатура.Параметры.РасшифровкаСклада = ВыборкаНоменклатура.Склад; ОбластьНоменклатура.Параметры.РасшифровкаНоненклатуры = ВыборкаНоменклатура.Номенклатура; ЭлементыФормы.ПолеТабличногоДокумента. Вывести(ОбластьНоменклатура, ВыборкаНоменклатура.Уровень()); КонецЦикла; КонецЦикла: ЭлементыФормы ПолеТабличногоДокумента. ЗакончитьАвтогруппировкуСтрокО; // Установить режим просмотра документа ЭлементыФормы.ПолеТабличногоДокумента.ТолькоПросмотр = Истина: Для того чтобы открыть табличный документ, содержа- щийся в форме, в отдельном окне, нужно вывести его в новый табличный документ, а затем показать этот доку- мент (листинг 13.211).
Рис. 13.191. Формирование табличного документа в форме Листинг 13.211. Показ табличного документа, содержащегося в форме, в отдельном окне ТабДок = Новый ТабличныйДокумент; ТабДок.Вывести(ЭлементыФормы.ПолеТабличногоДокумента); ТабДок.ПоказатьО; Использование события ПриАктивизацииОбласти Поле табличного документа обладает рядом событий, ко- торые могут быть обработаны в обработчиках, располо- женных в модуле формы. Прежде всего, это событие ПриАктивизацииОбласти. Это со- бытие возникает при смене текущей области табличного документа. Смена текущей области происходит, напри- мер, при нажатии клавиш управления курсором, при на- жатии мыши, при нажатии клавиши табуляции и т. д. В обработчик события передается элемент управления, вызвавший это событие, в данном случае — поле таблич- ного документа. Свойство ТекущаяОбласть поля табличного документа будет содержать ту область, которая стала те- кущей в результате смены текущей области. Таким образом, в обработчике события ПриАктивизацииОб- ласти можно проанализировать текущую область поля табличного документа и выполнить необходимые дейст- вия. При этом следует помнить, что текущей областью может быть как область ячеек табличного документа, так и рисунок табличного документа (листинг 13.212). Листинг 13.212. Пример использования обработчика события ПриАктивизацииОбласти поля табличного документа Процедура ПолеТабличногоДокументаПриАктивизацииОбласти( Элемент) ТекОбласть = Элемент.ТекущаяОбласть: Если ТипЗнч(ТекОбласть) = ТипС’ОбластьЯчеекТабличногоДокумента”) Тогда ... // алгоритм обработки ИначеЕсли ТипЗнч(ТекОбласть) = ТипСРисунокТабличногоДокумента") Тогда ... // алгоритм обработки КонецЕсли; Использование события Выбор Событие Выбор поля табличного документа возникает при выборе какой-либо области или рисунка табличного доку- мента. Если для области или рисунка табличного докумен- та разрешен только просмотр и установлено свойство Ги- перссылка, то выбор осуществляется по одинарному щелчку мыши или нажатию кнопки Enter. В остальных случаях выбор осуществляется по двойному щелчку мыши или при нажатии кнопки Enter. В процедуру обработки события Выбор передается три па- раметра: ♦ Элемент — поле табличного документа, которое вызвало это событие; ♦ Область — область/рисунок табличного документа, для которого был выполнен выбор; ♦ Стандартная обработка — признак выполнения стандарт- ных действий при выборе. По умолчанию имеет значе- ние Истина, это означает, что будет начато редактирова- ние выбранной области/рисунка табличного документа (в том случае, если редактирование разрешено). В обра- ботчике события Выбор этот параметр может быть уста- новлен в значение Ложь — тогда редактирование выбран- ной области/картинки осуществляться не будет. В качестве примера использования события Выбор можно рассмотреть сохранение рисунка, выведенного в таблич- ный документ, при щелчке на нем мышью. Для этого свойство Гиперссылка рисунка должно быть установлено в значение Истина, а результирующий табличный документ открыт, например, только для просмотра (листинг 13.213). Листинг 13.213. Пример использования обработчика события Выбор поля табличного документа Процедура ПолеТабличногоДокументаВыборОленент, Область, СтандартнаяОбработка) Если ТипЗнч(Область) = ТипСРисунокТабличногоДокумента”) Тогда Если Область.ТипРисунка = ТипРисункаТабличногоДокумента.Картинка Тогда // Организовать диалог выбора файла // для сохранения картинки Диалог = Новый ДиалогВыбораФайла( РежимДиалогаВыбораФайла.Сохранение); Диалог.Заголовок = "Сохраненение рисунка"; // Получить строковое представление формата картинки ФорматРисунка = НРег(Строка(Область.Картинка.Формат())); Если ФорматРисунка = ФорматКартинки.НеизвестныйФормат Тогда Предупреждение("Формат картинки неизвестен, | задайте расширение сохраняемого файла | самостоятельно”); Иначе Диалог.Фильтр = "Рисунок (*." + ФорматРисунка + ”)|*." + ФорматРисунка; КонецЕсли; // Сохранить картинку в в файл Если Диалог.ВыбратьО Тогда Область.Картинка.Записать(Диалог.ПолноеИмяФайла + Диалог.Расширение) ; КонецЕсли; КонецЕсли; КонецЕсли; КонецПроцедуры КонецПроцедуры
Следует иметь в виду, что если событие Выбор возникает в результате нажатия мыши в поле табличного докумен- та, то сначала будет вызвано событие ПриАктивизацииОбла- сти поля табличного документа. Причем если активизи- руемая область допускает редактирование, то двойной щелчок мышью в этой области вызовет два события При- АктивизацииОбласти и одно событие Выбор (рис. 13.192). Рис. 13.192. Последовательность вызова событий Расшифровка в поле табличного документа Событие ОбработкаРасшифровки вызывается в результате выполнения расшифровки области/рисунка табличного документа (подробнее про расшифровку можно прочи- тать в разделе «Использование расшифровки в таблич- ном документе», с. 496). В событие передается три параметра: Элемент, Расшифровка и СтандартнаяОбработка. Параметр Элемент содержит поле табличного документа, которое вызвало это событие. Параметр Расшифровка содержит значение параметра рас- шифровки области/рисунка табличного документа. Параметр СтандартнаяОбработка содержит по умолчанию значение Истина и определяет необходимость выполнения стандартной обработки расшифровки (для значений при- митивных типов стандартной обработкой является ото- бражение этих значений в отдельном окне). Как правило, целью алгоритма, выполняемого в обработ- ке расшифровки, является получение некоторых допол- нительных, уточняющих данных для определенной ячей- ки или области отчета. Поэтому значением параметра расшифровки в этом случае является, как правило, струк- тура, содержащая необходимую информацию. Например, для отчета о приходе товаров по складам значе- нием параметра расшифровки ячейки, содержащей коли- чество товара, поступившего на склад (листинг 13.214), может быть структура следующего вида (табл. 13.20). Таблица 13.20. Структура, передаваемая в параметр расшифровки Ключ Значение Склад Торговый зал Номенклатура Барбарис (конфеты) КоличествоРасход 30 Листинг 13.214. Пример заполнения расшифровки при выводе в поле табличного документа Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ТоварыНаСкладахОбороты.Склад КАК Склад, Т оварыНаСкладахОбороты.Склад.Представление КАК СкладПредставление, ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура, ТоварыНаСкладахОбороты.Номенклатура.Представление КАК НоменклатураПредставление, СУММАСГоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты КАК ТоварыНаСкладахОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОбороты.Склад. ТоварыНаСкладахОбороты.Номенклатура ИТОГИ СУММА(КоличествоРасход) ПО Склад. Номенклатура" Выборка = Запрос.Выполнить О.Выбрать(ОбходРезультатаЗапроса. ПоГруппировкам); ТабМакет = ПолучитьМакет("Макет"): ОбластьСклад = ТабМакет.ПолучитьОбластьС’Склад"): ОбластьНоменклатура = ТабМакет.ПолучитьОбласть("Номенклатура”); ЭлементыФормы.ПолетабличногоДокумента. НачатьАвтогруппировкуСтрок(); Пока Выборка.СледующийО Цикл ОбластьСклад.Параметры.Заполнить( Выборка): // Установить расшифровку поля Склад группировки Склад СтруктураРасшифровки = Новый Структура: СтруктураРасшифровки.Вставить("Склад", Выборка.Склад): СтруктураРасшифровки.Вставить("Номенклатура", Неопределено): СтруктураРасшифровки.Вставить("КоличествоРасход", Неопределено); ОбластьСклад.Параметры.РасшифровкаСклада = СтруктураРасшифровки; // Установить расшифровку поля КоличествоПриход // группировки Склад СтруктураРасшифровки = Новый Структура: СтруктураРасшифровки.Вставить("Склад", Выборка.Склад): СтруктураРасшифровки.Вставить("Номенклатура", Неопределено): СтруктураРасшифровки.Вставить("КоличествоРасход", Выборка.КоличествоРасход): ОбластьСклад.Параметры.РасшифровкаКоличества = СтруктураРасшифровки: ЭлементыФормы.ПолеТабличногоДокумента.Вывести(ОбластьСклад, Выборка.УровеньО); ВыборкаНоменклатура = Выборка. Выбрать (ОбходРезультатаЗапроса. ПоГ руппировкам); Пока ВыборкаНоменклатура.Следующий() Цикл ОбластьНоменклатура.Параметры. Заполнить(ВыборкаНоменклатура); // Установить расшифровку поля Склад // группировки Номенклатура СтруктураРасшифровки = Новый Структура: СтруктураРасшифровки.Вставить("Склад", ВыборкаНоменклатура.Склад);
СтруктураРасшифровки.Вставить("Ноненклатура", Неопределено); СтруктураРасшифровки.Вставить("КоличествоРасход". Неопределено): ОбластьНоменклатура.Параметры.РасшифровкаСклада = СтруктураРасшифровки; // Установить расшифровку поля Номенклатура // группировки Номенклатура СтруктураРасшифровки = Новый Структура; СтруктураРасшифровки. ВставитьС'Склад", ВыборкаНоменклатура.Склад); СтруктураРасшифровки.Вставить("Номенклатура", ВыборкаНоменклатура.Номенклатура); СтруктураРасшифровки.Вставить("КоличествоРасход", Неопределено); ОбластьНоменклатура.Параметры.РасшифровкаНоменклатуры = СтруктураРасшифровки; // Установить расшифровку поля КоличествоПриход // группировки Номенклатура СтруктураРасшифровки = Новый Структура; СтруктураРасшифров ки.Встав ит ь("Склад", ВыборкаНоменклатура.Склад); СтруктураРасшифровки.Вставить("Номенклатура", ВыборкаНоменклатура.Номенклатура); СтруктураРасшифровки.Вставить("КоличествоРасход". ВыборкаНоменклатура.КоличествоРасход); ОбластьНоменклатура.Параметры.РасшифровкаКоличества = СтруктураРасшифровки; ЭлементыФормы.ПолеТабличногоДокумента. Вывести(Облает ьНоменклатура, ВыборкаНоменклатура.Уровень()); КонецЦикла: КонецЦикла; ЭлементыФормы.ПолеТабличногоДокумента. ЗакончитьАвтогруппировкуСтрокО; // Установить режим просмотра документа ЭлементыФормы.ПолеТабличногоДокумента.ТолькоПросмотр = Истина: В этом случае обработка расшифровки, например, может вызывать выполнение процедуры, формирующей отчет о движениях товаров на складах (листинг 13.215). Листинг 13.215. Пример процедуры обработки события ОбработкаРасшифровки Процедура ПолеТабличногоДокументаОбработкаРасшифровкиОлемент, Расшифровка, СтандартнаяОбработка) СтандартнаяОбработка = Ложь; Склад = Расшифровка.Склад; Номенклатура = Расшифровка.Номенклатура: Количество = Расшифровка.КоличествоРасход; ПоказатьПоступлениеТоваров(Склад, Номенклатура, Количество); КонецПроцедуры При обработке события ОбработкаРасшифровки также нужно иметь в виду, что перед вызовом события ОбработкаРасшиф- ровки будет вызвано событие Выбор, а если событие Обра- боткаРасшифровки возникает в результате нажатия мыши в поле табличного документа, то сначала будет вызвано со- бытие ПриАктивизацииОбласти поля табличного документа. Причем, если активизируемая область допускает редак- тирование, то двойной клик мышью в этой области вызо- вет два события ПриАктивизацииОбласти, событие Выбор и со- бытие ОбработкаРасшифровки (рис. 13.193). Рис. 13.193. Последовательность вызова событий «Расшифровка» для сводной таблицы Для сводной таблицы, которая выводится в поле таблич- ного документа, также можно организовать механизм, аналогичный по своим функциям механизму расшифровки. Особенностью сводной таблицы является то, что она может быть сформирована интерактивно пользователем, поэто- му заранее присвоить значения параметрам расшифров- ки каких-либо ячеек не представляется возможным. Однако для ячеек сводной таблицы вызывается событие Выбор, которое можно обработать в модуле формы. При об- работке этого события используется метод сводной табли- цы ПолучитьЗначенияО. В параметр этого метода передается область сводной таблицы, для которой требуется получить значения. Метод возвращает структуру, содержащую в об- щем случае значения строки, колонки и всех ресурсов, со- держащихся в источнике данных сводной таблицы. Например, если в поле табличного документа выводит- ся сводная таблица (листинг 13.216), то обработчик собы- тия Выбор может выглядеть следующим образом (лис- тинг 13.217). Листинг 13.216. Вывод сводной таблицы в поле табличного документа Построитель = Новый ПостроительОтчетаО; Построитель.Текст = "ВЫБРАТЬ ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад, ТоварыНаСкладахОстаткиИОбороты.Склад.Код КАК КодСклада, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Ноненклатура КАК Ноненклатура, ТоварыНаСкладахОстаткиИОбороты.Ноненклатура.Представление, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот) КАК КоличествоОборот, СУММА(ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход ИЗ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты СГРУППИРОВАТЬ ПО ТоварыНаСкладахОстаткиИОбороты.Склад, ТоварыНаСкладахОстаткиИОбороты.Ноненклатура, ТоварыНаСкладахОстаткиИОбороты.Склад.Представление, ТоварыНаСкладахОстаткиИОбороты.Ноненклатура.Представление
ИТОГИ СУММА(КоличествоПриход). СУММА(КоличествоОборот), СУММА(КоличествоРасход) ПО ОБЩИЕ. Номенклатура Иерархия, Склад Иерархия" Построитель.ЗаполнитьНастройки(); Таблица = ЭлементыФормы.ПолеТабличногоДокумента.ВстроенныеТаблицы. Добавить(Тип("СводнаяТаблица"), ЭлементыФормы.ПолеТабличногоДокумента.0бласть(2, 2)); Таблица.ИсточникДанных = Построитель; Таблица.Обновление = Ложь; Таблица.Строки.Добавить("Номенклатура”); Таблица.Колонки.Добавить("Склад"); Таблица.Данные.Добавить("КоличествоПриход”); Таблица.Данные.Добавить("КоличествоРасход”); Таблица.Обновление = Истина; Листинг 13.217. Обработчик события Выбор для сводной таблицы Процедура ПолеТабличногоДокументаВыборОлемент, Область, СтандартнаяОбработка) Если ТипЗнч(Область) = ТипС'ОбластьЯчеекТабличногоДокумента") Тогда Структура = Элемент.ВстроенныеТаблицы. СводнаяТаблица!.ПолучитьЗначения(Область); Если Структура <> Неопределено Тогда Если Структура.Свойство("Номенклатура") И Структура. СвойствоС’Скл ад" )Тогда ЗначениеСклад = Структура.Склад; ЗначениеНоменклатура = Структура.Номенклатура; ЭначениеПриход = Структура.КоличествоПриход; ЗначениеОборот = Структура.КоличествоОборот; ЗначениеРасход = Структура.КоличествоРасход; // алгоритм расшифровки Если передаваемая область не входит ни в область дан- ных, ни в область заголовков строк, ни в область заголов- ков колонок сводной таблицы, метод вернет значение Не- определено. Если передаваемая область входит в область строк/коло- нок сводной таблицы (не итоговые) (рис. 13.195), будет возвращена структура, содержащая итоговые значения ресурсов (для выбранного измерения) и значение вы- бранного измерения в строке/колонке сводной таблицы. шмама Тара Инвентарь Обувь Бытовая техника Продукты Оптовые склады________Розничные склады >о Количеств от] Ко личеств of Количеств оГ| КоличествсР! /мчествйтриход КоличествоРасход 3 705 3 478 90 225 7 523 186 210 35 17 448 50 2150 95 3 645 5 940 25 104 "129 30 50 5855 3573 3 735 225 13468 25 186 210 139 17 577 Рис. 13.195. Область сводной таблицы Если передаваемая область входит в область данных (или заголовков), содержащую итоговые значения ресурсов (колонки или строки ресурсов) (рис. 13.196), будет воз- вращена структура, содержащая только итоговые значе- ния ресурсов. Склад [Данные-- Номенклатура Тара___________ Инвентарь Обувь бытовая техника продукты Итог КоличествоПриход 3705 3 478 90 186 210 35 50 2150 95 3 645 10 50 5 855 3 573 3 735 225 25 186 210 139 7 528 448 5 940 1 2 13 468 577 КонецЕсли; КонецЕсли; КонецЕсли; КонецПроцедуры В приведенном примере метод ПолучитьЗначения О выпол- няется только в том случае, если область, для которой вы- звано событие Выбор, находится внутри области данных сводной таблицы без учета итоговых строк и колонок (рис. 13.194). Рис. 13.196. Область сводной таблицы Если передаваемая область входит в область данных, со- держащую итоговые значения ресурсов (итоги, не являю- щиеся колонками или строками ресурсов) (рис. 13.197), будет возвращена структура, содержащая итоговые зна- чения ресурсов (для выбранного измерения) и значение выбранного измерения в строке/колонке сводной таб- лицы. Склад |Даниче~ Розничные склады Склад [Данные Оптовые склады | КоличествоПриход КоличествоРасход 50 5 855 3 573 3 735 225 25 186 210 139 13468 577 Рис. 13.194. Область сводной таблицы Однако в общем случае этот метод может быть выполнен для произвольной области табличного документа — это не вызовет ошибки. Разница будет заключаться в возвра- щаемом значении. рптовыа склады_________Розничные ск лады Количествог! Количество^ 3 705 3 478 90 186 210 35 50 2150 95 3 645 186 210 139 3 573 3 735 225 13468 7528 448 5 940 129 Рис. 13.197. Область сводной таблицы 577 Значения в табличном документе Области табличного документа, помимо текста, могут со- держать значения произвольного типа. Для этого свойст- во СодержитЗначение области ячеек табличного документа должно быть установлено в значение Истина. При этом становятся доступны свойства ТипЗначения и ЭленентУправ- ления области ячеек. Свойство ТипЗначения определяет тип того значения, ко- торое будет содержаться в области ячеек табличного до-
кумента. Это могут быть значения примитивных типов (например, Число, Дата), ссылочных типов (например, СправочникСсылка.Номенклатура) и т. д. Свойство ЭлементУправления определяет тип элемента управ- ления, который будет использован для редактирования значения, содержащегося в области табличного документа. Элемент управления не может быть выбран произвольно, возможные типы элементов управления определяются типом значения, хранящегося в области табличного до- кумента. Например, если выбран тип значения Дата, то в качестве элемента управления может быть использова- но только поле ввода. Если выбран тип Число, то в качест- ве элемента управления может быть использовано поле ввода или флажок. Метод УстановитьЭлементУправленияО области ячеек табличного документа позволяет указать требуемый вид элемента управления, который будет ис- пользоваться для редактирования значения. Хранение значений в областях табличного документа мо- жет быть использовано, например, в ситуации, когда об- ласть ячеек табличного документа является источником данных для модели прогноза или построителя отчета. Также хранение значений в областях табличного доку- мента применяется, например, когда табличный доку- мент используется для ввода и обработки данных. Обработка данных, введенных в табличный документ, может быть выполнена в обработчике события ПриИзнене- нииСодержимогоОбласти. Это событие возникает в тот мо- мент, когда содержимое какой-либо области табличного документа изменяется. В обработчик события передаются два параметра: Эле- мент — поле табличного документа, и Область — область ячеек табличного документа, значение которой было из- менено. Использование этого события и областей, содержащих значения, можно проиллюстрировать на примере состав- ления ведомости времени, отработанного сотрудниками. В поле табличного документа создается шаблон ведомо- сти (рис. 13.198), в котором для области R5C4:R8C10 свойство Защита устанавливается в значение Ложь, а для всего поля табличного документа свойство ТолькоПросмотр устанавливается в значение Истина. Рис. 13.198. Форма В результате этих действий пользователь сможет редак- тировать только указанную область. После этого для области R6C4:R8C11 свойство Содержит- Значение устанавливается в значение Истина, и указывается тип значения — Число (рис. 13.199). Теперь в ячейках указанной области табличный доку- мент сможет хранить числовые значения. Часть из них будет вводиться пользователем, а часть (значения в ко- лонке Итого) — рассчитываться в обработчике события ПриИзмененииСодержимогоОбласти (листинг 13.218). Рис. 13.199. Форма Листинг 13.218. Обработчик события ПриИзмененииСодержимогоОбласти Процедура ПолеТабличногоДокументаПриИзмененииСодержимогоОбласти( Элемент, Область) ПолеТабДок = ЭлементыФормы.ПолеТабличногоДокумента; Для СчетчикСтрок = 6 по В Цикл Итог = 0; Для СчетчикКолонок = 4 по 10 Цикл Область = ПолеТабДок.Область(СчетчикСтрок, СчетчикКолонок); Итог = Итог + Область.Значение; КонецЦикла: ПолеТабДок.Область(СчетчикСтрок. 11).Значение = Итог: КонецЦикла: КонецПроцедуры В результате пользователь сможет заполнить форму, а ито- говые суммы будут посчитаны автоматически (рис. 13.200). Рис. 13.200. Результат заполнения формы Значения могут храниться не только в областях ячеек табличного документа, но и в рисунках табличного доку- мента, однако такой возможностью обладают только ри- сунки, имеющие тип Текст. При этом работа со значениями, хранящимися в рисунках, аналогична работе со значе- ниями, хранящимися в областях ячеек табличного доку- мента.
Если область/рисунок табличного документа содержит значение, то для такой области/рисунка можно исполь- зовать возможность отметки незаполненного значения. Для этого свойство АвтоОтнеткаНезаполненного области/ рисунка табличного документа следует установить в значение Истина. В этом случае в нижней части облас- ти/рисунка табличного документа будет выведена крас- ная пунктирная линия, если значение области/рисунка является значением по умолчанию. Отметка незапол- ненных значений служит для привлечения внимания пользователя к тем областям/рисункам табличного до- кумента, значения которых обязательно должны быть заполнены. Свойство ОтиеткаНезаполненного области/рисунка таблич- ного документа предназначено только для чтения и по- зволяет определить, выведена ли в этой области/рисунке отметка незаполненного значения. Если отметка выведе- на, свойство будет иметь значение Истина. Табличный документ позволяет выполнять поиск опре- деленного значения в табличном документе. Для этого используется метод табличного документа НайтиЗначе- ние(), который содержит следующие параметры: ♦ Значение — значение, которое должно быть найдено. ♦ Начало — имеет тип ОбластьЯчеекТабличногоДокумента. Представляет собой область, после которой начинается поиск. Если этот параметр не указан, то поиск будет вы- полнен с начала табличного документа (начиная с об- ласти R1C1). ♦ Где — имеет тип ОбластьЯчеекТабличногоДокунента. Пред- ставляет собой область, в пределах которой осуществ- ляется поиск текста. Если этот параметр не указан, то поиск будет осуществляться во всем табличном доку- менте. ♦ Искать по строкам — имеет тип Булево. Определяет способ поиска — по строкам или по колонкам. Значение по умолчанию — Истина, что означает поиск по строкам. При этом поиск будет осуществляться в соответствии со значением параметра Искать вперед. ♦ Искать вперед — имеет тип Булево и определяет направле- ние поиска. Значение по умолчанию — Истина — искать вперед. Значение Ложь означает поиск назад. Таким образом, по умолчанию метод осуществляет поиск первой области/рисунка табличного документа, содержа- щего указанное значение, причем поиск выполняется во всем документе, начиная с ячейки R1C1, по строкам впе- ред. В случае успешного завершения поиска, метод возвраща- ет найденную область табличного документа (или рису- нок табличного документа, если значение найдено в нем). Если значение не найдено — метод возвращает значение Неопределено. Элементы управления в табличном документе Элементы управления, содержащиеся в ячейках/рисун- ках табличного документа, обладают той же функцио- нальностью, что и элементы управления, расположенные в форме. Е1апример, для них могут быть настроены раз- личные свойства и назначены обработчики событий (лис- тинг 13.219). Листинг 13.219. Изменение свойств элемента управления и назначение обработчика события Область = ЭлементыФормы.ПолеТабличногоДокумента.0бласть!2, 2); Область.СодержитЗначение = Истина: Область.ТипЗначения = Новый ОписаниеТиповСДата"): Область.ЭлементУправления.КнопкаВыбора = Истина; Область.ЭлементУправления.УстановитьДействиеС’ПриИзменении", Новый Действие!"ПолеВводаТабличногоДокументаПриИзменении")); В приведенном фрагменте кода указывается, что область ячеек табличного документа будет содержать значение типа Дата, и полю ввода, которое будет использоваться для редактирования этого значения, устанавливается флаг отображения кнопки выбора. После этого полю вво- да в качестве обработчика события ПриИзменении назнача- ется процедура с именем ПолеВводаТабличногоДокунентаПри- Изненении. Для назначения обработчика события полю ввода ис- пользуется метод расширения элементов управления, при- надлежащих табличному документу УстановитьДействиеО. Кроме этого метода расширение также содержит метод ПолучитьДействиеО, который позволяет определить дейст- вие, назначенное для обработки указанного события. При редактировании значений, содержащихся в областях табличного документа, следует учитывать, что при этом будут вызваны как события поля табличного документа, так и события элемента управления, используемого для редактирования значения. Например, при редактировании значения даты из лис- тинга 13.220 в общем случае будет вызвана следующая последовательность событий (рис. 13.201). Элементы управления могут использоваться не только для редактирования значений, содержащихся в табличном до- кументе, но и как обычные элементы управления, только расположенные не в форме, а в поле табличного документа. При этом элементы управления могут быть расположены в поле табличного документа двумя способами: ♦ «поверх» ячеек поля табличного документа; ♦ встроенные в ячейку поля табличного документа. Чтобы расположить элемент управления в поле таблич- ного документа (рис. 13.202), необходимо использовать метод Добавить!) коллекции ЭлементыФормы, указав при этом в качестве четвертого параметра этого метода поле таб- личного документа, в котором должен быть размещен этот элемент управления (см. листинг 13.220). Затем нужно указать размеры и положение элемента управле- ния, также можно связать элемент управления с данными (реквизитом формы), определить его свойства, назначить обработчики событий. Листинг 13.220. Размещение элемента управления в поле табличного документа НовоеПолеВвода = ЭлементыФормы.ДобавитьСГипС'ПолеВвода"), "ПолеВводаТабличногоДокумента", ЭлементыФормы.ПолеТабличногоДокумента); НовоеПолеВвода.Лево = 10: НовоеПолеВвода.Верх = 10: НовоеПолеВвода.Высота = 5: НовоеПолеВвода.Ширина = 30; НовоеПолеВвода.Данные = "ПолеВводаТабличногоДокумента"; НовоеПолеВвода.УстановитьДействиеС’ПриИзменении", Новый Действие! "ПолеВводаТабличногоДокументаПриИзменении”));
Рис. 13.201. Последовательность событий Рис. 13.202. Размещение элемента управления «поверх» ячеек поля табличного документа Установка положения и размеров элемента управления осуществляется с помощью свойств расширения элемен- тов управления, расположенных в поле табличного доку- мента Лево, Верх, Высота и Ширина. Назначение обработчика события выполняется с помощью метода УстановитьДей- ствиеО расширения элементов управления, расположен- ных в поле табличного документа. Альтернативным способом размещения элемента управ- ления в поле табличного документа является использо- вание метода Расположить О расширения элементов управ- ления, расположенных в поле табличного документа (листинг 13.221). Этот метод позволяет разместить эле- мент управления точно в пределах заданной области таб- личного документа (рис. 13.203). Для того чтобы встроить элемент управления в ячей- ку поля табличного документа, необходимо установить свойство расширения элементов управления, расположен- ных в поле табличного документа ВстроенВЯчейку в значе- ние Истина (листинг 13.222). Элемент управления будет размещен в ячейке, в которой был расположен верхний ле- вый угол элемента управления (рис. 13.204). При этом свойство Видимость элемента управления будет автоматиче- ски установлено в значение Ложь. Это означает, что элемент управления, встроенный в ячейку, будет показан пользо- вателю только при входе в режим редактирования ячейки. Еще раз хочется акцентировать внимание на отличии ис- пользования элемента управления для редактирования значения в ячейке поля табличного документа и элемента управления, встроенного в ячейку. Листинг 13.221. Размещение элемента управления в поле табличного документа НовоеПолеВвода = ЭлементыФормы.ДобавитьСГипС'ПолеВвода"). "ПолеВв одаТаблич ног оДокумента”, ЭлементыФормы.ПолеТабличногоДокумента); НовоеПолеВвода.Расположить(ЭлементыФормы. ПолеТабличногоДокумента. ОбластьСЗ. 2. 4. 3)): НовоеПолеВвода.Данные = "ПолеВводаТабличногоДокуиента"; НовоеПолеВвода.УстановитьДействиеС'ПриИзменении", Новый Действие! "ПолеВводаТабличногоДокументаПриИзменении”)); Рис. 13.203. Размещение элемента управления в указанной области поля табличного документа
Листинг 13.222. Встраивание элемента управления в ячейку поля табличного документа НовоеПолеВвода = ЭлементыФормы.Добавить(Тип("ПолеВвода"). "ПолеВводаТабличногоДокумента", ЭлементыФормы.ПолеТабличногоДокумента); НовоеПолеВвода.Расположить(ЭлементыФормы. ПолеТабличногоДокумента. ОбластьСЗ, 2, 4, 3)); НовоеПолеВвода.ВстроенВЯчейку = Истина; НовоеПолеВвода.Видимость = Истина; НовоеПолеВвода.Данные = "ПолеВводаТабличногоДокумента"; НовоеПолеВвода.УстановитьДействиеС'ПриИзменении", Новый ДействиеС “ПолеВводаТабличногоДокументаПриИзменении")): Рис 13.204. Встраивание элемента управления в ячейку поля табличного документа Когда элемент управления используется для редактиро- вания значения ячейки, ячейка содержит значение того типа, которое редактируется в элементе управления, и это значение доступно через свойство области ячеек таблич- ного документа Значение. Представление этого значения доступно через свойство области ячеек табличного доку- мента Текст. Когда элемент управления встроен в ячейку, то значение, редактируемое в этом элементе управления, содержится в реквизите формы, с которым связан данный элемент управления (или в самом элементе управления, если он не связан с данными — свойство Значение расширения эле- ментов управления, расположенных в поле табличного документа). Свойство Значение области ячеек табличного документа недоступно, а в свойстве Текст области ячеек табличного документа содержится представление редак- тируемого значения. Рис. 13.206. Установка свойств, управляющих перетаскиванием Рис. 13.205. Форма документа и отчет об остатках Перетаскивание в табличном документе Поле табличного документа поддерживает механизм пе- ретаскивания, который позволяет с помощью мыши пере- носить значения из/в табличный документ. В качестве примера можно рассмотреть формирование документа Заказ, при котором значения номенклатуры перетаскиваются в табличную часть документа мышью из сформированного отчета о продажах номенклатуры. Предположим, что для формирования отчета об остатках используется некоторая обработка, форма которой содер- жит поле табличного документа, в которое и выводится от- чет об остатках. Документ Заказ также имеет форму доку- мента, содержащую табличное поле, связанное с данными табличной части документа Номенклатура (рис. 13.205). Как табличное поле, расположенное в форме документа, так и поле табличного документа, расположенное в фор- ме обработки, имеют два свойства, которые управляют возможностью перетаскивания. Это свойства Разрешить- НачалоПеретаскивания и РазрешитьПеретаскивание. Свойство РазрешитьНачалоПеретаскивания управляет источником дан- ных, а свойство РазрешитьПеретаскивание — приемником. В нашем случае источником данных будет являться поле табличного документа, поэтому его свойство РазрешитьНа- чалоПеретаскивания должно быть установлено в значение Истина. Приемником данных будет являться табличное поле, поэтому его свойство РазрешитьПеретаскивание также должно быть установлено в значение Истина (рис. 13.206). В процессе перетаскивания система генерирует четыре события: НачалоПеретаскивания, ПроверкаПеретаскивания, Пе- ретаскивание и ОкончаниеПеретаскивания. Два из этих собы- тий генерируются в источнике, а два — в приемнике (рис. 13.207). РазрешитьПеретаскивание = Истина Р*Хжо>»тЛас* ’ аскивания = Истина
РазрешитьПеретаскивание = Истина РазрешитьНачалоПеретаскивания = Истина Рис. 13.207. События, сопровождающие перетаскивание ется выполнять при перетаскивании. Это свойство при- нимает значения системного перечисления ДопустимыеДей- ствияПеретаскивания (табл. 13.21). Значение этого свойства, установленное системой по умолчанию или заданное раз- работчиком при обработке события НачалоПеретаскивания, будет одним и тем же во всех обработчиках событий пере- таскивания (если, конечно, разработчик не изменит его явным образом в одном из обработчиков). Рис. 13.208. Выбор действия из контекстного меню Эти события содержат различные параметры, но общим для всех событий является параметр ПаранетрыПеретаскивания, ко- торый позволяет анализировать действия, выполняемые при перетаскивании, и управлять процессом перетаскивания. Этот параметр содержит объект ПаранетрыПеретаскивания, который имеет три свойства: Значение, Действие и Допусти- мыеДействия. Значение — в этом свойстве содержится перетаскиваемое значение. В нашем случае таким значением будет таблич- ный документ, состоящий из одной ячейки, — той, кото- рую перетаскивают. Действие — это свойство имеет тип системного перечисле- ния ДействияПеретаскивания и определяет текущее действие перетаскивания. Текущее действие перетаскивания зави- сит от того, каким образом пользователь выполняет пере- таскивание, и оно может принимать различные значения в каждом из обработчиков событий перетаскивания. Если перетаскивание выполняется правой кнопкой мыши, то свойство Действие будет иметь значение Выбор. Это озна- чает, что в результате перетаскивания будет открыто кон- текстное меню, из которого пользователь сможет выбрать необходимое действие (например, копирование, переме- щение или отмена) (рис. 13.208). Если перетаскивание выполняется левой клавишей мыши с нажатой клавишей Control, то свойство Действие будет иметь значение Копирование. Если перетаскивание выполняется только левой клави- шей мыши, то свойство Действие будет иметь значение Пе- ремещение. Свойство Действие может принимать еще одно значение — Отмена. Это значение может быть установлено только средствами встроенного языка или системой, в результа- те анализа условий перемещения. Значение Отмена озна- чает, что перетаскивание не может быть выполнено. Свойство ДопустимыеДействия объекта ПараметрыПеретаскива- ния определяет те действия, которые в принципе допуска- Таблица 13.21. Значения системного перечисления ДопустимыеДействияПеретаскивания Значение Пояснение Копирование Допускается только копирование КопированиеИПеремещение Допускается копирование или перемещение Перемещение Допускается только перемещение НеОбрабатывать Не осуществляется никаких действий В каждом обработчике события перетаскивания система анализирует значение свойств Действие и ДопустимыеДейст- вия на непротиворечивость. Допускаются следующие со- четания значений (табл. 13.22). Таблица 13.22. Сочетания значений свойств ДопустимыеДействия и Действие ДопустимыеДействия Действие КопированиеИ Перемещение Копирование Перемещение Выбор Отмена Копирование Копирование Выбор Отмена Перемещение Перемещение Выбор Отмена НеОбрабатывать Отмена
Если допустимым действием является копирование, а дей- ствие — перемещение, будет выполняться копирование. Если допустимым действием является перемещение, а действие — копирование, будет выполняться переме- щение. Кроме непротиворечивости значений перечисленных свойств, системой принимается во внимание то, какие данные содержатся в источнике и приемнике. Например, при перетаскивании из поля табличного документа, от- крытого в режиме только просмотр, система позволит вы- полнить лишь копирование (или не выполнять никаких действий). При перетаскивании в табличном поле, содер- жащем, например, список документов, система не позво- лит выполнить копирование. В то же время при перетас- кивании в табличном поле, источником данных которого является таблица значений, содержащая необъектные данные, копирование будет разрешено. Также, если, на- пример, в табличном поле, источником данных которого является иерархический справочник, выполняется пере- таскивание группы справочника в элемент справочника, система запретит любые действия, кроме отмены. В результате анализа непротиворечивости действий и данных источника и приемника система определяет, какое же действие перетаскивания будет выполняться. В соответствии с этим система изменяет форму курсора. Если определено, что будет выполняться копирова- ние, курсор отображается с пиктограммой копирования (рис. 13.209). Рис. 13.209. Копирование Если определено, что будет выполняться перемещение или выбор, курсор отображается с пиктограммой переме- щения (рис. 13.210). Действие Выбор не имеет отдельной пиктограммы. Если определено, что будет выполняться отмена, то кур- сор отображается пиктограммой, изображающей пере- черкнутую окружность (рис. 13.211). Рис. 13.211. Отмена перетаскивания Для формирования отчета будем использовать макет, в котором для ячейки, содержащей параметр Номенклатура, указано, что она содержит значение типа СправочникСсыл- ка. Номенклатура (рис. 13.212). Рис. 13.212. Макет отчета Рис. 13.210. Перемещение Именно эти значения разрешено будет перетаскивать в форму документа. Для этого следует воспользоваться событием НачалоПеретаскивания поля табличного докумен- та. В нем нужно проанализировать перетаскиваемую об- ласть и разрешить перетаскивание только в том случае, если область содержит значение. Событие НачалоПеретаскивания поля табличного документа поставляет три параметра: ♦ Элемент — элемент управления, вызвавший событие; в нашем случае поле табличного документа. ♦ ПараметрыПеретаскивания — параметры перетаскивания. ♦ СтандартнаяОбработка — признак выполнения стандарт- ной обработки. Стандартная обработка заключается
собственно, в начале перетаскивания данных. По умол- чанию имеет значение Истина. Для того чтобы разрешить перетаскивание только ячеек табличного документа, содержащих значения номенкла- туры, проанализируем признак СодержитЗначение текущей области табличного документа. Если область не содержит значение — перетаскивание выполнять не будем (лис- тинг 13.223). Листинг 13.223. Обработчик события НачалоПеретаскивания Процедура ПолеТабличногоДокуиентаНачалоПеретаскиванияОлемент, ПаранетрыПеретаскивания, СтандартнаяОбработка) Если ПаранетрыПеретаскивания.Значение. ТекущаяОбласть.СодержитЗначение = Ложь Тогда СтандартнаяОбработка = Ложь; КонецЕсли; КонецПроцедуры После того как обработано событие НачалоПеретаскивания, у приемника (в нашем случае — табличное поле) будет вы- звано событие ПроверкаПеретаскивания. Это событие вызы- вается всякий раз, когда курсор попадает на новый объ- ект в элементе управления (например, в новую ячейку табличного поля), а также при нажатии и отпускании клавиши Control. Событие ПроверкаПеретаскивания табличного поля постав- ляет пять параметров: ♦ Элемент — элемент управления, вызвавший событие; в нашем случае табличное поле. ♦ ПаранетрыПеретаскивания — параметры перетаскивания. ♦ СтандартнаяОбработка — признак выполнения стандартной обработки. Стандартная обработка заключается в провер- ке возможности вставки значения, то есть проверяется тип вставляемого значения, и если он совпадает с типом отображаемых данных, то производятся стандартные дей- ствия. ♦ Строка — строка, над которой находится курсор. Имеет тип <иня вида объектов»ТабличнаяЧастьСтрока.<иия объек- та». <иня табличной части» или Неопределено. ♦ Колонка — колонка, над которой находится курсор. Име- ет тип КолонкаТабличногоПоля или Неопределено. Так как в нашем случае источником данных табличного поля является объект ДокументТабличнаяЧасть.Заказ.Но- менклатура, а перетаскиваемое значение имеет тип таб- личный документ, то стандартную обработку необходи- мо отключить и устанавливать действие перетаскивания вручную. Например, можно разрешить перетаскивание только в том случае, если курсор находится над областью табличного поля, не содержащей строк (листинг 13.224). При отпускании клавиши мыши в элементе управле- ния, который является приемником, будет вызвано со- бытие Перетаскивание. Обработчик этого события может быть использован для того, чтобы заполнить приемник данными, если способ заполнения отличается от стан- дартного. Рис. 13.213. Пример сравнения двух табличных документов
Обработчик этого события имеет такие же параметры, как и обработчик события ПроверкаПеретаскивания. В нашем случае необходимо отказаться от выполнения стандартной обработки (так как тип данных табличного поля не совпадает с типом перетаскиваемого значения) и заполнить приемник данными самостоятельно (лис- тинг 13.225). Листинг 13.224. Обработчик события ПроверкаПеретаскивания Процедура НоменклатураПроверкаПеретаскиванияОлеиент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Колонка) СтандартнаяОбработка = Ложь; Если Строка о Неопределено И ДокументОбъект.Номенклатура.КоличествоО <> 0 Тогда ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Отмена; Иначе ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Копирование: КонецЕсли; КонецПроцедуры Листинг 13.225. Обработчик события Перетаксивание Процедура НоиенклатураПеретаскиваниеОлеиент, ПараметрьЛеретаскивания. СтандартнаяОбработка. Строка, Колонка) ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Копирование; ТабДок = ПараметрыПеретаскивания.Значение; Значение = ТабДок.ТекущаяОбласть.Значение; НоваяСтрока = ДокументОбъект.Номенклатура.ДобавитьО; НоваяСтрока.Номенклатура = Значение; НоваяСтрока.Количество = 1; КонецПроцедуры Сравнение табличных документов Система 1 С:Предприятие позволяет выполнять автома- тическое сравнение двух табличных документов. Для это- го используется механизм сравнения файлов, который подробно описан в разделе «Сравнение текстовых доку- ментов», с. 471. Сравнение табличных документов может быть использова- но, например, в тех случах когда необходимо визуально про- анализировать отличия в двух больших отчетах (рис. 13.213).
Глава 14. Интеграция с другими информационными системами Очень часто при решении задач комплексного учета воз- никает необходимость в рамках одного программного комплекса использовать возможности другого программ- ного комплекса, проводить обмен данными между раз- личными системами и т. п. Это может быть обусловлено спецификой автоматизируемых задач, особенностями структуры автоматизируемой компании (организации) и массой других причин. К примеру, при необходимости работы с каким-либо оборудованием «общение» с ним производится через специализированную программу (драйвер). В компании может быть принято оформлять договоры в формате программы Word, в связи с этим возникает необходи- мость «работы» с данной программой, хранения полу- ченных документов в информационной базе. При ор- ганизации обмена с такой же системой (информаци- онной базой) или с другими возникает как задача формирования (и чтения) файла обмена, так и задача его доставки. На самом деле все подобные задачи не перечесть. Но возможность их решения определяет, насколько велик потенциал используемого программного комплекса по интеграции (организации совместной работы) с други- ми системами. Система 1С:Предприятие является открытой системой. Предоставляется возможность для интеграции практиче- ски с любыми внешними программами и оборудованием на основе общепризнанных открытых стандартов и про- токолов передачи данных. В системе 1С:Предприятие имеется целый набор средств, с помощью которых можно: ♦ создавать, обрабатывать и обмениваться данными раз- личных форматов; ♦ осуществлять доступ ко всем объектам системы 1С:Пред- приятие, реализующим ее функциональные возможно- сти; ♦ поддерживать различные протоколы обмена; ♦ поддерживать стандарты взаимодействия с другими под- системами; ♦ разрабатывать собственные интернет-решения. Проведем краткий обзор технологий, которые могут ис- пользоваться платформой 1С:Предприятия при решении задач интеграции. Текстовый документ. Встроенный язык системы 1 С: Пред- приятие позволяет разработчику создавать, динамически формировать и записывать текстовые документы. Обмен данными с использованием текстовых документов может быть одним из менее «ресурсоемких» способов организа- ции взаимодействия с другими информационными систе- мами. Помимо обычных способов работы с текстовыми доку- ментами (чтение, запись, вставка и добавление строк, по- лучение строк), разработчик имеет возможность динами- ческого формирования текстовых документов на основе заранее созданных шаблонов. XML. Система 1С:Предприятие позволяет организовы- вать интеграцию с прикладными системами с использо- ванием XML-документов, являющихся на сегодняшний день общепринятым средством представления данных. DBF-файлы. Механизм работы с базами данных формата DBF предназначен для обеспечения возможности мани- пулирования ими непосредственно из встроенного языка системы 1С:Предприятие 8.0. Возможно практически лю- бое манипулирование данными. COM-соединение. Основная задача, решаемая с помощью СОМ-соединения, — обеспечение надежного и быстрого программного доступа к данным системы 1С:Предпри- ятие из внешних приложений. В общем и целом работа с системой 1 С:Предприятие через COM-соединение по- добна работе с системой 1 С: Предприятие в режиме Automation-сервера. Существенное отличие заключается в том, что запускается вариант 1С:Предприятия, не со- держащий интерфейсной части (подразумевается работа с данными только программными средствами, без ис- пользования интерфейсных возможностей). Automation Client/Server. Основное назначение Automa- tion-сервера 1С:Предприятия — управление приложе- нием системы 1 С: Предприятие из других приложений и выполнение действий, аналогичных интерактивным действиям. Работа с HTML-документами. Средства работы с HTML- документами позволяют встраивать их в формы приклад- ного решения и выполнять их редактирование средства- ми встроенного языка. Работа с файлами. 1 С: Предприятие средствами встроен- ного языка предоставляет доступ к функциям работы с файловой системой. Эта возможность может быть ис- пользована при организации взаимодействия с другими информационными системами через общие каталоги. ActiveX. Платформа 1 С: Предприятия 8.0 позволяет вне- дрять в формы и табличные документы дополнительные элементы управления, поддерживающие технологию ActiveX. Макеты ActiveDocument. Технология ActiveDocument предназначена для редактирования документов внешни- ми по отношению к 1 С: Предприятию 8.0 редакторами. Работа с Интернетом. Работа с Интернетом возможна непосредственно из встроенного языка. Разработчик мо- жет выполнять отправку и прием писем электронной почты, а также осуществлять обмен данными по протоко- лам HTTP (HTTPS) и FTP.
WEB-расширение. Является отдельным программным продуктом и позволяет встраивать доступ к данным 1С:Предприятие в существующие веб-сайты и веб- приложения, а так же создавать готовые веб-приложе- ния, использующие информационную базу 1 С: Пред- приятия. Обмен данными. Механизмы обмена данными, реализо- ванные в технологической платформе 1 С: Предприятия, позволяют создавать территориально распределенные информационные системы как на основе информацион- ных баз 1С:Предприятия, так и с участием других ин- формационных систем, не основанных на 1 С: Предпри- ятии. Например, можно организовать работу главного офиса, фи- лиалов и складов предприятия в единой информационной базе, или обеспечить взаимодействие информационной базы ЮПредприятия с существующей базой данных Oracle и т. п. Работа с WEB-расширением описана в разделе «Web- расширение», с. 606, механизмы обмена данными описа- ны в разделе «Создание распределенных информацион- ных систем», с. 571, чсе остальные механизмы будут рас- смотрены в данной главе. Форматы файлов обмена При реализации обмена данными между информацион- ными системами одной из подзадач, требующей решения, является определение варианта передачи данных (и его реализация). Это может быть: ♦ использование механизмов взаимодействия «напрямую» (например, OLE, СОМ); ♦ использование промежуточных файлов. В данном же разделе рассмотрим подробно второй вари- ант — использование промежуточных файлов для передачи изменений данных. Будем считать, что известно, какими данными необходимо обмениваться. Тогда необходимо определиться с форматом файла передачи данных. С точ- ки зрения ЮПредприятия можно использовать различ- ные форматы файлов. Наиболее часто обмен реализуется посредством: ♦ текстовых файлов; ♦ файлов dbf; ♦ XML-документов. Рассмотрим все три варианта на примере задачи выгруз- ки и загрузки справочника Номенклатура. Считаем, что элемент справочника характеризуется (с точки зрения за- дачи обмена) следующими реквизитами: ♦ код элемента (тип Число); ♦ наименование элемента (тип Строка); ♦ закупочная цена (тип Число); ♦ единица измерения. Работа с текстом Работа с текстовыми файлами в ЮПредприятии может осуществляться в контексте двух моделей: ♦ работа в модели последовательного доступа (объекты ЗаписьТекста, ЧтениеТекста); ♦ работа с текстовым документом, который полностью загружается в память (объект ТекстовыйДокунент, эле- мент управления ПолеТекстовогоДокунента). При использовании модели последовательного доступа, как при чтении, так и при записи, обрабатывается опреде- ленный «фрагмент» текста. Доступ к таким фрагментам осуществляется последовательно. Нельзя «перескочить» какой-либо фрагмент. Рассмотрение возможностей работы с текстовыми файла- ми начнем с модели, в которой содержимое файла загру- жается полностью. Прежде чем приступить к реализации обмена посредст- вом текстовых файлов, сторонам (между которыми будет производиться обмен) необходимо «договориться» о ло- гической структуре этого файла: ♦ вариант использования текста: с фиксированной дли- ной полей, с переменной длиной полей; ♦ если выбран вариант с переменной длиной полей, то ка- кой используется разделитель; ♦ последовательность следования данных; ♦ возможная структура текстового документа и т. д. Считаем, что в результате были достигнуты следующие договоренности. В первой строке текстового документа с позиции №1 по позицию 39 включительно указывается наименование ор- ганизации — отправителя данных. Далее указывается дата отправки в формате «ДД.ММ.ГГГГ», то есть первые две цифры — это день месяца, далее две цифры — это но- мер месяца, далее четыре цифры — это номер года. В каждой следующей строке выгружается элемент спра- вочника Номенклатура. Последовательно производится выгрузка кода, наименования, закупочной цены, наиме- нования единицы измерения. Выгружаемые значения заключаются в кавычки, разделителем значения счита- ется «,». Для включения как запятой, так и кавычек в выгружаемые данные используется символ «\». То есть для включения строки Комплект «Подарочный», на 4 персоны она должна быть преобразована к виду: «Комплект \«Пода- рочный\”\, на 4 персоны». Пример файла, который будет использоваться при обме- не, приведен в листинге 14.1. Листинг 14.1. Пример файла обмена ООО "Быстрее Выше Сильнее” 20.01.2006 "7","Атлант МХМ 1704-00".,Т4000"."шт" Только после фиксирования подобных договоренностей можно приступать к реализации механизмов выгрузки и загрузки.
Текстовый документ, поле текстового документа Для иллюстрации возможностей работы с текстовым фай- лом (с использованием объекта ТекстовыйДокунент и элемен- та управления ПолеТекстовогоДокунента) создадим обработ- ку, в которой будет производиться чтение и запись текста. В диалоге основной формы обработки разместим эле- мент управления ПолеТекстовогоДокунента с именем ПолеТД (рис. 14.1). Рис. 14.1. Вставка поля текстового документа Для записи данных из справочника в текстовый доку- мент может использоваться следующий программный код (листинг 14.2-14.4). Инициирует процесс записи процедура Записать (см. лис- тинг 14.4). В процедуре производится создание объекта ТабличныйДокунент. Запись строки в файл производится ме- тодом ДобавитьСтрокуОтекстового документа. Для получения заголовка (первой строки) используется функция СформироватьЗаголовок (см. листинг 14.3), для записи элемента справочника в строку используется функция ЭлементВСтроку (см. листинг 14.2). Эти две функ- ции реализуют достигнутые при переговорах о формате файла «договоренности». Листинг 14.2. Функция ЭлементВСтроку Функция ЭленентВСтрокуфленент) Результат = СтрЗаменить(Элемент.Наименование, И Заменить символы ” и , на \" и \. Результат = СтрЗаменить(Результат. Символ(34), "\" + Символ(34)); Результат = Символ(34) + Строка(Элемент.Код) + Символ(34) + + Символ(34) + Результат + Символ(34); И Убирать пробелы из строкового представления числа Цена = СтрЗаменить(СтрокаОлемент.ЗакупочнаяЦена). " ", Результат = Результат + "+ Символ(34) + Цена + Символ(34) + + Символ(34) + Строка(Элемент.ЕдиницаИзмерения) + Символ(34); Возврат Результат; КонецФункции Листинг 14.3. Функция СформироватьЗаголовок Функция СформироватьЗаголовок(НаименованиеКомпании) Результат = СокрЛП(НаименованиеКомпании); КоличествоСимволов = СтрДлина(Результат): Для Счетчик = КоличествоСимволов По ЗВ Цикл Результат = Результат + " КонецЦикла; СтрокаДаты = Формат(РабочаяДата, "ДЛФ=О"): Результат = Результат + СтрокаДаты; Возврат Результат; Листинг 14.4. Процедура Записать Процедура Записать(Кнопка) И Необходимо установить реальный путь Путь = "с:\": ТД = Новый ТекстовыйДокунент; И Кодировка UTF8 является кодировкой по умолчанию ТД.УстановитьТипФайла(КодировкаТекста.иТР8): ТД.ДобавитьСтроку(СфориироватьЗаголовок( "Наименование компании”)); Выборка = Справочники.Номенклатура.ВыбратьО; Пока Выборка.Следующий() Цикл И Выгрузить только элементы справочника Если Не Выборка.ЭтоГруппа Тогда ТД. ДобавитьСтрокуОлементВСтроку(Выборка)); КонецЕсли; КонецЦикла; ТД.Записать(Путь + "nomen.txt"); КонецПроцедуры Для чтения данных из полученного файла может исполь- зоваться следующий программный код (листинг 145 и 14.6). Листинг 14.5. Функция РазобратьСтроку Функция РазобратьСтроку(СтрокаДляРазбора) Результат = Новый СтруктураС'Код, Наименование, Цена, ЕдиницаИзмерения"); И Прочитать код Позиция = Найти(СтрокаДляРазбора. ",”); Код = Сред(СтрокаДляРазбора, 2. Позиция - 3); Результат.Код = Код; И Отрезать прочитанный фрагмент СтрокаДалее = Сред(СтрокаДляРазбора. Позиция + 2); И Прочитать наименование Позиция = Найти(СтрокаДалее. "."); Наименование = Сред(СтрокаДалее, 1, Позиция - 2); Результат.Наименование = Наименование; // И т. д. Возврат Результат; КонецФункции Листинг 14.6. Процедура Прочитать Процедура Прочитать(Кнопка) И Необходимо установить реальный путь Путь= "с:\"; ТД = Новый ТекстовыйДокунент; ТД.Прочитать(Путь + "nomen.txt"); Заголовок = ТД.ПолучитьСтроку(1); НазваниеОтправителя = СокрЛП(Сред(Заголовок, 1. 39)); ДатаТекстом = СокрЛП(Сред(Заголовок, 40)); Для ТекущаяСтрока = 2 По ТД.КоличествоСтрокО Цикл ПрочитаннаяСтрока = ТД.ПолучитьСтроку(ТекущаяСтрока); Значение = РазобратьСтроку(ПрочитаннаяСтрока); КонецЦикла; КонецФункции КонецПроцедуры
Процесс чтения начинается с выполнения процедуры Прочитать (см. листинг 14.6). Для чтения создается объект ТекстовыйДокунент. При выполнении его метода Прочитать!) файл полностью загружается в оперативную память. По- лучение строк производится с помощью метода Получить - Строку!) текстового документа. Функция РазобратьСтроку (см. листинг 14.5) извлекает из строки данные по элементу справочника, исходя из дого- воренностей по формату данных. Разбор заголовка реа- лизован в процедуре Прочитать (см. листинг 14.6). Более подробно о текстовом документе можно прочитать в разделе «Текстовый документ», с. 465. Отображение текстового документа До сих пор для работы с текстовым файлом использовались возможности объекта ТекстовыйДокунент. Пришло время рассмотреть возможности элемента управления ПолеТек- стовогоДокумента. Для чтения и отображения в диалоге содержимого тек- стового документа может использоваться следующая про- цедура (листинг 14.7). Листинг 14.7. Процедура Просмотр Процедура Просмотр(Кнопка) // Необходимо установить реальный путь Путь = "с:\": ЭлементыФормы.ПопеТД.Очистить!): ЭлементыФормы.ПолеТД.Прочитать(Путь + "nomen.txt"): ЭлементыФормы.ПолеТД.ВставитьСтроку!1. "Показывается в оригинальном виде"); КонецПроцедуры Перед выводом текстового документа элемент управле- ния очищается, после вывода в качестве первой вставля- ется строка «Показывается в оригинальном виде» (она «сдвигает» ранее загруженные строки). Пользователь может проводить любые корректировки представленного в элементе управления текста, записать результат работы в файл, можно воспользоваться сле- дующей процедурой (листинг 14.8). Листинг 14.8. Процедура записи результата в файл Процедура ЗаписьИзПоля(Кнопка) // Необходимо установить реальный путь Путь = "с:\"; ЭлементыФормы.ПолеТД.Записать(Путь + "result.txt"): ЭлементыФормы. ПолеТД. Очистить О; КонецПроцедуры После записи элемент управления очищается (это можно и не делать). При работе с текстовыми файлами в 1С:Предприятии следует учитывать особенности представления раздели- телей строк в файлах Windows и в тексте, используемом для обработки «внутри» 1С:Предприятия. Для целей внутренней обработки текста используется разделитель, состоящий из одного символа, в то время как в файлах Windows в качестве разделителя строк используется ком- бинация из двух последовательных символов. Внутри 1С:Предприятия разделителем строк является символ Символы.ПС, он же «LF» (Line Feed, Перевод Строки), который имеет шестнадцатеричный код ОА. В то же время в кодировке текстовых файлов для Windows принято, что разделителем строк является пара символов — «CR-LF». «CR» (Carriage Return, Возврат Каретки), имеет шестна- дцатеричный код 0D. При записи и чтении текстовых файлов 1С:Предприятие производит преобразование внутренних разделителей строк в представление, принятое в текстовых файлах Windows. То есть при записи символ «ПС» («LF») преоб- разуется в пару символов «ВК-ПС» («CR-LF»). При чте- нии происходит обратное преобразование, то есть пара «ВК-ПС» («CR-LF») преобразуется в одиночный символ «ПС» («LF»). Символ «ВК» («CR») при записи файла не преобразуется и не выбрасывается, то есть попадает в файл как есть. При чтении файла символы «ВК» («CR») и «ПС» («LF»), не образующие пару, также считываются без преобразо- ваний. Модель последовательного доступа В ранее рассмотренном примере работы с текстовыми файлами содержимое файла загружалось в оператив- ную память полностью. При работе с файлами большого размера такой подход может привести к замедлению об- работки данных из файла. В этом случае можно восполь- зоваться возможностью 1С:Предприятия работать с тек- стовыми файлами в рамках модели последовательного доступа. Данная модель реализована объектами ЗаписьТекста и Чте- ниеТекста. Для записи данных может использоваться следующая процедура (листинг 14.9). Листинг 14.9. Пример записи текста Процедура ПоследовательнаяЗапись(Кнопка) // Необходимо установить реальный путь Путь = "с:\": ЗаписьТекста = Новый ЗаписьТекста(Путь + "nomen.txt". КодировкаТекста.UTFB); ЗаписьТекста. ЗаписатьСтроку(СформироватьЗаголовок( "Наименование компании")); Выборка = Справочники.Номенклатура.ВыбратьО; Пока Выборка. Следующий О Цикл ЗаписьТекста. ЗаписатьСтрокуОлементВСтроку(Выборка)): КонецЦикла; ЗаписьТекста.Закрыт ь(); КонецПроцедуры Текст функций СформироватьЗаголовок и ЭлементВСтроку приводился ранее (см. листинги 14.2 и 14.3). Для чтения данных может использоваться следующая процедура (листинг 14.10). Следует отметить, что чтение данных может осуществ- ляться не только построчно, но и по указанному коли- честву символов (метод Прочитать!) объекта Чтение- Текста).
Листинг 14.10. Пример чтения текста Процедура ПоследовательноеЧтение(Кнопка) // Необходимо установить реальный путь Путь = "с:\": Текст = Новый ЧтениеТекста(Путь + "nomen.txt", КодировкаТекста.1ЛТ8); // Считать первую строку ПрочитаннаяСтрока = Текст.ПрочитатьСтроку(): НазваниеОтправителя = СокрЛП(Сред(ПрочитаннаяСтрока. 1, 39)); ДатаТекстом = СокрЛП(Сред(ПрочитаннаяСтрока. 40)); // Цикл выполняется, пока не будет достигнут конец файла Пока ПрочитаннаяСтрока <> Неопределено Цикл ПрочитаннаяСтрока = Текст. ПрочитатьСтрокуО: Значение = РазобратьСтроку(ПрочитаннаяСтрока); КонецЦикла: КонецПроцедуры Работа с DBF Для работы с базами данных формата DBF (dBase III) в системе имеется специальный объект — XBase. Меха- низм работы с базами данных формата DBF предназна- чен для обеспечения возможности манипулирования ими непосредственно из встроенного языка системы 1 (^Пред- приятие. Возможно практически любое манипулирова- ние данными. Помимо работы с существующими базами данных, объ- ект XBase имеет набор методов, позволяющих создать но- вую базу данных произвольной структуры, новые индек- сы и новый индексный файл. Следует отметить, что если использование методов, изменяющих структуру базы данных, возможно только для объектов, не связанных с существующей базой данных (то есть для вновь создавае- мых баз данных), то создание новых индексов и индекс- ного файла возможно как для создаваемых баз данных, так и для уже существующих и открытых. Для записи данных в файл DBF может использоваться следующий фрагмент кода (листинг 14.11). Листинг 14.11. Пример записи данных в файл DBF Путь = "с:\": БД = Новый XBase: БД.Поля.ДобавитьС'СООЕ", "S". 5): БД.Поля.ДобавитьС'МАМЕ", "S", 40); БД.Поля.ДобавитьССОБТ", "N", 5. 0): БД.Поля.ДобавитьС"ED", "S", 10); БД.СоздатьФайл(Путь + "nomen.dbf". Путь + "index.cdx"); БД.Индексы. ДобавитьСЮХСООЕ". "CODE"); ИБД = БД.СоздатьИндексныйФайл(Путь + "index.cdx"); БД.Автосохранение = Истина; Выборка = Справочники. Номенклатура. ВыбратьО: Пока Выборка.Следующий() Цикл БД.ДобавитьО; БД.CODE = Выборка.Код; БД.NAME = Выборка.Наименование: БД.COST = Выборка.ЗакупочнаяЦена; БД.ЕО = Выборка.ЕдиницаИзмерения; КонецЦикла; БД.ЗакрытьФайлО; Создается файл, у которого определяются четыре поля (CODE, NAME, COST, ED). Поле COST имеет числовой тип, ос- тальные поля имеют строковый тип. У создаваемого DBF-файла определяется один индекс- ный файл. Следует отметить, что у DBF-файла может быть определено несколько индексов, но создаваемый при этом индексный файл всегда один. При записи данных следует обращать внимание на свой- ство АвтоСохранение объекта XBase. Если оно установлено в значение Истина, то добавление записи в файл произво- дится при вызове следующего метода ДобавитьО (создаю- щего новую запись). Для чтения данных может использоваться следующий фрагмент кода (листинг 14.12). Листинг 14.12. Пример чтения данных из файла DBF Путь = "с:\": БД = Новый XBase; БД.ОткрытьФайл(Путь + "nomen.dbf". Путь + "index.cdx"); Пока БД.СледующаяО Цикл Сообщить(БД.CODE + БД.Name): КонецЦикла; БД.ЗакрытьФайлО; В приведенном фрагменте не используется определен- ный при записи индекс, порядок отображения дан- ных может быть следующий (фактически это соответст- вует физическому положению записей в файле) (лис- тинг 14.13). Листинг 14.13. Порядок отображения данных 6 ELECTROLUX ER 9007 8 3 Indesit WS 105 TX 7 Атлант МХМ 1704-00 2 СтиральнАгбо TL 1000 EX-1 1 Стиральные машины 4 Холодильники Изменим код, добавив в него использование индекса (листинг 14.14). Листинг 14.14. Пример чтения данных из файла DBF Путь = "с:\"; БД = Новый XBase; БД.ОткрытьФайл(Путь + "nomen.dbf". Путь + "index.cdx"); БД.ТекущийИндекс = БД.Индексы.IDXCODE; Пока БД.Следующая() Цикл Сообщить(БД.CODE + БД.Name); КонецЦикла; БД.ЗакрытьФайлО; В этом случае в результате будут получены только сле- дующие записи (листинг 14.15). Листинг 14.15. Полученные записи 6 ELECTROLUX ER 9007 В 7 Атлант МХМ 1704-00 При выполнении метода Следующий () объект XBase пози- ционируется на записи, которая является физически пер- вой в файле. Однако с точки зрения используемого индекса она предпоследняя. Поэтому в результате выпол- нения данного кода из шести записей обходятся только две. Для того чтобы обойти все записи, необходимо явно ис- пользовать метод Первая(), как приведено ниже (лис- тинг 14.16). В результате будут получены все записи по возрастанию кода.
Листинг 14.16. Пример использования метода ПерваяО Путь = "с:\": БД = Новый XBase; БД.ОткрытьФайл(Путь + "nomen.dbf", Путь + "index.cdx"); БД.ТекущийИндекс = БД.Индексы.IDXCODE; Если БД.ПерваяО Тогда Сообщить(БД.С00Е + БД.Name); КонецЕсли; Пока БД.Следующая О Цикл Сообщить(БД.С00Е + БД.Name); КонецЦикла; БД.ЗакрытьФайлО; Индексы полезно использовать не только для упорядочи- вания выборок записей по какому-либо полю, но и для реализации каких-либо «поисковых механизмов». Рас- смотрим пример кода (листинг 14.17). Листинг 14.17. Пример чтения данных из файла DBF Путь = "с:\": БД = Новый XBase; БД.ОткрытьФайл(Путь + "nomen.dbf". Путь + "index.cdx"); Если БД.Найти("5", ">=") Тогда Пока БД.СледующаяО Цикл Сообщить(БД.Нате): КонецЦикла; КонецЕсли; БД.ЗакрытьФайлО; Выполнение данного кода приведет к получению следую- щей выборки (листинг 14.18). Листинг 14.18. Полученные записи 6 ELECTROLUX ER 9007 В 3 Indesit WS 105 ТХ 7 Атлант МХМ 1704-00 2 СтиральнАгЦо TL 1000 ЕХ-1 1 Стиральные машины 4 Холодильники Фактически это полная выборка (так как первая запись уже удовлетворяет условию поиска). Добавим использование индекса (листинг 14.19). Листинг 14.19. Пример чтения данных из файла DBF Путь = "с:\": БД = Новый XBase; БД.ОткрытьФайл(Путь + "nomen.dbf", Путь + "index.cdx"): БД.ТекущийИндекс = БД.Индексы. IDXCODE; Если БД.НайтиС’Б", ">=") Тогда Пока БД. Следующая О Цикл Сообщить(БД.Иате); КонецЦикла; КонецЕсли; БД.ЗакрытьФайлО; В результате будут получены только две записи (лис- тинг 14.20). Листинг 14.20. Полученные записи 6 ELECTROLUX ER 9007 В 7 Атлант МХМ 1704-00 Менять текущий индекс можно и во время выборки (одна- ко следует помнить, что при «умелой» манипуляции ин- дексами можно никогда не достигнуть конца DBF-файла). Работа с XML-документами Ранее были рассмотрены возможности работы с тексто- выми файлами и файлами DBF. К недостаткам рассмот- ренных подходов следует отнести тот факт, что обмен возможен после установки определенных «договоренно- стей». Фактически для каждого такого случая необходи- мо индивидуально создавать какие-либо обработки, реа- лизующие механизм записи и чтения данных из файлов представленного формата. При организации обмена боль- шим количеством типов данных (со сложной иерархией), алгоритмы данных механизмов будут получаться очень сложными и громоздкими. Отклонение от подобного формата в лучшем случае при- ведет к ошибке, в худшем к получению искаженных (не- правильно проинтерпретированных) данных, причем факт искажения может быть и не замечен даже при использо- вании этих данных (например, перепутали цену с количе- ством и т. п.). При таком подходе получается, что задача обмена очень часто решается в индивидуальном порядке. На каждый обмен — свой формат. К определенному моменту развития различных программ- ных комплексов, форматов обмена стало просто громад- ное количество. В итоге назрела необходимость в разра- ботке универсального формата обмена. В качестве такого универсального формата в 1991 году и был представлен язык XML (расширяемый язык разметки). Считается, что для организации обмена данными посред- ством XML-документов достаточно договориться только о факте обмена с использованием этого формата. Основные положения XML-документ в общем случае представляет собой файл с расширением xml, имеющий текстовое наполнение. Ис- ходя из этого, можно сказать, что самым простейшим редактором таких документов может служить Блокнот (Notepad), хотя существует довольно большое количест- во специализированных редакторов. Может возникнуть вопрос: если XML-докумеит имеет текстовое наполнение, то чем же он отличается от обыч- ного текстового файла (ведь можно сказать, что язык XML является частным случаем обмена посредством тек- стовых файлов), в чем его универсальность? Можно выделить несколько основных отличий: ♦ XML-документ создается по строгим правилам, внут- ри него соблюдается четкая иерархия составных час- тей, вместе с данными передается структура этих дан- ных; ♦ описание возможной структуры документа определяет- ся на специальном, формализованном языке (одном из нескольких), вследствие чего эта структура может быть программно разобрана (на приемной стороне можно разобрать возможную структуру, описанную на специ- альном языке, сопоставить структурные элементы до- кументами с метаданными системы и после этого про- извести загрузку данных); ♦ при работе с XML-документами используется объект- ный подход (а не разбор строки с помощью специаль- ных функций работы со строковыми значениями); ♦ формальное описание типов. Теперь если вернуться к универсальности XML-докумен- тов, то под ней понимается, что при необходимости про- извести обмен данными посредством XML-документов должны быть реализованы такие понятия, как:
♦ XML-документ с данными (созданный в соответствии со стандартом, определенным ко всем XML-документам); ♦ к документу существует описание его структуры, которое можно формально разобрать (схема XML-документа); ♦ определены пространства имен (в которых, в том числе, описаны типы данных, используемые в документе). Следует отметить, что, рассматривая особенности меха- низмов, позволяющих работать с XML-документами из ЮПредприятия, мы в дальнейшем не будем подробно касаться таких понятий, как пространство имен (описан- ное в нем пространство типов), схема XML-документа. Но необходимо отдавать себе отчет в том, что при органи- зации обмена с произвольными информационными сис- темами понадобится более детальная работа с ними. Пора перейти к рассмотрению структуры и общих прин- ципов формирования XML-документов. При рассмотрении внутреннего наполнения XML-доку- ментов в них можно выделить определенные формати- рующие конструкции. По аналогии с HTML (наверное, самый простой из языков разметки) их пока можно на- звать тегами. Под тегом будем понимать некое выраже- ние, заключенное в угловые скобки «выражение». Различают открывающий тег <тег> и закрывающий тег </тег> (отличие в наклонной черте перед именем тега). Если продолжать сравнение с языком разметки HTML, то в языке HTML набор тегов фиксирован. Теги HTML условно можно разделить на теги определения структуры документа и теги «форматирования» представляемых данных. К примеру, с тега <body> начинается основное тело HTML-документа, весь текст, попавший между тега- ми <Ь> и </Ь>, отображается полужирным и т. п. Для тегов можно задать значения характерных для них свойств. На- пример, <body text=red>. Свойство text определяет цвет текста тела документа по умолчанию (в примере он будет красным). Таким образом, изучение языка HTML сво- дится к ознакомлению с множеством тегов (их назначе- нием), свойств тегов и их возможных значений. В языке XML имена тегов не фиксированы, разработчик волен давать им собственные имена, определять у них произвольные свойства с любыми типами значений. В имени «тега» XML могут использоваться точки (прав- да, это может не поддерживаться рядом специализиро- ванных редакторов). В содержимом атрибутов, элемента пробелы и символы табуляции не игнорируются. Перейдем от термина «тег» к терминам более правиль- ным по отношению к XML-документу. Можно сказать, что минимальной логической единицей XML-документа является элемент. У элемента может быть определено не- сколько атрибутов (упрощенно атрибут можно назвать свойством элемента). У любого элемента может быть один (непосредственный) элемент владелец (его нет только у единственного корневого элемента XML-доку- мента) и любое количество подчиненных элементов (рис. 14.2). Следует отметить, что в различной литературе исполь- зуемая терминология может отличаться. То, что в данной главе называется элементом, может называться «узлом». В используемой нами терминологии понятие «узел» также встречается, но под ним понимается структурная часть элемента XML (такая как начало элемента, текст и т. д.). Рассмотрим структуру элемента XML (рис. 14.3). Рис. 14.2. Пример иерархии элементов XML Элемент Атрибут = "Значение атрибута" .Имя.эямиента. Содержимое элемента (может быть текст или другие элементы] /Имя элемента Открывающий тег Область действия тега Закрывающий тег Элемент вместе со всем содержимым Рис. 14.3. Схема элемента XML Пример, иллюстрирующий приведенную схему, приведен в листинге 14.21. Листинг 14.21. Пример элемента XML «Товар ИняСправочника = "Номенклатура" Код = "14">Ardo TL 1000 ЕХ-1«/Товар> В данной строке определен элемент с именем Товар. В на- чале элемента определяются два атрибута с именами ИмяСправочника и Код (соответственно со значениями Но- менклатура и 14). Между началом элемента и его концом (</Товар>) расположен текст элемента (его значение Ardo TL 1000 ЕХ-1). Вместо текста между тегами, описывающи- ми начало и конец элемента, может находиться описание вложенных элементов. Также допускается следующий вариант определения эле- мента XML-документа (рис. 14.4). ________________Элемент.________________________ ________________________________________________.Имаалемеита/_ф Атрибут = “Значение атрибута" J Открывающий и он же закрывающий тег Рис. 14.4. Схема элемента XML Вышепредставленная схема представляет следующий ва- риант описания элемента (листинг 14.22). Листинг 14.22. Пример элемента XML «Товар Код = "14" Наименование = "Ardo TL 1000 ЕХ-1"/> Данный вариант допустим, когда между открывающим и закрывающим тегом нет текста и нет вложенных эле- ментов. Поэтому вместо «Товар>«/Товар> допустима конст- рукция <Товар/>. В приведенном описании определяется элемента с именем Товар и два атрибута с именами Код и Наименование. Рассмотрим пример XML-документа (листинг 14.23). В первой строке XML-документа определяется директи- ва, указывающая на то, что данный документ с текстовым содержимым является XML-документом. Далее опреде- ляется элемент Корневой. Внутри него определяются дру-
гие элементы. Можно сказать, что в данном документе просматривается определенная древовидная структура (она показана на рис. 14.5). Листинг 14.23. Пример XML-документа <?xml version="1.0" ?> <Корневой> <DocumentDbject.Приходная> <Ref>4с0а4с73-905d-lldB-92а4-00030d0ca645</Ref> <Deleti onMark>false</DeletionMark> <Date>2004-04-17T14:52:43</Date> <Number>l</Number> <Posted>true</Posted> <KoHTpareHT>4c0a4c72-905d-lld8-92a4-00030d0ca645</KoHTpareHT> <Товары> <Row> «Номенклатура^ bfeaf4-831d - lld8 - 957e - 00c026abdd5e </Номенклатура> <Количество>10</Количество> <Цена>900</Цена> <Сумна>1000</Сумна> </Row> <Row> «Номенклатурам! bfeaf6 -831d - lldB - 957e - 00c026abdd5e </Номенклатура> <Количество>10</Количество> <Цена>1000«/Цена> <Сумма>10000</Сумма> </Row> </Товары> «/DocumentDbject.Приходная> </Корневой> Рис. 14.5. Древовидная структура XML-документа Эта структура обеспечивается тем, что у XML-документа всегда один корневой элемент, описание одного элемента всегда находится внутри описания другого элемента (ис- ключение составляет корневой элемент). Можно сказать, что древовидность структуры является обязательным при- знаком правильности оформленного XML-документа. При рассмотрении любого XML-документа можно гово- рить о его синтаксической правильности и корректности. Синтаксически правильный XML документ (упрощенно) удовлетворяет следующим условиям: ♦ язык XML чувствителен к регистру символов. Это обя- зательно нужно учитывать при описании начала и кон- ца элемента; ♦ все значения атрибутов, используемых в определении элементов, должны быть заключены в кавычки; ♦ каждому открывающему «тегу» соответствует закры- вающей «тег». Можно сказать, что XML-документ является совокупностью элементов. Два возможных ва- рианта описания элементов были представлены выше; ♦ элементы образуют древовидную структуру с одним корневым элементом (он обязательно один). Это дости- гается тем, что области «действия тегов» не могут пере- секаться (либо они «рядом», либо одна находится цели- ком внутри другой). Базовые средства ^Предприятие 8.0 для работы с XML В 1С:Предприятии существует базовая подсистема рабо- ты с XML-документами. Основой этой подсистемы явля- ются два объекта 1С:Предприятие: ♦ ЧтениеХМЬ; ♦ ЗаписьХМЕ. Данные объекты реализуют, при работе с XML-докумен- тами, модель последовательного доступа. Основная осо- бенность работы в этой модели заключается в том, что до- кумент не загружается полностью, работа идет только с текущим его фрагментом (частью элемента XML, напри- мер началом элемента, текстом элемента и т. д.). Поэтому при работе с документом нет возможности получать вы- борки элементов, «перепрыгивать» узлы и т. п. Запись данных в XML-документ Вернемся к задаче обмена данными об элементах спра- вочника Номенклатура. Рассмотрим пример использова- ния объекта ЗаписьХМЕ (листинг 14.24). Листинг 14.24. Пример записи XML-документа ЗаписьХМЕ = Новый ЗаписьХМЕ; ЗаписьХМЕ.ОткрытьФайл("с:\document.xml"); // Записать директиву ЗаписьХМЕ.ЗаписатьОбъявлениеХМЕ(): // Записать начало корневого элемента ЗаписьХМЕ.ЗаписатьНачалоЭлемента("Корневой"); // Записать атрибут корневого элемента ЗаписьХМЕ.ЗаписатьАтрибутС'ИмяСправочника". "Номенклатура"); ЗаписьХМЕ. ЗаписатьКомментарий("Выгрузка элементов справочника"): Выборка = Справочники.Номенклатура.ВыбратьО; Пока Выборка.Следующий() Цикл Если Не Выборка.ЭтоГруппа Тогда ЗаписьХМЕ.ЗаписатьНачалоЭлементаС'ЭлементСправочника"): ЗаписьХМЕ.ЗаписатьНачалоЭлемента("Код"); ЗаписьХМЕ.ЗаписатьТекст(Строка(Выборка.Код)); ЗаписьХМЕ. ЗаписатьКонецЭлементаО; ЗаписьХМЕ.ЗаписатьНачалоЭлемента("Наименование"); ЗаписьХМЕ.ЗаписатьТекст(Выборка.Наименование); ЗаписьХМЕ. ЗаписатьКонецЭлементаО; ЗаписьХМЕ.ЗаписатьНачалоЭлементаС’ЗакупочнаяЦена"): ЗаписьХМЕ.ЗаписатьТекст(Строка(Выборка.ЗакупочнаяЦена)); ЗаписьХМЕ. ЗаписатьКонецЭлементаО; ЗаписьХМЕ. ЗаписатьКонецЭлементаО; КонецЕсли; КонецЦикла; ЗаписьХМЕ. ЗаписатьКонецЭлементаО; ЗаписьХМЕ.Закрыть О;
В результате выполнения представленного кода будет по- лучен следующий XML-документ (листинг 14.25). Листинг 14.25. Полученный XML-документ <?xml version="1.0"?> «Корневой ИмяСправочника="Номенклатура"> <!--Выгрузка элементов справочника--> <ЭлементСправочника> <Код>5</Код> <Наименование>В05СН KGS 3760 IE </Наименование> <ЗакупочнаяЦена>24 000</ЗакулочнаяЦена> </ЭлементСправочника> <ЭлементСправочника> <Код>6</Код> <Наименование>ЕЕЕСТЯОЕиХ ER 9007 В</Наименование> <ЗакупочнаяЦена>38 000</ЗакулочнаяЦена> </ЗлементСправочника> «ЭлементСправочника* <Код>3</Код> <Наименование>1пбеэ11 WS 105 ТХ</Наименование> <ЗакупочнаяЦена>10 000</ЗакупочнаяЦена> </ЭлементСправочника> <ЭлементСправочника> <Код>7</Код> <Наименование>Атлант МХМ 1704-00</Наименование> <ЗакупочнаяЦена>14 000</ЗакупочнаяЦена> </ЭлементСправочника> <ЭлементСправочника> <Код>2</Код> <Наименование>Агс1о TL 1000 ЕХ-1</Наименование> <ЗакупочнаяЦена>8 000</ЗакулочнаяЦена> </ЭлементСправочника> </Корневой> Первой строкой кода создается объект ЗаписьХМЬ. Через созданный объект в модели последовательного доступа будет производиться запись данных в XML-документ. С помощью метода ОткрытьФайлО указывается имя файла, куда будет производиться запись данных. Метод Запи- сатьОбъявлениеХМК) определяет директиву, что создаваемый документ будет являться XML-документом (директива размещается в первой строке созданного документа). Для записи элемента XML-документа используются ме- тоды ЗаписатьНачалоЭлементаО, ЗаписатьАтрибутО, Записать- Текст!), ЗаписатьКонецЭлементаО, которые производят за- пись соответствующего узла элемента XML в файл. При этом важно соблюдать порядок (иерархию) вызова этих методов. Напомним, что элемент можно представить в виде сле- дующих узлов (листинг 14.26). Листинг 14.26. Узлы элемента XML <ИМЯ АТРИБУТ=Значение> Содержимое (Текст или описание другого элемента) </ИМЯ> Для записи вышепредставленного элемента можно ис- пользовать следующую последовательность методов (лис- тинг 14.27). Листинг 14.27. Пример записи элемента XML ЗаписьХМЕ.ЗаписатьНачалоЗлементаС'ИМЯ"): ЗаписьХМЕ.ЗаписатьАтрибут!"АТРИБУТ", "Значение"); ЗаписьХМБ.ЗаписатьТекст( "Содержимое (Текст или описание другого элемента)"); ЗаписьХМБ.ЗаписатьКонецЭлемента(); Следует обратить внимание на тот факт, что если при оп- ределении начала элемента в соответствующем методе указывается его имя, то при закрытии имя не указывается. Закрывается элемент открытый последним. В связи с этим следует внимательно относиться к последовательности ис- полняемых методов, чтобы не запутаться в иерархии (в ряде случаев для упрощения алгоритмов создания доку- ментов сложной структуры могут использоваться рекур- сивные вызовы процедур, ответственных за создание эле- ментов). Последовательность методов объекта ЗаписьХМБ, вызывае- мых при создании элементов, можно проиллюстрировать следующей схемой (рис. 14.6). Рис 14.6. Последовательность использования методов при записи XML-документа Правильный XML-документ содержит единственный кор- невой элемент, запись всего документа начинается с запи- си этого элемента. Запись любого элемента XML начинается с записи «от- крывающего тега» (начала элемента, выполняемого с по- мощью метода ЗаписатьНачалоЭленентаО). Только в контек- сте начала элемента можно записывать атрибуты XML- документа (используется метод ЗаписатьАтрибутО, вызы- ваемый последовательно для каждого атрибута). Запи- сать атрибут после записи текста или конца элемента нельзя. После записи начала элемента и всех его атрибутов мож- но провести запись текста (это означает, что у формируе- мого элемента XML нет вложенных элементов), или ре- курсивно перейти к записи другого вложенного элемента. После того, как либо текст, либо другой вложенный эле- мент (элементы) закрыты, производится запись конца элемента (метод ЗаписатьКонецЭлементаО). Чтение данных из XML-документа Объект ЧтениеХМЕ предназначен для чтения данных из XML-документа. Также как при записи данных, чтение элемента производится узлами. Перечень узлов опреде- лен в системном перечислении ТипУзлаХМЕ): ♦ НачалоЭлемента; ♦ Атрибут; ♦ Текст; ♦ КонецЭлемента;
♦ Ничего; ♦ ИнструкцияОбработки. Какой узел получен при чтении следующего структурно- го элемента, можно узнать, обратившись к свойству Тип- Узла объекта ЧтениеХМЕ. Будем исходить из того, что необходимо прочитать сле- дующий XML-документ (полученный при выгрузке с по- мощью объекта ЗаписьХМЕ) (листинг 14.28). Листинг 14.28. Читаемый XML-документ «?xml version="1.0"?> «Корневой ИняСправочника="Номенклатура''> «•--Выгрузка элементов справочника--» «ЭлементСправочника» «Код>5«/Код> «Наименование»В05СН KGS 3760 IE «/Наименование» <ЗакупочнаяЦена»24 000«/ЗакупочнаяЦена» «/ЭлементСправочника» «ЭлементСправочника» «Код»6«/Код> «Наименование»ЕЕЕСТКОШХ ER 9007 В«/Наименование> <ЗакупочнаяЦена»38 000«/ЗакупочнаяЦена» «/ЭлементСправочника» «ЭлементСправочника» «Код»3«/Код> «Наименование»1пбе511 WS 105 ТХ«/Наименование> «ЗакупочнаяЦена>10 000«/ЗакупочнаяЦена» «/ЭлементСправочника» «ЭлементСправочника» «Код»7«/Код» «Наименование»Атлант МХМ 1704-00«/Наименование> «ЗакупочнаяЦена>14 000«/ЗакупочнаяЦена» «/ЭлементСправочника» «ЭлементСправочника» «Код»2«/Код> «Наименование»Агбо TL 1000 ЕХ-1«/Наименование> «ЗакупочнаяЦена>8 000«/ЗакупочнаяЦена» «/ЭлементСправочника» «/Корневой» Пример использования объекта ЧтениеХМЕ (листинг 14.29). Листинг 14.29. Чтение XML-документа Файл = Новый ЧтениеХМЕ; Файл.ОткрытьФайл("с:\document.xml"); // Прочитать фрагменты элемента Пока Файл.Прочитать!) Цикл // После чтения проверить тип узла Если Файл.ТипУзла = ТипУзлаХМЕ.НачалоЭлемента Тогда Сообщить(Файл.Имя); // Прочитать атрибуты Пока Файл.ПрочитатьАтрибутО Цикл Сообщить("атрибут:” + Файл.Имя + "=" + Файл.Значение); КонецЦикла; КонецЕсли; Если Файл.ТипУзла = ТипУзлаХМЕ.Текст Тогда Сообщить(Файл.Значение); КонецЕсли; Если Файл.ТипУзла = ТипУзлаХМЕ.КонецЭлемента Тогда СообщитьС'/" + Файл.Имя); КонецЕсли; КонецЦикла; Файл.Закрыть!); Процесс чтения начинается с создания объекта ЧтениеХМЕ. С помощью метода ОткрытьФайл О производится указание файла, из которого в дальнейшем будет производиться чтение данных. Само чтение осуществляется с помощью метода ПрочитатьО. Данный метод возвращает значение Истина, в случае если получилось позиционироваться на следующем узле элемен- та XML. Для того чтобы понять, какой узел является теку- щим, производится обращение к свойству ТипУзла. В случае если это НачалоЭленента, можно провести выборку атрибутов (они существуют только в контексте начала элемента). После того, как метод ПрочитатьО возвращает значение Ложь (достигнут конец документа) работа с XML-доку- ментом завершается вызовом метода Закрытье. Порядок работы с объектом ЧтениеХМЕ можно проиллюст- рировать следующей схемой (рис. 14.7). Рис. 14.7. Последовательность использования методов при чтении XML-документа Общий принцип работы довольно прост. Открывается XML-документ, далее в цикле выполняется метод Прочи- татьО. После чтения анализируется тип полученного узла. В зависимости от типа предпринимаются некие специфи- ческие действия по извлечению данных. В случае если полученный узел является началом элемента, предприни- мается попытка получить все атрибуты, которые могут быть в нем определены. XML-сериализация Как уже говорилось ранее, XML-документ имеет текстовое содержимое. Это в первую очередь означает, что при за- писи в него любого значения (числа, даты, ссылки на объ- ект и т. д.) оно преобразуется к строке. При получении данных возникает обратная задача по преобразованию значения из строкового в нужный тип. С одной стороны, с помощью базовых средств чтения и записи документов XML можно решить любую задачу, связанную с организацией обмена. Но решение задачи преобразования типов в строковый и обратно потребует от разработчика очень больших затрат времени (на само- стоятельную реализацию данных преобразований). При- дется в полной мере работать со стандартными типами (W3C), определять собственное пространство имен (для описания некоторых типов ЮПредприятия в XML) и т. д.
Альтернативным (более простым и удобным) решением данной задачи может быть использование уже реализо- ванных средств XML-сериализации. С точки зрения данной системы каждый объект данных ЮПредприятия представляется как элемент XML-до- кумента. Этот элемент может иметь подчиненные эле- менты. Как раз с этой точки зрения (есть у элемента под- чиненные или нет) типы значений делятся на простые и сложные. К простым типам данных относятся типы, значения ко- торых представляются подсистемой XML-сериализации в виде элементов XML только с текстовым содержимым (листинг 14.30). Листинг 14.30. Пример сериализации значения ссылки на справочник <CatalogRef.Номенклатура> 17Ba492a-3fd4-llda-alf2-0011d8388a5d </CatalogRef.Номенклатура> Значения сложных типов представляются в виде эле- ментов XML, содержащих вложенные элементы (лис- тинг 14.31). Листинг 14.31. Пример сериализации значения типа УдалениеОбъекта <vB:ObjectDeletion xmlns="http://vB.lc.ru/data"> <v8:Ref xsi:type="CatalogRef.Банки"> 60c5cec3-7f6f-4ec3-9620-e757fe3614ca </v8:Ref> </v8:ObjectDeleti on> Если проанализировать типы, которые требуется подвер- гать преобразованию то их можно разделить на три группы: ♦ типы, которым можно найти «прямое» соответствие в типах, определенных в документе XML Schema Part 2: Datatypes консорциума W3C (пространство имен - http://www.w3.org/2001/XMLSchema). Значения данных типов могут представляться в виде элемента с тексто- вым содержимым; ♦ предопределенные типы ЮПредприятия 8.0 (простран- ство имен — http://v8.lc.ru/data). Эти типы не зависят от структуры метаданных и существуют в любой ин- формационной базе. Исходя из этого, имеет смысл опи- сать их в специализированном пространстве имен. Они могут относиться как к простым типам, так и к слож- ным; ♦ типы, производные от метаданных конфигурации 1С:Предприятия 8.0. Наличие таких типов зависит от состава и специфики определения объектов конфигура- ции. В каждой информационной базе они могут иметь произвольную реализацию. Исходя из этого, нет воз- можности описать все возможные варианты этих типов в каком-либо пространстве имен (при создании объек- та конфигурации разработчик имеет столько степеней свободы, что описать все возможные варианты созда- ваемых объектов в принципе невозможно). В итоге, та- кие типы не относятся ни к какому пространству имен и тоже могут являться как простыми, так и сложными типами (например, ссылка на объект относится к про- стым типам, сам объект — к сложным). При рассмотрении примеров представления различных значений в XML и при дальнейшем изложении будем ис- ходить из предположения, что определены следующие соответствия пространств имен (после xmLns определены их префиксы): ♦ xml ns:xsd=”http://www. w3.org/2001/XMLSchema”; ♦ xml ns:xsi="http://www.w3.org/2001/XMLSchema-instance"; ♦ xml ns:v8="http://v8.lc.ru/data". К простым типам, с точки зрения представления в XML, относятся следующие типы ЮПредприятия: ♦ Число; ♦ Строка; ♦ Дата; ♦ Булево; ♦ ДвоичныеДанные; ♦ Null; ♦ УникапьныйИдентификатор; ♦ ХранилищеЗначения; ♦ все ссылки на объекты базы данных; ♦ ссылки на перечисления, определяемые в метаданных. К сложным типам, значения которых могут быть пред- ставлены в XML, относятся следующие типы: ♦ Тип; ♦ ОписаниеТипов; ♦ КонстантаМенеджерЗначения.<имя>; ♦ все объекты базы данных; ♦ наборы записей регистров, последовательностей, пере- расчетов; ♦ УдалениеОбъекта. Простые типы Рассмотрим различные варианты представления значе- ний простых типов в XML-документе. Число Типу Число соответствует тип данных XML decimal из пространства имен http://www.w3.org/2001/XMLSchema (пре- фикс xsd). Правила представления значений данного типа определе- ны в документе XML Schema Part 2: Datatypes. Ниже приве- дены примеры представления значений типа Число в XML (листинг 14.32). Листинг 14.32. Варианты представления значения типа Число — 3.14156 <!-- Не задано явно имя корневого элемента --> <deci mal>3.14156</deci mal> <!-- Явно задано имя корневого элемента XML --> <Amount>3.14156</Amount> <!-- Явно указан тип данных XML --> <Data xsi:type="xsd:decimal">3.14156</Data> В первом случае имя типа (пространство имен http:// www.w3.org/2001/XMLSchema) совпадает с именем элемен- та, в котором передается значение. Во втором случае именем узла является имя переменной (свойства, рекви- зита), из которого/в который должна производиться за- пись. В третьем случае тип определен явно. Использует- ся тот факт, что в пространстве имен с префиксом xsi определена возможность использования такого атрибута
как type. С помощью значения этого атрибута может ука- зываться тип, который был преобразован к строковому и размещен в тексте элемента XML. В нашем случае указа- но, что при загрузке текст «3.14156» необходимо интер- претировать как тип decimal из пространства имен с пре- фиксом xsd. Строка Типу Строка соответствует тип данных string из простран- ства имен http://www.w3.org/2001/XMLSchema. Строка за- писывается в XML как есть. Ниже приведены примеры представления в XML значе- ний типа Строка (листинг 14.33). Листинг 14.33. Варианты представления значений типа Строка <! Не задано явно имя корневого элемента --> <string>3ro такая cTpoKa</string> <!-- Явно задано имя корневого элемента XML --> <Мате>Иванов</Иате> <! Явно указан тип данных XML --> <Data xsi:type="xsd:string">3T0 такая crpoKa</Data> Дата Значения типа Дата представляются в виде CCYY-MM- DDTHH:MM:SS, где CCYY — год, представленный в виде 4-х цифр, ММ — месяц, представленный 2-мя циф- рами, DD — день месяца 2-мя цифрами, Т — латинская буква Т, НН — час суток, ММ — минута, SS — секунда. Такой формат даты определен как допустимый в доку- менте XML Schema Part 2: Datatypes. Ниже приведены примеры представления в XML значе- ний типа Дата, (листинг 14.34). Листинг 14.34. Варианты представления значений типа Дата <!-- Не задано явно имя корневого элемента -> «dateT1me>2003-11-21Т12:00:00</dateT1me> <! Явно задано имя корневого элемента XML --> <Started>200110-30Т19:00:00</Started> <!-- Явно указан тип данных XML --> <Data xsi:type=’’xsd:dateTime">1980-08-25T10:00:00</Data> Булево Типу Булево соответствует тип данных boolean из про- странства имен http://www.w3.org/2001/XMLSchema. Значения Ложь представляется строкой false, а значение Истина — строкой true. Такой формат предусмотрен в до- кументе XML Schema Part 2: Datatypes. Ниже приведены примеры представления в XML значе- ний типа Булево (листинг 14.35). Листинг 14.35. Варианты представления значений типа Булево <!-- Не задано явно имя корневого элемента -> <Ьоо1 ean>fal se</bool ean> <!-- Явно задано имя корневого элемента XML --> <Posted>true</Posted> <!-- Явно указан тип данных XML --> «Data xsi:type="xsd:boolean">true</Data> ДвоичныеДанные Типу ДвоичныеДанные соответствует тип данных XML base64Binary из пространства имен http://www.w3.org/2001/ XMLSchema. Значения данного типа представляются как двоичные данные, закодированные с использованием алгоритма Base64, описанного в RFC 2045. Ниже приведены примеры представления в XML значе- ний типа ДвоичныеДанные (листинг 14.36). Листинг 14.36. Варианты представления значений типа ДвоичныеДанные <!-- Не задано явно имя корневого элемента --> <base64Bi nary>YWJjZGVm</base64Binary> <!-- Явно задано имя корневого элемента XML --> <Bi naryData>YWJjZGVm«/Bi naryData> <!-- Явно указан тип данных XML --> «Data xsi:type="xsd:base64Binary“>YWJjZGVm«/Data> Null Типу Null соответствует тип данных XML Null из про- странства имен http://v8.lc.ru/data. Данный тип имеет од- но-единственное значение, которое представляется пус- той строкой. Ниже приведены примеры представления в XML значе- ний типа Null (листинг 14.37). Листинг 14.37. Варианты представления значения типа Null <!-- Не задано явно имя корневого элемента --> <v8:Null/> <!-- Явно задано имя корневого элемента XML --> <Selected/> <!-- Явно указан тип данных XML --> «Data xsi:type="vB:Null’7> УникальныйИдентификатор Типу УникальныйИдентификатор соответствует тип данных XML UUID из пространства имен http://v8.lc.ru/data. Значения данного типа представляются в XML в соответ- ствии с общепринятой практикой и стандартами (ISO- 11578, DCE 1.1: Remote Procedure Call — Universal Unique Identifier). Ниже приведены примеры представления в XML значе- ний типа УникальныйИдентификатор (листинг 14.38). Листинг 14.38. Варианты представления значений типа УникальныйИдентификатор «!-- Не задано явно имя корневого элемента --> «v8:UUID>3294be0f-c039-41a9-bd65-596da0dcfe68«/vB:UUID> «!-- Явно задано имя корневого элемента XML --> «Id>da035e32-3f7a-4d87-9c6d-accf7db8cb4b«/Id> «!-- Явно указан тип данных XML --> «Data xsi:type="vB:UUID">08893b0b-5ec3-4a53-a9f5-173312316919 «/Data> ХранилищеЗначения Типу ХранилищеЗначения соответствует тип данных XML Valuestorage из пространства имен http://v8.lc.ru/data.
Значения данного типа представляются в XML как дан- ные ХранилищеЗначения, сохраненные в файл, а затем зако- дированные с использованием алгоритма Base64. Ниже приведены примеры представления в XML значе- ний типа ХранилищеЗначения (листинг 14.39). Листинг 14.39. Варианты представления значений типа ХранилищеЗначения <!-- Не задано явно имя корневого элемента <v8: Vai ueStorage>AQEDAft<W^AAA0+7v3si Uy I si jHQoSJ9 </v8:VaiueStorage> <!-- Явно задано имя корневого элемента XML --> <Data>AQE0AAVAAVA0+7v3siUyIsIjHQoSJ9</Data> <!-- Явно указан тип данных XML --> <Data xsi:type="v8:ValueStorage"> AQE: AAAAAA/'.‘lAD+7v3si Uy I si jHQoS J9 </Data> ПРИМЕЧАНИЕ В используемом примере, а также в других примерах дан- ной главы присутствуют длинные строки (например, «<Data xsi:type="v8:ValueStorage">AQEOAAAAAAAAAO+ 7v3siUylsljHQoSJ9</Data>»). В книге они приводятся в не- сколько строк. Реально такие строки записываются в моду- ле в одну строку. Тип ссылки на объект базы данных Каждому из типов ссылок на объекты базы данных соот- ветствует свой собственный тип данных XML. Имя типа данных XML для ссылок на объекты базы данных соот- ветствует англоязычному имени типа значения ссылки 1 С: Предприятия. Так, например, для справочника Валюты англоязычное имя типа ссылки будет выглядеть как CataLogRef-Валюты. Также будет выглядеть и имя типа данных XML. Типы данных XML для ссылок на объекты базы данных не относятся ни к какому пространству имен (зависит от определенных в конфигурации объектов метаданных). Значения ссылок представляются в XML как значения типа УниальныйИдентификатор, полученные из ссылок. Ниже приведены примеры представления в XML значе- ний ссылок на объекты базы данных (листинг 14.40). Листинг 14.40. Варианты представления значений типа ссылки на объект базы данных <!-- Не задано явно имя корневого элемента --> <CatalogRef.8aHKM>911b5b8b-llf5-4993-9673-2c9a7aB995d5 </CatalogRef.Банки> <!-- Явно задано имя корневого элемента XML --> <Ref>911b5b8b-Ilf5-4993-9673-2c9a7a8995d5</Ref> <!-- Явно указан тип данных XML --> <Data xsi:type="CatalogRef.Банки"> 911b5b8b-Ilf5-4993 -9673 -2c9a7a8995d5 </Data> Тип ссылки на значение перечисления Каждому из типов ссылок на значения перечислений, оп- ределенных в конфигурации, соответствует свой собст- венный тип данных XML. Имя типа данных XML для ссылок на значения перечисления соответствует англо- язычному имени типа ЮПредприятия. Так, например, для перечисления ВидыАдресов англоязыч- ное имя типа ссылки на значение будет выглядеть как Ел umRef. ВидыАдресов. Также будет выглядеть и имя типа данных XML. Типы данных XML для ссылок на значения перечислений не относятся ни к какому пространству имен (также опре- деляются структурой любой конфигурации ЮПредпри- ятия). В XML ссылки на значения перечислений пред- ставляются в виде имени соответствующего значения перечисления. Ниже приведены примеры представления в XML ссылок на значения перечислений (листинг 14.41). Листинг 14.41. Варианты представления значений типа ссылки на значение перечисления <!-- Не задано явно имя корневого элемента --> <ЕпитНеСВидыАдресов>К1ридический</ЕпитНеС ВидыАдресов > <!-- Явно задано имя корневого элемента XML --> <ВеЕ>Юридический</ВеГ> <!-- Явно указан тип данных XML --> <Data xsi:type="EnumRef.ВидыАдресов">Физический</0аТа> Работа с простыми типами Для работы с XML-представлениями значений простых типов предназначены два метода глобального контек- ста — ХМЕСтрокаО и ХМЬЗначениеО. Метод ХМЕСтрокаО имеет единственный параметр — значе- ние, для которого нужно получить XML-представление. Это значение должно относиться к типу, являющемуся простым с точки зрения XML-сериализации. В против- ном случае будет вызвано исключение. При нормальном завершении функция возвращает строку, которая может быть использована как текст элемента XML, представ- ляющего значение простого типа. Метод ХМЕЗначениеО выполняет противоположную зада- чу. У этого метода два параметра. Первый параметр — тип значения, которое нужно получить из строки, второй па- раметр — сама строка. Для преобразования типа данных ЮПредприятия в тип данных XML, и наоборот, предназначены методы ХМЬТипО и ИзХМЕТипаО. Метод ХМЕТипО имеет один параметр — тип, для которого надо получить соответствующий тип дан- ных XML. Если соответствующий тип данных XML опре- делен, то метод возвращает значение типа ТипДанныхХМЕ Если же соответствующего типа данных XML нет, то ме- тод возвращает значение Неопределено. Метод ИзХМЕТипаО имеет два варианта вызова. В первом варианте метод имеет единственный параметр типа ТипДанныхХМЕ. Во втором варианте параметра два: имя типа XML и пространство имен. В обоих случаях метод воз- вращает соответствующий типу данных XML тип данных ЮПредприятия, если таковой имеется, или Неопределено в противном случае. Рассмотрим пример использования вышеперечисленных методов. Считаем, что в контексте процедуры существует переменная СсылкаНаНоменклатуру (тип СправочникСсылка. Ноненклатура). Рассмотрим фрагмент кода (листинг 14.42). Особенность вышеприведенного механизма заключается в том, что при записи элемента в его имя записывается имя типа XML (получаемого при обращении к значению,
полученному при обращении к методу ХМЬТипЗнчО). Так- же записывается пространство имени типа. Следует отме- тить, что тип XML можно было получить и при обраще- нии к методу ХМ1_Тип(). Листинг 14.42. Пример Файл = Новый ЗаписьХМ1_; Файл.ОткрытьФайлС"c:\my_xml.xml"); Файл.ЗаписатьОбъявлениеХМЕО; Файл.ЗаписатьНачалоЭлемента("Корневой"); // Получить значение "ТипДанныхХМЕ" для числа ТипХМЕ = ХМЬТипЗнч(ЮОО); // Создать элемент, имя которого совпадает с именем // типа ХМЕ.при этом записать и пространство имен типа XML Файл. ЗаписатьНачалоЭлемента(ТипХМЕ.ИмяТипа. ТипХМЕ.иИШространстваИмен); Файл. Записат ьТекст (ХМЕСтрока (1000)); Файл.ЗаписатьКонецЭлементаО; // Получить значение "ТипДанныхХМЕ" для ссылки // на номенклатуру ТипХМЕ = ХМ1_ТипЗнч(СсылкаНаНоменклатуру): Файл. ЗаписатьНачалоЭлементаСГипХМ!.. ИмяТипа, ТипХМЕ. ШГПространстваИмен); Файл. Записат ьТекст (ХМ1_Строка (СсылкаНаНоменклатуру)); Файл.ЗаписатьКонецЭлементаО; Файл.ЗаписатьНачалоЭлемента(ТипХМЕ.ИмяТипа. ТипХМС.икШространстваИмен); Файл.ЗаписатьТекст(Строка(СсылкаНаНоменклатуру)); Файл.ЗаписатьКонецЭлементаО; Файл.ЗаписатьКонецЭлемента(): Файл. Закрыть О; В результате выполнения фрагмента кода сформируется следующий документ (листинг 14.43). Листинг 14.43. Пример сформированного XML-документа <?xml version="1.0"?> <Корневой> «decimal xmlns="http://www.w3.org/2001/XMLSchema"> 1000 </decimal> <CatalogRef. Номенклатура* 178a492a-3fd4-llda-alf2-0011d8388a5d </CatalogRef.Номенклатура* <CatalogRef.Номенклатура* Ardo TL 1000 EX-1 </CatalogRef.Номенклатура* «/Корневой* Обращаем внимание на тот факт, что, несмотря на то, что пространство имен типов записывается для каждого эле- мента с данными, во втором и третьем элементах (для ссылки справочника номенклатуры), оно не определено. Но так и должно быть, ведь для типов данных, производ- ных от объектов метаданных, пространство имен не опре- деляется. Кроме этого обратите внимание на различие результата записи ссылки. В первом случае используется метод ХМЕСтрокаО, записывается значение уникального иденти- фикатора ссылки. Во втором записывается представле- ние ссылки (чаще всего это наименование). Для чтения выгруженного XML-документа (см. лис- тинг 14.43) может использоваться следующий программ- ный код (листинг 14.44). Листинг 14.44. Пример чтения XML-документа Файл = Новый ЧтениеХМЕ; Файл.0ткрытьФайл("с:\ту_хш1.xml"); // Спозиционироваться на начале элемента "Корневой" Файл.ПрочитатьО: // Спозиционироваться на начале элемента "decimal" Файл.ПрочитатьО: // Из имени элемента (совпадающего с именем типа) //и URI пространства имен получить тип 1С:Предприятия ТипЗначения = ИзХМЕТипаСФайл.Имя, Файл.ЕШПространстваИмен); // Спозиционироваться на тексте Файл.ПрочитатьО: // Прочитать значение не указав тип нельзя ПолученноеЗначение = ХМЕЗначениеСТипЗначения. Файл.Значение): // Конец элемента "decimal" Файл.ПрочитатьО; // Начало элемента "CatalogRef.Номенклатура" Файл.ПрочитатьО; // Из имени элемента и URI пространства имен // получить тип 1С:Предприятия ТипЗначения = ИзХМЕТипа(Файл.Имя,Файл.ЕШПространстваИмен); Файл.ПрочитатьО: // Получить ссылку на номенклатурную позицию ПолученноеЗначение = ХМЕЗначениеОипЗначения, Файл.Значение); // Конец элемента "CatalogRef.Номенклатура" Файл.ПрочитатьО; // Начало элемента "CatalogRef.Номенклатура" Файл.ПрочитатьО; //Из имени элемента и URI пространства имен получить // тип 1С:Предприятия ТипЗначения = ИзХМЕТипаСФайл.Имя, Файл.ШШространстваИмен); Файл.ПрочитатьО; // Попытка выполнить следующий оператор приведет к ошибке, // так как в документе содержится строковое значение, // попытка преобразовать его к ссылке и приведет к ошибке //ПолученноеЗначение = ХМЕЗначениеОипЗначения, // Файл.Значение); // Конец элемента "CatalogRef.Номенклатура" Файл.ПрочитатьО: Файл. Закрыть О; Сложные типы Перейдем к рассмотрению сложных (с точки зрения се- риализации) типов. Тип Типу Тип соответствует тип данных XML Туре из про- странства имен http://v8.lc.ru/data. Элемент XML, пред- ставляющий значение данного типа, содержит текст, в ко- тором записано имя типа XML, соответствующего типу данных ЮПредприятия. Примеры представления в XML значений типа Тип приве- дены ниже (листинг 14.45). На первый взгляд, тип Тип относится не к сложным, а к простым типам данных, так как элемент, представ- ляющий значение данного типа, не содержит вложенных
элементов. Однако это не так. Вложенных элементов дей- ствительно нет. Но при этом текст элемента, содержащий имя типа данных XML содержит префикс пространства имен типа, который должен быть определен в данном эле- менте или одном из родительских элементов, что делает текст элемента не вполне самодостаточным. Поэтому данный тип не отнесен к простым типам. Листинг 14.45. Варианты представления значений типа Тип <!-- Не задано явно имя корневого элемента --> <v8:Type*v8:VaiueStorage</v8:Type* <!-- Явно задано имя корневого элемента XML --> «Tp*xsd:string*/Тр> <!-- Явно указан тип данных XML --> «Data xsi:type="v8:Type"*v8:ValueStorage<Data> ОписаниеТипов Типу ОписаниеТипов соответствует тип данных XML Type- Description из пространства имен http://v8.lc.ru/data. Корневой элемент, представляющий значение типа Описа- ниеТипов, содержит ряд вложенных элементов, каждый из которых содержит некоторую составляющую часть опи- сания типов. Назначение составляющих частей понятно из примера (листинг 14.46). Листинг 14.46. Пример представления значений типа ОписаниеТипов <v8: TypeDescri pti on> <v8:Types> <v8:Type>v8:UUID«/v8:Type> <v8:Type>CatalogRef.Банки</у8:Type> <v8:Type>xsd:boolean</v8:Type> <v8:Type>xsd:decimal</v8:Type> </v8:Types> <v8:NumberQuali fi ers> <v8:Di gi ts>10</v8:Di gi ts> <v8:Fracti onDi gi ts*2</v8:Fracti onDi gi ts> «v8:AllowedSign*Any«/v8:AllowedSign* </v8:NumberQuali tiers* <v8:Stri ngQuali f i ers* <v8:Length*30</v8:Length* <v8:Al1owedLength*Vari able«/v8:Al1owedLength* </v8:Stri ngQuali fi ers* <v8:DateQuali f i ers* <v8: DateFracti ons*Date«/v8: DateFracti ons* </v8:DateQuali f i ers* </v8:TypeDescri pti on* Вложенный элемент Types из пространства имен http:// v8.lc.ru/data содержит представления отдельных типов, входящих в описание типов. Элемент с именем Number- Qualifiers из пространства имен http://v8.lc.ru/data содер- жит квалификаторы числового значения. А элементы с именами StringQualifiers и DateQualifiers из того же про- странства имен содержат квалификаторы строки и даты соответственно. КонстантаМенеджерЗначения.<имя> Каждому из типов КонстантаМенеджерЗначения.«иня> соот- ветствует тип данных XML ConstantValueManager.<MHB>, не относящийся ни к какому пространству имен. Пример приведен ниже (листинг 14.47). Листинг 14.47. Пример представления значения типа КонстантаМенеджерЗначения.НазваниеОрганизации «ConstantValueManager-НазваниеОрганизации* <Value>000 "Мебиус"«/Уа1ие* </Соп51ап1Уа1иеМападег.Название0рганизации> Объект Объекты базы данных представляются в XML как сово- купность значений реквизитов и табличных частей. Имя типа данных XML, соответствующего объекту базы дан- ных, определяется как англоязычное имя типа значения 1С:Предприятия. Типы данных XML для объектов базы данных не относятся ни к какому пространству имен. Со- став элементов XML, вложенных в корневой элемент, оп- ределяется типом объекта, а также составом реквизитов и табличных частей. Каждый из реквизитов представляется элементом XML, имя которого соответствует имени реквизита. Если тип значения имеет составной тип, то элемент XML, пред- ставляющий реквизит, содержит атрибут xsi:type, в кото- ром указан тип значения XML. Каждая из табличных частей представляется элементом XML, имя которого совпадает с именем табличной части. Каждая из строк табличной части представляется эле- ментом XML с именем Row. Реквизиты табличной части представлены элементами XML, вложенными в элемент Row. Ниже приведен пример представления в XML объекта типа Документ.ЗаказПокупателя (листинг 14.48). Листинг 14.48. Пример представления значения типа Документ.ЗаказПокупателя «DocumentObject.ЗаказПокупателя* «Ref*8dl06783-9726-lld7-9334-0050ba8480bd</Ref> «Deleti onMark*false</Deleti onMark* «Date*2003 - 04 - 15T12:00:00</Date* <Number*00000006</Number> <Posted*true</Posted> «ПодразделениеКонпании*317Г130Р-5а08-11Д7-9324-0050Ьа8480Ьб «/ПодразделениеКонпании* «СтруктурнаяЕдиница xsi:type="CatalogRef.КассыКонпании"* 317 f12f4-5a08-1ld7-9324-0050ba8480bd «/СтруктурнаяЕдиница* «Контрагент*12952ас7-5a08-lld7-9324-0050ba8480bd «/Контрагент* «ЮрФизЛицоКонтрагента xsi:type="CatalogRef. ЮридическиеЛица"* 0aadfe81-5a08-lld7-9324-0050ba8480bd «/ЮрФизЛицоКонтрагента* «ВалютаДокумента*029156Ь4-5a08-lld7-9324-0050ba8480bd «/ВалютаДокумента* «КурсДокунента*1</КурсДокумента> «УчитыватьНДС*1гие«/УчитыватьНДС> <УчитыватьНП*Га15е«/УчитыватьНП> «СумнаВключаетНДС*Га15е«/СумнаВключаетНДС* «СумнаВключаетНП*Га15е</СумнаВключаетНП> «Комментарий/* «СуннаДокумента>44077.14</СуммаДокумента> «ВидОперации*СчетНаОплату«/ВидОперации> <ДоговорВзаинорасчетов*Ь040И23-6е84-1М7-932с-0050Ьа8480Ьб «/ДоговорВзаинорасчетов* «СкладКонпании>317 f1317-5а08-lld7-9324-0050ba8480bd «/СкладКонпании* <ТипЦен>317П311-5а08-11Р7-9324-0050Ьа8480ЬД«/ТипЦен> «Дата0платы*2003-04-15Т00:00:00</ДатаОплаты* «АвтоРезервирование*Га15е«/АвтоРезервирование* «АвтоРазмещение*Та15е«/АвтоРазмещение* <КурсВзаинорасчетов*33.4209«/КурсВзаинорасчетов* <ТипСкидкиНаценки*00000000-0000 - 0000 - 0000-000000000000 «/ТипСкидкиНаценки*
<0рганизация>317П308-5а08-11й7-9324-0050Ьа8480Ь<1 «/Организация* <ДатаОтгрузки>2003-04-15Т00:00:00</ДатаОтгрузки> «0тветственный*4Тf40e0b-5ас5-lld7-9325-0050ba8480bd «/Ответственный* «КратностьДокунента*1«/КратностьДокунента> <КратностьВзаииорасчетов*1«/КратностьВзаииорасчетов> «Товары* «Row* «Номенклатура*297с6534-5а08-lld7-9324-0050ba8480bd «/Номенклатура* «ЕдиницаИзнерения* 297с6535-5а08-1ld7-9324-0050ba8480bd «/ЕдиницаИзнерения* «Цена*4537.56«/Цена> «Сумна*13612.68«/Сунна> «Став каНДС*НДС20«/Став каНДС* «СуннаНДС>2722.54«/СумнаНДС> «Став каНП*1ас7373б-5а08-lld7-9324-0050ba8480bd «/СтавкаНП* «Сун н аНП*0«/Сун н аНП* «ХарактеристикаНоненклатуры* 00000000-0000-0000-0000-000000000000 «/ХарактеристикаНоненклатуры* «Размещение xsi:nil="true’7> «Коэффициент*1«/Коэффициент> «Количество*3«/Копичество> <ПроцентСкидкиНаценки*0</ПроцентСкидкиНаценки* «/Row* «Row* «Ноненклатура*317Т12Д8-5а08-11Д7-9324-0050Ьа8480ЬД «/Номенклатура* «ЕдиницаИзнерения* 317 f12d9-5а08-1ld7-9324-0050ba8480bd «/ЕдиницаИзнерения* <Цена>4915.55</Цена> «Сум ма*19662.2</Сумна> «СтавкаНДС*НДС20«/СтавкаНДС> «СуммаНДС*3932.44«/СуммаНДС> «СтавкаНП*1ас73736-5а08-1ld7-9324-0050ba8480bd «/СтавкаНП* «СуммаНП>0«/СумнаНП> «ХарактеристикаНоненклатуры* 00000000-0000-0000-0000-000000000000 «/ХарактеристикаНоненклатуры* «Размещение xsi:nil="true"/> «Коэффициент>1«/Коэффициент> «Количество*4«/Количество> «ПроцентСкидкиНаценки*0</ПроцентСкидкиНаценки* «/Row* «/Товары* «ВозвратнаяТара/* «/Documentobject.ЗаказПокупателя* Набор записей Представление в XML набора записей включает отбор, по которому получен набор записей и сами записи, входя- щие в отбор. Значения отбора представлены во вложен- ном элементе XML с именем Filter, не относящимся ни к какому пространству имен. А все записи, составляющие набор записей, во вложенном элементе с именем Records, также не относящимся ни к какому пространству имен. Записи представлены элементами XML с именем Record, вложенными в элемент Records. Имя элемента Record так- же не относится ни к какому пространству имен. Ниже приведен пример представления в XML набора за- писей регистра накопления ОстаткиТоваровКонпании (лис- тинг 14.49). УдалениеОбъекта Типу УдалениеОбъекта соответствует тип данных XML ObjectDeletion из пространства имен http://v8.lc.ru/data. Корневой элемент XML-представления значения типа УдалениеОбъекта содержит один вложенный элемент с именем Ref из пространства имен http://v8.lc.ru/data, в котором находится представление ссылки на объект базы данных. Ниже приведен пример представления в XML объекта типа УдалениеОбъекта (листинг 14.50). Листинг 14.49. Пример представления значения типа РгистрНакопленияНаборЗаписей.ОстаткиТоваровКомпании «AccumulationRegisterRecordSet.ОстаткиТоваровКонпании* «Filter* «Recorder xsi:type= "0оситеп1КеТ.РеализацияТоваров"*1725Т36е-6Т35-11Д7-932б- 0050ba8480bd«/Recorder> «/Filter* «Records* «Record* «Recorder xsi :type="DocurnentRef. РеализацияТоваров"* 1725f36e-6f35-lld7-932d-0050ba8480bd «/Recorder* <Period>2003-04-13T17:45:39«/Peri od> <MovementType*Expense«/MovernentType> «Active*true«/Acti ve* «Ноненклатура*297с6556-5a08-lld7-9324-0050ba8480bd «/Ноненклатура* «СкладКонпании*317Т1317-5a08-lld7-9324-0050ba8480bd «/СкладКонпании* «Заказ xsi:nil="true"/> <ЦенаВРознице>0«/ЦенаВРознице* «ХарактеристикаНоненклатуры* 00000000-0000-0000-0000-000000000000 «/ХарактеристикаНоненклатуры* <Количество*2«/Количество> «ПодразделениеКонпании* 317f130d-5а08-lld7-9324-0050ba8480bd «/ПодразделениеКонпании* «/Record* «Record* «Recorder xsi:type="DocumentRef.РеализацияТоваров"* 1725f36e-6f35-lld7-932d-0050ba8480bd «/Recorder* «Peri od>2003-04-13T17:45:39«/Peri od> <MovementType*Expense«/MovementType> «Active*true«/Acti ve* «Нонен клатура>297c6558 - 5a08 -1 ld7 - 9324- 0050ba8480bd «/Ноненклатура* «CKnaflKoHnaHHH*317fl317-5a08-lld7-9324-0050ba8480bd «/СкладКонпании* «Заказ xsi:nil="true"/> «ЦенаВРознице>0«/ЦенаВРознице* «ХарактеристикаНоненклатуры* ac47d77e-5ec7-lld7-9329-0050ba8480bd «/ХарактеристикаНоненклатуры* <Количество*2«/Количество> «ПодразделениеКонпании* 317 f130d-5a08-1ld7-9324-0050ba8480bd «/ПодразделениеКонпании* «/Record* «/Records* «/AccumulationRegi sterRecordSet.ОстаткиТоваровКонпании* Листинг 14.50. Пример представления значения типа УдалениеОбъекта <v8:ObjectDeleti on xmlns="http://v8.lc.ru/data"> «v8:Ref xsi:type="CatalogRef.Банки"* 60c5cec3-7f6f-4ec3-9620-e757fe3614ca «/v8:Ref> </v8:ObjectDeleti on* Работа co сложными типами Для работы со сложными с точки зрения сериализации значениями могут использоваться следующие методы ^Предприятия (они же могут использоваться и для простых типов):
♦ ЗаписатьХМК); ♦ ПрочитатьХМК). Метод ЗаписатьХМЦ) имеет два обязательных параметра. Первый параметр — это объект типа ЗалисьХМЬ, через кото- рый осуществляется запись XML, а второй — значение, ко- торое должно быть записано в XML. Необязательные па- раметры образуют три различных варианта вызова метода. В простейшем случае параметра три, и в качестве третьего параметра указывается значение перечисления Назна- чениеТипаХМЬ, определяющее необходимость явного указа- ния типа данных XML в атрибуте xsi:type корневого эле- мента XML. У следующего варианта вызова в качестве третьего пара- метра используется строковое значение, указывается имя корневого элемента XML. При этом подразумевается, что пространство имен не определено. Четвертый параметр — значение типа НазначениеТипаХМС, определяющее необходи- мость явного указания типа данных XML. И, наконец, у последнего варианта вызова после парамет- ра, указывающего имя корневого элемента XML, появля- ется еще один параметр — строковое значение, обозна- чающее пространство имен, к которому относится корневой элемент. Последний параметр по-прежнему имеет тип НазначениеТипаХМЬ. Рассмотрим пример использования объекта ЗаписьХМ). (листинг 14.51). Листинг 14.51. Пример использования объекта ЗаписьХМЬ Знач = "Строка такая”; ЗаписатьХМКЗп, Знач); ЗаписатьХМКЗп, Знач, "Root", НазначениеТипаХМС.Явное); ЗаписатьХМЦЗп. Знач, "Root", "urnrsome-namespace"); В результате выполнения приведенного кода будет полу- чен следующий XML-фрагмент (листинг 14.52). Листинг 14.52. Фрагмент XML-документа <striпд>Строка такая</з1гтпд> <Root xsi:type="xsd:string”>CTpoKa такаяс/Root» <dlpl:Root xmlns:dlpl=”urn:some-namespace">CTpoKa такая </dlpl:Root> Если в качестве значения, помещаемого в XML, будет пе- редано значение типа, который не может быть представ- лен в XML, то будет вызвано исключение. Метод ПрочитатьХМК) предназначен для чтения значений из XML. Данный метод имеет один обязательный пара- метр — объект ЧтениеХМС, из которого должно быть прочи- тано значение. В качестве второго параметра может быть указан тип значения, которое должно быть прочитано из XML. Если тип значения явно указан в XML, то в качест- ве второго параметра может быть указано значение Неоп - ределено или же он может быть вообще опущен. В этом случае метод ПрочитатьХМК) пытается определить тип чи- таемого значения по содержимому атрибута xsi:type, а если атрибут xsi:type отсутствует, то по имени элемента. Если тип установить не удалось или значение указанного типа не может быть прочитано из XML, то вызывается исклю- чение. При удачном завершении метод ПрочитатьХМК) воз- вращает считанное значение. Следует обратить внимание на то, как считываются менед- жеры значений констант, объекты базы данных и наборы записей. После успешного выполнения чтения метод ПрочитатьХМК) возвращает считанное из XML значение, но это значение еще не записано в базу данных. Если, например, считан элемент справочника, то для того, чтобы считанный элемент справочника оказался запи- санным в базу данных, необходимо обратиться к его ме- тоду ЗаписатьО, как и при «обычной» записи изменен- ного состояния объекта. Это же относится и к другим объектам базы данных, менеджерам записи констант и наборам записей. При чтении объекта базы данных из XML в базе дан- ных производится поиск объекта с таким же значением ссылки. Если такой объект найден, то считывание из XML выглядит так, как будто объект был прочитан из базы данных, после чего значения его реквизитов, таб- личных частей и т. п. перезаписываются полученными из XML значениями. Если же объект по ссылке не най- ден, то считывание из XML выглядит как создание но- вого объекта, установка ему значения ссылки и запол- нение его содержимого значениями, прочитанными из XML. Метод ВозможностьЧтенияХМК) определяет, возможно ли считывание значения из объекта ЧтениеХМЬ, находящегося в текущей позиции документа XML. Объект ЧтениеХМС пе- редается данному методу в качестве параметра. Если ме- тод возвращает Истина, то чтение возможно, если Ложь — значение не может быть считано. Метод ПолучитьХМСГипО позволяет получить из объекта ЧтениеХМЬ тип данных XML, соответствующий текущей позиции документа XML. Данный метод также имеет один параметр — ЧтениеХМЬ. Рассмотрим использование вышеперечисленных методов на примере. В контексте процедуры СложныеЗаписать су- ществует переменная Документ (тип ДокументСсылка.<имя>). Данный документ имеет следующую структуру: ♦ реквизит Контрагент, тип СправочникСсылка.Контрагенты; ♦ табличная часть Товары, реквизиты табличной части: Номенклатура, тип СправочникСсылка.Номенклатура; Количество, тип Число; Цена, тип Число; Сумма, тип Число. Следует отметить, что метод ЗаписатьХМК) сам определяет структуру выгружаемого объекта, в данном случае она приводится для того, чтобы пояснить полученный XML- документ. Процедура, используемая для выгрузки, имеет следую- щий код (листинг 14.53). Листинг 14.53. Процедура СложныеЗаписать Процедура СложныеЗаписать(Элемент) Файл = Новый ЗаписьХМС; Файл.0ткрытьФайл("с:\бос_хт1.хт]"); Файл .ЗаписатьОбъявлениеХМК); Объект = Документ. ПолучитьОбъектО; ЗаписатьХМКФайл, Объект, Назначение!wiaXML.Явное); Файл.ЗакрытьО ; КонецПроцедуры В результате работы процедуры сформируется XML-до- кумент следующего вида (листинг 14.54).
Листинг 14.54. Пример сформированного XML-документа <?xml version="1.0"?> «OocumentObject. Расходная xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Documentobject.Расходная"> <Ref*d5af75ed - 8c6d- Ud8 - 958a - 00c026abdd5e«/Ref> <Deleti onMark*false</Deleti onMark> «Date*2004-12 - 08T14:40:38</Date> <Number>l</Number> <Posted>true</Posted> <Контрагент>еЬТ9f318-a8dl-lld8-a063-00c026abdd5e «/Контрагент* «Товары* «Row* «Номенклатура* efbfeaf4-831d-lld8-957e-00c026abdd5e «/Номенклатура* «Количество*1«/Количество> «Цена>100«/Цена> «Сумма*100«/Сумма> «/Row* «Row* «Номенклатура* efbfeafb-831d-lld8-957e-00c026abdd5e «/Номенклатура* «Количество*1«/Количество> «Цена*200</Цена> «Сумма*200«/Сумма> «/Row* «/Товары* «/OocumentObject.Расходная* Можно сказать, что структура выгруженного документа повторяет структуру его метаданных, причем дополни- тельно включаются такие данные, как: ♦ ссылка на документ (Ref); ♦ пометка на удаление (DeletionMark); ♦ дата (Date); ♦ номер (Number); ♦ проведен (Posted). Процедура чтения данных представлена в листинге 14.55. Листинг 14.55. Процедура чтения данных Процедура СложныеПрочитат ь(Кноп ка) Файл = Новый ЧтениеХМЕ; Файл.ОткрытьФайл("с:\doc_xml.xml"); // Позиционируемся на начале элемента, содержащего документ Если Файл.Прочитать О Тогда // Проверка на возможность чтения значения Если ВозможностьЧтенияХМКФайл) Тогда // Получается значение ДокументОбъект.Имя. // если значения с таким внутренним идентификатором // нет, то создается новый Объект = ПрочитатьХМКФайл); Объект.ЗаписатьО: КонецЕсли; КонецЕсли; Файл.Закрытье); (^нецПроцедуры Следует отметить, что в случае если объект, в который производится загрузка, имеет отличную структуру (отли- чается состав реквизитов, табличных частей, реквизитов табличных частей или порядок их следования) от выгру- жаемого объекта, то метод ВозможностьЧтенияХМЬО может возвратить значение Истина. При попытке проведения чтения объекта из XML-документа будет вызвано исключение. Это объясняется тем, что метод ВозможностьЧтенияХМК) анализирует текущее состояние объекта ЧтениеХМЕ. В этот момент текущим является начало соответствующего эле- мента. Если имя элемента, атрибуты «понятны» методу, он и возвращает значение Истина. Проверка структуры, других моментов методом ВозможностьЧтенияХМК) не про- изводится. Пример реализации обмена при разной структуре объектов конфигурации Даже при организации обмена данными между информа- ционными базами 1 (/Предприятия довольно редкой яв- ляется ситуация, когда структура объектов конфигура- ции (даже в рамках обмениваемых данных) полностью совпадает. Что делать, когда структура объектов различа- ется? Один из вариантов решения задачи приводится ниже (данный подход не обязательно должен использо- ваться только при организации обмена между базами 1 (/Предприятия 8.0). Считаем, что конфигурации, между которыми произво- дится обмен, отличаются только структурой справоч- ника Номенклатура. Структура остальных объектов сов- падает. В базе данных — источнике, в справочнике Номенклатура присутствует реквизит Артикул (тип СправочникСсылка.Ар- тикулы), в базе-приемнике существует реквизит Куратор (тип СправочникСсылка.ФизическиеЛица), все остальные рек- визиты совпадают, их состав: ♦ Код, тип Число; ♦ Наименование, тип Строка; ♦ ПолноеНаименование, тип Строка; ♦ ЗакупочнаяЦена, тип Число; ♦ Картинка, тип ХранилищеЗначения. Выгрузка данных выполняется с помощью трех процедур: ВыгрузкаДанных (листинг 14.56), ЗаписатьДанные (лис- тинг 14.57) и НоменклатураЗаписатьХМк (листинг 14.58). Листинг 14.56. Процедура ВыгрузкаДанных Процедура Вы г руз каДанных(Кнопка) ЗаписьХМЕ = Новый ЗаписьХМЕ; ЗаписьХМЕ. ОткрытьФайл ("с: \out .xml''); ЗаписьХМЕ.ЗаписатьОбъявлениеХМК); ЗаписьХМЕ.ЗаписатьНачалоЭлемента("Корневой"); // Для сокращения размера файла сообщения записываем // соответствие пространств имен ЗаписьХМЕ.ЗаписатьСоответствиеПространстваИмен("х5б". "http://www.w3.org/2001/XMLSchema"): ЗаписьХМЕ.ЗаписатьСоответствиеПространстваИмен("х51", "http://www.w3.org/2001/XMLSchema-i nstance"); ЗаписьХМЕ.ЗаписатьСоответствиеПространстваИмен('\8", "http://v8.lc.ru/data"); // Получаем выборку данных из табличной части Для Каждого Элемент Из ВыгружаемыеДанные Цикл Данные = Элемент. СсылкаНаОбъект. ПолучитьОбъектО;
11 Записываем данные ЗаписатьДанныеОаписьХМЕ, Данные); КонецЦикла; ЗаписьХМЬ.ЗаписатьКонецЭленентаС): ЗаписьХМЕ.ЗакрытьО; КонецПроцедуры Листинг 14.57. Процедура ЗаписатьДанные Процедура ЗаписатьДанные(ЗаписьХМ1_. Данные) Если ТипЗнч (Данные) = Тип("СправочникОбъект.Ноненклатура") Тогда // Записываем элемент справочника вручную НоменклатураЗаписатьХМКЗаписьХМЕ, Данные); Иначе // Записываем данные с помощью стандартного метода ЗаписатьХМКЗаписьХМЕ, Данные); КонецЕсли КонецПроцедуры Листинг 14.58. Процедура НоменклатураЗаписатьХМЕ Процедура НоменклатураЗаписатьХМЦЗаписьХМЕ, Номенклатура) // Записываем начало элемента XML ЗаписьХМЕ.ЗаписатьНачалоЭлемента( "CatalogObject.Номенклатура.Вручную"); // Ссылка ЗаписатьХМКЗаписьХМЕ, Номенклатура.Ссылка, "Ref". НазначениеТипаХМЕ.Явное); // ЭтоГруппа ЗаписатьХМЕСЗаписьХМЕ, Номенклатура.ЭтоГруппа. "IsFolder", НазначениеТипаХМЕ.Явное); // Родитель ЗаписатьХМЕ(ЗаписьХМЕ, Номенклатура.Родитель, "Parent". НазначениеТипаХМЕ.Явное): // Код ЗаписатьХМЕ(ЗаписьХМЕ. Номенклатура.Код, "Code", НазначениеТипаХМЕ.Явное); // Наименование ЗаписатьХМЕСЗаписьХМЕ, Номенклатура.Наименование, "Description", НазначениеТипаХМЕ.Явное); // Реквизиты, выгружаемые только для элемента справочника, // а не для группы Если Не Номенклатура.ЭтоГруппа Тогда // ЗакупочнаяЦена ЗаписатьХМЕ(ЗаписьХМЕ, Номенклатура.ЗакупочнаяЦена, "ЗакупочнаяЦена". НазначениеТипаХМЕ.Явное); // Картинка ЗаписатьХМЕСЗаписьХМЕ, Номенклатура.Картинка. "Картинка", НазначениеТипаХМЕ.Явное); // ПолноеНаименование ЗаписатьХМЕСЗаписьХМЕ. Номенклатура.ПолноеНаименование, "ПолноеНаименование". НазначениеТипаХМЕ.Явное); КонецЕсли; // Записываем конец элемента ЗаписьХМЕ.ЗаписатьКонецЭлемента(); КонецПроцедуры Порядок взаимодействия данных процедур можно про- иллюстрировать следующей схемой (рис. 14.8). Рис. 14.8. Взаимодействие процедур при записи данных В процедуре ВыгрузкаДанных (см. листинг 14.56) произво- дится перебор выгружаемых данных. Данные для выгруз- ки определяются в табличной части ВыгружаемыеДанные. У табличной части один реквизит табличной части Ссыл- каНаОбъект (набор типов Любая ссылка). В процедуре ЗаписатьДанные (см. листинг 14.57) проверя- ется: если записываемый объект является элементом спра- вочника Номенклатура, то вызывается специализирован- ная процедура для его записи НоменклатураЗаписатьХМЕ (см. листинг 14.58), в противном случае запись произво- дится с помощью метода системы ЗаписатьХМЕО. В процедуре НоменклатураЗаписатьХМЕ производится «руч- ное» формирование элемента CatalogObject.HoMeHKnary- ра.Вручную (начиная с записи начала элемента и заканчи- вая записью конца элемента). При выгрузке двух элементов, первый из которых пред- ставляет собой элемент справочника Контрагенты, а вто- рой — элемент справочника Номенклатура, полученный XML-документ будет иметь следующий вид (листинг 14.59). Загрузка данных из XML-документа может быть осу- ществлена с помощью следующих процедур и функций: ЗагрузкаДанных (листинг 14.60), ВозможностьЧтенияДан- ных (листинг 14.61), ПрочитатьДанные (листинг 14.62) и НоменклатураПрочитатьХМЕ (листинг 14.63). Порядок взаимодействия процедур можно представить в виде следующей схемы (рис. 14.9).
Листинг 14.59. Пример сформированного XML-документа <?xml version="1.0”?> «Корневой xml ns:xsd="http://www.w3.org/2001/XMLSchema" xml ns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml ns:v8="http://v8.lc.ru/data"> <CatalogObject.Контрагенты* <Ref>b5268606-4ae7-llda-a21c-000b0d063032</Ref> <1sFolder>false</IsFolder> <DeletionMark>false</Deleti onMark* <Parent>00000000-0000-0000-0000-000000000000</Parent> <Code>0000001</Code> <Descri р11оп>Контрагентов </Descri pti on* <Вид>0рганизация</Вид* «ТипЦен>00000000-0000 -0000-0000-000000000000</ТипЦен> </CatalogObject.Контрагенты* <CatalogObject.Номенклатура.Вручную* «Ref xsi:type="CatalogRef.Номенклатура"* 178a492a-3fd4-llda-alf2-D011d8388a5d </Ref> «IsFolder xsi:type="xsd:boolean"*false«/IsFolder> «Parent xsi:type="CatalogRef.Номенклатура"* 00000000-0000-0000-0000-000000000000 «/Parent* «Code xsi:type="xsd:string"*0000014«/Code> «Description xsi:type="xsd:string"* Ardo TL 1000 EX-1 «/Description* «ЗакупочнаяЦена xsi:type="xsd:decimal">9000 «/ЗакупочнаяЦена» «Картинка xsi:type="v8:ValueStorage"> AQEIAAAAAAAAM>+7v3si VSJ9 «/Картинка* «ПолноеНаименование xsi:type="xsd:string"> Ardo TL 1000 EX-1 «/ПолноеНаименование* «/CatalogObject.Номенклатура.Вручную* «/Корневой* Листинг 14.60. Процедура ЗагрузкаДанных Процедура ЗагрузкаДанных(Кнопка) // Создаем объект чтения XML ЧтениеХМЕ = Новый ЧтениеХМЕ; ЧтениеХМЕ.ОткрытьФайл("c:\out.xml"); // Позиционируемся на корневом элементе ЧтениеХМЕ.Прочитать(); // Позиционируемся на первом элементе, содержащим данные ЧтениеХМЕ.ПрочитатьО: // Читаем данные пока это возможно Пока ВозможностьЧтенияДанных(ЧтениеХМЕ) Цикл // Читаем очередное значение Данные = ПрочитатьДанные(ЧтениеХМЕ): // Записываем полученные данные Данные.Записать(); КонецЦикла: Чтен иеХМЕ. ЗакрытьО: КонецПроцедуры Листинг 14.61. Функция ВозможностьЧтенияДанных Функция ВозможностьЧтенияДанных(ЧтениеХМЕ) И Получаем тип данных XML, который может быть И считан в данный момент ТипХМЕ = ПолучитьХМЕТип (ЧтениеХМЕ): Если ТипХМЕ = Неопределено Тогда Возврат Ложь; КонецЕсли: Если ТипХМЕ.ИмяТипа = "CatalogObject.Номенклатура.Вручную" И ТипХМЕ.ЕШПространстваИмен = Тогда Возврат Истина: КонецЕсли; Возврат ВозможностьЧтенияХМЕ(ЧтениеХМЕ); КонецФункции Листинг 14.62. Функция ПрочитатьДанные Функция ПрочитатьДанные(ЧтениеХМЕ) ТипХМЕ = ПолучитьХМЕТип(ЧтениеХМЕ): Если ТипХМЕ = Неопределено Тогда Возврат Неопределено: КонецЕсли; Если ТипХМЕ.ИмяТипа = "CatalogObject.Номенклатура.Вручную" И ТипХМЕ. (ШПространстваИмен = "" Тогда // Пытаемся прочесть значение справочника Номеклатура Возврат НомеклатураПрочитатьХМЕ(ЧтениеХМЕ); КонецЕсли; // Пытаемся прочесть значение из объекта // ЧтениеХМЕ стандартным образом Возврат ПрочитатьХМЕ(ЧтениеХМЕ); КонецФункции // ПрочитатьДанные(ЧтениеХМЕ) Листинг 14.63. Функция НомеклатураПрочитатьХМЕ Функция НомеклатураЛрочитатьХМЕ(ЧтениеХМЕ) Перем Номенклатура: // элемент справочника Номенклатура Если ЧтениеХМЕ.ТипУзла <> ТипУзлаХМЕ.НачалоЭлемента Тогда ВызватьИсключение "Ошибка чтения XML"; КонецЕсли: // Чтение следующего узла ЧтениеХМЕ.Прочитать(); // Чтение ссылки на элемент справочника НомеклатураСсылка = ПрочитатьХМЕ(ЧтениеХМЕ); Если ТипЗнч(НомеклатураСсылка) <> Тип("СправочникСсылка.Номенклатура") Тогда ВызватьИсключение "Ошибка чтения XML"; КонецЕсли; // Пытаемся создать объект по полученной ссылке Номенклатура = НомеклатураСсылка.ПолучитьОбъектО; // Чтение признака группы ЭтоГруппа = ПрочитатьХМЕ(ЧтениеХМЕ); Если Номенклатура «> Неопределено Тогда Если Номенклатура.ЭтоГруппа <> ЭтоГруппа Тогда ВызватьИсключение "Некорректные данные"; КонецЕсли; Иначе // Создаем элемент справочника Если ЭтоГруппа = Истина Тогда // Создаем группу Номенклатура = Справочники.Номенклатура.СоздатьГруппу(); Иначе // Создаем элемент справочника Номенклатура = Справочники.Номенклатура.СоздатьЭлемент(); КонецЕсли;
И Устанавливаем значение ссылки для нового объекта Номенклатура.УстановитьСсылкуНового(НомеклатураСсылка); КонецЕсли; // Родитель Номенклатура. Родитель = ПрочитатьХМЦЧтениеХМ!.); // Код Номенклатура. Код = ПрочитатьХМЦЧтениеХМ!.); // Наименование Номенклатура. Наименование = ПрочитатьХМЦЧтениеХМ!.): // Реквизиты, загружаемые только для элемента справочника. // а не для группы Если Не Номенклатура.ЭтоГруппа Тогда // ЗакупочнаяЦена Номенклатура. ЗакупочнаяЦена = ПрочитатьХМЦЧтениеХМ!.); // Картинка Номенклатура. Картинка = ПрочитатьХМЦЧтениеХМ!.); // ПолноеНаименование Номенклатура.ПолноеНаименование = ПрочитатьХМЦЧтениеХМ!.); КонецЕсли; // Проверяем, что текущим узлом является КонецЭлемента Если ЧтениеХМЕ.ТипУзла <> ТипУзлаХМЕ.КонецЭлемента Тогда ВызватьИсключение "Ошибка чтения XML"; КонецЕсли; // Чтение следующего узла для завершения чтения элемента ЧтениеХМЕ.Прочитать(): Возврат Номенклатура; КонецФункции // НомеклатураПрочитатьХМЕ(ЧтениеХМЕ) В процедуре ЗагрузкаДанных (см. листинг 14.60) произ- водится выборка (последовательный обход) элементов, содержащих данные. Для каждого элемента в функции ВозможностьЧтенияДанных (см. листинг 14.61) проверяет- ся возможность чтения. Причем если имя типа равно CatalogObject.HoMeHWiarypa.Вручную, возвращается значе- ние Истина, в противном случае вызывается «штатный» метод 1С:Предприятие для выполнения этой проверки для других типов. Чтение данных из элемента производится в функции ПрочитатьДанные (см. листинг 14.62). Если читается эле- мент СаЕа1одОЬ]’есЕ.Номенклатура.Вручную, то тогда для чте- ния вызывается специализированная функция (Номен- клатураПрочитатьХМЕ (см. листинг 14.63)), в противном случае чтение осуществляется с помощью «штатного» метода ПрочитатьХМЩ. Следует обратить внимание на тот факт, что в данном случае потребовалась «ручная» отработка изменений, как на стороне выгрузки, так и на стороне загрузки. Может возникнуть вопрос, что делать, если в объекте приемника добавлен (по сравнению с объектом источника) дополни- тельный реквизит. Стоит ли вносить изменения как на стороне выгрузки, так и на стороне загрузки? Разберем этот вопрос последовательно. Да, можно выгрузить объ- ект как есть, но при этом в XML-элементах, подчиненных элементу объекта, не будет данных о типах свойств, рек- визитов. В итоге их загрузка (универсальная) будет за- труднена. Скорее всего, в этом случае придется прописы- вать очень жесткие механизмы (если этот элемент имеет имя Картинка, значит, его тип ХранилищеЗначений и т. п.). Единственным случаем, когда можно обойтись без изме- нения процедуры загрузки, это когда в объекте приемни- ка меньше реквизитов, чем в источнике. В этом случае можно «подделать» структуру элемента так, чтобы метод ПрочитатьХМЩ его воспринял. Работа с ZIP-архивами При решении задач обмена может потребоваться переда- ча довольно большого объема данных, как посредством каких-либо Интернет-технологий, так и другими средст- вами. В связи с объемом этих данных может возникнуть необходимость в их сжатии перед передачей и распаков- кой после приема. Платформа 1С: Предприятия предос- тавляет возможности работы с ZIP-архивами. Для этого в системе существуют объекты Запись21РФайла (ответствен- ный за запись) и Чтение71РФайла (ответственный за чтение архивов). Создание архива Для того чтобы записать файлы в ZIP-архив, необходимо выполнить несколько простых действий: ♦ создать архив с необходимыми параметрами, в который будут помещаться файлы; ♦ поместить в архив необходимые файлы; ♦ записать архив. Рассмотрим эти действия на следующем примере (лис- тинг 14.64). Листинг 14.64. Пример записи файла в ZIP-архив Архив = Новый Запись/1РФайла("с:\архив.2тр", "Пароль", "Комментарий", МетодСжатия71Р.Сжатие, УровеньСжатия71Р.Максимальный, МетодШифрования71Р.71р20); Архив.Добавить("с:\f11е.xls". РежимСохраненияПутей21Р.НеСохранятьПути); Архив.Записать!);
Создание объекта Запись71РФайла можно осуществить дву- мя путями: ♦ создать инициализированный объект (см. листинг 14.64); ♦ создать неинициализированный объект и вызвать у него метод Открытье (файл архива не должен существовать в этом случае) (листинг 14.65). Листинг 14.65. Пример использования неинициализированного объекта Запись21Рфайла Архив = Новый Запись71РФайла(); Архив.Открытье"с:Хархив.zi р", "Пароль”, "Комментарий”, МетодСжатия21Р.Сжатие. УровеньСжатиягТР.Максимальный. МетодШифрования71Р.7тр20); При создании нового архива (либо при создании конст- руктором, либо методом Открытье) требуется указать: ♦ имя файла, куда будет записан архив. Этот параметр является обязательным. Если такой файл уже сущест- вует на диске, он будет перезаписан (в момент вызова метода Записать О); ♦ пароль доступа к архиву. Если этот параметр пропущен или равен пустой строке, то шифрование производится не будет; ♦ комментарий к архиву; ♦ метод сжатия файлов в архиве. На выбор предоставля- ется возможность скопировать файлы в архив без сжа- тия или сжать их. По умолчанию файлы сжимаются; ♦ уровень сжатия файлов в архиве. Можно выбирать между минимальным, оптимальным и максимальным сжатием. По умолчанию используется оптимальное сжатие; ♦ метод шифрования. Можно защитить архив методом шифрования ZIP 2.0, совместимым с большинством программ, или с помощью шифрования на основе но- вейшего стандарта AES с различной длиной ключа (123, 192 и 256 бит). Однако следует помнить, что дан- ный метод может быть не совместим с некоторыми про- граммами архивирования старых версий. После создания объекта необходимо добавить в него сжи- маемые файлы. Для этой цели используется метод Доба- вить!). У него три параметра: ♦ полное имя файла или маска; ♦ режим сохранения путей к файлу. Можно сохранять полные пути, не сохранять пути совсем или сохранять пути относительно каталога; ♦ режим обработки подкаталогов. Можно обрабатывать подкаталоги рекурсивно или не обрабатывать их. Па- раметр имеет смысл, если в качестве имени указана маска. После того как все необходимые файлы добавлены, мож- но записать архив на диск, воспользовавшись методом За- писать!). Важно понимать, что до выполнения этого метода ника- ких реальных действий по созданию архива не происхо- дит. После записи архива на диск объект закрывает его, и для работы со следующим архивом необходимо выпол- нить метод Открыть!). Особенности упаковки файлов по маске Остановимся подробнее на особенностях упаковки фай- лов по маске. Предположим, что у нас есть следующие файлы: c:\ZIP\filel.xls c:\ZIP\file2.xls c:\ZIP\file.doc c:\ZIP\Test\file3.xls c:\ZIP\Test\file4.xls Для упаковки всех этих файлов в архив можно восполь- зоваться следующим кодом (листинг 14.66). Листинг 14.66. Пример записи файлов в ZIP-архив Архив.Добавить("с:\ZIP\filel.xls", РежинСохраненияПутей71Р.СохранятьПолныеПути): Архив.Добавить("с:\ZIP\Test\fi1еЗ.xls", РежимСохраненияПутейгТР.СохранятьОтносительныеПути); Архив.Добавить("с:\ZIP\Test\f11е4.xls", РежимСохраненияПутейгТР.НеСохранятьПути): // и так далее Следует отметить, что относительные пути актуальны только при задании маски (значение СохранятьОтноситель- ныеПути системного перечисления РежинСохраненияПутей71Р). В архив файлы попадут следующим образом: c:\ZIP\filel.xls \file3.xls \fiLe4.xls Добавить файлы в архив можно и другим способом (лис- тинг 14.67). Листинг 14.67. Пример добавления файлов в ZIP-архив Архив. Добавить! "c:\ZIPV.xls", РежимСохраненияПутейгТР.СохранятьОтносительныеПути, Режим0бработкиПодкаталогов21Р.НеОбрабатывать); В результирующий архив попадут следующие файлы: \filel.xls \file2.xls При создании архива можно включать файлы во вложен- ных каталогах (листинг 14.68). Листинг 14.68. Пример добавления файлов из вложенных каталогов в ZIP-архив Архив. Добавить! "c:\ZIPV.xls", РежинСохраненияПутейгТР.СохранятьОтносительныеПути, Режим0бработкиПодкаталогов21Р.ОбрабатыватьРекурсивно); В результирующий архив попадут следующие файлы: \filel.xls \file2.xls \Test\file3.xls \Test\file4.xls Особенности работы метода Добавить() Упаковать файлы в архив можно несколькими способами в зависимости от того, какой результат необходим. Упаковать некоторые файлы в папке ZIP с сохранением структуры каталогов.
Предположим, что у нас есть следующие файлы: c:\ZIP\filel.xls c:\ZIP\Test\file3.xls Добавить их в архив можно, вызывая для каждого метод ДобавитьО с указанием требуемых параметров (лис- тинг 14.69). Листинг 14.69. Пример добавления файлов в ZIP-архив Архив.Добавить("с:\ZIP\filel.xls", РежимСохраненияПутей71Р.СохранятьПолныеПути); Архив.Добавить!"с:\ZIP\Test\file3.xls", РежимСохраненияПутей71Р.СохранятьПолныеПути); В архив файлы попадут следующим образом: \ZIP\filel.xls \ZIP\Test\file3.xls Упаковать все файлы в папке ZIP без сохранения струк- туры каталогов. Предположим, что у нас есть следующие файлы: c:\ZIP\filel.xls c:\ZIP\Test\file3.xls Для добавления всех файлов передадим в метод Доба- витьО маску для поиска всех файлов (*.*), скажем, что нет необходимости сохранять пути для файлов, и ука- жем, что требуется производить поиск в подпапках (лис- тинг 14.70). Листинг 14.70. Пример добавления файлов в ZIP-архив Архив.ДобавитьС"с:\ZIP\*.*”, РежимСохраненияПутей71Р.НеСохранятьПути, Режим0бработкиПодкаталогов71Р.0брабатыватьРекурсивно); В архив файлы попадут следующим образом: \filel.xls \file3.xls При этом следует помнить, что если в разных папках бу- дут файлы с одинаковыми именами, то операция выпол- нена не будет из-за того, что фактически мы попытаемся добавить в архив файлы с одинаковыми именами. Упаковать все файлы в папке ZIP с сохранением относи- тельных путей. Предположим, что у нас есть следующие файлы: c:\ZIP\filel.xls c:\ZI Р\Т est\fi 1еЗ .xls Для добавления всех файлов передадим в метод Доба- витьС) маску для поиска всех файлов (*.*), скажем, что не- обходимо сохранять относительные пути для файлов, и укажем, что требуется производить поиск в подпапках. При этом следует помнить, что относительные пути бу- дут начинаться от папки, в которой начался поиск (лис- тинг 14.71). Листинг 14.71. Пример добавления файлов в ZIP-архив Архив.Добавить("с:\ZIР\*. *", РежимСохраненияПутей71Р.Сохранять0тносительныеПути, Режим0бработкиПодкаталогов71Р.ОбрабатыватьРекурсивно); В архив файлы попадут следующим образом: \filel.xls \Test\file3.xls Чтение ZIP-архивов На приемной стороне при получении архива возникает задача его чтения. С точки зрения объекта Чтение7трФайла необходимо выполнить два действия: ♦ открыть полученный архив; ♦ распаковать файлы (извлечь их из архива). Создание объекта Чтение71рФайла может производиться двумя способами: ♦ создать инициализированный объект (листинг 14.72); ♦ создать неинициализированный объект (листинг 14.73). Листинг 14.72. Пример использования объекта Чтениег!рфайла Архив = Новый Чтение71рФайла!"с:\архив.2тр", "Пароль"): Листинг 14.73. Пример использования объекта Чтениег!рфайла Архив=Новый Чтение7трФайла(): Архив.Открыть("с:\архив.ziр", "Пароль"); Извлечение файлов из архива может осуществляться двумя методами: ♦ метод ИзвлечьВсеО (листинг 14.74); ♦ метод Извлечь!) (каждый файл по отдельности) (лис- тинг 14.75). Листинг 14.74. Пример извлечения файлов из ZIP-архива Архив.ИзвлечьВсе!"с:\Temp", РежимВосстановленияПутейФайлов71Р.НеВосстанавливать); Листинг 14.75. Пример извлечения файлов из ZIP-архива Для Каждого Элемент Из Архив.Элементы Цикл Архи в.Из влеч ь(Элемен т, "c:\Temp", РежимВосстановленияПутейФайлов71Р.НеВосстанавливать, ?(Элемент.Зашифрован, Пароль, "")); КонецЦикла; Посмотрев на приведенный код, может возникнуть во- прос — зачем же указывать пароль для расшифровки, если мы уже указали его при открытии? Суть этого в том, что формат ZIP-архива позволяет указать произ- вольный пароль для любого файла, и многие популяр- ные программы архивирования поддерживают такую возможность. При указании индивидуального пароля распаковки будет использоваться он. А если индивиду- альный пароль не указан, — то пароль, указанный при открытии архива. После извлечения файлов для прекращения работы с ар- хивом необходимо выполнить метод Закрыть!). Приведем пример распаковки файлов из архива (лис- тинг 14.76). Листинг 14.76. Пример распаковки файлов из ZIP-архива Пароль = Подсказка = "Введите пароль на архив"; // Запросим пароль на архив Если ВвестиСтроку(Пароль, Подсказка, 0, Ложь) Тогда Архив = Новый Чтение71рФайла("с:\архив.21р", Пароль); Сообщить!"Комментарий: " + Архив.Комментарий); Для Каждого Элемент Из Архив.Элементы Цикл СообщитьС’Распаковывается файл: " + Элемент.Имя + " размер: " + Элемент.РазмерНесжатого):
Архив.Извлечь(Элемент, "c:\Temp", РежинВосстановленияПутейФайлов!!Р. НеВосстанавливать, ?(Элемент.Зашифрован, Пароль, КонецЦикла; Архив.ЗакрытьО; КонецЕсли; Работа с файлами большого объема При работе с большими объемами данных могут возник- нуть проблемы при пересылке архивных файлов. Типич- ной такой ситуацией является ограничение некоторых почтовых серверов на размер сообщения — если письмо превышает некий заранее установленный размер, оно от- брасывается сервером. Применительно к 1 С: Предпри- ятию такая ситуация может возникнуть при пересылке больших сообщений обмена данными. Для решения этих проблем можно использовать функ- ции РазделитьФайлО и ОбъединитьФайлыО. Функция РазделитьФайлО предназначена для разбиения файла на несколько частей указанного размера. Функция ОбъединитьФайлыО наоборот, позволяет из нескольких то- мов собрать один файл. Пример использования функции РазделитьФайлО приве- ден в листинге 14.77. Листинг 14.77. Пример использования функции РазделитьФайлО Массив = РазделитьФайл("с;\архив.к1р", 1024 * 1024, "с:\"); Первый параметр функции содержит имя архива, во вто- рой записывается размер каждой части файла в байтах, в третьем параметре указывается путь, по которому будут размещаться создаваемые файлы. Функция возвращает массив имен созданных файлов. Функцию ОбъединитьФайлыО можно использовать двумя способами: ♦ указывая в первом параметре массив файлов, которые необходимо объединить (листинг 14.78); ♦ указывая в первом параметре шаблон, в соответствии с которым будет производиться объединение (лис- тинг 14.79). Листинг 14.78. Пример использования функции ОбъединитьФайлы() МассивИмен = Новый Массив(2): МассивИмен.ДобавитьС“с:\архив.zip.001"); МассивИмен.Добавить("с;\архив.zip.002"); ОбъединитьФайлыСМассивИмен, "с:\архив.zip"); Листинг 14.79. Пример использования функции ОбъединитьФайлыО ОбъединитьФайлыС"с:\apxMB.zip.*", "с:\apxHB.zip"); Во втором параметре функции указывается полное имя создаваемого в результате объединения файла. Кроме этого способа существует также возможность объ- единить файлы в один с помощью команды операци- онной системы COPY. Для этого надо воспользоваться ее возможностью конкатенации двоичных файлов (лис- тинг 14.80). Листинг 14.80. Пример использования команды COPY C:\>COPY архив.zip.001 /В + архив.zip.002 /В архив.гт'р Использование Интернет-технологий Прежде чем приступить к рассмотрению возможностей Интернет-технологий, которые могут использоваться платформой 1 С: Предприятия для реализации различ- ных механизмов интеграции с другими информацион- ными системами, рассмотрим основы работы этих тех- нологий. Среди Интернет-технологий распространена модель «Клиент-Сервер», разделяющая взаимодействующие сто- роны по функциональности клиента (запрашивающего выполнение операции) и сервера (выполняющего запро- шенную операцию). Взаимодействие клиента и сервера производится в соответствии с определенными правила- ми (протоколом). Схематично модель «Клиент-Сервер» можно изобразить следующим образом (рис. 14.10). Каждый компьютер в глобальной сети Интернет обладает неким уникальным идентификатором (IP-адресом). При организации любого взаимодействия учитывается 1Р-ад- рес, как клиента, так и сервера. Кроме IP-адресов допол- нительно используется такое понятие, как «порт». Под портом понимается некая адресная точка (локально на компьютере), через которую и производится взаимодей- ствие. Как на стороне сервера, так и на стороне клиента порт обслуживается какой-либо (специализированной) программой. Рис. 14.10. Модель «Клиент-Сервер» Доступ клиента (это может быть программа Microsoft Internet Explorer и т. д.) из локальной сети в сеть Интер- нет может производиться как напрямую, так и через спе- циализированную службу: прокси-сервер (некая служ- ба — посредник). Задача службы выполнять запросы
клиентов к серверу от своего имени, получать, выдавать, хранить (для повторной отправки) «ответы» серверов. При использовании этой службы клиент выполняет за- прос не к серверу, а к прокси-серверу (с указанием дан- ных сервера, содержащего запрашиваемый ресурс). Если такой запрос уже проходил через прокси-сервер и «от- вет» хранится в его базе данных (это определяется набо- ром факторов, например таких, как «время жизни отве- та», политика администратора сервера и т. п.), то запрос к серверу, содержащему запрашиваемый ресурс, не про- изводится, ответ выбирается из базы данных. Использо- вание такой службы позволяет экономить внешний (по отношению к локальной сети) трафик, более быстро по- лучать «ответы» на часто задаваемые «вопросы». Схематично этот процесс можно отразить следующим об- разом (рис. 14.11). Рис. 14.11. прокси-сервер После рассмотрения основных принципов перейдем к рассмотрению конкретных технологий, которые могут использоваться механизмами, реализованными в 1 С: Пред- приятие. Работа с HTML Можно сказать, что HTML-документ представляет собой текстовый файл, имеющий определенную структуру и ко- торому принудительно дано расширение НТМ или HTML На самом деле более правильно говорить о языке HTML (язык разметки гипертекста). С этой точки зрения HTML- документ, — это документ с текстовым содержимым, на- писанный на языке HTML. «Структура» HTML-документа задается с помощью так называемых «тегов» (выражений заключенных в угловые скобки). Набор тегов и их свойств (значений свойств) за- фиксирован. Изучение языка HTML сводится к изуче- нию конечного множества тегов, свойств тегов и их зна- чений. Если говорить о «задаче, решаемой языком HTML», то это форматирование отображаемых данных. В этом смыс- ле теги можно разбить на «теги структуры документа», «теги форматирования» и «другие». Основные теги, задающие структуру HTML-документа, следующие (листинг 14.81). В теле документа могут располагаться различные «фор- матирующие теги». Пример таких тегов приведен в лис- тинге 14.82. Листинг 14.81. Основные теги, задающие структуру HTML-документа <html> <head> <meta content="text/html; charset=windows-1251"> <title>3aronoBOK страницы</Г1tle> </head> <body bgcolor=lightyellow text=darkblue> “Тело" документа </body> </html> Листинг 14.82. Примео «форматирующих» тегов <Ь1>Заголовок 1-го уровня (можно до 6-ro)</hl> <Ь>Полужирный<1> полужирный и наклонный </Ь> наклонный<1> обычный текст <р> новый абзац. Данные в HTML-документе можно организовывать в таб- лицы (листинг 14.83). Листинг 14.83. Пример таблицы <table> <tr> <td>nepeoe</td> <td>BTopoe</td> </tr> <tr> <td>rpeTbe</td> <td>4eTBeproe</td> </tr> </table> Для «навигации» (переходу к другим ресурсам) могут ис- пользоваться гиперссылки (листинг 14.84). Листинг 14.84. Пример использования гиперссылки <а href=”pecypc">TeKCT гиперссылки</а> Следует отметить, что в данном разделе не ставится зада- ча познакомить со всем множеством тегов, это удел спе- циализированной литературы. Рассматриваем только ос- новные понятия. Если собрать все продемонстрированные фрагменты и запустить полученный HTML-документ на просмотр в специализированной программе (например, Microsoft Internet Explorer), то получим, например, следующее (рис. 14.12). «Тело» документа Заголовок 1-го уровня (можно до 6-го) Полужирный полужирный и наклонный наклонный обычный текст новый абзац. первое второе третье четвертое текст гиперссылки Рис. 14.12. Пример НТМ L-доку мента В платформе 1 С: Предприятие существует специализиро- ванный элемент управления, который позволяет про- сматривать НТМ L-доку менты.
Поле HTML-документа Функциональность элемента управления ПолеНТМЬДокумента целиком зависит от установленной на локальном компь- ютере программы Microsoft Internet Ехрогег (она ею обеспечивается). Для просмотра различных Интернет-ресурсов, возвра- щающих ответ в виде HTML-документа (это не обяза- тельно должны быть определенные в явном виде HTML- документы, также можно смотреть результат обращения к файлам *.asp, *jsp и т. д.)? может использоваться метод Перейти!) (листинг 14.85), в который передается адрес за- прашиваемого ресурса. Листинг 14.85. Пример использования метода ПерейтиО ЭлементыФормы.ПолеНТМЬ.Перейти(URL); Для работы с историей просмотренных страниц можно использовать методы Вперед!) и Назад!) (листинг 14.86). Листинг 14.86. Пример использования методов ВпередО и НазадО ЭлементыФормы.ПолеНТМЬ.Вперед(): ЭлементыФормы.ПолеНТМЬ.Назад!): Поле HTML-документа может использоваться как для просмотра, так и для редактирования HTML-документов. В каком режиме находится элемент управление зависит от установленного режима, который определяется зна- чением системного перечисления РежимПоляНТМЬДокумента (листинг 14.87). Листинг 14.87. Пример установки режима поля HTML-доку мента ЭлементыФормы.ПолеНТМЬ. УстановитьРежим(РежимПоляНТМЬДокумента.Редактирование); Рассматриваемый элемент управления, так же как и боль- шинство специализированных программ, поддерживает работу с объектной моделью HTML-документа (реали- зуемой браузером). Эту модель можно представить в виде набора взаимосвязанных объектов (каждый из которых определяется при помощи соответствующих тегов HTML). Схема фрагмента данной модели представлена на рис. 14.13. Рассмотрим следующий HTML-документ (листинг 14.88). Листинг 14.88. Пример HTML-документа <html> <head> <titlе>Анкета</Ь1tlе> </head> <body> <form name='anketa' action='input.asp’> <table> <tr> <td>0praHH3aunfl</td> <td> <input type=text name='firma’> </td> </tr> <tr> <td>K0Hy</td> <td> <input type=text name='to'> </td> </tr> <tr> <td>no»enaHne</td> <td> <input type=text name='message’> </td> </tr> <tr> <td colspan=2 align=center> <input type=submit name=’ok' value='Отправить'> </td> </tr> </table> </form> </body> </html> Рис. 14.13. Фрагмент объектной модели HTML-документа Визуально этот документ отображается следующим обра- зом (рис. 14.14). Организация Кому Пожелание | Отправить | Рис. 14.14. НТМЬ-документ С точки зрения объектной модели его можно упрощенно представить следующим образом (рис. 14.15). Рис. 14.15. Структура НТМЬ-документа
Для того чтобы заполнить анкету, загруженную в поле HTML-доку мента, можно воспользоваться следующим фрагментом кода (листинг 14.89). Листинг 14.89. Пример заполнения анкеты Док = ЭлементыФормы.ПолеНТМ!..Документ; Док.forms["anketa"].firma.Value = "ООО Вперед": Док.forms["anketa"].to.Value = "директору"; Док.forms["anketa"].message.Value = "здоровья и счастья!"; Свойство Документ поля HTML-документа позволяет по- лучить СОМОбъект, который содержит объект document пред- ставленной объектной модели. У рассматриваемого элемента управления большое коли- чество обрабатываемых событий. Их можно разделить на три группы: ♦ события, связанные с клавиатурой (нажатие на кнопку, обжатие кнопки и т. п.); ♦ события, связанные с мышью (движение мыши, уход мыши с HTML-элемента и т. д.); ♦ событие Документ сформирован. В случае если понадобится активно работать с объектной моделью, настоятельно рекомендуем использовать обра- ботчик события поля HTML-документа ДокументСфор- мирован. Событие возникает, когда документ загружен полностью (либо в ряде случаев, когда загружен пустой документ: blank). Этот момент можно использовать для начала попытки работы с объектной моделью. НТТР-соединение Протокол HTML (hypertext transfer protocol) — это про- токол обмена гипертекстом (фактически обмен HTML- документами и их составляющими — картинками, flash- анимацией и т. д.). В качестве HTTP-сервера (програм- мы, которая обслуживает нужный порт) может исполь- зоваться соответствующая служба Microsoft Internet Information Services. Для обращения к HTML-ресурсу нужно знать имя серве- ра и порт, который обслуживается нужной программой (обычно этот порт имеет номер 80). При настройке соединения для указания параметров дос- тупа к прокси-серверу используется объект ИнтернетПрок- си, для указания параметров доступа к HTTP-серверу ис- пользуется объект НТТРСоединение. Пример работы с объектами НТТРСоединение и ИнтернетПрок- си приведен в листинге 14.90. Листинг 14.90. Пример работы с НТТР-соединением Функция ЗапроситьФайлыССервера(СерверИсточник, СтрокаПаранетраПолучения, ИмяВходящегоФайла, HTTP = Неопределено) Экспорт Если ТипЗнч(НТТР) <> Тип("НТТРСоединение") Тогда HTTP = Новый НТТРСоединение(СерверИсточник); КонецЕсли; Попытка HTTP.Получить(СтрокаПаранетраПолучения, ИмяВходящегоФайла); Возврат Истина; Исключение Если Найти(ОписаниеОшибки(), "407") о О И Найти(НРег(ОписаниеОшибки()), "authentication") <> 0 Тогда // Скорее всего соединяемся через прокси HTTP = СоздатьСоединениеЧерезПроксиО; Если ТипЗнч(НТТР) <> Тип("НТТРСоединение") Тогда Сообщить("Соединение с сервером не установлено."); Возврат Ложь; Иначе Возврат Истина; КонецЕсли; Иначе Возврат Ложь; КонецЕсли; КонецПопытки; КонецФункции Все данные, необходимые для подключения (имя сервера, какой ресурс запрашиваем, в файл с каким именем сохраня- ем результат), передаются функции в качестве параметров. Далее в случае неудачной попытки подключения к серве- ру напрямую производится попытка подключения с ис- пользованием объекта ИнтернетПрокси (в случае если код ошибки равен 407 и в описании ошибки есть слово «authen- tication») (листинг 14.91). Листинг 14.91. функция СоздатьСоединениеЧерезПрокси Функция СоздатьСоединениеЧерезПроксиО Перем HTTP; Перем ПроксиСервер; ПроксиСервер = Новый ИнтернетПроксиО; ПроксиСервер.Пользователь = ИмяПользователя; ПроксиСервер.Пароль = ПарольПользователя; Попытка HTTP = Новый НТТРСоединение(СерверИсточник, , , , ПроксиСервер); HTTP.Получить(СтрокаПаранетраПолучения, ИмяВходящегоФайла); Исключение HTTP = Неопределено; КонецПопытки; Возврат HTTP; КонецФункции То, что ни в каком из объектов явно не указываются пор- ты обращения к серверам, говорит о том, что используют- ся значения по умолчанию. Использование FTP Работать с FTP-ресурсами (копировать на них или с них файлы) можно двумя способами: ♦ основываясь на функциональности процедуры Копировать- ФайлО (он может использоваться и для копирования фай- лов в локальной сети, и для работы по протоколу FTP). ♦ используя специализированные объекты ГГРСоединение, ГГРФайл, ИнтернетПрокси. Рассмотрим оба варианта и начнем с первого. Процедура Копироватьфайл() Для того чтобы выложить файл с данными либо на FTP- сервер, либо на любое место в локальной сети, может
использоваться представленный ниже фрагмент кода (листинг 14.92). Листинг 14.92. Пример использования процедуры КопироватьФайлО // ИмяФайлаСообщения - параметр, содержащий // имя отправляемого файла. // В имени содержится № сообщения // АдресОбмена параметр, указывающий, куда поместить файл // Необходимо для использования схем http, https и ftp Путь = СтрЗаменить(АдресОбмена. "\", "/"): // Копируем файл в каталог, определенный для данного узла Попытка КопироватьФайл(ИмяФайла. Путь + ?(Прав(Путь. 1) = "/". ”/") + ИмяФайлаСообщения); Исключение Сообщить(" Ошибка публикации файла: " + ИмяФайлаСообщения); Сообщить(ОписаниеОшибки()); Возврат; КонецПопытки; Сообщить(" - Опубликован файл: " + ИмяФайлаСообщения); Для перемещения файла с FTP-сервера (или ресурса ло- кальной сети) в локальный каталог компьютера можно использовать следующий фрагмент кода (листинг 14.93). Листинг 14.93. Пример использования процедуры Копироватьфайл() //МаскаФайлов - параметр, содержащий маску для файлов загрузки //АдресОбмена - параметр, указывающий где смотрим файлы ИмяФайлаСообщения = // Ищем файлы по маске в каталоге загрузки Файлы = НайтиФайлы(АдресОбмена, МаскаФайлов); И Отбираем файл с максимальным номером в имени, // то есть последний выгруженный Для Каждого Файл Из Файлы Цикл Если ПустаяСтрока(ИмяФайлаСообщения) ИЛИ Файл.ПолноеИмя > ИмяФайлаСообщения Тогда ИмяФайлаСообщения = Файл.ПолноеИмя; КонецЕсли: КонецЦикла; Если Не ПустаяСтрока(ИмяФайлаСообщения) Тогда Сообщить(" - Считывается файл " + ИмяФайлаСообщения); Попытка // Копируем файл с сообщением обмена в указанный файл КопироватьФайл(ИмяФайлаСообщения. ИмяФайла); Исключение Сообщить(" " + ОписаниеОшибкиО); Возврат; КонецПопытки; // Файл с сообщением обмена получен успешно КонецЕсли; ЕТРСоединение Для доступа к FTP-серверам можно использовать спе- циализированный объект ЕТРСоединение. Кроме этого, мо- жет использоваться объект ИнтернетПрокси. Протокол FTP — это протокол обмена файлами. В каче- стве FTP-сервера (программы, которая обслуживает нуж- ный порт) может использоваться соответствующая служ- ба Microsoft Internet Information Services. Для обращения к FTP-pecypcy нужно знать имя FTP-сер- вера и порт, который обслуживается нужной программой (обычно этот порт имеет номер 21). При настройке соединения для указания параметров дос- тупа к прокси-серверу используется объект ИнтернетПрок- си, для указания параметров доступа к FTP-серверу ис- пользуется объект ЕТРСоединение. Пример работы с объектами ЕТРСоединение и ИнтернетПрокси приведен в листинге 14.94. Листинг 14.94. Пример использования объекта ЕТРСоединение Если ИспользуетсяПрокси = Истина Тогда ПроксиСервер = Новый ИнтернетПроксиО; ПроксиСервер.Пользователь = ИмяПользователяНаПрокси; ПроксиСервер.Пароль = ПарольПользователяНаПрокси; Попытка Сервер = Новый ЕТРСоединение(СерверОбмена, Порт, Им яПоль з ователяЕТР, ПарольПользователяЕТР, ПроксиСервер); Исключение СообщитьС'Не удалось соединиться с сервером"); Возврат; КонецПопытки: Иначе Попытка Сервер = Новый ЕТРСоединение(СерверОбмена, Порт, ИмяПользователяЕТР, ПарольПользователяЕТР); Исключение СообщитьС'Не удалось соединиться с серверои"); Возврат; КонецПопытки; КонецЕсли; // Находим файлы в нужном каталоге по указанной маске МассивФайлов = Сервер.НайтиФайлы(ПутьНаСервере. МаскаФайлов); Для Каждого Файл Из МассивФайлов Цикл // Не каталог ли это Если Файл.ЭтоФайл() Тогда // Копируем файл в локальный каталог Сервер.Получить(Файл.Значение.ПолноеИмя, Путь + Файл.Значение.ПолноеИмя); КонецЕсли; КонецЦикла: В рассмотренном механизме используются следующие «внешние» параметры: ♦ МаскаФайлов — параметр, содержащий маску для фай- лов загрузки; ♦ ПутьНаСервере — содержит путь на FTP-сервере до нуж- ных файлов; ♦ СерверОбмена — параметр, указывающий сервер, где смотрим файлы; ♦ Путь — параметр, определяющий каталог, куда переме- щать файлы; ♦ Порт — по умолчанию 21 (для FTP); ♦ ИмяПользователяЕТР — параметр, содержащий имя поль- зователя прокси-сервера;
♦ ПарольПользователяПР — параметр, содержащий пароль на доступ к прокси-серверу; ♦ ИспользуетсяПрокси — параметр, определяющий, ис- пользуется ли прокси-сервер (тип Булево). Работа с электронной почтой Работа с электронной почтой из 1 С: Предприятия воз- можна двумя способами: ♦ через установленного на компьютере пользователя поч- тового клиента (почтовой программы, такой как Outlook Express, Outlook, Bat и т. п.). Основным объектом явля- ется объект Почта; ♦ работая напрямую с почтовым сервером (например, с корпоративным почтовым сервером, сервером yandex, mail.ru и т. д.). Основным объектом является объект Ин- гернетПочта. Каждый из вариантов имеет свои достоинства и недостатки. Почта Объект почта позволяет принимать и отправлять почто- вые сообщения посредством установленного (и настроен- ного) почтового клиента (почтовой программы). Все настройки, связанные с подключением к почтовым серве- рам, определяются в учетной записи почтового клиента. Через объект Почта фактически происходит подключение к учетной записи программы — почтового клиента по умолчанию. Чтение писем производится из папки Входящие (из дру- гих папок произвести это нельзя), при этом есть возмож- ность получить только непрочитанные письма. При отправке писем нужно учитывать особенности сис- темы безопасности каждого почтового клиента. Обычно стоит запрет на отправку сообщения «из другой програм- мы от имени почтового клиента». Этот факт особенно важно учитывать при организации отправки без участия пользователя (ночью с сервера...). Пример, позволяющий отправить почтовое сообщение, приведен в листинге 14.95. Листинг 14.95. Пример отправки почтового сообщения Почта=Новый Почта: // Создаем сообщение Сообщ = Новый ПочтовоеСообщение: Сообщ.Текст = "Здравствуйте, дорогая Катерина Матвеевна!..."; Сообщ.Тема = "Письмо с данными": Данные = Новый ДвоичныеДанныеС'сАоиТ.гтр"); Сообщ.Вложения.Добавить(Данные,"data.zip"); Сообщ.Получатели.Добавить("получатель@почтовыйсервер.ги”); Попытка И Попытка подключения к почтовому клиенту Почта.Подключиться("user", "password"); Исключение Сообщить("Ошибка подключения к почтовому клиенту"); Возврат; КонецПопытки; // Отсылка сообщения Почта.Послать(Сообщ, Ложь); Почта.ОтключитьсяО; Пример, позволяющий получить почтовое сообщение, при- веден в листинге 14.96. Листинг 14.96. Пример получения почтового сообщения Почта = Новый Почта; Попытка // Попытка подключения к почтовому клиенту Почта.Подключиться!"user", "password"); Исключение Сообщить("Ошибка подктючения к почтовому клиенту"); Возврат; КонецПопытки; // Истина - только непрочитанные. Ложь - конверты вместе // с вложениями мсвСообщений = Почта.Выбрать(Истина, Ложь); Для Каждого Сообщение Из мсвСообщений Цикл Сообщить("Тема: " + Строка(Сообщение.Тема)); Сообщить("Текст: " + Строка(Сообщение.Текст)); Для Каждого Вложение Из Сообщение.Вложения Цикл Сообщить(" Вложение: " + Строка(Вложение.Наименование)); КонецЦикла; КонецЦикла; Следует отметить, что работа с объектом Почта на стороне сервера 1С:Предприятии из модуля внешнего соедине- ния невозможна. К достоинствам данного подхода следует отнести отсут- ствие необходимости указывать все настройки подключе- ния к почтовому серверу в коде (они содержатся в почто- вом клиенте и настраиваются администратором). Интернет-почта С помощью объекта ИнтернетПочта можно организовывать прием, отправку писем. В отличие от объекта Почта (рас- смотренного выше), на локальной машине не требуется наличие установленного (и настроенного) почтового кли- ента по умолчанию. Объект ИнтернетПочта позволяет рабо- тать с почтовыми серверами напрямую по протоколам SMTP, POP3. Прежде чем приступить к рассмотрению материала дан- ного раздела, вспомним основные понятия, используемые при рассмотрении различных Интернет-технологий. Для подключения к какому-либо серверу (в том числе и к почтовому) необходимо знать его адрес и порт, на ко- тором обслуживаются запросы в соответствии с интере- сующим протоколом. Для работы с почтовым сервером объект ИнтернетПочта может использовать протокол SMTP (отправка сообщений, порт по умолчанию № 25) и POP3 (получение сообщений, порт по умолчанию № 110). На- стройки обращения к почтовым серверам указываются в специализированном объекте ИнтернетПочтовыйПрофиль. Рассмотрим пример, позволяющий отправлять почтовые сообщения (листинг 14.97). Листинг 14.97. Пример отправки почтовых сообщений Профиль = Новый ИнтернетПочтовыйПрофиль; Профиль.АдресСервераЗМТР = CepeepSMTP; Профиль.ПользовательЗМТР = Пользователь; Профиль.ПарольSMTP = Пароль; // Формируем сообщение обмена Сообщение = Новый ИнтернетПочтовоеСообщение; Сообщение.Тема = "СООБЩЕНИЕ_ОБМЕНА: " + ИмяФайлаСообщения; Сообщение.Получатели.Добавить(ПочтовыйАдресОбмена);
ФайлСообщения = Новый Файл(ИмяФайлаСообщения); // Создаем вложение с файлом обмена Сообщение.Вложения.Добавить(ИмяФайла. ФайлСообщения.Имя); Почта = Новый ИнтернетПочта; Попытка Почта.Подключиться(Профиль); // Отправляем сообщение с файлом обмена Почта.Послать(Сообщение); Исключение Сообщить(" - Ошибка при отправки файла: " + ИмяФайлаСообщения); Сообщить(ОписаниеОшибки()); Возврат; КонецПопытки; Сообщить(" - Отправлен файл " + ИмяФайлаСообщения + " на адрес " + ПочтовыйАдресОбмена); Почта.ОтключитьсяО; В данном примере используются следующие входные па- раметры: ♦ ИмяФайлаСообщения — полное имя отправляемого файла; ♦ CepeepSMTP — имя сервера, например smtp.yandex.ru; ♦ ПочтовыйАдресОбмена — почтовый адрес; ♦ Пользователь; ♦ Пароль. Прочитать сообщения можно, используя следующий фраг- мент кода (листинг 14.98). Листинг 14.98. Пример чтения почтовых сообщений Профиль = Новый ИнтернетПочтовыйПрофиль; Профиль. АдресСервераРОРЗ = СерверРОРЗ; Профиль.Пользователь = Пользователь; Профиль.Пароль = Пароль; Попытка Почта = Новый ИнтернетПочта; Почта.Подключиться(Профиль); // Получаем все сообщения из почтового ящика МассивСообщений = Новый Массив; МассивСообщений = Почта.Выбрать(Ложь): Исключение // Ошибка при подключении к серверу или // при приеме сообщения обмена Сообщить(" - Ошибка при подключении или приеме" + ОписаниеОшибки()); Возврат Ложь; КонецПопытки; И Массив будет содержать сообщения, И которые впоследствии будут удалены с сервера МассивСообщенийОбиена = Новый Массив; Если МассивСообщений.КоличествоО = 0 Тогда // Сообщений в почтовой ящике нет Возврат Ложь; КонецЕсли; ИмяФайлаСообщения = Для Индекс = 0 По МассивСообщений.КоличествоО - 1 Цикл // Отсеиваем только сообщения, которые содержат // файлы обмена для участвующих в обмене узлов. ЧастьТемы = "СООБЩЕНИЕОБМЕНА: " + "Message" + СокрП(Ссылка.Код) + СокрП(ПланыОбмена.УдаленныеСклады.ЗтотУзел().Код); Если Лев(МассивСообщений[Индекс].Тема, СтрДлина(ЧастьТемы)) = ЧастьТемы Тогда Если МассивСообщений[Индекс].Вложения[0].Имя > ИмяФайлаСообщения Тогда // Выбираем сообщение с последним номером // сообщения обмена ИмяФайлаСообщения = МассивСообщений[Индекс].Вложения[0].Имя; ИндексСообщения = Индекс; КонецЕсли; МассивСообщенийОбиена.Добавить(МассивСообщений[Индекс]); КонецЕсли; КонецЦикла; Если ИндексСообщения <> Неопределено Тогда // Записываем файл обмена во временный файл МассивСообщений[ИндексСообщения].Вложения[0].Данные. Записать(ИмяФайла); Сообщить(" - Принят файл обмена данными " + ИмяФайлаСообщения + ' с адреса ” + ПочтовыйАдресОбмена): // Удаляем все сообщения обмена с сервера для узлов, // участвующих в обмене Почта.УдалитьСообщения(МассивСообщенийОбмена); Почта.ОтключитьсяО; Иначе // Сообщений обмена в почтовом ящике нет Почта.Отключиться(); Возврат Ложь; КонецЕсли; В примере используются следующие входящие данные: ♦ СерверРОРЗ — содержит адрес сервера, например pop3.yandex.ru; ♦ Пользователь; ♦ Пароль. У метода Выбрать О в данном случае определен один пара- метр (Ложь), означающий, что письма с сервера не удаля- ются. Из всех писем, которые находятся на почтовом сер- вере, отбираются только те, у которых в теме определен префикс СообщениеОбмена. Остальные сообщения (счита- ем, что они личные) остаются на сервере. Обращаем внимание на тот факт, что при работе с объек- том ИнтернетПочта отсутствует такое понятие, как «не про- читанные письма». Это понятие реализуется почтовым клиентом, а не почтовым сервером, с которым происхо- дит взаимодействие. В ряде случаев возникает необходи- мость оставлять находящиеся на сервере сообщения до- вольно длительное время (даже после прочтения). При большом потоке писем полная их загрузка может зани- мать много времени (такие потери времени могут быть крайне не желательны). Для того чтобы решить эту про- блему, существует возможность не загружать полностью
все почтовые сообщения, а первоначально загружать только их конверты. Метод ПолучитьЗаголовкиО объекта ИнтернетПочта позволя- ет получать с сервера только заголовки сообщений. Бла- годаря этому, например, можно получить информацию о теме, отправителе и т. д. и решить, принимать ли это письмо, оставить его или сразу удалить его. Данный метод возвращает массив объектов типа Интерне- тПочтовоеСообщение. Каждый объект содержит информа- цию из заголовка сообщения. Вложения и тексты с серве- ра не принимаются. Например, требуется получить все заголовки почтовых сообщений (листинг 14.99). Листинг 14.99. Пример получения заголовков почтовых сообщений Профиль = Новый ИнтернетПочтовыйПрофиль; Профиль. АдресСервераРОРЗ = "pop3.yandex.ru"; Профиль Пользователь = "user"; Профиль Пароль = "password"; И Подключиться к почтовому серверу Почта = Новый ИнтернетПочта; Почта.Подключиться(Профиль); // Принять заголовки всех писем, находящихся на сервере // ЗаголовкиСообщений - это массив с объектами типа // ИнтернетПочтовоеСообщение ЗаголовкиСообщений = Почта.ПолучитьЗаголовкиО: При просмотре можно заполнять новый массив заголов- ками сообщений, которые в дальнейшем можно попы- таться получить полностью. Сам процесс получения мо- жет выглядеть следующим образом (листинг 14.100). Листинг 14.100. Пример получения почтовых сообщений Попытка // Получить полные сообщения ПолученныеСообщения = Почта.Выбрать(Ложь, НужныеЗаголовкиСообщений), Исключение Сообщить (ОписаниеОшибкиО); КонецПопытки; Используя метод ПолучитьЗаголовкиО, можно получать со- общения по-одному. Кроме того, можно заключить про- цедуру получения в операторы Попытка ... Исключение, что позволит продолжить получение, если при приеме опре- деленного сообщения произошла ошибка. Также можно поместить в форме индикатор для графического отобра- жения процесса получения сообщений. Следует отметить, что работа с объектом ИнтернетПочта возможна как со стороны сервера ЮПредприятие, так и из модуля внешнего соединения (в противоположность объекту Почта). Использование MSMQ MSMQ — это технология, включающая в себя набор воз- можностей по обмену сообщениями между компьюте- рами. MSMQ поддерживает как асинхронный (послав сообщение, приложение продолжает работать, не дожида- ясь ответа), так и синхронный способы передачи сообще- ний в распределенной среде. MSMQ гарантирует достав- ку сообщения, эффективную маршрутизацию, защиту и нужную приоритетность. Кроме этого, MSMQ предо- ставляет набор COM-объектов, благодаря чему ее можно использовать в обмене данными вместе с 1С: Предпри- ятием 8.0. Перед использованием данной технологии нужно устано- вить компонент Windows Message Queuing. Для установки нужно выполнить следующие шаги (все ниже сказанное справедливо для Windows ХР и выше): ♦ открыть панель управления (Control Panel); ♦ выбрать Установка или удаление программ (Add or Remove Programs); ♦ нажать кнопку Установка компонентов Windows (Add/Remove Windows Components), которая находится справа; ♦ в появившемся списке поставить галочку напротив Message Queuing и нажать на кнопку Далее. При установке Message Queuing на Windows 2000, после нажатия на кнопку Далее мастер установки потребует указать дополнительные параметры WSMQ. В основе MSMQ лежат два понятия — очереди (queue- qinfo) и сообщения (message-Сообщение). Сообщение яв- ляется неким логическим контейнером порции данных. Очередь представляет собой виртуальную таблицу, поля- ми которой являются свойства сообщений, а строками, соответственно, сообщения. Это позволяет организовать доступ к MSMQ через ADO. Механизм MSMQ предусматривает защиту отдельных сообщений средствами криптозащиты (шифрования и электронной подписи) и поддерживает инфраструктуру открытых ключей. Рассмотрим пример использования данной технологии. Размещение данных в очереди представлено в листин- ге 14.101. Листинг 14.101. Пример размещения данных в очереди MSMQ Процедура КнопкаВыполнитьНажатие(Кнопка) // Флаги HQ SEND ACCESS = 2; MQDENYNONE = 0; qinfo = Новый COMOObeKrC'MSMQ.MSMQQueuelnfo"); ОчередьОбненаМЗМО = ".\MyLocale": ИмяФайлаСообщения = "data.xml"; И Формируем путь к очереди на удаленном компьютере qinfo. PathName = ОчередьОбменаМЗМО + + ЦентрОфис"; И Если очередь не создана, создаем Попытка qinfo.CreateO; Исключение КонецПопытки:
И Открываем очередь на запись Очередь = qinfo.Open(MQ_SEND_ACCESS, MQDENYNONE): ДанныеОбмена = Новый ЧтениеТекста; ДанныеОбмена.Открыть("с:\out.xml"); // Создаем сообщение, содержащее данные обмена Сообщение = Новый COMO6beKT("MSMQ.MSMQMessage"); Сообщение.Label = ИмяФайлаСообщения; Сообщение. Body = ДанныеОбмена.ПрочитатьО; Сообщение.ResponseQueuelnfo = qinfo: // Помещаем сообщение в очередь Сообщение.5епб(0чередь); Сообщить!" - Помещен файл " + ИмяФайлаСообщения + " в очередь " + ОчередьОбиенаМЗМО); Очередь.Close!); ДанныеОбмена.Закрыть(); КонецПроцедуры В указанном примере данные размещаются в очереди на локальной машине. При размещении данных на другом компьютере имя очереди складывается из <ИняМашины>/ <ИмяОчереди>. Получение данных из локальной очереди представлено в листинге 14.102. Листинг 14.102. Получение данных из очереди MSMQ Процедура Загрузить(Кнопка) // Флаги MQDENYNONE = 0; MQ RECEIVE ACCESS = 1; MQNOTRANSACTION = 0; ОчередьОбменаМЗМО = "AMyLocale"; qinfo = Новый C0M06beKT("MSMQ.MSMQQueueInfo"); // Находим позицию начала имени очереди в АдресОбменаМЗМО И Хотя в нашем случае могли установить Индекс=2 Индекс = СтрДлина(ОчередьОбменаМЗМО); Пока (Индекс <> 0) Цикл Если Сред(ОчередьОбменаМ5МО. Индекс, 1) = "\" Тогда Прервать; КонецЕсли; Индекс = Индекс - 1; КонецЦикла; // Собираем путь к очереди для чтения данных обмена // В нашем случае qinfo.PathNarne = ",\МуЕоса1е_Центр0фис” qinfo.PathName = "А” + Прав(ОчередьОбменаМ5МО, СтрДлина(ОчередьОбменаМ5МО) - Индекс) + "ЦентрОфис"; Попытка qinfo.Create!); Исключение КонецПопытки; // Открываем очередь Очередь = qinfo.Open(MQ_RECEIVE ACCESS. MQ DENY NONE); // Временный объект необходим для поиска // последнего сообщения СообщениеВрем = Новый C0M06beKT("MSMQ.MSMQMessage"): // Читаем первое сообщение СообщениеВрем = Очередь.Receive(MQ_NO TRANSACTION. , , 0); Пока (СообщениеВрем <> Неопределено) Цикл Сообщение = СообщениеВрем: // Читаем последующие сообщения, если они присутствуют СообщениеВрем = Очередь.Receive(MQ_NO_TRANSACTION, , , 0); КонецЦикла; // Закрываем очередь Очередь.Close!): И Если получили сообщение, разбираем его и передаем данные // обмена дальше для обработки Если Сообщение <> Неопределено Тогда ИмяФайлаСообщения = Сообщение.Label; ФайлОбмена = Новый ЗаписьТекста!"c:\input.xml"); ФайлОбмена.Записать(Сообщение.Body); ФайлОбиена.Закрыть(); Сообщить!" - Принят файл обмена данными " + ИмяФайлаСообщения + ' из очереди " + ОчередьОбменаМЗМО); КонецЕсли; КонецПроцедуры Данные выбираются из локальной очереди. В общем слу- чае возникает задача получения из имени очереди отдель- но локального имени очереди и имени машины. Имя машины нужно заменить на «./» (обращение идет к ло- кальной очереди). В примере действующий фрагмент кода реализует универсальный механизм разбора (ищем символ «/», меняем имя машины на «./»). Использование WSMQ IBM WebSphere MQ представляет собой средство для управления обменом данными в распределенной системе. Одна из главных особенностей таких программ — это га- рантированная доставка сообщений, даже если в данный момент времени компьютер-получатель недоступен по каким-либо причинам. IBM WebSphere MQ — мощный и гибкий программный комплекс, благодаря чему его мож- но использовать совместно с 1С: Предприятием 8.0 для обмена данными. Опишем некоторые основные понятия, более подробную информацию можно найти на сайте производителя (IBM WebSphere MQ). Сообщение (message). Набор данных, посылаемый одной программой и предназначенный для другой. Очередь (queue). Очередь сообщений или просто оче- редь — это именованный адресат, которому доставляется сообщение. Сообщения накапливаются в очереди до тех пор, пока приложение их оттуда не считает. Очередь при-
надлежит менеджеру очередей и управляется им же. Дос- туп приложения к очереди происходит только через внешние сервисы менеджера очередей. Приложение мо- жет открыть очередь, поместить в очередь сообщение, прочить сообщение из очереди, а также закрыть очередь. Кроме того, можно устанавливать или узнавать парамет- ры очереди. Менеджер очередей (manager queue). Менеджер очередей — это системная программа, которая предоставляет необхо- димые средства для работы с очередью. Менеджер очере- дей также предоставляет дополнительные функции, ко- торыми могут пользоваться администраторы: создание очереди, изменение параметров уже существующих оче- редей, а также контроль деятельности менеджера очере- дей. Кластер (cluster). Кластер — это некоторая сеть, объеди- няющая несколько менеджеров очередей. Если сеть IBM WebSphere MQ использует модель распределенных оче- редей без кластеризации, все менеджеры сообщений неза- висимы. В этом случае, если одному менеджеру сообщений нужно послать сообщение другому, необходимо будет оп- ределить специальную транспортную очередь, а также ка- нал для связи с удаленным менеджером очередей. Этого можно избежать, разместив всех менеджеров очередей в кластере. В этом случае любая очередь может управляться любым менеджером очередей, находящемся в кластере. Репозитарий (repository). Репозитарий — это набор ин- формации обо всех менеджерах очередей, находящихся в кластере. Эта информация включает в себя имена менед- жеров очередей, их расположение, информацию о кана- лах передачи данных, информацию об очередях и т. д. Все последующие действия будут выполняться при помо- щи интерфейса IBM WebSphere MQ Explorer, интегриро- ванного в Microsoft Management Console (MMC). IBM WebSphere MQ Explorer доступен только пользователям Windows и является альтернативой команд MSMQ. Перед использованием данного механизма необходимо установить и соответствующим образом настроить про- граммный продукт IBM WebSphere MQ. Общая схема следующая: ♦ создаются два менеджера очередей, на локальном и уда- ленном компьютере, между которыми необходимо обес- печить обмен данными; ♦ затем создается кластер, в который включаются создан- ные менеджеры очередей; ♦ после этого создается по одной локальной очереди на каждом компьютере. Создание менеджера очередей В иерархическом списке в левой части окна нужно уста- новить курсор на узел Queue Managers и после нажатия на правую кнопку мыши выбрать New. Запустится мастер создания нового менеджера очередей (рис. 14.16). В первом окне необходимо указать уникальное имя ме- неджера очереди латинскими символами (например: Head Office) и нажать на кнопку Next. Все остальные на- стройки остаются без изменений, кроме последнего окна, где нужно указать номер порта, например: 1515 (порт не должен быть занят какой-либо другой службой). Анало- гично создается менеджер очередей на удаленном компь- ютере. Ffe Action View Favorites Window Help Ф- -» £)[]. ЙГ if №1 Cl Console Root Ё WebSphere MQ Show Queue Manager... Hide Queue Manager... New Window From Here Name C^Queue Managers (□clusters AU Tasks Refresh Й C3 Help Рис. 14.16. Запуск менеджера очередей Создание кластера В иерархическом списке в левой части окна нужно уста- новить курсор на узел Cluster и после нажатия на правую кнопку мыши выбрать New. Запустится мастер создания нового кластера (рис. 14.17). Рис. 14.17. Запуск мастера создания нового кластера Первое окно просто информативное. В следующем окне нужно ввести имя будущего кластера. Имя вводится ла- тинскими буквами, например: enterprise. Далее указыва- ется менеджер очереди на локальном компьютере, кото- рый также будет и репозитарием (repository). Выбрать можно из списка менеджеров очередей. Менеджер очере- ди не должен быть уже репозитарием, а также находиться в другом кластере. Далее необходимо указать второй ре- позитарий, находящийся на удаленном компьютере. В первом текстовом поле указывается имя менеджера очередей, который, как и в первом случае, не должен уже быть репозитарием и находиться в другом кластере. Да- лее указываются имя для принимающего канала, а также имя соединения. Эти параметры можно оставить без из- менения. Аналогично для отправляющего канала. Все на- строенные параметры можно распечатать, нажав на кноп- ку Print в последнем окне мастера. Создание очередей В менеджере очередей находится папка Queue. Для созда- ния новой очереди достаточно правой кнопкой мыши кликнуть на эту папку и выбрать пункт меню
New Local Queue, указать имя новой очереди, а также на вкладке Cluster выбрать Shared in cluster и указать кластер, который будет управлять этой очередью (рис. 14.18). Не Action View Favorites Window Help Cj Console Root B -WebSphere MQ 0- Cj Queue Managers B-^i Head_Office Name Q Queue Managers [^Clusters i E-ifo 1 E i® j 0 Й i E• Fl Pl Clus New Window from Here Refresh Help Alias Queue Model Queue Remote Queue Definition Рис. 14.18. Создание новой очереди Подобные действия необходимо выполнить и на другом компьютере. Работа с IBM WebSphere MQ из встроенного языка В качестве иллюстрации порядка работы с данной техно- логией рассмотрим следующий пример. Фрагмент кода, позволяющий разместить сообщение в очереди удаленного компьютера. Имя очереди опреде- ляется в переменной УдаленнаяОчередь. (листинг 14.103). Листинг 14.103. Пример размещения сообщения в очереди // Определяем флаг MQOOOUTPUT = 16; // Указываем очередь в которую нужно поместить данные УдаленнаяОчередь = "RemoteQueue"; Попытка // Подключаемся к менеджеру очереди Сессия = Новый C0M06beKT("MQAX200.MQSession"); МенеджерОчереди = Сессия.AccessQueueManagerC""); Исключение Сообщить(’’ - Ошибка доступа к очереди: ” + ОписаниеОшибкиО); Возврат: КонецПопытки; Попытка И Открываем очередь на запись Очередь = МенеджерОчереди.Ассе550иеие(Удаленная0чередь, MQOOOUTPUT); Исключение Сообщить(" - Ошибка открытия очереди: " + ОписаниеОшибкиО); Возврат; КонецПопытки; Попытка И Создаем новое сообщение Сообщение = Сессия. AccessMessageO; // Открываем файл с данными обмена ДанныеОбмена = Новый ЧтениеТекста: ДанныеОбмена.Открыть("с:\out.xml"); И Считываем данные из файла в сообщение, И которое затем помещается в очередь Сообщение.wri teStri ng(ДанныеОбмена.Прочитать()); // Помещаем сообщение в очередь Очередь. РиНСообщение): Исключение Сообщить(" - Ошибка размещения сообщения в очереди: " + ОписаниеОшибкиО); Возврат; КонецПопытки; Сообщить(" - Помещен файл в очередь " + УдаленнаяОчередь); ДанныеОбмена.Закрыт ь(); Фрагмент кода, позволяющий прочитать сообщение из очереди. В переменной ЛокальыаяОчередь указывается имя очереди, определенной на данном (локальном) ком- пьютере (листинг 14.104). Листинг 14.104. Пример чтения сообщения из очереди И Определяем флаг MQOO_INPUT_AS_Q_DEF = 1; И указываем локальную очередь, из которой нужно И прочитать данные ЛокальнаяОчередь = "LocaleQueue"; Попытка И Подключаемся к менеджеру очереди Сессия = Новый C0M06beKT(''MQAX200.MQSession”); МенеджерОчереди = Ceccnfl.AccessQueueManagerC'"); Исключение Сообщить(" - Ошибка доступа к очереди: " + ОписаниеОшибкиО); Возврат; КонецПопытки; И Открываем очередь для чтения из нее данных обмена Попытка Очередь = МенеджерОчереди.Ассе550иеие(Локальная0чередь, MQOO_INPUT_AS_Q_DEF); Исключение Сообщить(" - Ошибка открытия очереди: " + ОписаниеОшибкиО); Возврат; КонецПопытки; Попытка И Создаем сообщение Сообщение = Сессия. AccessMessageO; И получаем сообщение Очередь.Get(Сообщение); Исключение Сообщить!" - Ошибка чтения данных из очереди: " + ОписаниеОшибкиО); Возврат: КонецПопытки; И Читаем из сообщения данные обмена и сохраняем их в файл Данные = Сообщение.ReadString(Сообщение.MessageLength); ФайлОбмена = Новый ЗаписьТекста("с:\1прЩ.хгп1"); ФайлОбнена.Записать(Данные); ФайлОбмена.Закрыть(); Сообщить(" - Принят файл обмена данными из очереди ” + ЛокальнаяОчередь); Имена очередей, как и другие параметры, от которых за- висит обмен, рекомендуется хранить в реквизитах планов обмена (в случае если они используются).
Automation Технология Automation предназначена для программного использования объектов, чаще всего не имеющих визу- ального представления (исключения составляют, напри- мер, объекты Microsoft Office Word.Application и Excel. Application, при этом они отображаются в отдельном окне, отличном от окна 1С: Предприятия). Обычно задачи, которые решаются с помощью этой тех- нологии, — это запись и чтение данных в/из специфиче- ские (для других приложений) форматы, записи и чтения в какие-либо базы данных. 1 С:Предприятие может выступать как в роли Automation Server, так и в роли Automation Client. Automation Server Основное назначение Automation-сервера ЮПредпри- ятия — управление приложением системы 1С:Предпри- ятие из других приложений и выполнение действий ана- логичных интерактивным действиям. Automation-сервер 1 С:Предприятие предоставляет дос- туп ко всем свойствам и методам своего глобального кон- текста, имеет дополнительные свойства и методы для вы- полнения действий, специфичных для работы в режиме Automation. Для запуска системы 1С:Предприятие в качестве Auto- mation-сервера из внешнего приложения выполняется следующая последовательность действий: ♦ создается COM-объект с идентификатором VS.Application; ♦ выполняется инициализация системы 1 С:Предприятие методом CormectO; ♦ вызываются свойства и методы системы 1 С: Предпри- ятие как Automation-сервера. Поставим задачу загрузить данные из листа программы MS Excel в базу данных 1С:Предприятие В листе данные расположены следующим образом (рис. 14.19). Признаком конца табличной части является наличие в колонке Номер символа «#». Пример кода приведен в листинге 14.105. В данном примере запускается и инициализируется кон- фигурация 1С:Предприятие 8.0 с базой данных в каталоге c:\InfoBases\Trade. Далее создается экземпляр документа Приходная. Из листа извлекаются данные документа и за- писываются в объект 1С:Предприятие 8.0. В конце алго- ритма открывается форма вновь созданного документа. Листинг 14.105. Пример чтения данных из писта Excel Sub OLE() Dim trade As Object Dim Элемент As Object Set trade = Create0bject("V8.Application") trade.Connect (”Fi1e="”с:\InfoBa ses\Trade" ";Usr=""Director'"’:") Rem создаем документ Set Документ = trade.Документы.Приходная.СоздатьДокументО Rem получаем данные из листа Set Контрагент = trade.Справочники.Контрагенты. НайтиПоНаименованию(Арр1ication.Cel1s(1, 2).Vaiue) НомерДокумента = Application.Cells(2, 2).Value Дата = Application.Cells(3. 2).Value Rem записываем полученные данные в документ Документ.Контрагент = Контрагент Документ.Дата = Дата Документ.Номер = НомерДокумента Номер = б 'Первая строка табличной части НомерСтроки = Application.Cells(HoMep, 1).Value Rem в последней строке табличной части будет символ # While НомерСтроки <> Rem получаем данные из листа Set Номенклатура = trade.Справочники.Номенклатура. НайтиПоНаиненованию(Арр11cat 1 on. Cells(HoMep, 2).Value) Количество = Application.CelIs(Номер. 5).Value Цена = Application.Cells(HOMep, 6).Value Сумма = Application.Cells(HoMep. 7).Value Rem записываем полученные данные в строку Rem табличной части Set Строка = Документ.Товары.ДобавитьО Строка.Номенклатура = Номенклатура Строка.Количество = Количество Строка.Цена = Цена Строка.Сумма = Сумма Номер = Номер + 1 НомерСтроки = Application.CellsCHoMep, 1).Value Wend Документ.Записать Документ.ПолучитьФорму.ОткрытьМодально End Sub Объект Automation-сервер ЮПредприятия в качестве своих свойств может иметь: ♦ системные константы; ♦ значения заданных в конфигураторе объектов, доступ к которым осуществляется с помощью менеджеров (на- пример, константы, перечисления, справочники, доку- менты, журналы документов, отчеты, обработки, планы видов характеристик, планы счетов, планы видов расче- та, регистры); ♦ переменные, объявленные в модуле приложения с клю- чевым словом Экспорт. Automation-сервер Ю Предприятие 8.0 в качестве своих методов может иметь: ♦ системные процедуры и функции; ♦ процедуры и функции модуля приложения и общих модулей, объявленные с ключевым словом Экспорт; ♦ два дополнительных метода — ConnectO и NewObjectO.
Как и многие современные программные продукты, 1 С:Предприятие может выступать в роли клиентов Automation. Поэтому имеется возможность из системы ЮПредприятие обращаться к другой копии 1 С:Пред- приятия (например, к другой конфигурации) для обмена данными (листинг 14.106). Листинг 14.106. Пример использования системы ЮПредприятие в качестве Automation Client VB = Новый С0М0бъект('У8.Application"); Попытка Открытие = V8.Connect C'File=” + Путь + ";Usr="''Usrl"“;Pwd=" + Пароль + Исключение Предупрежденное"База данных не открыта!!!”); Возврат; КонецПопытки; МенеджерНоненклатуры = V8.Справочники.Номенклатура: НовыйЭлемент = МенеджерНоненклатуры. СоздатьЭлементО; НовыйЭленент.Наименование = "Созданный": НовыйЭлемент.Записать(); Фрм = НовыйЭлемент.ПолучитьФормуО; Фрм.ОткрытьМодальноО: Automation Client Основное назначение Automation-клиента 1С:Предпри- ятия — управление другими приложениями из системы 1 (^Предприятие и выполнение действий, аналогичных интерактивным действиям. Можно сказать, что технология рекомендуется к приме- нению в случае, когда не требуется предоставлять пользо- вателю интерфейс, выходящий за рамки возможностей 1С:Предприятия, но в то же время требуется взаимодей- ствие с «внешней функциональностью». В общем случае применение этой технологии состоит из двух частей — создание объекта по его идентификатору и последующее использование объекта. Создание объекта выполняется оператором Новый СОМОбъект (Идентификатор- Объекта). Использование созданного объекта ничем не отличается от использования остальных объектов 1С:Предприятия. Дополнительные возможности предоставляет функция ПолучитьСОМОбъектО. С ее помощью можно создать Auto- mation-объект из файла или подключиться к уже сущест- вующему в операционной системе экземпляру Auto- mation-объекта. Пример работы с к тигой программы MS Excel приведен в листинге 14.107. Листинг 14.107. Пример работы с книгой Excel Путь= "с\”; Документ = ПолучитьСОМОбъект(Путь + "документ.xls"); НомерЛиста = 1; Контрагент = Документ. Sheets(HoMepJlMCTa).Cells(l, 1).Value; И дальнейшая обработка данных шапки документа НомерСтроки=3: Номер=Документ.Sheets!иНои).Cel15(НомерСтроки, 1).Vaiue; Пока СокрЛП(Номер) <> Цикл Номенклатура = Документ.Sheets(мНом). Се115(НомерСтроки, 2).Value; Цена = Документ.Sheets(MHoM).Cells(HoMepCTpoKM, 3).Value; И дальнейшая обработка данных табличной части документа НомерСтроки = НомерСтроки+1; Номер = Документ.Sheets(MHoM).Cells(HoMepCTpoKM, 1).Value; КонецЦикла; И завершение работы Документ.Application.Quit!); Следует отметить, что для завершения работы с объекта- ми Microsoft Office, имеющими метод Quit(), его жела- тельно вызывать в явном виде. СОМ-соединение Основная задача, решаемая с помощью СОМ-соедине- ния, — обеспечение надежного и быстрого программного доступа к данным системы 1 С:Предприятие из внешних приложений. В общем и целом, работа с системой ЮПредприятие через СОМ-соединение подобна работе с системой ЮПредприятие в режиме Automation-серве- ра. Основные отличия заключаются в следующем: ♦ в случае Automation-сервера запускается полноценное приложение 1С:Предприятия, а в случае СОМ-соеди- нения запускается относительно небольшой внутри- процессный СОМ-сервер; ♦ при работе через СОМ-соединение недоступны функ- циональные возможности, так или иначе связанные с организацией пользовательского интерфейса системы ЮПредприятия; ♦ при работе COM-соединения не используется модуль приложения конфигурации ЮПредприятия. Его роль при работе с COM-соединением играет модуль внешне- го соединения. При использовании COM-соединения для доступа к дан- ным системы ЮПредприятие имеются следующие пре- имущества по сравнению с использованием Automation- сервера: ♦ более быстрая установка соединения, так как не требу- ется создания отдельного процесса операционной сис- темы, а все действия производятся в рамках вызываю- щего процесса; ♦ более быстрое обращение к свойствам и методам объек- тов системы Ю:Предприятие, так как для организации обращения не требуется организации межпроцессной коммуникации; ♦ меньший расход ресурсов операционной системы. Для организации доступа к данным системы ЮПред- приятие через СОМ-соединение выполняется следующая последовательность действий: ♦ создается COM-объект, с помощью которого произво- дится установка соединения;
♦ через полученный объект COM-соединения произво- дится обращение к допустимым методам, свойствам и объектам информационной базы, с которой установле- но соединение. Поставим задачу загрузить данные из листа программы MS Excel в базу данных ЮПредприятие (посредством механизма СОМ). В листе данные расположены так же, как и в предыдущем примере (см. рис. 14.19). Признаком конца табличной части является наличие в колонке Номер символа «#». Пример кода приведен в листинге 14.108. Листинг 14.108. Пример чтения данных из листа Excel Sub COMO Dim trade As Object Dim Элемент As Object Set obj = Create0bject(''V8.ComConnector”) Set trade = obj. Connect ("Fi 1 e=" “c: \InfoBases\Trade”"; Usr=” ''Di rector" ”;") Rem создаем документ Set Документ = trade.Документы.Приходная.СоздатьДокументО Rem получаем данные из листа Set Контрагент = trade.Справочники.Контрагенты. НайтиПоНаименованию(АррИсаНоп. Cells(l, 2).Value) НомерДокумента = Application.Cells(2, 2).Value Дата = Application.Cells(3, 2).Value Rem записываем полученные данные в документ Документ.Контрагент = Контрагент Документ.Дата = Дата Документ.Номер = НомерДокумента Номер = 6 'Первая строка табличной части НомерСтроки = Application.Cells!Номер, 1).Value Rem в последней строке табличной части будет символ # While НомерСтроки <> Rem получаем данные из листа Set Номенклатура = trade.Справочники.Номенклатура. НайтиПоНаименованию!Application. Cells(HoMep, 2).Value) Количество = Application.CelIs(Номер. 5).Value Цена = Application.Cells(HoMep, 6).Value Сумма = Application.CellsCHoMep, 7).Value Rem записываем полученные данные в строку Rem табличной части Set Строка = Документ.Товары.Добавить!) Строка.Номенклатура = Номенклатура Строка.Количество = Количество Строка.Цена = Цена Строка.Сумма = Сумма Номер = Номер + 1 НомерСтроки = Application.Cells(HoMep, 1).Value Wend Документ.Записать End Sub В данном примере запускается и инициализируется кон- фигурация ЮПредприятие с базой данных в каталоге c:\InfoBases\Trade. Далее создается экземпляр документа Приходная. Из листа извлекаются данные документа и за- писываются в объект ЮПредприятие. В конце алгорит- ма документ сохраняется. Обязанности модуля приложения при работе через СОМ- соединение выполняет модуль внешнего соединения. Данный модуль может иметь процедуры-обработчики со- бытий, в которых могут быть размещены действия, выполняемые при инициализации и завершении соеди- нения соответственно. Процедуры, функции и глобальные переменные, опреде- ленные в модуле внешнего соединения с ключевым сло- вом Экспорт, становятся, как и в случае модуля приложе- ния, частью глобального контекста. COM-соединение с информационной базой 1 (^Предпри- ятие 8.0 предоставляет полный доступ к глобальному контексту и в качестве своих свойств может иметь: ♦ системные константы; ♦ значения заданных в конфигураторе объектов, доступ к которым осуществляется с помощью менеджеров (на- пример, константы, перечисления, справочники, доку- менты, журналы документов, отчеты, обработки, планы видов характеристик, планы счетов, планы видов расче- та, регистры); ♦ переменные, объявленные в модуле внешнего соедине- ния с ключевым словом Экспорт. В качестве своих методов COM-соединение может иметь: ♦ системные процедуры и функции; ♦ процедуры и функции модуля внешнего соединения и общих модулей, объявленные с ключевым словом Экспорт. Имеется возможность из системы ЮПредприятие обра- щаться к другой копии 1 С:Предприятие (например, к другой конфигурации) для обмена данными (лис- тинг 14.109). Листинг 14.109. Пример обращения к другой информационной базе ЮПредприятия V8 = Новый C0M06beKT("VB.ComConnector"): Попытка Открытие = V8.Connect(”File=" + Путь + ";Usr=”"Usrl"":Pwd=" + Пароль + ";"); Исключение Предупреждение!"База данных не открыта!!!'1): Возврат: КонецПопытки; МенеджерНоменклатуры=От крытие.Справочники.Номенклатура; НовыйЭлемент = МенеджерНоменклатуры.СоздатьЭлементО; НовыйЭлемент.Наименование = "Добавлен": НовыйЭлемент.Записать(); Использование СОМ для интеграции с Интернет- приложением В ряде случаев может возникнуть задача организации связи какого-либо Интернет-приложения (например, интернет-магазина) с базой системы 1 С: Предприятия. Это может быть обусловлено необходимостью получе- ния текущих остатков на складе, регистрации заказов и т. д. Архитектура веб-приложений может быть различной, но в рамках данного раздела будем рассматривать вариант, в котором приложение состоит из двух частей: ♦ набор HTML-, ASP-документов, находящихся в опре- деленном виртуальном каталоге;
♦ база данных, в которой находятся отображаемые дан- ные, и данные, вводимые пользователями. Клиент, используя специальную программу (следует от- метить, что очень часто под «клиентом» понимается именно программа отсылающая запрос, а не пользова- тель), посылает запрос на просмотр интересующего его ресурса. Этот ресурс находится на каком-либо сервере, под управлением специального программного обеспече- ния (для примера будем рассматривать Microsoft IIS). IIS может работать с так называемыми ASP-документами. Эти документы, как и HTML-документы, представляют собой текстовый файл, которому было дано расширение ASP. Основное отличие состоит в том, что ASP документ выполняется на сервере и клиенту отсылается результат выполнения. Само «выполнение» возможно благодаря тому, что ASP документ в общем случае представляет со- бой скрипт (описание команд на выполнение). Для написания скриптов используются две конструкции: <% код скрипта %> или набор тегов <script language= "имя языка" runat= "server"> и </script>. Первая конструкция ис- пользуется для написания кода на первичном языке, вто- рая, на указанном в параметре language. На одной странице может быть несколько скриптовых конструкций. Поря- док их выполнения довольно сложный. Для облегчения отслеживания порядка выполнения скриптов рекоменду- ется в конструкциях <script> помещать определение про- цедур, функций и вызывать их при использовании тегов <%%>. Только таким образом можно обеспечить одно- значность последовательности исполнения скриптов. Для указания странице языка по умолчанию использует- ся директива <%@ 1_АМСиАСЕ=ИмяЯзыка%>, для указания кодовой страницы используется директива CODEPAGE и т. п. Из текста скрипта (документа ASP) можно создавать раз- личные объекты, в том числе и использовать СОМ-соеди- нение с базой 1С:Предприятия, обращаться к специально определенным процедурам и т. д. Общая схема работы представлена на рис. 14.20. Рис. 14.20. Общая схема рассматриваемого примера Клиент производит запрос ASP-документа. IIS получа- ет этот запрос, выполняет данный документ. В процессе выполнения создается подключение (через СОМ) к Ю.Предприятию и, к примеру, выполняется функция, описанная в модуле внешнего соединения. При выполне- нии формируется HTML-документ (или XML, который потом преобразуется в HTML). Сформированный доку- мент возвращается как результат выполнения функции в IIS. IIS, в свою очередь, «передает» ответ на запрос клиенту. Важно понимать, что языки скриптов — это отдельные языки, требующие их дополнительного изучения. Средства Интернет-сервера В контексте ASP-документов помимо объектов, опреде- ляемых выбранным языком скриптов, существует шесть дополнительных объектов, которые добавляют дополни- тельные возможности при работе с Интернет приложени- ем. Это следующие объекты: ♦ Application — с помощью данного объекта можно управ- лять всем приложением, создавать видимые во всем приложении объекты; ♦ Objectcontext — для введения или снятия транзакции; ♦ Request — для «приема» данных. Поддерживает следую- щие методы: Form() — прием данных, отосланных формой методом Post; QueryString() — прием данных, отосланных формой методом Get; Cookies(); ♦ Response — для «вывода» данных. Поддерживает сле- дующие методы и свойства: Write() — вывод данных (часто HTML-текст) в фор- мируемый документ; CacheControl — контроль кеширования; Charset — кодовая страница; ♦ Server — объект, позволяющий управлять определенными параметрами сервера. Поддерживает метод CreateObject(); ♦ Session — объект, позволяющий работать с текущей сес- сией. Поддерживает метод SessionlD — получение иден- тификатора сессии. В данном перечне содержатся далеко не все свойства и методы объектов, поддерживаемых IIS. В задачу данно- го раздела их подробное рассмотрение и не входит. В рам- ках следующего материала будет использоваться только метод Write() объекта Response. Например, использование конструкции Response.Write("<b>nepBoe</b>") приведет к появлению в результирующем документе слова Первое, выделенного полужирным шрифтом. Пример использования В каталоге, являющимся корневым для нашего веб-серве- ра, разместим два ASP-документа. Документ default.asp. Он будет стартовым файлом web- ресурса (листинг 14.110). Листинг 14.110. Документ default.asp <t@ Language=javascript t> <html> <head> <title>Ham web site«/title> <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> <meta http-equiv=”Content-Type" content=“text/htnir'> «script id="clientEventHandlersJS" language="javascript"> function bbutclickO { alert("Dont strike this button!"); } </script> </head> «body BGC0L0R="#99ffff" TEXT="#990033"> «form ID="Forml"> «hl align="center’’> Демонстрация WEB-сервера на базе внешнего
соединения 1С:Предприятия. </hl> <р align="center”> <а href="reflist.asp"> <font size="5">CnpaBO4HHKH</font> </a> </p> </form> </body> </html> Файл reflist.asp, при обращении к нему (вызывается из файла по умолчанию) возвращает имена всех справочни- ков, определенных в конфигурации (листинг 14.111). Листинг 14.111. Файл reflist.asp <№ Language=javascript Я> <Х entConn = new ActiveXObjectC'vB.comconnector”): conn = entConn.connect("file=c:/demo/democonfig"); conn. Кат алогХБШреобразований = "c:/demo/xsl"; Response.Wri te(conn.getRefLi st()); %> Корневой каталог web сервера определяется в свойствах веб-сервера по умолчанию в оснастке Internet Information Services (свойство Local Path) (рис. 14.21). Рис. 14.21. Установка корневого каталога веб-сервера В данном документе (см. листинг 14.110) производится создание СОМ-объекта 1 С:Предприятия, подключение к информационной базе. Производится установка перемен- ной (экспортной) модуля внешнего соединения (опреде- ляется путь до файлов XSL преобразований). Вызывает- ся функция getRefList(), которая возвращает HTML текст, включаемый с помощью метода Write() в ответ сервера клиенту. В информационной базе, которая выступает в качестве COM-сервера для веб-приложения, в модуле внешне- го соединения необходимо определить следующий текст (листинг 14.112). Листинг 14.112. Фрагмент модуля внешнего соединения Перен КаталогХЗбПреобразований Экспорт; И Получить список справочников в формате XML и преобразовать // его к HTML при помощи XSL-трансформации. Функция getRefListO Экспорт РезультатХМЕ = Писатель = Новый XMLWriter; Писатель.УстановитьСтроку(); Писатель.Записать0бъявлениеХМЕ(); Писатель.Записат ьНачалоЭлемента("references“); Счетчик = 1; Для Каждого Спр Из Метаданные.Справочники Цикл Писатель. ЗаписатьНачалоЭлемента( "reference''); Писатель.ЗаписатьНачалоЭлементаС"number”): Писатель.ЗаписатьТекстС" + Нун); Писатель.ЭаписатьКонецЭлемента(); Писатель.ЗаписатьНачалоЭлементаС"name"); Писатель. ЗаписатьТекстС" + Спр); Писатель.ЗаписатьКонецЭлементаС); Писатель.ЗаписатьКонецЭлементаС); Счетчик = Счетчик + 1; КонецЦикла; Писатель.ЗаписатьКонецЭлементаС); РезультатХМЕ = Писатель.ЗакрытьО; Трансформатор = Новый ПреобразованиеХЗС; Трансформатор. ЗагрузитьИзФайлаСКаталогХЭШреобразований + "/refl 1st.xsi"); РезультатНТМЕ = Трансформатор.ПреобразоватьИзСтроки(РезультатХМЦ); Возврат РезультатНТМЕ; КонецФункции Файл стиля, используемого для проведения преобразова- ния (файл reflist.xsl) показан в листинге 14.113. Листинг 14.113. Файл reflist.xsl <?xml version=“1.0"?> <xsl:stylesheet xmlns:xsl= "http://www.w3.org/1999/XSL/Transform" vers1on="1.0"> <xsl:tempi ate match="references"> <html> <head> <meta name="GENERATOR" content="lC:Enterprise" charset="windows-1251" /> <meta http-equiv="Content-Type" content="text/html" /> <ti tlе>Список справочников.</title> </head> <body BGCOLOR="#FFFFFF" TEXT="#OOOOOO"> <form ID="Forml"> <Н1 а11дп="сепЕег">Справочники информационной базы.</Н1> <table width="100t" border=”l" cel1paddi ng="0" cel 1 spaci ng=" 1" > <tr align="center”> <td> <font 51ге="5">Наименование справочника</Гоп> </td> </tr> <xsl:apply-tempiates seiect=”reference"/> </table> </form> </body> </html> </xsl;tempiate> <xsl .-template match="reference"> <tr align=”center"> <td> <a href="refone.asp?key={number}"> <xslrvalue-of seiect="name”/> </a> </td> </tr> </xsl:tempiate> </xsl:stylesheet> Преобразование, выраженное через XS LT, описывает пра- вила преобразования исходного дерева XML-документа в конечное дерево другого документа. Преобразование строится путем сопоставления образцов и шаблонов. Об- разец сравнивается с элементами исходного дерева, а шаб- лон используется для создания частей конечного дерева. Структура конечного дерева может полностью отличать- ся от структуры исходного дерева. В ходе построения ко- нечного дерева элементы исходного дерева могут подвер- гаться фильтрации и переупорядочению, также может быть добавлена новая структура.
Разберемся в представленном механизме поэтапно. В результате работы объекта Писатель получаем XML-до- кумент следующего вида (листинг 14.114). Листинг 14.114. Пример XML-документа <?xml version=”1.0"?» «references» «reference» «number»l«/number» «пате»Номенклатура«/пате> «/reference» «reference» «number»2«/number> «пате»Склады«/пате» «/reference» «reference» «number»3«/number> «пате»Контрагенты«/пате» «/reference» «reference» «number»4«/number> <пате»Типы цен«/пате» «/reference» «/references» Изначально из файла стиля выбирается шаблон для кор- невого элемента XML-документа (можно сказать он раз- мещается пока в пустом конечном документе) (лис- тинг 14.115). Листинг 14.115. Шаблон для корневого элемента XML- документа <html» «head» «meta name=”GENERATOR" content="lC:Enterprise" charset="windows-1251" /> «meta http-equiv="Content-Type" content="text/html" /> «titlе»Список справочников.«/11tle» «/head» «body BGCOLOR=”#FFFFFF” TEXT="#000000"» «form ID=''Forml"> <H1 align=''center"» Справочники информационной базы. «/Hl> «table width="100V border=”l" cel1paddi ng="0” cel1 spaci ng=“1"> «tr align="center"> «td»«font size="5"» Наименование cnpaBO4HHKa«/font> «/td> «/tr> «xsi :apply-templates seiect="reference’’/» «/table» «/form» «/body» </html> Далее полученный документ анализируется и в отведен- ное место (вместо <xsl:apply-templates select=«reference»/>) записывается шаблон для узла reference. Результат пред- ставлен в листинге 14.116. Листинг 14.116. Результат после записи шаблона <html> «head» «meta name="GENERATOR" content=’’lC:Enterprise" charset=”windows-1251" /> «meta http-equiv="Content-Type" content="text/html ’’ /> «tltlе»Список справочников.«/title» «/head» «body BGCOLOR="#FFFFFF" TEXT="#000000”» «form ID="Forml’’» «HI align="center”> Справочники информационной базы. «/HI» «table width=“100V border=”l" cel 1 paddi ng= ”0 ’’ cel 1 spaci ng=" 1 "> «tr align="center"» «td> «font size=”5"> Наименование справочника «/font» «/td> «/tr» «tr align=’’center"» «td> «a href="refone.asp?key={number)”> «xsi:value-of seiect="name"/» </a» </td> «/tr» <tr align="center”> <td> «a href="refone.asp?key={number)”> «xsl:value-of select="name”/> </a» «/td» «/tr» <tr align="center“> «td> «a href=" ref one. asp?key={number) ’’> «xsi:value-of select="name"/> </a» </td» «/tr» <tr align="center"> «td» «a href=”refone.asp?key={number)"> <xsl:value-of select-'name"/» </a> «/td» «/tr» «/table» «/form» «/body» «/htrnl» После полного применения преобразования получаем ко- нечный HTML-документ (листинг 14.117). Листинг 14.117. Конечный HTML-документ «htrnl> «head» «meta name=”GENERATOR" content=”lC:Enterprise” charset="windows-1251” /> «meta http-equiv="Content-Type" content="text/html" /> «ННе»Список справочников.«/title» «/head» «body BGCOLOR="#FFFFFF” TEXT="#000000”» «form ID="Forml"> <H1 align="center”» Справочники информационной базы. «/HI» «table width="100V border="l" cel 1 paddi ng=’’O ” cel 1 spaci ng=" 1 "> <tr align="center"» «td> «font size="5"» Наименование справочника «/font» «/td» «/tr> «tr align="center"> «td> «a href=”refone.asp?key=l”»Номенклатура«/а» «/td> «/tr> «tr align=’’center"> «td>
<a href="refone.а5р?кеу=2">Склады</а> </td> </tr> <tr al 1gn="center"> <td> <a href="refone.asp?key=3">KoHTpareHTu</a> </td> </tr> <tr align="center”> <td> <a href=”refone.asp?key=4”>TMnbi цен</а> </td> </tr> </table> </form> </body> </html> При желании, просматривать формы списков каждого справочника в рассматриваемый пример необходимо до- бавить файл refone.asp (листинг 14.118), разместить в нужном каталоге дополнительный файл стиля refone.xsl (листинг 14.120) и добавить в модуль внешнего соедине- ния функцию getRefOne() (листинг 14.119). Листинг 14.118. Файл refone.asp <^@ Language=javascript %> <% entConn = new ActiveXObject("vB.comconnector”); conn = entConn.connectC"file=c:/demo/democonfig"); сопп.КаталогХБЬПреобразований = "c:/demo/xsl"; grVal = Request.QueryString("group"); if (grVal.Count = 0) { var empty; Response.Wr i te(conn.getRefOneCRequest. QueryStri ng("key")(1). empty)); } else Response.Wri te C conn.getRefOne(Request. QueryStri ng(”key")(1), grValCl))): X> Листинг 14.119. функция getRefOne // Получить список элементов справочника по текстовому // представлению ссылки на родительский элемент Функция getRef0ne(HoMepCnpaBO4HMKa, СсылкаНаЗапись) Экспорт СтрокаСоСсылкой = + СсылкаНаЗапись + МдСпр = Метаданные.Справочники[Число(НомерСправочника) - 1]; Спр = Справочники[МдСпр.Имя]; Если СсылкаНаЗапись = Неопределено ИЛИ СсылкаНаЗапись = Тогда Выборка = Спр. выбратьССпр. ПустаяСсылкаО): Иначе Выборка = Спр.выбрать(ЗначениеИзСтрокиВнутр(СтрокаСоСсылкой)); КонецЕсли; РезультатХМЕ = Писатель = Новый XMLWriter; Писатель.УстановитьСтрокуС); Писатель .ЗаписатьОбъявлениеХМК); Писатель.Записат ьНачапоЭлемента("reference"); Писатель.ЗаписатьНачалоЭлементаС"name"): Писатель. ЗаписатьТекст + МдСпр); Писатель. ЗаписатьКонецЭлементаО; Писатель.Записат ьНачапоЭлемента("code"); Писатель.ЗаписатьТекстС"' + НомерСправочника); Писатель.ЗаписатьКонецЭлементаС): Пока Выборка.СледующийО Цикл Если Выборка.ЭтоГруппа Тогда Писатель.ЗаписатьНачалоЭлементаС"group"); Иначе Писатель.ЗаписатьНачалоЭлементаС"item"): КонецЕсли; Писатель.ЗаписатьНачалоЭлементаС"id”); СтрокаСоСсылкой = ЗначениеВСтрокуВнутрСВыборка.ссылка); Писатель.ЗаписатьТекст(СредССтрокаСоСсылкой, 6. СтрДлина(СтрокаСоСсылкой) - 6)); Писатель.ЗаписатьКонецЭлементаС); Писатель.ЗаписатьНачалоЭлементаС"code"); Писатель.ЗаписатьгекстС”" + Выборка.Код); Писатель.ЗаписатьКонецЭлементаС): Писатель.ЗаписатьНачалоЭлементаС"description"); Писатель.ЗаписатьТекстСВыборка.Наименование); Писатель. ЗаписатьКонецЭлементаО: Писатель.ЗаписатьКонецЭлементаС); КонецЦикла; Писатель.ЗаписатьКонецЭлементаС); РезультатХМЕ = Писатель.ЗакрытьС): Трансформатор = Новый ПреобразованиеХЗЕ: Трансформатор.ЗагрузитьИзФайла(КаталогХ5ЕПреобразований + "/refone.xsl"); РезультатНТМЕ = Трансформатор.ПреобразоватьИзСтроки(РезультатХМЕ): Возврат РезультатНТМЕ; КонецФункции Листинг 14.120. Файл стиля refone.xsl <?xml version="1.0"?> <xsl:stylesheet xml ns;xsi= "http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl template match=”reference”> <html> <head> <meta name="GENERATOR” content=”lC:Enterprise" charset="windows-1251" /> <meta http-equiv=”Content-Type" content="text/html" /> <titlе>Содержимое справочника.</title> </head> <body BGCOLOR="#FFFFFF" TEXT="#000000"> <form ID="Forml"> <xsl:apply-templates select="name"/> <table width="100V border="l” cellpadding="0" cell spacing="l"> <tr align=”center"> <td><font size=”5">Kofl</font></td> <td> <font size="5">HanMeHOBaHHe</font> </td> </tr> <xsl:apply-tempiates seiect="group"/> <xsl.-apply-tempiates select="item"/> </table> </form> </body> </html> </xsl:tempiate> <xsl:template match="name"> <H1 align="center”> Справочник: <xsl:value-of select=".'7> </Hl> </xsl:tempiate> <xsl:tempi ate match="group"> <tr align="center"> <td> <a href="refone.asp?key={../code}&amp;group={id}"> <font size="4"><xsl;value-of seiect="code"/> </font> </a> </td>
<td> <a href="refone.asp?key={. ./code}&amp;group={id}''> <font size="4"> <xsl:value-of select="description"/> </font> </a> </td> </tr> </xsl:tempiate» <xsl:tempi ate match="item"> <tr align="center"» <td> <a href="refitem.asp?key={../code}&amp:item={id}"> <xsl:value-of seiect="code"/» </a» </td> <td> <a href="refitem.asp?key={../code}&amp;1tem={id}"> <xsl:value-of select="description'7> </a» </td> </tr> </xsl:tempi ate» </xsl:stylesheet» Механизм работы добавленных файлов такой же, как и ранее рассматриваемый. ActiveX При конструировании форм в ряде случаев может воз- никнуть необходимость в предоставлении в диалоге или в табличном документе некой «нестандартной возможно- сти». Можно попытаться реализовать ее с использовани- ем стандартных элементов управления, поддерживаемых 1 С:Предприятием, а можно воспользоваться возможно- стью внедрения в диалог (табличный документ) дополни- тельных элементов управления, поддерживающих техно- логию ActiveX. Можно сказать, что такой элемент управления является OLE-объектом, который можно размещать в диалоге формы, табличном документе. Работа с дополнительными ActiveX-элементами управле- ния по возможности максимально приближена к работе с «родными» элементами управления ЮПредприятия. Для всех элементов управления одинаково организованы визуальное редактирование свойств элементов управле- ния, связь с обработчиками событий, выбор шрифта и цвета. Однако следует заметить, что, помимо общих черт, ActiveX могут обладать серьезными отличиями — таки- ми, как визуальные отличия от общего вида интерфейса ЮПредприятия или отсутствие локализации на опреде- ленный язык. Доступ к элементам управления ActiveX осуществляется так же, как и в случае Automation — как к обычным объ- ектам ЮПредприятия. Для размещения элемента управления ActiveX в диало- ге формы можно воспользоваться пунктом главного меню конфигуратора 1 С:Предприятия Форма | Вста- вить ActiveX. Откроется список элементов управления (рис. 14.22). Следует заметить, что списки ActiveX-объектов, встраи- ваемых в формы и табличные документы, различаются — это обусловлено деталями реализации этих объектов, од- нако работа с этими объектами ведется одинаково неза- висимо от способа встраивания. К объектам, встраиваемым только в табличные докумен- ты, относятся, в частности, некоторые объекты Microsoft Office — такие, как Word или Excel. Рис. 14.22. Список элементов управления ActiveX Технология ActiveX применяется в случае, когда для ре- шения задачи требуется именно визуальное взаимодейст- вие с объектами (управление или отображение), реали- зованными как ActiveX-объекты. При этом желательно максимально сохранить общий вид пользовательского интерфейса ЮПредприятия, поэтому если задача может быть решена с использованием элементов управления из состава ЮПредприятия, то такой вариант выглядит предпочтительнее. В качестве примера можно рассмотреть возможность раз- мещения в диалоге элемента управления ActiveX Microsoft Media Player (для элемента управления — WMP). С помощью следующего кода можно осуществлять вос- произведение аудио- и видеофайлов (листинг 14.121). Листинг 14.121. Пример использования элемента управления ActiveX Режим = РежимДиалогаВыбораФайла.Открытие; ДиалогВыбораФайла = Новый ДиалогВыбораФайла(Режим); ДиалогВыбораФайла.Фильтр = "Все файлы (все)|*.*“; ДиалогВыбораФайла.Заголовок - "Выберите медиа файл"; Если ДиалогВыбораФайла.Выбрать()Тогда ПутьКМедиаФайлу = ДиалогВыбораФайла.ПолноеИмяФайла; И В зависимости от варианта объекта запись полного пути // к файлу производится либо в свойство FileName, // либо в свойство URL. Попытка ЭлементыФормы.WMP.FileName = ПутьКМедиаФайлу; Исключение ЭлементыФормы.WMP.URL = ПутьКМедиаФайлу; КонецПопытки; КонецЕсли;
ActiveDocument Технология ActiveDocument предназначена для редактиро- вания документов внешними по отношению к 1 С: Пред- приятию редакторами. Эта технология позволяет в режиме конфигурирования (в пользовательском режиме данная особенность недос- тупна) редактировать документы визуально (например, Word или Excel) непосредственно в окне 1С:Предпри- ятия, при этом элементы пользовательского интерфейса (меню, панели команд и т. д.) заменяются на предоставляе- мые редактором. Документы могут быть предварительно отредактированы и сохранены в макетах конфигурации, а затем макеты могут использоваться пользователями как основы для создания окончательных версий документов. Для добавления в конфигурацию возможности работы с Active Document необходимо для требуемого объекта (например, для справочника Номенклатура) создать новый макет и при этом выбрать соответствующий тип макета (рис. 14.23). Рис. 14.23. Конструктор макета Эта технология применяется в случае, когда в конфигу- рации необходимо хранить данные, редактируемые дру- гим приложением? — такие, например, как шаблоны для факсов или деловых писем, созданные в Microsoft Word, или шаблоны прайс-листов в Microsoft Excel. Такая необ- ходимость возникает, как правило, при регламентирова- нии формата документов (как во внутреннем документо- обороте, так и при обмене документами со сторонними организациями и клиентами), однако при отсутствии ограничений на формат документа рекомендуется ис- пользовать существующие в 1С:Предприятии возможно- сти по оформлению электронных и печатных документов. Ниже (листинг 14.122) приведен пример кода, получаю- щего из макета (имеющего тип «Active document») заго- товку документа программы Microsoft Word. Имя макета определено как Договор. Листинг 14.122. Пример использования макета Active Document Договор = ПолучитьМакетСДоговор"): // Получить объект из макета. MSWord = Договор.ПолучитьО: НаименованиеКонтрагента = "ООО Торгуем всем": Попытка Документ = MSWord.Application.Documents(l); Документ.Acti vate(); И Получить объект, который будем использовать // для поиска и замены. Замена = Документ.Content.Find; // Заменить заранее определенные ключевые конструкции И на требуемый текст. Замена. ЕхеаЛе("<НазваниеКомпании>", Ложь, Истина, Ложь, Истина, Ложь, НаименованиеКонтрагента); // Далее аналогично для остальных ключевых конструкций. И Делаем видимым приложение и активизируем его. MSWord.Application.Visible = Истина: MSWord. Activate О; Исключение // Если произойдет ошибка? выводятся данные об ошибке И и объект закрывается. Сообщить (ОписаниеОшибки()): MSWord.Application.Quito: КонецПопытки; После получения производится поиск специальным об- разом определенных ключевых фраз и замена их на дан- ные из информационной базы.
Глава 15. Создание распределенных информационных систем При решении различных задач может возникнуть необхо- димость в создании распределенной информационной системы (в силу территориальной распределенности ор- ганизации, использовании разнородного программного обеспечения для решения отдельных подзадач и т. п.). Технологическая платформа ЮПредприятия позволяет решать такие задачи, причем распределенные информа- ционные системы могут строиться как на основе инфор- мационных баз ЮПредприятия, так и с задействованием совершенно других систем. Одной из самых важных задач, которую необходимо ре- шить при организации распределенных информационных систем, — это задача обмена между ее составными частями. Обмен данными в системе 1 С: Предприятие реализуется благодаря использованию ряда средств технологической платформы, которые разработчик может применять как по отдельности, так и в различных комбинациях, в зависимо- сти от конкретной решаемой задачи. Такой подход позволя- ет обеспечить гибкость механизмов обмена и их настраи- ваемость на решение как можно большего круга задач. В состав средств платформы, используемых для построе- ния схем обмена данными, входят: ♦ объекты конфигурации План обмена; ♦ базовые средства работы с XML; ♦ средства XML-сериализации. При помощи этих средств могут быть реализованы два механизма обмена данными: ♦ универсальный механизм обмена данными; ♦ механизм распределенных информационных баз. Универсальный механизм обмена данными позволяет соз- давать произвольные распределенные системы и прак- тически не накладывает никаких ограничений на струк- туру создаваемой системы. Можно связывать в единое целое как базы 1 С: Предприятие с отличными друг от друга конфигурациями, так и осуществлять обмен с принципиально отличными информационными систе- мами (базами данных). Механизм распределенных информационных баз, напро- тив, предназначен для обмена данными только с иден- тичными конфигурациями ЮПредприятия 8.0 и жест- ко регламентирует структуру создаваемой системы. Он является аналогом компонента «Управление распреде- ленными информационными базами», существующего в технологической платформе ЮПредприятия 7.7, од- нако существенно превосходит этот механизм по гибко- сти настройки и разнообразию поддерживаемых схем обмена. Основные отличия механизма универсального обмена данными от механизма распределенных информацион- ных баз можно проиллюстрировать табл. 15.1. Перед тем как перейти к рассмотрению возможностей ор- ганизации, как универсального обмена, так и создания распределенных информационных баз ЮПредприятия, рассмотрим функциональность такого объекта платфор- мы как План обмена. Таблица 15.1. Сравнение механизмов обмена данными Универсальный механизм обмена данными Механизм распределенных информационных баз В узлах плана обмена находятся Произвольные базы данных, в том числе информационные базы ЮПредприятие Только информационные базы ЮПредприятия 8.0 Конфигурации информационных баз Могут быть разные (применительно к информационным базам ЮПредприятия) Только идентичные В сообщениях обмена передаются Только изменения данных Изменения данных, изменения конфигурации Направление передачи Произвольное, между двумя связанными узлами Изменения данных — произвольное, изменения конфигурации — от главного к подчиненному Формат файлов обмена Произвольный, чаще всего XML XML Создание распределенной базы и выполнение обмена Требуется написание кода (определение порядка разрешения коллизий, стратегии распростране- ния данных, создания начальных выгрузок, ре- шение задачи синхронизации данных) Может быть выполнено исключи- тельно интерактивными средствами, без кодирования (действуют согла- шения по умолчанию) Структура распределенной системы Произвольная. Может отсутствовать понятие главный-подчиненный (отсутствовать иерар- хия) Древовидная. Любой узел (кроме корневого) имеет один главный и произвольное количество подчи- ненных узлов
Планы обмена При организации постоянного обмена может возникнуть ряд задач: ♦ с кем будет производиться обмен (определение состава участников обмена); ♦ какими данными будет производиться обмен (с одной стороны, это определение перечня типов объектов, с дру- гой стороны, определения «экземпляров»); ♦ определение регламента обмена (например, нумерация сообщений, адресация, процесс разрешения коллизий и т. п.). Все эти задачи в той или иной мере могут решаться с ис- пользованием функциональности планов обмена. Рас- смотрим данный объект более подробно. Как объект конфигурации План обмена характеризуется со- ставом реквизитов, табличных частей (составом реквизи- тов табличных частей), определенными для него форма- ми, макетами. У узла плана обмена существует свойство Код, Наименование и т. п. В конфигурации может быть оп- ределено любое количество планов обмена. Элементами данных плана обмена являются узлы плана обмена, подобно тому, как элементами данных справоч- ника являются элементы справочника. Каждый из узлов плана обмена обозначает участника обмена данными по данному плану обмена. Один из узлов (он является пред- определенным) соответствует данной информационной базе, а остальные — другим участникам, с которыми дан- ная информационная база может обмениваться данными (рис. 15.1). Рис. 15.2. Пример узла плана обмена Рис. 15.1. Узлы плана обмена В связи с самим понятием узла реквизиты и табличные части (реквизиты табличных частей) в планах обмена мо- гут использоваться для указания «специфических» дан- ных по участнику обмена. С их помощью определяется порядок взаимодействия с данным участником, привязка его к другим объектам базы. Например, может указывать- ся, что данный узел, с точки зрения базы данных, являет- ся «таким-то» складом (элементом справочника Склады), файл выгрузки данному получателю необходимо отправ- лять по «такому-то» FTP-адресу и т. п. (рис. 15.2). Данные переносятся между узлами с помощью сообще- ний. Средства работы с сообщениями образуют инфра- структуру сообщений. Каждое сообщение относится к оп- ределенному плану обмена, имеет определенный узел- отправитель и определенный узел-получатель. Сообще- ние не может быть отправлено неизвестному узлу и не может быть принято от неизвестного узла. Каждое сооб- щение имеет свой собственный целочисленный номер. С точки зрения инфраструктуры сообщений у узла суще- ствует два свойства: ♦ номер отправленного сообщения; ♦ номер принятого сообщения. Для предопределенного узла эти свойства смысла не име- ют (база данных сама с собой данными не обменивается). Служба регистрации изменений предназначена для реги- страции изменений данных, производимых 1 С: Пред при- ятием, чтобы при обмене данными иметь возможность передавать не все данные, а только новые, измененные и удаленные. Настройка состава объектов, для которых включается ре- гистрация изменений, производится в режиме Конфигу- ратор, на закладке Прочие объекта конфигурации «План- Обмена» (необходимо нажать кнопку Состав) (рис. 15.3). План обмена МдаленныеСклады _ 2"l X Основные Даннь« Формы Макеты I Подсчете Ввод на о Права Интерфвй ► Прочее | Модуль объекта ] Состав План обмена УдаленныеСклады. Состав Действия * j ! Ijk К онст.энты| Справочники Номенклатура Hfc Склады • Hfc Контрагенты ТипыЦен Ш Документы Е04й Регистры сведений Регистры накопления Рис. 15.3. Состав плана обмена - q В Разрешил В Разрешил В Разрешил В Разрешил
Можно сказать, что состав объектов, для которых вклю- чается регистрация изменений, является «входными» дан- ными для службы регистрации изменений. Задача этой службы состоит в том, что опираясь на данный перечень объектов, отслеживать изменения объектов, их удаление и производить соответствующие записи в таблицах реги- страции изменений объектов. При этом отслеживаются ситуации «повторного» изменения (но об этом более под- робно в разделе, посвященном именно службе регистра- ции изменений). Обобщив ранее изложенный материал, можно сказать, что планы обмена: ♦ определяют состав участников обмена (любой узел, кроме предопределенного, соответствует какому-либо участнику обмена); ♦ позволяют производить регистрацию изменений объек- тов (служба регистрации изменений как объектов, так и самой конфигурации); ♦ реализуют инфраструктуру сообщений. Служба регистрации изменений Довольно сложно разделить службу регистрации измене- ний и инфраструктуру сообщений, их функциональность довольно тесно переплетается, но все же постараемся рас- смотреть особенности их работы по отдельности. Начнем со службы регистрации изменений. Суть регистрации изменений состоит в том, чтобы иметь перечень измененных элементов данных, которые долж- ны быть переданы в очередном сообщении тому или ино- му узлу, с которым производится обмен данными. При каждом изменении данных должно быть зарегистрирова- но, что имеются изменения, которые предстоит передать во все узлы, с которыми поддерживается обмен этими данными. При получении подтверждения приема сооб- щения, в котором были отправлены изменения, записи регистрации изменений должны быть удалены. Регистрация изменений может выполняться для следую- щих элементов данных: ♦ КонстантаМенеджерЗначения.<имя>; Объекты базы данных: СправочникОбъект.<имя>; ДокументОбъект.<имя>; ПланСчетовОбъект.<имя>; План ВидовХарактеристикОбъект.<имя>; ПланВидовРасчетаОбъект.<имя >; БизнесПроцессОбъект.<имя>; ЗадачаОбъект.<имя>; ♦ Наборы записей: РегистрСведенийНаборЗаписей.<имя >; РегистрБухгалтерииНаборЗаписей.<имя>; РегистрНакопленияНаборЗаписей.<имя>; • ПоследовательностьНаборЗаписей.<имя>; РегистрРасчетаНаборЗаписей.<имя>; ПерерасчетНаборЗаписей.<имя>. Для каждого из приведенных элементов данных ведется своя таблица регистрации изменений. Таблицы имеют разную структуру, в зависимости от того, для каких эле- ментов данных регистрируются изменения, но все-таки структуры таблиц подобны. В структуре можно выделить три составляющих: ♦ ключ элемента данных, для которого регистрируются изменения; ♦ ссылка на узел, в который изменение должно быть пе- редано; ♦ номер сообщения, в котором изменение передано в пер- вый раз. Следует отметить, что в конфигурации может быть опре- делено несколько планов обмена. Для каждого из них мо- жет включаться регистрация изменений какого-либо объ- екта. Так вот, вне зависимости от количества планов обмена, в рамках которого регистрируются изменения ка- кого-либо объекта, таблица регистрации изменений у объекта одна (можно сказать, что поле, содержащее ссыл- ку на узел плана обмена, может иметь составной тип). Структуры таблиц регистрации изменений для разных данных отличаются ключом, так как ключи у разных дан- ных разные: ♦ для константы ключом является идентификатор кон- станты; ♦ для объектов базы данных в качестве ключа использу- ется ссылка на объект; ♦ для наборов записей, для которых определен регистра- тор, в качестве ключа используется ссылка на объект- регистратор; ♦ для набора записей регистра сведений, в случае если ре- гистратор не определен, в качестве ключа используется совокупность измерений, входящих в основной отбор. А если регистр сведений является периодическим и включен основной отбор по периоду, то в ключ входит еще и период. Основной отбор (для регистров сведений) позволяет оп- ределять логическую единицу обмена данными. Рассмот- рим это понятие более подробно (рис. 15.4). Имя Номенклатура Синоним Номенклатура _______________ Комментарий Ведущее 0 Запрет незаполненьН Рис. 15.4. Свойство Основной отбор Понятно, что физически минимальной единицей обмена является запись регистра сведений. Но всегда ли пра- вильно обмениваться записями? Рассмотрим пример. Есть регистр сведений, в котором содержатся данные о допол- нительных свойствах номенклатурных позиций. Речь идет именно о свойствах, которые четко характеризуют товар- ную позицию, если для какого-то товара свойство имеет другое значение, то значит, что это другой товар. Напри- мер, такое свойство как количество компрессоров холо- дильника. У данного регистра сведений два измерения: ссылка на номенклатуру и ссылка на свойство.
Если обмен будет производиться по каждой записи от- дельно, то в случае, если у одного участника обмена доба- вили одно свойство, а в другом участнике обмена добави- ли другое, в результате обмена у элемента номенклатуры появилось два свойства. Но в данном случае более пра- вильно, чтобы свойства отдельно взятого товара пред- ставляют собой единое логическое целое (входили в не- кий логический квант данных). Как раз для того, чтобы объединить несколько физиче- ских записей в один логический набор данных, и исполь- зуется понятие Основной отбор. В приведенном примере, если для измерения Номенклатура (содержащего ссылку на номенклатурную позиций) поставить флаг Основной от- бор, то при изменении хотя бы одной физической записи обмен будет производиться всеми свойствами данной но- менклатуры. В качестве примера рассмотрим следующие данные (на- полнение регистра сведений) (табл. 15.2). в основной отбор и период), то логической единицей об- мена будет отдельно взятая запись регистра сведений. Таблица 15.4. Записи, попавшие в регистрацию изменений Измерение «Номенклатура» (входит в основной отбор) Измерение «Свойство» (не входит в основной отбор) Значение Атлант МХМ 1704-00 Количество компрессоров 2 Атлант МХМ 1704-00 Цвет Белый Атлант МХМ 1704-00 Отделов в морозильной камере 3 Таблица 15.2. Записи регистра сведений Измерение «Номенклатура» (входит в основной отбор) Измерение «Свойство» (не входит в основной отбор) Значение Атлант МХМ 1704-00 Количество компрессоров 2 Атлант МХМ 1704-00 Цвет Белый Ardo TL 1000 EX-1 Тип загрузки Вертикальная Ardo TL 1000 EX-1 Количество подшипников 1 Добавим в регистр запись о новом свойстве (выделена се- рым фоном) (табл. 15.3). Таблица 15.3. В регистр сведений добавлена запись Измерение «Номенклатура» (входит в основной отбор) Измерение «Свойство» (не входит в основной отбор) Значение Атлант МХМ 1704-00 Количество компрессоров 2 Атлант МХМ 1704-00 Цвет Белый Атлант МХМ 1704-00 Отделов в морозильной камере 3 Ardo TL 1000 EX-1 Тип загрузки Вертикальная Ardo TL 1000 EX-1 Количество подшипников 1 В результате будут зарегистрированы следующие изме- нения (табл. 15.4). Если в основной отбор включить все измерения (и в слу- чае если регистр сведений периодический, то включить Следует отметить тот факт, что при записи набора в ре- гистр сведений, состав этого набора определяется логи- кой работы конфигурации и не обязательно совпадает с набором, получаемым «при использовании» основного набора. А при принудительной регистрации изменений для набора записей обязательно должен быть установ- лен отбор, совпадающий с основным (иначе будет вы- звано исключение). Такой порядок работы определяется тем, что основной отбор является специфической чертой именно механизма обмена данными. Исходя из сказан- ного выше, следует, что при изменении основного отбо- ра необходимо будет менять и программный код, в кото- ром производится принудительная регистрация записей регистра сведений (во всех вхождениях в конфигура- цию). При изменении элемента данных его изменение должно быть зарегистрировано для всех узлов, в которые измене- ние должно быть передано. Таким образом, в результате изменения элемента данных в таблице регистрации изме- нений должно появиться N записей (наборов записей), где N — количество узлов, для которых регистрируются изменения (все узлы плана обмена, за исключением пред- определенного). В каждой из этих записей (наборе запи- сей) указано одно и то же значение ключа элемента дан- ных и различные значения ссылки на узел. Непосредственно после выполнения регистрации изме- нения номер сообщения имеет значение NULL. При первой отправке изменения в составе сообщения в данное поле помещается номер сообщения, в котором изменение от- правлено. Рассмотрим приведенный алгоритм на примере. Считаем, что в плане обмена включена регистрация для документа Расходная накладная. В плане обмена определено три узла: один предопределенный, другие с кодами Оптовый и Роз- ничный. После включения регистрации было изменено два документа. В соответствии с этим таблица регистра- ции изменения примет следующий вид (табл. 15.5). После этого было произведено формирование и отправка сообщения с номером 1 для узла Оптовый. Таблица приня- ла следующий вид (табл. 15.6). Далее было зарегистрировано изменение еще одного до- кумента (табл. 15.7).
Таблица 15.5. Состав таблицы регистрации изменений ДокументСсылка. РасходнаяНакладная Узел Номер сообщения Расходная накладная №1 от... Оптовый Null Расходная накладная №1 от... Розничный Null Расходная накладная №2 от... Оптовый Null Расходная накладная №2 от... Розничный Null Таблица 15.6. Состав таблицы регистрации изменений ДокументСсылка. РасходнаяНакладная Узел Номер сообщения Расходная накладная №1 от... Оптовый 1 Расходная накладная №1 от... Розничный Null Расходная накладная №2 от... Оптовый 1 Расходная накладная №2 от... Розничный Null Таблица 15.7. Состав таблицы регистрации изменений ДокументСсылка. РасходнаяНакладная Узел Номер сообщения Расходная накладная №1 от... Оптовый 1 Расходная накладная №1 от... Розничный Null Расходная накладная №2 от... Оптовый 1 Расходная накладная №2 от... Розничный Null Расходная накладная №3 от... Оптовый Null Расходная накладная №3 от... Розничный Null После этого были сформированы и отправлены сообще- ния для узлов Оптовый и Розничный. Фактически было проведено две выгрузки (сформировано два сообщения). Для узла Розничный сообщение имело номер 1, для узла Оптовый — номер 2 (табл. 15.8). Таблица 15.8. Состав таблицы регистрации изменений ДокументСсылка. РасходнаяНакладная Узел Номер сообщения Расходная накладная №1 от... Оптовый 1 Расходная накладная №1 от... Розничный 1 Расходная накладная №2 от... Оптовый 1 Расходная накладная №2 от... Розничный 1 Расходная накладная №3 от... Оптовый 2 Расходная накладная №3 от... Розничный 1 После выгрузки для узла Оптовый запись в таблице для документа Расходная накладная №3 отмечается номером сообщения 2 (первый раз «изменение» ушло именно в со- общении с таким номером), другие записи (для которых в поле НомерСообщения содержалось значение 1) остались без изменений (именно таким образом работает служба регистрации изменений). Для узла Розничный все изменения были отнесены сооб- щением с номером 1. Предположим, что после выполнения вышеуказанных действий произошло повторное изменение документа Расходная накладная №1. В этом случае таблица регистра- ции изменений будет иметь следующий вид (табл. 15.9). Таблица 15.9. Состав таблицы регистрации изменений ДокументСсылка. РасходнаяНакладная Узел Номер сообщения Расходная накладная №1 от... Оптовый Null Расходная накладная №1 от... Розничный Null Расходная накладная №2 от... Оптовый 1 Расходная накладная №2 от... Розничный 1 Расходная накладная №3 от... Оптовый 2 Расходная накладная №3 от... Розничный 1 Продолжая разговор о службе регистрации изменений, следует отметить, что состав плана обмена распространя- ется на все узлы данного плана обмена. Поэтому если, на- пример, с разными узлами надо обмениваться разным со- ставом информации, нужно создавать несколько планов обмена, в которых объединять узлы, обменивающиеся одинаковым составом информации. Например, если с одним узлом необходимо обмениваться изменениями в справочнике Номенклатура, а с другим — изменениями в документах Расходная Накладная, то не сто- ит создавать один план обмена, лучше создать план обме- на ПоНоменклатуре (с соответствующей настройкой соста- ва данных, по которым ведется регистрация изменений) и план обмена Расходные (с другим составом). Управление регистрацией изменений При рассмотрении вышеприведенного примера акцент делался на заполнение таблицы регистрации изменений. Каким образом производилась регистрация, не учитыва- лось. Можно сказать, что рассматривалась функциональ- ность службы регистрации изменений с учетом того, что для всех объектов включена авторегистрация изменений. Пришло время рассмотреть и этот аспект работы про- граммного комплекса. При определении состава объектов, для которых произ- водится регистрация изменений (кнопка Состав на за- кладке Прочее объекта конфигурации План обмена), для каждого объекта можно определить свойство Авторегист- рация (рис. 15.5). Авторегистрацию можно разрешить или запретить. Если авторегистрация разрешена, то при изменении данных регистрация будет выполнена автоматически. Если за- прещена, то регистрацию изменения необходимо выпол- нять «вручную» (определив код на встроенном языке). Следует отметить, что можно «корректировать» резуль- тат регистрации и в том случае, если авторегистрация
объекта включена. Оба действия будут подробнее рас- смотрены несколько позже. План обмена УдаленныеСклады Состав Действия ’ Е 1ИУ1Константы №9 Справочники Sfc Номенклатура : Склады Qfc Контрагенты ТипыЦен Разрешить Разрешить В Разрешить Рис. 15.5. Свойство Авторегистрация У каждого объекта имеется свойство ОбменДанными, имею- щее тип ПараметрыОбненаДанными. Данное свойство может быть использовано только для чтения и предназначено как для управления различными параметрами при обме- не данными, так и при реализации других механизмов, связанных с изменением объекта. Например, такое свой- ство, как Загрузка может определять необходимость про- ведения (не проведения) каких-либо проверок в момент записи объекта (при записи в режиме загрузки можно от- казаться от проверки номеров, кодов объектов, наличия каких-либо связанных с загружаемым данных и т. п., так как эти данные могут быть загружены после). Следует обратить внимание на тот факт, что значение данного свойства не хранится в базе данных. В соответст- вие с этим, все изменения (определения различных кол- лекций, свойств), которые выполняются через данное свойство, «работают» только в течение «времени жизни» объекта. У объекта ПараметрыОбненаДанными есть свойство Получатели, имеющее тип НаборУзлов. В данном свойстве хранится пе- речень узлов, для которых будет выполняться регистра- ция изменений при записи или удалении данных. Рассмотрим особенности регистрации изменений, как в слу- чае автоматической регистрации изменений, так и в об- ратном случае. Автоматическая регистрация изменений В случае если для объекта включена автоматическая ре- гистрация изменений, этот список получателей (свойство Получатели) заполняется автоматически перед тем, как бу- дет вызван обработчик ПередЗаписью (при выполнении за- писи данных) или ПередУдалением (при выполнении уда- ления). Перед вызовом данных обработчиков событий список получателей предварительно очищается. Исходя из этого, вносить изменения в список получателей (в слу- чае если для объекта включена автоматическая регистра- ция изменений) можно только в обработчиках ПередЗапи- сью (и/или ПередУдалением). При этом следует помнить, что список получателей может содержать только ссылки на узлы, относящиеся к планам обмена, в состав которых входит соответствующий объект метаданных. В приведенном ниже примере обработчик ПередЗаписью исключает из списка получателей узел с кодом Оптовый плана обмена УдаленныеСклады (листинг 15.1). Следует вспомнить, что значение свойства ОбменДанными не хранится в информационной базе. Можно сказать, что данное свойство заполняется некими значениями по умолчанию при создании объекта (в оперативной памяти). Одним из таких свойств, которое в дальней- шем определяет порядок регистрации изменений, является свойство Автозаполнение. То есть, несмотря на тот факт, что при настройке состава регистрации изме- нений авторегистрация для объекта была включена, при создании объекта (при создании, получении из кода, при открытии формы объекта) это свойство мож- но переопределить. Пример реализации приведен в листинге 15.2. Листинг 15.1. Пример обработчика события ПередЗаписью Процедура ПередЗаписьюО Узел = ПланыОбмена.УдаленныеСклады.НайтиПоКодуС"Особый"); ОбменДанными.Получатели.Удалить(Узел); КонецПроцедуры Листинг 15.2. Пример изменения свойства Автозаполнение Узел = ПланыОбмена.УдаленныеСклады.НайтиПоКодуС"Оптовый"); Объект.ОбменДанными.Получатели.Автозаполнение = Ложь; Объект.ОбменДанными.Получатели.Добавить(Узел); Объект.Записать(); В этом случае автозаполнение отключается и состав кол- лекции получателей можно определять в любом возмож- ном месте (участке кода, отвечающего за работу с объек- том). Также следует напомнить, что в конфигурации может быть определено несколько планов обмена. В одном из них для объекта может быть включена автоматическая регистрация изменений, в другом она может быть отклю- чена. Рассмотрим пример. План обмена УдаленныеОфисы (авто- матическая регистрация изменений для документа Рас- ходная накладная включена), состав непредопределенных узлов: ♦ Центральный склад; ♦ Офис на «Рублевке». План обмена УдаленныеСклады (автоматическая регистра- ция изменений для документа Расходная накладная отклю чена), состав непредопределенных узлов: ♦ Розничный склад; ♦ Оптовый склад. Подобная настройка планов обмена может быть выполне- на исходя из соображений, что документ Расходная на- кладная должен присутствовать во всех офисах компании и при этом он должен быть выгружен только на «свой» склад. При создании документа Расходная накладная (изменении существующего) в таблице регистрации изменений дан- ного документа появится две записи, для узлов: ♦ УдаленныеОфисы — Центральный склад; ♦ УдаленныеОфисы — Офис на «Рублевке». Следует оговориться, что такое поведение системы на- блюдается только в том случае, если не предпринимает- ся никаких шагов по принудительной регистрации из- менений. Кстати, свойство Автозаполнение в коллекции Получатели в данном примере установлено в значение Ис- тина.
«Ручная» регистрация изменений В случае если автоматическая регистрация изменений не производится, то перед вызовом обработчиков ПередЗапи- сью и ПриУдалении сброс и заполнение списка получателей не осуществляется. Исходя из этого, заполнение данного списка может производиться в любом фрагменте кода, как показано в листинге 15.3. Листинг 15.3. Пример заполнения списка узлов Узел = ПланыОбмена.УдаленныеСклады.НайтиПоКоду("Оптовый"); Объект.ОбменДанныни.Получатели.Добавить(Узел): Объект.ЗаписатьО; Если автоматическая регистрация изменений для объек- та отключена и в конфигурации нигде не встречаются строки кода подобные тем, которые приведены выше (или будут рассматриваться ниже), экземпляры данного объекта никогда не попадут в таблицу регистрации изме- нений (для данного объекта она будет пустой). Вернемся к примеру с несколькими планами обмена (ус- ловия в предыдущем разделе). Несмотря на тот факт, что в свойстве Автозаполнение кол- лекции Получатели (свойства ОбменДанныни) установлено значение Истина, для не предопределенных узлов, опреде- ленных в плане обмена УдаленныеСклады, регистрация изме- нений не проводится. Но список получателей перед вызо- вом обработчиков событий ПередЗаписью и ПередУдалением очищается. Исходя из этого, для ручной регистрации из- менений можно в модуле объекта (документа) опреде- лить следующий обработчик события (листинг 15.4). Листинг 15.4. Пример обработчика события ПередЗаписью Процедура ПередЗаписью(Отказ) Если ОбменДанныни.Получатели.Автозаполнение Тогда ВключитьРегистрациюСОбненДанныни, Склад); // Проверка, что изленился склад Если Не ЗтоНовыйО Тогда Запрос = Новый Запросе |ВЫБРАТЬ Склад |ИЗ Докунент.РасходнаяНакладная |ГДЕ |Ссылка = &ТекСсылка”); Запрос.УстановитьПараметрС"ТекСсылка”, Ссылка); Выборка = Запрос. Выполнить О.ВыбратьО; Выборка.Следующий(); Если Выборка.Склад <> Склад Тогда ВключитьРегистрациюСОбменДанными. Выборка.Склад); КонецЕсли; КонецЕсли; КонецЕсли; // Выводим диагностическое сообщение // о регистрации изменений ВывестиРегистрацию(ЗтотОбъект); КонецПроцедуры В общем модуле определим следующую процедуру (лис- тинг 15.5). Обе рассмотренные процедуры одновременно решают две задачи: ♦ регистрируют изменения для узла, у которого реквизит Склад совпадает со складом, указанном в документе; ♦ производят проверку (для ранее существовавших доку- ментов), а не изменился ли склад. В случае если склад изменился, то производится регистрации изменения для узла, значение реквизита Склад соответствует ста- рому значению документа (хранимому на момент про- верки в информационной базе). Далее в момент вы- грузки изменений данная регистрация может быть «подменена» на объект УдалениеОбъекта, что приведет к удалению накладной, «не свойственной» узлу. Листинг 15.5. Процедура ВключитьРегистрацию Процедура ВключитьРегистрациюСОбменДанными, Склад) Экспорт //Получение узлов для конкретного склада Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ УдаленныеСклады.Ссылка ИЗ ПланОбмена.УдаленныеСклады КАК УдаленныеСклады ГДЕ (УдаленныеСклады.Склад = &Склад ИЛИ УдаленныеСклады.Склад = &ПустойСклад) И УдаленныеСклады.Ссылка <> &ЗтотУзел"; Запрос.УстановитьПараметр("Склад", Склад); Запрос.УстановитьПараметр("ПустойСклад", Справочники.Склады.ПустаяСсылка()); Запрос.УстановитьПараметр("ЗтотУзел", ПланыОбмена.УдаленныеСклады.ЗтотУзел()); Выборка = Запрос. ВыполнитьО .Выбрать О; // Регистрация изменений для выбранных узлов Пока Выборка. Следующий О Цикл ОбменДанныни.Получатели.Добав и т ь(Выборка.Ссылка): КонецЦикла: КонецПроцедуры Принудительная регистрация изменений В некоторых случаях может потребоваться принудитель- ная регистрация изменений для какого-либо объекта, их списка (или всех объектов). Для этой цели может исполь- зоваться метод ЗарегистрироватьИзмененияО объекта Планы- ОбменаМенеджер. Данный метод позволяет выполнять реги- страцию изменений одиночных элементов данных или целых групп для одного или нескольких узлов. Первый параметр данного метода — ссылка на узел плана обмена или массив ссылок на узлы, для которых выпол- няется регистрация изменений. Если первый параметр представляет собой одиночную ссылку на узел, то второй параметр может быть опущен. При этом выполняется ре- гистрация изменений всех элементов данных, которые на данный момент присутствуют в базе данных и изменения которых могут быть зарегистрированы для данного узла (листинг 15.6). Листинг 15.6. Регистрация изменений данных для указанного узла Узел = ПланыОбмена.УдаленныеСклады.НайтиПоКодуСНовый"); ПланыОбмена.ЗарегистрироватьИзменения(Узел); Данный вариант использования метода может быть поле- зен для организации начальной передачи данных вновь созданному узлу. Если же первый параметр представляет собой массив ссылок на узлы, то второй параметр обязательно должен быть указан (листинг 15.7).
Листинг 15.7. Регистрация изменений элемента данных для указанных узлов Узлы = Новый Массив(2): Узлы[0] = ПланыОбмена.УдаленныеСклады.НайтиПоКодуСОптовый"); Узлы[1] = ПланыОбмена.УдаленныеСклады.НайтиПоКодуС"Розничный"): Данные = Справочники.Ноненклатура.НайтиПоКоду("14"): Планы0бмена.ЗарегистрироватьИзменения(Узлы, Данные); Впрочем, второй параметр может присутствовать и в том случае, если первый параметр — одиночная ссылка на узел. В зависимости от способа задания второго парамет- ра можно зарегистрировать изменения одного элемента данных или же всех данных, относящихся к одному объ- екту метаданных. Кроме этого, можно зарегистрировать удаление объекта (указав в качестве второго параметра объект типа УдалениеОбъекта). Для регистрации изменений одного элемента в качестве второго параметра может быть указан сам элемент дан- ных, ссылка на объект базы данных или объект метадан- ных. Пример регистрации изменений всех данных, относя- щихся к объекту метаданных, приведен в листинге 15.8. Листинг 15.8. Регистрация изменений данных, относящихся к объекту метаданных Узлы = Новый Массив(2): Узлы[0] = ПланыОбиена.УдаленныеСклады.НайтиПоКодуС'Оптовый"); Узлы[1] = ПланыОбнена.УдаленныеСклады.НайтиПоКоду("Розничный"); Планы0бнена.ЗарегистрироватьИзненения(Узлы, Метаданные.Справочники.Номенклатура); До сих пор ничего не говорилось об очистке таблицы ре- гистрации изменений. По большому счету существует две основные стратегии выполнения данного действия: ♦ гарантированная доставка сообщений. В этом случае очистка таблиц регистрации изменений производится сразу же после того, как сообщение будет сформировано; ♦ ожидание квитанции. В этом случае очистка таблиц ре- гистрации изменений производится при приеме сооб- щения исходя из номера последнего полученного «от нас» сообщения (этот номер передается как квитанция в заголовке сообщения). Рассмотрим следующий пример. Считаем, что таблица регистрации изменений документа Расходная накладная имеет следующее наполнение (табл. 15.10). Таблица 15.10. Таблица регистрации изменений ДокументСсылка. РасходнаяНакладная Узел Номер сообщения Расходная накладная №1 от... Оптовый 3 Расходная накладная №1 от... Розничный Null Расходная накладная №2 от... Оптовый 1 Расходная накладная №2 от... Розничный 1 Расходная накладная №3 от... Оптовый 2 Расходная накладная №3 от... Розничный 1 Расходная накладная №4 от... Оптовый 3 Расходная накладная №4 от... Розничный Null Исходя из данных таблицы, можно сказать, что в узел Оп- товый было отправлено три сообщения, в узел Рознич- ный — одно. Используется стратегия ожидания подтверждающей кви- танции, при этом от участника обмена Оптовый приходит сообщение, в котором указано, что последнее полученное от «нас» сообщение имело номер 2. Исходя из этой ин- формации, можно удалить изменения, отправленные в сообщениях 1 и 2 (поле НомерСообщения таблицы регист- рации изменений). Таблица примет следующий вид (табл. 15.11). Таблица 15.11. Таблица регистрации изменений ДокументСсылка. РасходнаяНакладная Узел Номер сообщения Расходная накладная №1 от... Оптовый 3 Расходная накладная №1 от... Розничный Null Расходная накладная №2 от... Розничный 1 Расходная накладная №3 от... Розничный 1 Расходная накладная №4 от... Оптовый 3 Расходная накладная №4 от... Розничный Null В случае гарантированной доставки таблица регистрации изменений очищается сразу после отправки сообщения. Например, таблица регистрации изменений имела сле- дующий вид (табл. 15.12). Таблица 15.12. Таблица регистрации изменений ДокументСсылка. РасходнаяНакладная Узел Номер сообщения Расходная накладная №1 от... Оптовый 3 Расходная накладная №1 от... Розничный Null Расходная накладная №2 от... Оптовый 1 Расходная накладная №3 от... Оптовый 2 Расходная накладная №4 от... Оптовый 3 Расходная накладная №4 от... Розничный Null В узел Розничный формируется сообщение с номером 2. После того как сообщение сформировано, таблица реги- страции имеет следующий вид (табл. 15.13). Таблица 15.13. Таблица регистрации изменений ДокументСсылка. РасходнаяНакладная Узел Номер сообщения Расходная накладная №1 от... Оптовый 3 Расходная накладная №1 от... Розничный 2 Расходная накладная №2 от... Оптовый 1 Расходная накладная №3 от... Оптовый 2 Расходная накладная №4 от... Оптовый 3 Расходная накладная №4 от... Розничный 2
Далее производится вызов метода по удалению записей в таблице регистрации изменений (метод рассматривает- ся чуть позже). Таблица регистрации изменений примет такой вид (табл. 15.14). Таблица 15.14. Таблица регистрации изменений ДокументСсылка. РасходнаяНакладная Узел Номер сообщения Расходная накладная №1 от... Оптовый 3 Расходная накладная №2 от... Оптовый 1 Расходная накладная №3 от... Оптовый 2 Расходная накладная №4 от... Оптовый 3 Для удаления записей регистрации изменений у менед- жера планов обмена имеется метод УдалитьРегистрациюИз- мененийО. В качестве первого параметра метода может ис- пользоваться ссылка на узел или массив таких ссылок. В качестве второго параметра может указываться ссылка на объект, УдалениеОбъекта, объект метаданных, число (но- мер сообщения). Для удаления записей таблицы регистрации изменений с номерами сообщения не больше переданного (в приме- ре с номерами 1 и 2) может использоваться фрагмент кода (листинг 15.9). Листинг 15.9. Пример удаления записей таблицы регистрации ЧтениеХМЕ = Новый ЧтениеХМЕ; ЧтениеХМЕ.ОткрытьФайл(ИмяФайла); // Загрузка из найденного файла ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщенияО: ЧтениеСообщения .НачатьЧтение(ЧтениеХМЕ); // Считаем, что получен номер сообщения равный 2 НомерПринятого = ЧтениеСообщения.НомерПринятого; ПланыОбмена.УдалитьРегистрациюИзмененийСУзел, НомерПринятого): Пример удаления записей регистрации изменений для всех данных, которые зарегистрированы для узла, приве- ден в листинге 15.10. Листинг 15.10. Пример удаления записей таблицы регистрации Узел = ПланыОбмена.УдаленныеСклады.НайтиПоКодуС"Склад!"); ПланыОбмена.УдалитьРегистрациюИзменений(Узел); Можно удалить записи регистрации изменений конкрет- ного элемента данных для одного или нескольких узлов (листинг 15.11). Листинг 15.11. Пример удаления записей таблицы регистрации Узлы = Новый Массив(2); Узлы[0] = ПланыОбмена.УдаленныеСклады.НайтиПоКодуС "Оптовый"); Узлы[1] = ПланыОбмена.УдаленныеСклады.НайтиПоКодуС"Розничный"); Данные = Справочники.Номенклатура.НайтиПоКодуС"14”); ПланыОбмена.УдалитьРегистрациюИзмененийСУзлы, Данные): Можно также удалить записи регистрации изменений всех данных, относящихся к объекту метаданных для од- ного или нескольких узлов (листинг 15.12). Листинг 15.12. Пример удаления записей таблицы регистрации Узлы = Новый Массив(2); Узлы[0] = ПланыОбмена. УдаленныеСклады. НайтиПоКодуС "СкладГ); Узлы[1] = ПланыОбмена.УдаленныеСклады.НайтиПоКодуС"Склад2"); ПланыОбмена.УдалитьРегистрациюИзменений(Узлы, Метаданные.Справочники.Номенклатура); Инфраструктура сообщений Важнейшей составляющей инфраструктуры сообщений яв- ляются сами сообщения. Как уже отмечалось, сообщения передаются в рамках плана обмена от одного узла другому. То есть каждое сообщение точно ассоциировано с планом обмена, имеет одного отправителя и одного получателя. Рассмотрим, что такое сообщение. Сообщение оформля- ется как документ XML, имеющий определенную струк- туру. В качестве примера рассмотрим следующее сообще- ние (листинг 15.13). Листинг 15.13. Пример сообщения обмена <vBmsg:Message xmlns:v8msg="http://v8.lc.ru/messages"> <vBmsg:Header> <v8msg: ExchangePl ап>УдаленныеСклады</у8п)5д: ExchangePl an> <v8msg:То>Склад1</v8msg:To> <v8msg:From>O0MC</v8msg:From> <v8msg:MessageNo>20</v8msg:MessageNo> <v8msg:ReceivedNo>15</v8msg:Recei vedNo> </v8msg:Header> <v8msg:Body> <!- Тело сообщения --> </v8msg:8ody> </v8msg:Message> Все сообщение находится внутри элемента XML с именем Message, относящимся к пространству имен http://v8.lc.ru/ messages. Сообщение делится на заголовок Header и тело сообщения Body. Оба относятся к пространству имен http://v8.1с. ru/messages. Структура заголовка жестко задана. Информация заго- ловка представлена в нескольких элементах XML, вло- женных в элемент Header; все элементы, вложенные в эле- мент Header, относятся к пространству имен http://v8.lc.ru/ messages: ♦ элемент с именем ExchangePlan содержит имя плана об- мена, к которому относится сообщение; ♦ элемент с именем То содержит код узла-отправителя; ♦ элемент с именем From содержит код узла, для которого предназначено сообщение; ♦ элемент с именем MessageNo содержит номер данного сообщения. Номер сообщения является положитель- ным целым числом и присваивается узлом-отправите- лем. Номер каждого последующего сообщения равен номеру предыдущего отправленного сообщения плюс 1; ♦ элемент с именем ReceivedNo содержит максимальный номер сообщения, которое узел-отправитель данного сообщения принял от узла-получателя данного сообще- ния. Данное значение включено в состав заголовка со- общения для подтверждения приема сообщений. Тело сообщения содержится в элементе XML с именем Body, относящемся к пространству имен http://v8.lc.ru/messages. Данный элемент может иметь произвольное содержимое, определяемое прикладными потребностями. Инфраструк-
турой сообщений содержимое тела сообщения никак не регламентируется. Пример создания сообщения для выгрузки данных (лис- тинг 15.14). Листинг 15.14. Пример сообщения для выгрузки данных ЗаписьХМ!. = Новый ЗаписьХМЮ; ЗаписьХМ1.0ткрытьФайл("с:\выгрузка.хш1"); Узел = ПланыОбмена.УдаленныеСклады.НайтиПоКодуС"Оптовый"); // Создаем объект "ЗаписьСообщенияОбмена” ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщенияО; ЗаписьСообщения. НачатьЗапись (ЗаписьХМ!., Узел); // Запись тела сообщения ЗаписьСообщения .ЗакончитьЗаписьО; ЗаписьXML.Закрыть!): Выгрузка данных сопровождается созданием объекта с ти- пом ЗаписьСообщенияОбмена (переменная ЗаписьСообщения). Сра- зу после создания этот объект еще «не знает» своего номера, получателя и т. п. Вся подобная информация указывается при выполнении метода НачатьЗаписьО. В качестве первого параметра передается объект ЗаписьХМ!., в качестве второго: ссылка на узел плана обмена (ссылка на получателя). При выполнении этого метода сообщению присваивается номер, определяемый как номер предыдущего отправлен- ного сообщения, увеличенный на 1 (информация берется их узла-получателя). Производится запись в XML-доку- мент заголовка сообщения, а также записывается начало элемента XML, соответствующего телу сообщения. Уста- навливается блокировка на запись базы данных (соответ- ствующая узлу плана обмена. Завершить запись сообщения можно с помощью двух ме- тодов объекта ЗаписьСообщенияОбмена: ♦ ЗакончитьЗаписьО; * ПрерватьЗаписьО. Вызов метода ПрерватьЗаписьО прерывает запись сообще- ния, при этом оно считается не отправленным (счетчик отправленных сообщений в итоге не увеличивается). Не- явный вызов этого метода происходит также в случае по- вторного вызова метода НачатьЗапись О (без последующего вызова метода ЗакончитьЗаписьО), либо при разрушении (окончании времени жизни переменной, связанной с объ- ектом) объекта ЗаписьСообщенияОбмена. Метод ЗакончитьЗаписьО осуществляет нормальное заверше- ние записи сообщения. В этом случае в сообщение записы- вается конец элемента XML (представляющего тело сооб- щения). В узел плана обмена записывается номер сообщения обмена данными. Блокировка с записи узла плана обмена снимается и сообщение считается отправленным. Для чтения записанного в файл сообщения может ис- пользоваться следующий фрагмент кода (листинг 15.15). ЧтениеХМк в данном случае — это объект типа ЧтениеХМЬ. После открытия XML-документа, содержащего сообще- ние, создается объект ЧтениеСообщенияОбмена. Чтение дан- ных начинается с выполнения метода НачатьЧтениеО объ- екта ЧтениеСообщенияОбмена. При этом производится чтение заголовка сообщения обмена данными, проверяются со- держащиеся в заголовке данные. Если какие-либо данные указаны неправильно (задан неизвестный план обмена, указан узел, не входящий в план обмена, номер сообще- ния не соответствует ожидаемому), инициируется ис- ключение. Листинг 15.15. Пример чтения сообщения обмена // Создаем объект "ЧтениеСообщенияОбмена" ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщенияО; ЧтениеСообщения. НачатьЧтение(ЧтениеХМ!_, ДопустимыйНомерСообщения.Больший); // Чтение тела сообщения ЧтениеСообщения.ЗакончитьЧтение(); ЧтениеХМБ.Закрыть(); При начале чтения сообщения устанавливается блоки- ровка на запись узла плана обмена. Используя второй па- раметр метода, можно установить вариант ожидаемого номера сообщения: ♦ любой (фактически контроль номеров сообщения не производится); ♦ очередной (строго больший на единицу, чем предыдущий); ♦ больший. Следует обратить внимание на тот факт, что в приведен- ном фрагменте кода нет ни указания на используемый план обмена (их в конфигурации может быть несколько), ни указания на узел-отправитель. Данная информация получается из заголовка сообщения (в случае невозмож- ности определения, как и было сказано выше, возникает исключение). Завершить чтение сообщения можно с использованием двух методов: ♦ ЗакончитьЧтениеО; ♦ ПрерватьЧтениеО. Обращение к методу ПрерватьЧтениеО вызывает немедлен- ное прерывание чтения сообщения. Блокировка с записи узла плана обмена снимается. В соответствующий узел плана обмена не вносится никаких изменений (не изме- няется номер последнего принятого сообщения). Этот же метод вызывается неявно при разрушении (окончания времени жизни переменной, связанной с данным объек- том) объекта ЧтениеСообщенияОбнена или перед повторным вызовом метода НачатьЧтениеО. Выполнение метода ЗакончитьЧтениеО вызывает попытку нормального завершения чтения сообщения. При этом проверяется нормальное завершение сообщения (теку- щим элементом в объекте ЧтениеХМБ является конец эле- мента, реализующего само сообщение). Номер принятого сообщения помещается в реквизит НомерПринятого узла плана обмена. Блокировка записи узла плана обмена сни- мается и сообщение считается принятым. Универсальный механизм обмена данными Универсальный механизм обмена данными может ис- информационных баз, так и по отдельности (для решения пользоваться как вместе с механизмом распределенных задач организации обмена данными информационных
баз 1С:Предприятия 8.0 с различными программными системами). В качестве программных систем, с которыми может быть организован универсальный обмен данными, могут вы- ступать другие информационные базы ЮПредприятия, в том числе с отличающимися конфигурациями, совер- шенно другие программные комплексы (в этом и состоит отличие от механизма распределенных информационных баз, в рамках которого организуется обмен между базами данных с идентичными конфигурациями). К универсальному механизму обмена данными могут быть отнесены: ♦ средства чтения и записи документов XML; ♦ XML-сериализация; ♦ планы обмена. Функциональность планов обмена была рассмотрена в пре- дыдущих разделах данной главы. Возможности базовых средств чтения и записи XML документов подробно рас- сматривается в разделе «Работа с XML-документами», с. 533. При желании познакомиться с данными механиз- мами более подробно рекомендуем обратиться к соответ- ствующим разделам книги. Использование возможностей работы с XML-документами До данного момента рассматривались только механизмы регистрации, удаления регистрации изменений. Рассмот- рим пример кода, реализующий (в рамках универсально- го обмена) полный цикл выгрузки данных (включает в себя выборку данных, для которых были зарегистрирова- ны изменения). При этом в качестве файлов «носителей данных» будут использоваться документы XML. Следует отметить тот факт, что обмен данными может выполняться через файлы других форматов, но создать объект ЧтениеСообщения и ЗаписьСообщения без указания в ка- честве параметра объектов ЧтениеХМЕ и ЗаписьХМЕ нельзя (листинг 15.16). Листинг 15.16. Пример выгрузки данных ЗаписьХМЕ = Новый ЗаписьХМЕ!) ЗаписьХМЕ.ОткрытьФайл(ИмяФайлаСообщения): Узел = ПланыОбмена.УдаленныеСклады.НайтиПоКоду(КодУзла); ЗаписьСообщения = ПланыОбнена.СоздатьЗаписьСообщенияО: ЗаписьСообщения.НачатьЗапись(ЗаписьХМЕ, Узел); Выборка = Планы0бмена.ВыбратьИзменения(Узел, ЗаписьСообщения.НомерСообщения); Пока Выборка.Следующий() Цикл Данные = Выборка.Получить!): ЗаписатьХМЕСЗаписьХМЕ, Данные): КонецЦикла: ЗаписьСообщения .ЗакончитьЗапись (); Для получения выборки данных, для которых зарегист- рированы изменения, используется метод ВыбратьИзмене- ния(). Для обхода полученных данных используется ме- тод СледующийО выборки. В процессе выборки изменений в записи таблиц регистрации изменений (которые рань- ше не выгружались и у которых, соответственно, в поле таблицы НомерСообщения находится значение Null) про- ставляется номер сообщения обмена данными, в котором должны передаваться изменения. Представленный алгоритм выгрузки предполагает, что отправленные сообщения могут быть потеряны по тем или иным причинам. В случае если потерь сообщения не может быть в принципе (гарантированная доставка), то в конце алгоритма можно разместить следующую строку (листинг 15.17). Листинг 15.17. Удаление регистрации изменений при гарантированной доставке Плаиы0бмена.УдалитьРегистрациюИзмеиеиий(Узел. НокерСообщения); В этом случае будет произведена очистка таблиц регист- рации изменений для узла, ссылка на который передана в качестве первого параметра метода, с номерами сообще- ний (в которых была произведена первая отправка изме- нения) равными или меньшими значению, передаваемо- му в качестве второго параметра метода. Фрагмент кода, в котором производится чтение сообще- ния, содержащего измененные данные, выглядит следую- щим образом (листинг 15.18). Листинг 15.18. Пример чтения сообщения обмена ЧтениеХМЕ = Новый ЧтениеХМЕ!) ЧтениеХМЕ.ОткрытьФайл(ИмяФайлаСообщения); ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения!); ЧтениеСообщения.НачатьЧтение(ЧтениеХМЕ); ПланыОбмена.УдалитьРегистрациюИзменений( ЧтениеСообщения.Отправитель. ЧтениеСообщения.НомерСообщения); Пока ВозможностьЧтенияХМЕ(ЧтениеХМЕ) Цикл Данные = ПрочитатьХМЕ(ЧтениеХМЕ); Данные.ОбменДанными.Отправитель = ЧтениеСообщен ия.Отправитель; Данные.ОбменДанными.Загрузка = Истина; Данные.ЗаписатьО; КонецЦикла; ЧтениеСообщения.ЗакончитьЧтение(); В приведенных выше примерах чтения и записи сообще- ний не учитывалось, что при обмене данными может слу- читься так, что один и тот же элемент данных будет из- менен одновременно в двух обменивающихся данными узлах. В этом случае непонятно, какое из изменений должно быть, в конечном счете, принято. Такая ситуация называется коллизией. Одним из способов разрешения коллизий может быть оп- ределение, какой из узлов является главным, а какой — подчиненным. При этом должно быть принято измене- ние, сделанное в главном узле, а изменение, сделанное в подчиненном узле, должно быть отвергнуто. Для реализации этого при приеме сообщения перед запи- сью данных необходимо установить, зарегистрировано ли изменение этих данных, и в зависимости от роли узла в данной паре получатель-отправитель принять решение: записывать или не записывать данные. Ниже приведен пример реализации стратегии «глав- ный — подчиненный» при чтении сообщения. Предпола- гается, что для хранения роли узла в плане обмена был определен реквизит Главный, имеющий тип Булево. Листинг 15.19. Пример реализации стратегии главный — подчиненный ЧтениеХМЕ = Новый ЧтениеХМЕ!) ЧтениеХМЕ.ОткрытьФайл(ИмяФайлаСообщения); ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения!); ЧтениеСообщения.НачатьЧтение(ЧтениеХМЕ):
ПланыОбмена.УдалитьРегистрациюИзмененийС ЧтениеСообщения.Отправитель, ЧтениеСообщения.НомерПринятого); Отправитель = ЧтениеСообщения.Отправитель: Главный = Отправитель.Главный; Пока ВозможностьЧтенияХМКЧтениеХМи Цикл Данные = ПрочитатьХМЕ(ЧтениеХМЕ); Если Главный ИЛИ (Не ПланыОбмена.Изменение3арегистрировано(0тправитель, Данные)) Тогда Данные.ОбменДанныни.Отправитель = ЧтениеСообщения.Отправитель; Данные.ОбменДанныни.Загрузка = Истина; Данные. ЗаписатьО: КонецЕсли; КонецЦикла: ЧтениеСообщения. ЗакончитьЧтениеО; Следует обратить внимание на необходимость установки у загружаемого элемента данных свойства Загрузка в зна- чение Истина. В обработчиках событий записи объекта рекомендуется отслеживать данный режим и не делать каких-либо проверок на корректность заполнения, при- сутствие каких-либо связанных данных. Это обусловлено тем фактом, что на момент загрузки данного объекта дру- гие объекты могут быть еще не загружены. знакомиться с данными механизмами поближе рекомен- дуем обратиться к данной главе. Состав плана обмена представлен на рис. 15.6. Рис. 15.6. Состав плана обмена Пример реализации универсального обмена Рассмотрим пример реализации механизмов универсаль- ного обмена (фактически это выборочное описание меха- низмов, реализованных в демонстрационной конфигура- ции «Обмен данными», ее можно установить с диска «ИТС»), Считаем, что в некой конфигурации определен план об- мена УдаленныеОфисы. У данного плана обмена определе- ны следующие реквизиты: ♦ Описание (строка) — содержит описание участника об- мена; ♦ Склад (тип СправочникСсылка.Склады) — ссылка на склад, представляющий данный узел; ♦ Главный (тип Булево) — для реализации стратегии «глав- ный-подчиненный»; ♦ АдресОбмена (строка) — для указания ресурса, куда вы- гружаются сформированные сообщения и откуда они загружаются. У плана обмена определены следующие узлы; ♦ Центральный офис (предопределенный узел, код Центр- Офис); ♦ Склад розничный (код Розница); ♦ Склад оптовый (код Опт). Флаг Главный установлен у предопределенного узла. Рек- визит Склад узла Офис содержит пустую ссылку. Следует отметить, что в реальной жизни для каждого узла (через реквизиты, табличные части плана обмена) можно указывать используемые способы доставки сооб- щений (электронная почта, ftp, MSMQ и т. п.). Особенно- сти организации доставки сообщений разными спосо- бами рассматриваются в главе «Интеграция с другими информационными системами», с. 528. При желании по- Обращаем ваше внимание на тот факт, что некоторые объекты (Документ.РасходнаяНакладная, РегистрНакопления. УчетНоменклатуры) входят в состав плана обмена, и при этом авторегистрация для них запрещена (при изменении соответствующих объектов список узлов получателей свойства ОбменДанныни автоматически не заполняется). Это сделано, чтобы продемонстрировать ручное управление регистрацией изменений. При решении задачи обмена следует принять во внима- ние следующие моменты; ♦ при обмене каждая накладная должна уйти в свой узел (реквизит Склад узла плана обмена должен совпасть со складом, выбранном в документе); ♦ пользователям разрешается менять склад в документе. Если документ уже «ушел» в «не правильный узел», он должен в нем удалиться и отправиться в «правильный». На случай если при программном создании документа РасходнаяНакладная в нем (посредством свойства Обмен- Данныни) будет включен режим Автозаполнение, в модуле объекта РасходнаяНакладная размещен обработчик собы- тия ПередЗаписью (листинг 15.20). Листинг 15.20. Обработчик события ПередЗаписью документа РасходнаяНакладная Процедура ПередЗаписью(Отказ) Если ОбменДанныни.Получатели.Автозаполнение Тогда ВключитьРегистрациюСОбменДанными, Склад); // Проверка, что изменился склад Если Не ЭтоНовыйО Тогда Запрос = Новый Запросе ВЬБРАТЬ Склад ИЗ Документ.РасходнаяНакладная ГДЕ Ссылка = &ТекСсылка"); Запрос.УстановитьПараметрС"ТекСсылка", Ссылка);
Выборка = Запрос.Выполнить().Выбрать(); Выборка.Следующий(); Если Выборка.Склад о Склад Тогда ВключитьРегистрацию(ОбменДанными, Выборка.Склад); КонецЕсли; КонецЕсли; КонецЕсли; // Выводим диагностическое сообщение // о регистрации изменений ВывестиРегистрацию(ЭтотОбъект); КонецПроцедуры В данном обработчике (в случае включения режима Авто- регистрация) производится проверка соответствия выбран- ного склада в объекте и записанного в информационной базе. В случае расхождения, документ регистрируется как для нового узла (в соответствии с измененным складом), так и для старого. Процедура с аналогичным назначением определена в мо- дуле набора записей регистра накопления УчетНоменкла- туры (листинг 15.21). Листинг 15.21. Обработчик события ПередЗаписью набора записей регистра УчетНоменклатуры Процедура ПередЗаписью(Отказ) Если ОбменДанными.Получатели.Автозаполнение Тогда СкладНабора = Неопределено; // Для каждой записи набора Для Каждого Запись Из ЭтотОбъект Цикл Если СкладНабора = Неопределено ИЛИ Запись.Склад <> СкладНабора Тогда ВключитьРегистрациюСОбменДанными. Запись.Склад); КонецЕсли; СкладНабора = Запись.Склад; КонецЦикла; // Проверка, что изменился склад Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ Различные | Склад |ИЗ | РегистрНакопления.УчетНоменклатуры |ГДЕ | Регистратор = &ТекСсылка”; Запрос.УстановитьПараметрС'ТекСсылка”, Отбор.Регистратор.Значение): Выборка = Запрос.ВыполнитьО .ВыбратьО; Пока Выборка.СледующийО Цикл // Включаем регистрацию изменений для ВключитьРегистрациюСОбменДанными, Выборка.Склад); КонецЦикла: КонецЕсли; // Выводим диагностическую информацию по набору записей ВывестиРегистрацию(ЭтотОбъект); КонецПроцедуры Обе эти процедуры используют процедуры ВключитьРеги- страцию и ВывестиРегистрацию. Они определены в общем модуле (его имя ОбменСУдаленнымиСкладами) (листинг 15.22). Процедура ВывестиРегистрацию выводит в окно сообще- ний данные об объекте, регистрация которого произошла, и узлах-получателях, для которых эта регистрация про- изошла (листинг 15.23). Листинг 15.22. Процедура ВывестиРегистрацию Процедура ВывестиРегистрацию(Данные) Экспорт ОбменДанными = Данные.ОбменДанными: СообщитьС - Регистрация ” + Данные.МетаданныеО + ” + Строка(Данные)); //Вывод списка узлов, куда будет выполняться регистрация Для Каждого Получатель Из ОбменДанными.Получатели Цикл Если Не ОбменДанными.Отправитель = Получатель Тогда СообщитьС" - " + Получатель); КонецЕсли; КонецЦикла; КонецПроцедуры Листинг 15.23. Процедура ВключитьРегистрацию Процедура ВключитьРегистрацию(ОбменДанными, Склад) Экспорт //Получение узлов для конкретного склада Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | УдаленныеСклады.Ссылка |ИЗ | ПланОбмена.УдаленныеСклады КАК УдаленныеСклады |ГДЕ (УдаленныеСклады.Склад = &Склад ИЛИ УдаленныеСклады.Склад = &ПустойСклад) И | УдаленныеСклады.Ссылка <> &ЭтотУзел"; Запрос.УстановитьПараметрС"Склад", Склад); Запрос.УстановитьПараметрС'ПустойСклад". Справочники.Склады.ПустаяСсылка()); Запрос.УстановитьПараметрС"ЗтотУзел”, ПланыОбмена.УдаленныеСклады.ЗтотУзел()); Выборка = Запрос.ВыполнитьО.Выбрать!); // Регистрация изменений для выбранных узлов Пока Выборка.Следующий() Цикл ОбменДанными.Получатели.Добавить(Выборка.Ссылка); КонецЦикла; КонецПроцедуры Задача процедуры ВключитьРегистрацию — определить всех возможных получателей регистрируемого изменения. В этот список попадут те узлы, у которых в реквизите Склад содержится ссылка на интересующий нас склад либо пустая ссылка (что расширяет функциональность решения), и естественно этот получатель не должен быть предопределенным узлом данного плана обмена. Для осуществления обмена по плану обмена Удаленные- Склады создана обработка УдаленныеСклады. Она позволя- ет решать следующие задачи: ♦ полная регистрация изменений для выбранного узла; ♦ удаление регистрации изменений для выбранного узла; ♦ выполнение выгрузки данных в узел; ♦ выполнение загрузки данных из узла. Рассмотрим реализацию данных механизмов. Полная регистрация изменений по узлу Полная регистрация изменений по выбранному узлу про- изводится с использованием одноименной процедуры,
определенной в общем модуле ОбменСУдаленнымиСклада- ми. У данной процедуры два параметра. В первый переда- ется ссылка на узел, для которого необходимо выполнить регистрацию изменений. Во второй параметр передается значение типа Булево. В случае если это значение Истина, то для данного узла будет выполняться регистрация из- менения всех объектов (невзирая на принадлежность данного узла к какому-либо определенному складу). Та- кой же вариант регистрации будет осуществлен, если в качестве первого параметра будет передан узел, у которо- го в реквизите Склад содержится пустая ссылка. Достигается полная регистрация всех объектов вызовом метода ЗарегистрироватьИзмененияО без указания второго параметра (его значение по умолчанию Неопределено). При этом на отключенную авторегистрацию (для документов РасходнаяНакладная и наборов записей регистра накопле- ния) внимание не обращается (листинг 15.24). Листинг 15.24. Полная регистрация изменений для узла Процедура ПолнаяРегистрацияДанныхПоУзпу(Узел, РегистрироватьВсе) Экспорт // Регистрация изменений всех данных для узла производится // в случае значения параметра РегистрироватьВсе = Истина // или значение склада в узле не установлено Если РегистрироватьВсе Или Узел.Склад.Пустая() Тогда Сообщить("Регистрация всех данных по узлу " + Узел); ПланыОбмена.ЗарегистрироватьИзменения(Узел); Иначе СообщитьС'Регистрация данных по узлу " + Узел + " ........ "); ПланОбмена = Узел.МетаданныеО; Состав = ПланОбмена.Состав; Для Каждого ЗлементСостава Из Состав Цикл СообщитьС Регистрация данных " + ЗлементСостава.Метаданные + ” по узлу " + Узел); Если ЗлементСостава.Метаданные = Метаданные.Документы.РасходнаяНакладная Тогда // Для документов РасходнаяНакладная регистрация // изменений для узла производится только при И совпадении складов узла и накладной, выбираем // документы РасходнаяНакладная по складу узла Запрос = Новый ЗапросС'ВЫБРАТЬ Ссылка ИЗ Документ.РасходнаяНакладная ГДЕ Склад = &Склад"): Запрос.УстановитьПараметр("Склад", Узел.Склад); Выборка = Запрос.ВыполнитьО .ВыбратьО: Пока Выборка.СледующийО Цикл // регистрируем изменение документа для узла ПланыОбмена.ЗарегистрироватьИзменения(Узел, Выборка.Ссылка); КонецЦикла; ИначеЕсли ЗлементСостава.Метаданные = Метаданные.РегистрыНаколления.УчетНоменклатуры Тогда // Выбираем всех различных регистраторов регистра Запрос = Новый ЗапросС'ВЫБРАТЬ РАЗЛИЧНЫЕ Регистратор ИЗ РегистрНакопления.УчетНоменклатуры ГДЕ Склад = &Склад"); Запрос.УстановитьПараметрС"Склад", Узел.Склад); Выборка = Запрос. ВыполнитьО. Выбрать О: Пока Выборка.Следующий О Цикл // Создаем набор записей регистра с отбором // по регистратору НаборЗаписей = РегистрыНаколления. УчетНоменклатуры. СоздатьНаборЗаписейО; НаборЗаписей.Отбор. Регистратор. Установить(Выборка.Регистратор); // регистрируем изменения набора записей // для узла ПланыОбмена.ЗарегистрироватьИзменения(Узел, НаборЗаписей); КонецЦикла; Иначе // Регистрация изменений всех данных объекта для узла ПланыОбмена.ЗарегистрироватьИзменения(Узел, ЗлементСостава.Метаданные) ; КонецЕсли: КонецЦикла: // обход состава плана обмена КонецЕсли; КонецПроцедуры В случае если в качестве второго параметра передается значение Ложь, расходные накладные и записи регистра накопления регистрируются как измененные только в случае совпадения склада со складом, определенным в узле плана обмена. Все остальные данные регистрируют- ся обычным образом. Удаление регистрации изменений по узлу Для осуществления данного действия определена про- цедура, текст которой приведен ниже. В качестве пара- метра передается ссылка на узел, для которого должна произойти очистка таблиц регистрации изменений (лис- тинг 15.25). Листинг 15.25. Удаление регистрации изменений для узла Процедура ПолноеУдалениеРегистрацииДанныхПоУзпу(Узел) Экспорт Сообщить("Удаление регистрации всех данных по узлу " + Узел); ПланыОбмена.УдалитьРегистрациюИзменений(Узел); КонецПроцедуры Выполнение выгрузки данных в узел Приведенная ниже процедура может являться обработ- чиком события нажатия на кнопку либо на гиперссылку. С помощью нее инициируется процесс выгрузки данных (листинг 15.26). Листинг 15.26. Процедура, инициирующая выгрузку данных Процедура ВыполнитьВыгрузкуНажатие(Злемент) // Получаем объект узла обмена УзелОбмена = Узел.ПолучитьОбъектО; // Записываем новое сообщение обмена УзелОбмена.ЗаписатьСообщениеСИзменениямиО; КонецПроцедуры
Взаимосвязь основных процедур и функций, используе- мых для проведения выгрузки, можно проиллюстриро- вать следующей схемой (рис. 15.7). Рис. 15.7. Взаимосвязь процедур и функций для выгрузки измененных данных В процедуре ЗаписатьСообщенияСИЗменениями (листинг 15.27) производится вызов процедур и функций, которые реша- ют следующие задачи: ♦ получение имени файла по заранее установленным пра- вилам (известным на приемной стороне); ♦ вызов функции, в которой производится запись сооб- щения в файл с именем, переданным в качестве пара- метра; ♦ вызов процедуры, осуществляющей доставку файла по указанному пути; ♦ удаление сформированного файла. Листинг 15.27. Процедура ЗаписатьСообщениеСИзменениями Процедура ЗаписатьСообщениеСИзменениямиО Экспорт // Формируем имя временного файла ИмяФайла = КаталогВременныхФайловО + "\" + ПолучитьИмяФайлаОбмена( ПланыОбмена.УдаленныеСклады.ЗтотУзел(), Ссылка, " W”): Сообщить("...... Выгрузка в узел " + Строка(ЭтотОбъект) + " ..........”): // Записываем новое сообщение обмена в файл НомерСообщения = ЗаписатьНовоеСообщение(ИмяФайла): // Публикуем файл с сообщением обмена ОпубликоватьФайлОбмена(ИмяФайла, НомерСообщения); Попытка // Удаляем файл с сообщением обмена УдалитьФайлы(ИмяФайла); Исключение КонецПопытки: Сообщить("...... Конец выгрузки----------"): КонецПроцедуры Функция ПолучитьИмяФайлаОбмена (листинг 15.28) соби- рает имя файла из ключевого слова Message, добавляя код узла источника и приемника. У файла определяется рас- ширение XML (листинг 15.28). Листинг 15.28. Функция ПолучитьИмяФайлаОбмена Функция ПолучитьИмяФайлаОбменаСУзелИсточник, УзелПриемник, Постфикс = "") Экспорт // формируем имя файла исходя из кодов источника // и приемника сообщения обмена Возврат "Message" + СокрЛП(УзелИсточник.Код) + + СокрЛП(УзелПриемник.Код) + СокрЛПСПостфикс) + ".xml"; КонецФункции В функции ЗаписатьНовоеСообщение() (листинг 15.29) в XML-файл с переданным в качестве параметра именем начинается запись данных. Для сокращения размера фай- ла сообщения первоначально определяется соответствие используемым пространствам имен. Создается новое со- общение, производится выборка изменений. Функция определена в модуле плана обмена, ссылка на узел полу- чатель получается из контекста выполнения функции (одноименное свойство Ссылка). Выбранные данные с помощью вызова функции НуженПе- реносДанных (листинг 15.30) проверяются на необходи- мость выгрузки. В случае если выгрузка производится, вызываются процедуры ЗаписатьДанные (листинг 15.31) и ВывестиДанные (листинг 15.32). В противном случае вы- зывается процедура УдалениеДанных (листинг 15.33). Все моменты, связанные с интерфейсной частью механизма (вывод информационных сообщений), выполняются толь- ко на стороне клиента (отмечено директивами препро- цессора) Листинг 15.29. Функция ЗаписатьНовоеСообщение Функция ЗаписатьНовоеСообщение(ИмяФайла) НомерСообщения = 0; // Создаем объект записи XML ЗаписьХМС = Новый ЗаписьХМС; ЗаписьХМС.ОткрытьФайл(ИмяФайла); ЗаписьХМС.ЗаписатьОбъявлениеХМСО: // Создаем новое сообщение ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщенияО: ЗаписьСообщения.НачатьЗапись(ЗаписьХМС, Ссылка): // Для сокращения размера файла сообщения записываем // соответствие пространств имен ЗаписьХМС.ЗаписатьСоответствиеПространстваИмен("xsd", 'http://www.w3.org/2001/XMCSchema”): ЗаписьХМС.ЗаписатьСоответствиеПространстваИмен("xsi". "http://www.w3.org/2001/XMCSchema-i nstance"): ЗаписьХМС. ЗаписатьСоответствиеПространстваИмен( "vB", "http://v8.lc.ru/data"): НомерСообщения = ЗаписьСообщения.НомерСообщения: СообщитьС’ Номер сообщения: “ + НомерСообщения): // Получаем выборку измененных данных Счетчик = 0; ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения( ЗаписьСообщения.Получатель, НомерСообщения): Пока ВыборкаИзменений.Следующий() Цикл Данные = ВыборкаИзменений.Получить О;
#Если Клиент Тогда Счетчик = Счетчик + 1; Состояние!"Выгрузка данных: " + Строка(Счетчик)); #КонецЕсли // Если перенос данных не нужен, то, возможно, // необходимо записать удаление данных Если Не НуженПереносДанных(Данные) Тогда // Получаем значение с возможным удалением данных УдалениеДанных(Данные); КонецЕсли: // Записываем данные в сообщение ЗаписатьДанные(ЗаписьХМЕ, Данные); #Если Клиент Тогда // Выводим диагностическое сообщение о записанных данных ВывестиДанные(Данные); #КонецЕсли КонецЦикла: // Завершаем запись сообщения ЗаписьСообщения.ЗакончитьЗапись(): ЗаписьХМЕ.Закрыть(): Возврат НомерСообщения; КонецФункции Функция НуженПереносДанных (см. листинг 15.30) реали- зует стратегию распространения данных. Документы При- ходнаяНакладная и РасходнаяНакладная (и соответствующие им наборы записей регистра накопления) выгружаются только в случае, если значение реквизита Склад документов (и наборов записей регистра накопления) совпадают по значению с одноименным реквизитом, определенным для узла получателя. Для набора записей регистра накопления производится проверка на то, что во всех записях используется один склад, Данная проверка может и не проводиться, если та- кая ситуация изначально не может встретиться. Листинг 15.30. Функция НуженПереносДанных Функция НуженПереносДанных(Данные) Перенос = Истина; Если ТипЗнч(Данные) = Тип("ДокументОбъект.ПриходнаяНакладная") ИЛИ ТипЗнч(Данные) = Тип("ДокументОбъект.РасходнаяНакладная") Тогда // Проверяем, что у документов склад совпадает Если Не Склад.Пустая() И Данные.Склад <> Склад Тогда Перенос = Ложь: КонецЕсли: ИначеЕсли ТипЗнч(Данные) = Тип("РегистрНакопленияНаборЗаписей.УчетНоменклатуры") Тогда // Проверяем, что у записей набора склад совпадает СкладНабора = Неопределено: Для Каждого Запись Из Данные Цикл Если СкладНабора <> Неопределено И Запись.Склад <> СкладНабора Тогда ВызватьИсключение "Склад должен быть | одинаковый для всех записей"; КонецЕсли; СкладНабора = Запись.Склад; КонецЦикла; Если Не Склад.Пустая() И СкладНабора <> Склад Тогда Перенос = Ложь; КонецЕсли; КонецЕсли: Возврат Перенос; КонецФункции Рассматриваемый механизм выгрузки данных относится к разряду универсальных и подразумевает, что обмен данных производится между конфигурациями, имеющими разную структуру. В процедуре ЗаписатьДанные (см. лис- тинг 15.31) производится разделение данных на те, кото- рые выгружаются в индивидуальном порядке (в нашем случае это элементы справочника Номенклатура), и выгру- жаемые с помощью метода платформы ЗаписатьХМК). Процедура НоменклатураЗаписатьХМЦ) рассматривается более подробно в разделе «Пример реализации обмена при разной структуре объектов конфигурации», с. 545. Листинг 15.31. Процедура ЗаписатьДанные Процедура ЗаписатьДанныеСЗаписьХМЕ. Данные) Удаление = ?(ТипЗнч(Данные) = ТипС'УдалениеОбъекта"), Истина. Ложь); // Получаем объект описания метаданного. // соответствующий данным ОбъектМетаданных = ?(Удаление. Данные.Ссылка.МетаданныеО. Данные.МетаданныеС)); // Если выгружаемыми данными является // Справочник.Номенклатура, то его выгружаем вручную Если Не Удаление И ОбъектМетаданных = Метаданные.Справочники.Номенклатура Тогда // Записываем элемент справочника вручную НоменклатураЗаписатьХМЕСЗаписьХМЕ, Данные); Иначе // Записываем данные с помощью стандартного метода ЗаписатьХМЕСЗаписьХМЕ, Данные); КонецЕсли КонецПроцедуры Текст процедуры, производящей вывод диагностических сообщений, приведен ниже (см. листинг 15.32). Листинг 15.32. Процедура ВывестиДанные Процедура ВывестиДанные(Данные) Перем Представление; Если ТипЗнч(Данные) = ТипС'УдалениеОбъекта") Тогда Представление = "Удаление объекта: " + Строка(Данные.Ссылка.Метаданные()) + ": “ + Строка(Данные.Ссылка); Иначе Представление = Строка (Данные. МетаданныеО) + ": ” + Строка(Данные); КонецЕсли; СообщитьС'- " + Представление); КонецПроцедуры В случае если данные (полученные при выборке измене- ний) не подлежат выгрузке в текущий узел плана обмена, производится вызов процедуры УдалениеДанных (см. лис- тинг 15.33). В данной процедуре для данных, имеющих объектную природу, создается объект УдалениеОбъекта. Этим дости- гается удаление в узле приемнике «ранее неправильно отосланных данных». Наборы записей регистров очища- ются.
Листинг 15.33. Процедура УдалениеДанных Процедура УдалениеДанных(Данные) // Получаем объект описания метаданного, соответствующий данным ОбъектМетаданных = ?(ТипЗнч(Данные) = Тип("УдалениеОбъекта"), Данные.Ссылка.МетаданныеО. Данные.МетаданныеО): Если Метаданные.Справочники.Содержит(ОбъектМетаданных) ИЛИ Метаданные.Документы.Содержит(ОбъектМетаданных) ИЛИ Метаданные.ПланыСчетов.Содержит(ОбъектМетаданных) ИЛИ Метаданные. ПланыВидовРасчета.Содержите ОбъектМетаданных) ИЛИ Метаданные. ПланыВидовХарактеристик. Содержит ( ОбъектМетаданных) Тогда // Перенос удаления объекта для объектных Данные = Новый УдалениеОбъекта(Данные.Ссылка); ИначеЕсли Метаданные.РегистрыСведений.Содержите ОбъектМетаданных) ИЛИ Метаданные.РегистрыНаколления.Содержите ОбъектМетаданных) ИЛИ Метаданные.РегистрыБухгаптерии.Содержите ОбъектМетаданных) ИЛИ Метаданные.РегистрыРасчета.Содержите ОбъектМетаданных) ИЛИ Метаданные.РегистрыРасчета.Содержит( ОбъектМетаданных.Родитель) ИЛИ Метаданные.Последовательности.Содержите ОбъектМетаданных) Тогда // Очищаем данные Данные.ОчиститьО; КонецЕсли; КонецПроцедуры С помощью процедуры ОпубликоватьФайлОбмена (лис- тинг 15.34) полученный в результате XML-документ мо- жет быть выложен на FTP-сервер либо на ресурс локаль- ной сети. Имя ресурса определено в реквизите АдресОбмена. Для того чтобы была возможность отправлять файл, ис- пользуя схемы FTP, HTTP, HTTPS, в пути приемника производится замена символов «\» на «/». Листинг 15.34. Процедура ОпубликоватьФайлОбмена Процедура ОпубликоватьФайлОбмена(ИмяФайла, НомерСообщения) ИмяФайлаСообщения = ПолучитьИмяФайлаОбмена( ПланыОбмена.УдаленныеСклады.ЭтотУзел(), Ссылка. Формат(НомерСообщения, "ЧЦ=10; ЧВН=; ЧГ=0")); Путь = СтрЗаменить(АдресОбмена, "\", "/"); // Копируем файл в каталог, определенный для данного узла Попытка КопироватьФайл(ИмяФайла, Путь + ?(Прав(Путь, 1) = "/", "/") + ИмяФайлаСообщения); Исключение Сообщить(" - Ошибка публикации файла: " + ИмяФайлаСообщения); Сообщить(ОписаниеОшибки()); Возврат; КонецПопытки: СообщитьС - Опубликован файл: " + ИмяФайлаСообщения): КонецПроцедуры При публикации файла его имя формируется из слова Message, кода узла отправителя (предопределенного узла), кода узла получателя и номера отправляемого сообщения (номер представлен в формате целого числа из 10 цифр). Из вышеуказанной процедуры производится возврат в про- цедуру ЗаписатьСообщениеСИзменениями (см. листинг 15.27) после завершения которой процесс выгрузки завершается. Выполнение загрузки данных из узла Приведенная ниже процедура может являться обработ- чиком события нажатия на кнопку либо на гиперссылку. С помощью нее инициируется процесс загрузки данных (листинг 15.35). Листинг 15.35. Процедура, инициирующая загрузку данных Процедура ВыполнитьЗагрузкуНажатие(Злемент) // Получаем объект узла обмена УзелОбмена = Узел.ПолучитьОбъектО; // Читаем новое сообщение обмена УзелОбмена. ПрочитатьСообщениеСИзменениями (): КонецПроцедуры Следует отметить, что используется ряд процедур, рас- смотренных в разделе «Выполнение выгрузки данных в узел», с. 584. В текущем разделе они повторно рассматри- ваться не будут (это касается функции ПолучитьИмяФайла- Обмена (см. листинг 15.28) и процедуры ВывестиДанные (см. листинг 15.32)). Взаимосвязь основных процедур, рассматриваемых в дан- ном разделе, показана на схеме, представленной ниже (рис. 15.8). Рис. 15.8. Взаимосвязь процедур и функций для загрузки измененных данных В процедуре ПрочитатьСообщениеСИзменениями (лис- тинг 15.36) первоначально получаем имя файла, которое
будет использоваться для создания временного докумен- та, из которого будет впоследствии производиться считы- вание данных. Имя складывается из слова Message, кода узла приемника, кода узла отправителя и постфикса _R. Процедура расположена в модуле плана обмена, поэтому для получения ссылки узла-источника используется од- ноименное свойство (Ссылка). Вызов функции ПолучитьФайлОбмена (листинг 15.37) (в слу- чае успешного получения файла) записывает данные во временный файл с ранее сформированным именем. Само чтение производится функцией ПрочитатьНовоеСообщение (листинг 15.38). Данная функция возвращает номер полу- ченного сообщения (он потом используется процедурой УдалитьФайлыОбмена (листинг 15.41) для удаления сообще- ний с внешнего ресурса с данным и меньшими номерами). Листинг 15.36. Процедура ПрочитатьСообщениеСИзменениями Процедура ПрочитатьСообщениеСИзмененияниО Экспорт Перен НонерСообщения: // Номер принимаемого сообщения // Формируем имя временного файла ИмяФайла = КаталогВременныхФайловО + ”\" + ПолучитьИмяФайлаОбменаСПланыОбмена. УдаленныеСклады.ЗтотУзел(), Ссылка, "_R"); СообщитьС........Загрузка из " + Строка (ЭтотОбъект) + "........"); // Получаем копию файла обмена с новым сообщением // во временный файл ФайлПолучен = ПолучитьФайлОбмена(ИмяФайла): Если ФайлПолучен Тогда Попытка // Читаем полученное сообщение из файла НонерСообщения = ПрочитатьНовоеСообщение(ИмяФайла); Исключение СообщитьС " + ОписаниеОшибкиО): КонецПопытки; Если НонерСообщения <> Неопределено Тогда // Удаляем файлы со старыми сообщениями обмена Удали т ьФайлыОбмен а(НомерСообщен ия); КонецЕсли; КонецЕсли; Попытка // Удаляем файл с сообщением обмена УдалитьФайлы(ИмяФайла); Исключение КонецПопытки; СообщитьС-------- Конец загрузки...........”); КонецПроцедуры При получении файла (см. листинг 15.37) обмена счита- ем, что файл, который мы ожидаем, имеет имя, состоящее из слова Message, кода узла отправителя, кода узла полу- чателя (предопределенного узла) и номера, состоящего из 10 цифр. По сформированной маске ищем сообщения с любым номером. Из всех найденных файлов выбираем тот, который обладает наибольшим номером. Исходя из стратегии очистки журнала регистрации данных «по по- лучению квитанции», в сообщении с большим номером будет находиться наиболее полная порция данных для за- грузки. После того как определились с файлом с помощью мето- да платформы КопироватьФайлО, копируем файл на ло- кальную машину (в каталог временных файлов). Листинг 15.37. Функция ПолучитьФайлОбмена Функция ПолучитьФайлОбнена(ИняФайла) // Получаем маску для поиска файлов с сообщениями обмена МаскаФайлов = ПолучитьИмяФайлаОбменаССсылка, ПланыОбмена.УдаленныеСклады.ЭтотУзелО, "??????????"); ИмяФайлаСообщения = // Ищем файлы по маске в каталоге загрузки Файлы = НайтиФайлыСАдресОбмена, МаскаФайлов); // Отбираем файл с максимальным номером в имени Для Каждого Файл Из Файлы Цикл Если ПустаяСтрока(ИмяФайлаСообщения) ИЛИ Файл.ПолноеИмя > ИмяФайлаСообщения Тогда ИмяФайлаСообщения = Файл.ПолноеИмя; КонецЕсли; КонецЦикла; Если Не ПустаяСтрока(ИмяФайлаСообщения) Тогда СообщитьС Считывается файл " + ИмяФайлаСообщения); Попытка // Копируем файл с сообщением обмена в указанный файп КопироватьФайл(ИмяФайлаСообщения. ИмяФайла); Исключение СообщитьС " + ОписаниеОшибкиО); Возврат Ложь; КонецПопытки: // Файл с сообщением обмена получен успешно Возврат Истина; КонецЕсли; Возврат Ложь; КонецФункции Чтение полученного сообщения (из временного файла) на- чинается в процедуре ПрочитатьНовоеСообщение (см. лис- тинг 15.38). В качестве параметра передается имя файла, куда произведено копирование сообщения. После того как создан объект ЧтениеСообщения и чтение на- чато, производится очистка таблиц регистрации измене- ний данных (этим реализуется стратегия «ожидание кви- танции»). Проверка возможности чтения очередной порции данных производится в функции ВозможностьЧтенияДанных (лис- тинг 15.39), непосредственно чтение производится с по- мощью функции ПрочитатьДанные (листинг 15.40). После того как данные получены, анализируется возмож- ность возникновения коллизий. При обнаружении кол- лизии принимается решение в пользу узла-приемника (они не принимаются), в случае если в узле-отправителе реквизит Главный установлен в значение Ложь. В функции ВозможностьЧтенияДанных (см. листинг 15.39) для данных с различающейся структурой (отрабатывае- мым по специальным алгоритмам) возвращается значение Истина. Остальные данные проверяются штатным методом платформы ЮПредприятие. Считается, что конфигура- ции, участвующие в обмене, отличаются только структу- рой справочника Номенклатура. Для переноса изменений в данных этого справочника используется специальным образом определенный элемент CatalogObject-Номенклату- ра.Вручную.
Листинг 15.38. Функция ПрочитатьНовоеСообщение Функция ПрочитатьНовоеСообщение(ИмяФайла) // Создаем объект чтения XML ЧтениеХМЕ = Новый ЧтениеХМЕ; ЧтениеХМЕ.ОткрытьФайл(ИмяФайла); // Загрузка из найденного файла ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщенияО; ЧтениеСообщения. НачатьЧтение(ЧтениеХМЕ); НомерСообщения = ЧтениеСообщения.НомерСообщения; Если ЧтениеСообщения.Отправитель <> Ссылка Тогда // Сообщение предназначено не для этого узла ВызватьИсключение "Неверный узел"; КонецЕсли: // Удаляем регистрацию изменений для узла-отправителя // сообщения по номеру принятого сообщения, // полученного из сообщения ПланыОбмена.УдалитьРегистрациюИзмененийС ЧтениеСообщения.Отправитель, ЧтениеСообщения.НомерПринятого); // Читаем данные из сообщения, пока это возможно Счетчик = 0; Пока ВозможностьЧтенияДанных(ЧтениеХМЕ) Цикл // Читаем очередное значение Данные = ПрочитатьДанные(ЧтениеХМЕ); #Если Клиент Тогда Счетчик = Счетчик + 1; Состояние!"Загрузка данных: " + Строка(Счетчик)); #КонецЕсли // Разрешение коллизий при одновременном изменении // в обоих узлах Если Не ЧтениеСообщения.Отправитель.Главный И ПланыОбмена.ИзменениеЗарегистрировано! ЧтениеСообщения.Отправитель. Данные) Тогда СообщитьС- Изменения отклонены:”); #Если Клиент Тогда ВывестиДанные(Данные); #КонецЕсли Продолжить; КонецЕсли: // Вывод диагностического сообщения о загружаемых данных ВывестиДанные(Данные); // Устанавливаем отправителя, чтобы для него при записи // не было бы зарегистрировано изменение Данные. ОбменДанныни. Отправитель = ЧтениеСообщения.Отправитель; // Включает режим Загрузка, так как данные могут // загружаться в произвольном порядке и нужно отключить, // такой контроль данных, как проверка // уникальности номеров Данные.ОбменДанныни.Загрузка = Истина; // Запись перенесенных данных Данные.Записать О; КонецЦикла; ЧтениеСообщения.ЗакончитьЧтениеС); ЧтениеХМЕ.Закрыть(): Возврат НомерСообщения; КонецФункции Функция ПрочитатьДанные (см. листинг 15.40) для чтения элемента справочника Номенклатура из элемента XML- документа CatalogObject.HoweHKnaTypa.Вручную использует специальную функцию НоменклатураПрочитатьХМЕ(), все остальные данные считываются стандартным методом подсистемы сериализации ПрочитатьХМК). Листинг 15.39. Функция ВозможностьЧтенияДанных Функция ВозможностьЧтенияДанных(ЧтениеХМЕ) // Получаем тип данных XML, который может быть // считан в данный момент ТипХМЕ = ПолучитьХМЕТип(ЧтениеХМЕ); Если ТипХМЕ = Неопределено Тогда Возврат Ложь; КонецЕсли; Если ТипХМЕ.ИмяТипа = "CatalogObject.Номенклатура.Вручную" И ТипХМЕ.иКШространстваИмен = Тогда Возврат Истина; КонецЕсли; Возврат ВозможностьЧтенияХМЕ(ЧтениеХМЕ); КонецФункции Листинг 15.40. Функция ПрочитатьДанные Функция ПрочитатьДанные(ЧтениеХМЕ) ТипХМЕ = ПолучитьХМЕТип(ЧтениеХМЕ); Если ТипХМЕ = Неопределено Тогда Возврат Неопределено; КонецЕсли; Если ТипХМЕ.ИмяТипа = "CatalogObject.Номенклатура.Вручную" И ТипХМЕ.ШИПространстваИмен = "" Тогда // Пытаемся прочесть значение справочника Номенклатура Возврат НомеклатураПрочитатьХМЕ(ЧтениеХМЕ); КонецЕсли: // Пытаемся прочесть значение из объекта ЧтениеХМЕ // стандартным образом Возврат ПрочитатьХМЕ(ЧтениеХМЕ); КонецФункции Принципы построения функции (и пример) Номенкла- тураПрочитатьХМЕ() рассматривается в разделе «Пример реализации обмена при разной структуре объектов кон- фигурации», с. 545. Процедура УдалитьФайлыОбмена (см. листинг 15.41) про- изводит очистку файлов — сообщений на внешнем ресур- се с номером сообщения, равным принятому или меньше- му (получаем все файлы по маске, удаляем по условию). Листинг 15.41. Процедура УдалитьФайлыОбмена Процедура УдалитьФайлыОбмена(НомерСообщения) // Получаем имя файла с номером сообщения МаксИмяФайла = ПолучитьИмяФайлаОбмена! Ссылка, ПланыОбмена.УдаленныеСклады.ЗтотУзел(), Формат(НомерСообщения, "ЧЦ=10; ЧВН=; ЧГ=О")); // Получаем маску для поиска файлов с сообщениями обмена МаскаФайпов = ПолучитьИмяФайлаОбмена! Ссылка, ПланыОбмена.УдаленныеСклады.ЗтотУзел(), "??????????”): // Ищем файлы по маске в каталоге загрузки Файлы = НайтиФайлы(АдресОбмена, МаскаФайлов); // Удаление файлов со старыми сообщениями обмена Для Каждого Файл Из Файлы Цикл // Удаляем только файлы, имена которых меньше или равны // имени файла с указанным номером сообщения Если Файл.Имя <= МаксИмяФайла Тогда Попытка
И Пытаемся удалить файл УдалитьФайлы(Файл.ПолноеИмя); Исключение КонецПопытки: КонецЕсли: КонецЦикла; КонецПроцедуры Регистрация в произвольные узлы В рассматриваем примере для документов ПриходнаяНак- ладная была включена автоматическая регистрация изме- нений. В случае если необходимо зарегистрировать из- менения для какого-либо определенного перечня узлов (отличного, от формируемого при авторегистрации), можно воспользоваться двумя способами: определить об- работчики события ПередЗаписью и ПередУдалением модуля объекта или воспользоваться следующими процедурами: ЗарегистрироватьПриходные (листинг 15.42) и ЗаполнитьНа- борУзлов (листинг 15.43). Листинг 15.42. Процедура ЗарегистрироватьПриходные Процедура ЗарегистрироватьПриходные(Узлы) Выборка = Документы.ПриходнаяНакладная.ВыбратьО; Пока Выборка.СледующийО Цикл Объект = Выборка.ПолучитьОбъект(): // заполняем набор узлов-получателей Объект.ОбменДанными.Получатели.АвтоЗаполнение = Ложь: ЗаполнитьНаборУзпов(Объект.ОбменДанными.Получатели. Узлы); // записываем элемент данных Объект.ЗаписатьО: КонецЦикла: КонецПроцедуры Процедура ЗарегистрироватьПриходные в качестве парамет- ра получает коллекцию узлов, для которых необходимо провести регистрацию изменений. В теле процедуры про- изводится выборка всех документов ПриходнаяНакладная. У каждого полученного объекта отключается автозапол- нение, и набор получателей формируется самостоятель- но (используется функция ЗаполнитьНаборУзлов (см. лис- тинг 15.43)). Листинг 15.43. Процедура ЗаполнитьНаборУзлов Процедура ЗаполнитьНаборУзловСНабор, Список) Набор.ОчиститьО: Для каждого Элемент Из Список Цикл Набор.Добавить(Элемент); КонецЦикла: КонецПроцедуры У документа РасходнаяНакладная отключена автомати- ческая регистрация изменений. Ее можно «включить» - используя механизм подобный приведенному (лис- тинг 15.44). Листинг 15.44. Процедура ЗарегистрироватьПриходные Процедура ЗарегистрироватьПриходные(Узлы) Выборка = Документы.РасходнаяНакладная.Выбрать(): Пока Выборка.Следующий() Цикл Объект = Выборка. ПолучитьОбъектО: // набор узлов-получателей заполнится автоматически Объект.ОбменДанными.Получатели.АвтоЗаполнение = Истина; // записываем элемент данных Объект. ЗаписатьО; КонецЦикла; КонецПроцедуры Следует отметить тот факт, что в обработчике события ПередЗаписью данного документа «установлена защита», которая не позволит зарегистрировать изменения доку- мента для всех узлов. Эта процедура рассмотрена в нача- ле раздела «Универсальный механизм обмена данными», с. 580. Распределенные информационные базы Распределенная информационная база представляет со- бой иерархическую структуру, состоящую из отдельных информационных баз ЮПредприятия — узлов распреде- ленной информационной базы, между которыми органи- зован обмен данными с целью синхронизации конфигу- рации и данных. В основе механизмов распределенных информационных баз лежат универсальные механизмы обмена данными, но они содержат некоторые дополнительные возможности, недоступные через универсальные механизмы. Главное отличие распределенных информационных баз от универсальных механизмов обмена данными заключается в том, что универсальные механизмы обмена данными по- зволяют выстраивать достаточно произвольные схемы об- мена данными, в то время как распределенные информа- ционные базы имеют более узкую специализацию. Общие принципы Распределенная информационная база — это совокупность информационных баз ЮПредприятия (узлов распре- деленной информационной базы), в которых поддер- живается синхронизация конфигурации и данных. Рас- пределенная информационная база имеет иерархическую структуру. У каждого узла распределенной информаци- онной базы может быть один главный и произвольное число подчиненных узлов. «Самый главный узел» или узел, у которого нет главного узла, называется корневым узлом распределенной информационной базы. Каждый из узлов может обмениваться данными только со своими «соседями», то есть со своими главным и подчиненными узлами (рис. 15.9).
Рис. 15.9. Структура узлов распределенной информационной базы Изменения конфигурации допускаются только в корне- вом узле распределенной информационной базы с после- дующим ее распространением по иерархии от корневого узла к его подчиненным и т. д. Таким образом, механизм управления распределенными информационными база- ми обеспечивает наличие во всех узлах распределенной информационной базы одной и той же конфигурации. Изменение данных допускается в любом узле распреде- ленной информационной базы. Синхронизация данных достигается путем распространения изменений данных, произведенных в одном узле, во все структуры распреде- ленной информационной базы (рис. 15.10). Рис. 15.10. Миграция данных в распределенной информационной базе Если в рамках всей распределенной информационной базы поддерживается полная идентичность конфигура- ции, то полная идентичность данных не обязательна. Со- став данных, изменения которых передаются в рамках распределенной информационной базы, может регулиро- ваться как «по вертикали» (путем определения множест- ва объектов метаданных, данные которых участвуют в об- мене), так и «по горизонтали» (путем задания условий на передачу и прием изменений на уровне отдельных эле- ментов данных). Планы обмена занимают центральное место и в управ- лении распределенными информационными базами. Но для того, чтобы тот или иной план обмена мог использо- ваться для организации распределенной информацион- ной базы, у него при конфигурировании должно быть ус- тановлено свойство Распределенная информационная база. Данные в распределенной информационной базе перено- сятся с помощью сообщений, предоставляемых инфра- структурой сообщений. В отличие от универсальных ме- ханизмов обмена данными, содержимое сообщений, пере- даваемых между узлами распределенной информаци- онной базы, не может быть произвольным, а является регламентированным протоколом обмена, принятым для распределенной информационной базы. Состав данных, изменениями которых будет произво- диться обмен в рамках распределенной информационной базы, определяется составом плана обмена. Вхождение объекта метаданных в состав плана обмена показывает, что изменения данных, соответствующих объекту мета- данных, могут регистрироваться для узлов данного плана обмена. Но в отличие от универсальных механизмов об- мена данными, номенклатура данных, обмен которыми может производиться в рамках распределенной информа- ционной базы, строго ограничена составом соответствую- щего плана обмена. Для регистрации изменений данных в распределенной ин- формационной базе задействована служба регистрации из- менений. Элементы данных помещаются в сообщение с использованием механизмов XML-сериализации. Помимо изменений данных между узлами распределенной инфор- мационной базы передаются изменения конфигурации, а также некоторая дополнительная служебная информа- ция. Регистрация изменений конфигурации и включение их в сообщение обмена в распределенной информацион- ной базе осуществляется полностью автоматически и не- доступно для пользователя и разработчика конфигураций. В отличие от универсальных механизмов обмена данны- ми, формирование и прием сообщения обмена данными в распределенной информационной базе производится «в одно действие», то есть все содержимое сообщения формируется путем вызова одного метода встроенного языка (листинг 15.45). Листинг 15.45. Пример вызова метода ЗаписатьИзмененияО ПланыОбмена.ЗаписатьИзмененияСЗаписьСообщения, 0); Аналогично и считывание содержимого сообщения про- изводится также путем вызова одного метода (лис- тинг 15.46). Листинг 15.46. Пример вызова метода ПрочитатьИзменения ПланыОбмена.ПрочитатьИзиенения(ЧтениеСообщения); Пример использования данных методов приведен в раз- деле «Запись и чтение сообщений обмена», с. 595. Для того чтобы управлять составом данных, помещаемых в сообщение, а также считываемых из сообщения и поме- щаемых в базу данных на уровне отдельных элементов данных, в модуле плана обмена могут быть определены обработчики событий: ♦ ПриОтправкеДанныхПодчиненному; ♦ ПриОтправкеДанныхГлавноиу; ♦ ПриПолученииДанныхОтПодчиненного; ♦ ПриПолученииДанныхОтГлавного. Таким образом, в распределенной информационной базе практически полностью задействованы универсальные механизмы обмена данными, но имеются и некоторые до- полнительные возможности, недоступные вне распреде- ленной информационной базы.
Главный и подчиненный узлы Как было указано выше, у каждого из узлов распределен- ной информационной базы может быть один главный и произвольное число подчиненных узлов. Для своего глав- ного узла узел является подчиненным и, соответственно, для своих подчиненных — главным. Узел, у которого нет главного узла, является корневым узлом распределенной информационной базы. Корневой узел распределенной ин- формационной базы — это единственное место, где разре- шено вносить изменения в конфигурацию информацион- ной базы. Распределенная информационная база может быть по- строена на основе нескольких планов обмена, с уста- новленным свойством Распределенная информационная база. Взаимодействие в каждой паре узлов «главный-подчи- ненный» производится в соответствии с одним из опреде- ленных в конфигурации планов обмена. Никаких ограни- чений на использование того или иного плана обмена в том или ином узле распределенной информационной базы не накладывается. Каждый из узлов распределенной информационной базы, как и в случае использования универсальных механизмов обмена данными, «знает» только своих «соседей», то есть свой главный и свои подчиненные узлы (рис. 15.11). Сообщение обмена данными в распределенной информационной базе Для передачи изменений данных и конфигурации в рас- пределенной информационной базе используются сообще- ния обмена данными предоставляемые инфраструктурой сообщений. Если в случае применения универсальных механизмов обмена данными разработчик конфигурации сам определяет, что и как помещается в тело сообщения, то в случае распределенной информационной базы структура и состав данных, помещаемых в тело сообщения, четко оп- ределены. Таким образом полная схема распределенной информа- ционной базы при наличии более чем двух уровней неиз- вестна никакому из узлов (это является особенностью службы регистрации изменений: изменения регистриру- ются для всех непредопределенных узлов, если в каком- либо плане обмена указать все узлы распределенной базы, то это нарушит структуру подчинения баз данных). Рассмотрим структуру сообщения обмена данными, ис- пользуемого в распределенной информационной базе. В качестве примера рассмотрим следующее сообщение (листинг 15.47). Как видно из примера, все особенности сообщения обме- на данными, используемого в распределенной инфор- мационной базе, сосредоточены в теле сообщения. Тело сообщения (элемент Body, относящийся к пространству имен http://v8.lc.ru/messages) содержит один-единст- венный элемент XML — Changes, относящийся к про- странству имен http://v8.lc.ru/dataexchange. Внутри это- го элемента сосредоточены все данные, передаваемые при обмене данными в распределенной информацион- ной базе. Рис. 15.11. Состав узлов распределенной информационной базы для узла Розничный магазин Листинг 15.47. Пример структуры сообщения обмена <v8msg:Message xml ns:v8msg="http://v8.lc.ru/messages“> <v8msg:Header» <v8msg:ExchangePIап>УдаленныеСклады</v8msg:ExchangePIan> <v8msg:То>Склад1</v8msg:To> <v8msg:Fгот»0фис</v8msg:From> <v8msg: MessageNo>20</v8msg: MessageNo» <v8msg:Recei vedNo>15</v8msg:Recei vedNo> </v8msg:Header» <v8msg:Body> <v8de:Changes xml ns:v8de="http://v8.lc.ru/dataexchange"> <v8de:Signature» 7b4d5320-f69c-4a7b-9273 -ff56607fc8ab </v8de:Signature» <v8de:Config xml ns:v8md="http://v8.lc.ru/metadata"» <!- Измененные объекты конфигурации --» <v8de:Digestl» 88d3f3a6ba3f4df03c7ec00fl54837fc </v8de:Digestl» <v8de:Digest2» 00cf636b02a488103a64c7a2cf81069e </v8de:Digest2» </v8de:Config» <v8de:Nodes» <v8de:Node» <!- Данные главного узла --» </v8de:Node» <v8de:Node> <!- Данные подчиненного узла --> </v8de:Node> </v8de:Nodes» <v8de:Data» <!- Измененные элементы данных --» </v8de:Data» </v8de:Changes» </v8msg:Body> </v8msg:Message> Элемент Changes может содержать четыре вложенных элемента, относящихся к тому же пространству имен: ♦ элемент Signature содержит «подпись» плана обмена, в соответствии с которым получено сообщение; ♦ элемент Config содержит изменения конфигурации, а также данные, идентифицирующие состояние конфи- гурации. Необязательные элементы Metadata, вложен- ные в Config, содержат изменения отдельных объектов
конфигурации. Если изменения конфигурации не пере- даются в сообщении, то элементы Metadata отсутствуют. Такие элементы могут присутствовать только в сооб- щениях, передаваемых от главного узла подчиненному. Элементы Digestl и Digest2 содержат цифровые подписи передаваемых в данном сообщении изменений конфи- гурации и всей конфигурации за вычетом изменений. Элементы Digestl и Digest2 присутствуют во всех сооб- щениях: передаваемых от главного узла подчиненному, и наоборот; ♦ элемент Nodes может присутствовать только в сообще- ниях, передаваемых от главного узла подчиненному. Этот элемент содержит два вложенных элемента Node, первый из которых содержит данные главного узла (от- правителя), а второй — подчиненного (получателя); ♦ и, наконец, элемент Data содержит измененные элемен- ты данных, передаваемые в сообщении. Элементы дан- ных помещаются в сообщение с помощью XML-сериа- лизации. Создание узла распределенной информационной базы Создание нового узла распределенной информационной базы в платформе ЮПредприятия можно выполнить не- сколькими способами: ♦ создать начальный образ; ♦ создать узел из конфигурации главного узла распреде- ленной информационной базы; ♦ создать узел из копии информационной базы главного узла распределенной информационной базы. Рассмотрим каждый из вариантов подробнее. Создание начального образа Данный вариант представляет собой наиболее простой способ создания нового узла распределенной информа- ционной базы. Процедуру создания начального образа можно инициировать путем выполнения соответствую- щей интерфейсной команды Создать начальный образ. Также это можно сделать при помощи метода встроен- ного языка объекта ПланыОбиенаМенеджер (листинг 15.48). Листинг 15.48. Пример использования метода СоздатьНачальныйОбразО ПланыОбмена.СоздатьНачальный0браз(Узел. СтрокаСоединения); Интерактивное создание начального образа Для того чтобы интерактивно создать начальный образ для узла плана обмена, необходимо открыть форму спи- ска плана обмена или непосредственно форму узла плана обмена. Для выбранного узла плана обмена следует вы- полнить команду Создать начальный образ (рис. 15.12). При этом на экране появится диалог создания начального образа, в котором будет предложено заполнить все не- обходимые параметры информационной базы — нового узла распределенной информационной базы. План обмена Магазины _ □ X Действия»! g 1g "6 X: I iQI® Изменить ч Удалить непосредственно Установить пометку удаления Записать изменения. Рис. 15.12. Интерактивное создание начального образа Структура диалога создания начального образа узла рас- пределенной информационной базы аналогична структу- ре диалога создания новой информационной базы. После заполнения всех необходимых параметров платформа ЮПредприятия выполнит создание начального образа: ♦ будет создана новая информационная база с указанны- ми параметрами; ♦ конфигурация распределенной информационной базы будет перенесена во вновь созданную информацион- ную базу; ♦ будет выполнен перенос данных текущей информаци- онной базы во вновь созданную, при этом для каждого элемента данных будет вызвана процедура узла плана обмена с предопределенным именем ПриОтправкеДанных- Подчиненному (то есть будут перенесены только те дан- ные, которые входят в состав соответствующего плана обмена, с учетом всех ограничений, фильтров, которые определены в обработчике события ПриОтправкеДанных- Подчиненному); ♦ в новом узле распределенной информационной базы будут заполнены данные узла ЭтотУзел плана обмена данными узла данной информационной базы, для кото- рого создается начальный образ; ♦ в новом узле распределенной информационной базы будет создан узел, соответствующий данной инфор- мационной базе, и его данные также будут перенесены, после чего ссылка на этот узел будет установлена в ка- честве значения главного узла созданного узла распре- деленной информационной базы; ♦ будут удалены все записи о регистрации изменений для узла, начальный образ которого был только что создан. Создание начального образа из встроенного языка Процесс создания начального образа при помощи метода СоздатьНачальныйОбразО менеджера планов обмена анало- гичен интерактивной процедуре, за исключением того, что все параметры новой информационной базы, а также узел, для которого необходимо создать начальный образ, должны быть переданы в качестве параметров при вызове указанной процедуры (листинг 15.49). Листинг 15.49. Пример создания начального образа Узел = ПланыОбмена.Магазины.НайтиПоКоду("Оптовый”): ПланыОбмена.СоздатьНачальныйОбраз(Узел, СтрокаСоединения): В строковой переменной СтрокаСоединения указывается информационная база, в которой будет создан начальный образ подчиненного узла распределенной информацион-
ной базы. Информационная база для создания начально- го образа должна быть пустой или не должна существо- вать вовсе. Строка соединения является набором параметров, каждый из которых представляет собой фрагмент вида <Имя>=<Значение>, где имя <Имя> — имя параметра, а <3на- чение> — его значение. Фрагменты отделяются друг от друга символами «;». Если значение содержит пробель- ные символы, то оно должно быть заключено в двойные кавычки ("). Набор параметров определяется вариантом создаваемой информационной базы: файловый или клиент-серверный. Для файлового варианта определены следующие пара- метры: ♦ File — каталог, в котором размещается файл информа- ционной базы; ♦ Locale — язык (страна), который будет использован при создании информационной базы. Допустимые значе- ния такие же, как у параметра Форматная строка метода ФорматО. Параметр Locale задавать не обязательно. Если этот па- раметр не задан, то будут использованы региональные установки текущей информационной базы. Для клиент-серверного варианта определены следующие параметры: ♦ Srvr — имя сервера 1 (^Предприятия; ♦ Ref — имя информационной базы на сервере; ♦ SQLSrvr — имя SQL-сервера; ♦ SQLDB — имя SQL-базы данных; ♦ SQLUID — имя пользователя SQL; ♦ SQLPwd — пароль пользователя SQL. Если пароль для пользователя SQL не задан, то данный параметр можно не указывать; ♦ SQLYOffs — смещение дат, используемое для хранения дат в SQL Server. Может принимать значения 0 или 2000. Данный параметр задавать не обязательно. Если не задан, принимается значение 0; ♦ Locale — язык (страна), который будет использован при создании информационной базы. Допустимые значе- ния такие же, как у параметра Форматная строка метода ФорматО. Параметр Locale задавать не обязательно. Если не задан, то будут использованы региональные установ- ки текущей информационной базы. Создание узла из конфигурации Данный способ является альтернативным способом созда- ния нового узла распределенной информационной базы. Он может применяться в случаях, когда, например, нет необходимости в операции переноса данных (происходя- щего при создании начального образа) во вновь создавае- мую информационную базу. Во многом операции, кото- рые необходимо выполнить для создания нового узла распределенной информационной базы данным спосо- бом, совпадают с операциями, выполняемыми платфор- мой 1С:Предприятия при создании начального образа. Опишем данный способ подробнее: ♦ в информационной базе — узле распределенной инфор- мационной базы, для которой необходимо создать под- чиненный узел, создаем узел плана обмена, устанавли- ваем его код и заполняем все необходимые для него ре- квизиты. В случае если узел, для которого необходимо создать информационную базу, уже существует, дан- ный пункт можно пропустить; ♦ сохраняем конфигурацию данной информационной базы в файл; ♦ создаем пустую информационную базу там, где необходи- мо создание узла распределенной информационной базы; ♦ загружаем конфигурацию, созданную в пункте 2, во вновь созданную информационную базу; ♦ обновляем конфигурацию базы данных; ♦ в режиме 1 (^Предприятия заполняем данные узла Этот- Узел плана обмена данными, соответствующими дан- ным узла, для которого создается узел распределенной информационной базы, в исходной информационной базе (информационной базе главного узла). Коды ука- занных узлов должны совпадать; ♦ создаем узел плана обмена, который будет соответство- вать информационной базе главного узла, и заполняем его данными, соответствующими данным узла ЗтотУзел в исходной информационной базе. Коды указанных уз- лов должны совпадать; ♦ при помощи метода УстановитьГлавныйУзелО менеджера планов обмена устанавливаем в свойство ГлавныйУзел значение ссылки на узел, созданный в предыдущем пункте (листинг 15.50). Листинг 15.50. Установка главного узла ГлавныйУзел = ПланыОбмена.Магазины.НайтиПоКодуСЦентрОфис"); ПланыОбмена.УстановитьГлавныйУзел(ГлавныйУзел): После выполнения последнего пункта создание узла рас- пределенной информационной базы считается закон- ченным. Созданная информационная база может участ- вовать в обмене данными в рамках распределенной информационной базы. Стоит отметить, что в созданной таким образом инфор- мационной базе узла распределенной информационной базы полностью отсутствуют данные. Наполнение данны- ми узла распределенной информационной базы должно выполняться самостоятельно. Для этого можно восполь- зоваться непосредственно механизмом распределенной информационной базы: ♦ в информационной базе главного узла распределенной информационной базы выполнить регистрацию дан- ных, которые необходимо передать в новый узел (лис- тинг 15.51); ♦ выполнить процедуру обмена данными между главным узлом и созданным узлом распределенной информаци- онной базы. Листинг 15.51. Пример регистрации изменений данных для узла Узел = ПланыОбмена.Магазины.НайтиПоКодуС"Магазин"): ПланыОбмена.ЗарегистрироватьИзменения(Узел, Неопределено): Создание узла из копии информационной базы Под копией информационной базы в данном случае мож- но понимать тем или иным способом полученный экзем- пляр информационной базы, полностью идентичный
оригиналу. Так как конфигурация копии информацион- ной базы идентична конфигурации оригинала, шаги, со- ответствующие синхронизации конфигураций, можно пропустить. Создание узла распределенной информаци- онной базы выполняется следующим образом: ♦ в оригинале информационной базы — узле распреде- ленной информационной базы, для которой необходимо создать подчиненный узел, создаем узел плана обмена, устанавливаем его код и заполняем все необходимые для него реквизиты. В случае если узел, для которого необходимо создать информационную базу, уже суще- ствует, данный пункт можно пропустить; ♦ в копии информационной базы удаляем все узлы соот- ветствующего плана обмена; ♦ создаем новый узел плана обмена путем копирования узла ЗтотУзел; ♦ заполняем данные узла ЗтотУзел значениями, аналогич- ными содержащимся в узле, созданном в первом пунк- те. Значение кодов узлов должны совпадать; ♦ изменяем код узла, созданного в пункте 3, на код узла ЗтотУзел информационной базы оригинала; ♦ при помощи метода УстановитьГлавныйУзелО менеджера планов обмена устанавливаем в свойство ГлавныйУзел значение ссылки на узел, созданный в пункте 3 (лис- тинг 15.52). Листинг 15.52. Установка главного узла ГлавныйУзел=Планы0бмена.Магазины.НайтиПоКодуС’ЦентрОфис"): ПланыОбмена.УстановитьГлав ныйУзел(ГлавныйУзел); После выполнения последнего пункта создание узла рас- пределенной информационной базы считается закончен- ным. Созданная информационная база может участвовать в обмене данными в рамках распределенной информаци- онной базы. Состав данных полученного узла распределенной инфор- мационной базы полностью соответствует составу дан- ных информационной базы оригинала (никакой фильт- рации данных согласно составу мигрирующих объектов и в процедуре ПриОтправкеДанныхПодчиненному произведено не было). Состав данных, необходимый для правильной ра- боты узла, должен быть скорректирован самостоятельно. Запись и чтение сообщений обмена Если план обмена используется в реализации механизма распределенных информационных баз, то в форме списка узлов данного плана обмена, в контекстном меню доступ- ны две команды по записи и чтению сообщения обмена (рис. 15.13). При выборе команды (например, записи изменений) от- крывается диалог, в котором указываются путь к файлу выгрузки, количество элементов данных, обрабатывае- мых в одной транзакции, и флаг Сжимать сообщение (XML- документ будет упакован в архив ZIP) (рис. 15.14). К недостатку данного метода следует отнести тот факт, что в данном случае нет возможности отследить оконча- ние как процесса выгрузки, так и процесса загрузки дан- ных из сообщения обмена. Рис. 15.13. Интерактивная запись и чтение изменений Запись сообщения с изменениями. Узел Оптовое подразделение X Имя Файла сообщения |СА)Ме$$аде ЦентрОфис Рптовое.г1р ~Н Количество з лемектов данных, •< в одной транзакции: | 1 ОООДЙ Сжимать сообщение 0 f |'От - Рис. 15.14. Диалог записи сообщения обмена Аналогичное действие можно реализовать и самостоя- тельно, используя для записи следующий фрагмент кода (листинг 15.53). Листинг 15.53. Пример записи сообщения обмена ЗаписьХМ!.. ОткрытьФайл("с: \out. xml"); ЗаписьХМС. ЗаписатьОбъявлениеХМСО; // Создаем новое сообщение Узел = ПланыОбмена.Магазины.НайтиПоКоду("Магазин"); ЗаписьСообщения = ПланыОбмена. СоздатьЗаписьСообщенияО; ЗаписьСообщения.НачатьЗапись(ЗаписьХМС, Узел); // Пишем изменения ПланыОбмена.ЗаписатьИзменения(ЗаписьСообщения, 1000); ЗаписьСообщения.ЗакончитьЗапись(); ЗаписьХМС.Закрыть!); Пример чтения сообщения обмена приведен в листин- ге 15.54. Листинг 15.54. Пример чтения сообщения обмена // Создаем объект чтения ХМС ЧтениеХМС = Новый ЧтениеХМС; ЧтениеХМС.ОткрытьФайл("с:\оиС.хт1''); // Загрузка из найденного файла ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщенияО; ЧтениеСообщения.НачатьЧтение(ЧтениеХМС); // Читаем изменения ПланыОбмена.ПрочитатьИзиенения(ЧтениеСообщения,1000); ЧтениеСообщения .ЗакончитьЧтениеО; ЧтениеХМС.Закрыть(); Данный подход позволяет отследить момент окончания процесса загрузки/выгрузки и при необходимости вы- полнить какие-либо действия. При необходимости производить упаковку полученного файла сообщений (или извлечение сообщения из архива) можно воспользоваться функциональностью платформы по работе с ZIP-архивами, рассмотренной в разделе «Ра- бота с ZIP-архивами», с. 548.
Подготовка конфигурации к работе в распределенной информационной базе Конфигурация, разработанная для обычной информа- ционной базы, в большинстве случаев требует адапта- ции для работы в распределенной информационной базе. В этом разделе мы рассмотрим основные методы адапта- ции конфигурации к работе в распределенной информа- ционной базе. Описанные методы не являются исчер- пывающими, ими можно ограничиться, в случае когда необходимо обеспечить простой обмен данными. Например, разделение на два офиса с полным дублирова- нием информации в них. Если же требуется реализация специфической схемы обмена, то может потребоваться реализация сложной архитектуры распределенного реше- ния, влекущая за собой серьезную переработку конфи- гурации. Предположим, разрабатывается схема обмена, в которой данные из организаций холдинга должны пере- даваться в центральную информационную базу в виде сводных данных за определенный период. В этом случае требуется реализация в конфигурации соответствующих объектов для хранения детальной и сводной информа- ции. Одной из особенностей работы в модели распределенной информационной базы является возможность создания в различных узлах объектов (документов, элементов спра- вочника, видов характеристик и т. д.), обладающих оди- наковыми номерами (кодами). Это может привести к воз- никновению в одной информационной базе объектов с одинаковыми номерами (кодами) и привести к опреде- ленным проблемам. Дело в том, что синхронизация объектов ведется по уни- кальному идентификатору. При создании объекта двух и более в различных информационных базах можно опре- делить у них одинаковые значения реквизитов, одинако- вые наборы данных в табличных частях, но при этом зна- чения уникальных идентификаторов (если механизм назначения уникальных идентификаторов не менялся раз- работчиком конфигурации) у них разные. В процессе за- грузки такие объекты будут считаться разными. И в этих случаях для справочника могут создаться элементы с одинаковым кодом, для документов, могут создаться эк- земпляры с одинаковым номером в определенном перио- де и т. д. В случае когда назначение номера (кода) выполняется системой автоматически, для подобных объектов необхо- димо ввести префиксацию, идентифицирующую место создание объекта. Для объектов, чьи номера (коды) уста- навливаются вручную, подобной префиксации реализо- вывать не нужно (например: коды счетов назначаются пользователями вручную, добавление префикса для них является неправильным). Для объектов, требующих на- личия префикса в номере (коде), необходимо: ♦ установить тип номера (кода) в значение Строка; ♦ добавить в конфигурацию объект метаданных Константа, в котором будет установлено значение префикса номе- ра (кода), однозначно идентифицирующее данный узел распределенной информационной базы (значение кон- станты должно быть уникальным среди всех узлов рас- пределенной информационной базы, сама константа не должна быть включена в состав плана обмена, на базе которого развернута распределенная информационная база); ♦ реализовать в модулях объектов предопределенные про- цедуры, выполняемые при установке номера (кода), — ПриУстановкеНовогоНомера (ПриУстановкеНовогоКода) (реали- зация должна использовать в качестве значения пре- фикса значение описанной ранее константы) (лис- тинг 15.55). Листинг 15.55. Пример назначения префикса Процедура ПриУстановкеНовогоКода(СтандартнаяОбработка. Префикс) Префикс = Константы.ПрефиксНоиеров.ПолучитьО: КонецПроцедуры Работа конфигурации в распределенной информацион- ной базе подразумевает обмен данными между узлами распределенной информационной базы. В процессе обме- на порядок следования данных в сообщениях обмена не определен. При чтении данных могут возникать ситуа- ции, при которых считанные данные ссылаются на несу- ществующие (возможно еще не загруженные) данные. При записи считанных данных в информационную базу необходимо учесть возможность наличия неразрешенных ссылок в записываемых данных. Для этого в предопреде- ленных процедурах ПередЗаписью, ПриЗаписи и ПередУдалени- ен необходимо учитывать свойство Загрузка: при записи данных средствами механизма распределенной информа- ционной базы данное свойство будет установлено в зна- чение Истина. В указанных процедурах в режиме Загрузка не следует выполнять различные проверки, связанные с наличием тех или иных данных, участвующих в обмене (например, регистратор записываемого набора записей регистра накопления может быть еще не прочитан из со- общения обмена), не рекомендуется также выполнять из- менение связанных данных. В данном режиме рекомендуется дать возможность сис- теме записать прочитанные данные. Контроль допусти- мости данных для данного узла распределенной информа- ционной базы может быть осуществлен в соответствующих обработчиках, вызываемых при чтении сообщения обме- на (ПриПолученииДанныхОтПодчиненного, ПриПолученииДанныхОт- Главного). Особое внимание следует уделить регистрам сведений, имеющим независимый режим записи (свойство Режим за- писи установлено в значение Независимый). Для данных ре- гистров гранулой обмена является набор записей с отбо- ром по измерениям, с установленным свойством Основной отбор. Необходимо проанализировать, будет ли соответст- вовать состав передаваемой информации логике работы конфигурации. Например, в регистре сведений хранится информация о характеристиках товаров. В основной отбор включены измерения: ♦ Характеристика (идентифицирующее характеристику то- вара); ♦ Товар (определяющее собственно товар). По логике работы конфигурации важно обеспечить цело- стность редактирования характеристик товара — состав
характеристик товара должен редактироваться целиком. Считаем, что ситуация, когда в одном узле исправляется одна характеристика, а в другом — другая и через некото- рое время (после обмена данными) в характеристиках произошло объединение исправлений, является недопус- тимой. В данном случае (когда все измерения регистра сведений входят в основной отбор) гранулой обмена данными вы- ступает одна запись регистра сведений. И это может при- вести к ситуации, при которой состав характеристик товара будет состоять из различных характеристик, полу- ченных из разных узлов распределенной информационной базы (мы можем считать эту ситуацию недопустимой). Для устранения подобных проблем следует внести кор- рективы в набор измерений, входящих в основной отбор регистра: исключить из основного отбора измерение, вно- сящее излишнюю гранулярность (характеристику из приведенного примера). Это позволит в процессе обмена передавать наборы записей, содержащие информацию, которая полностью соответствует логике работы конфи- гурации (все характеристики номенклатурной позиции являются логической единицей обмена). Выполнение этих рекомендаций позволяет просто на- строить обмен данными в рамках распределенной инфор- мационной базы, дальнейшая адаптация конфигурации зависит от конкретной специфики обмена. Сценарии обмена данными в распределенной информационной базе Обработчики событий ПриОтправкеДанныхПодчиненному, ПриОт- правкеДанныхГлавному, ПриПолученииДанныхОтПодчиненного, ПриПо- лученииДанныхОтГлавного, позволяют достаточно гибко управ- лять обменом данными в распределенной информационной базе. С использованием этих обработчиков может быть по- строено большое разнообразие сценариев обмена данными. В этом разделе в качестве примера будет рассмотрена орга- низация нескольких сценариев. Поведение по умолчанию Данный сценарий является наиболее простым и соответ- ствует поведению распределенной информационной базы по умолчанию. Для этого сценария характерно следующее: ♦ каждое изменение элемента данных, произведенное в любом из узлов распределенной информационной базы, стремится распространиться по всем узлам; ♦ разрешение коллизий производится на основании от- ношения узлов «главный-подчиненный». Для реализации такого сценария все обработчики не должны изменять значения переданных им параметров, или же обработчики могут быть не определены вовсе. Распределение данных по подчиненным узлам Данный сценарий подразумевает, что для некоторых эле- ментов данных, для которых он реализуется, выполняет- ся следующее: ♦ вся совокупность элементов данных присутствует в глав- ном узле; ♦ присутствие того или иного элемента данных в том или ином подчиненном узле определяется на основе срав- нения значений некоторых реквизитов элемента дан- ных с реквизитами подчиненного узла плана обмена; ♦ разрешение коллизий производится на основании от- ношения узлов «главный-подчиненный». Для реализации данного сценария надо обеспечить, что- бы при записи сообщения обмена данными в главном узле в сообщение не попадали элементы данных, которые не должны присутствовать в подчиненном узле. Кроме того, если значения реквизитов элемента данных могут быть изменены в подчиненном узле, то необходимо обеспечить, чтобы при получении сообщения обмена дан- ными в главном узле производилась регистрация измене- ний для тех объектов, которых в соответствии со зна- чениями их реквизитов в подчиненном узле быть не должно. Для более детального рассмотрения примера предполо- жим, что в качестве типа элементов данных, для которых реализуется сценарий, выступает документ РасходнаяНа- кладная. У данного документа имеется реквизит Склад типа СправочникСсылка.Склады. Обмен данными организо- ван в соответствии с планом обмена Склады. У этого плана обмена также определен реквизит Склад типа Справочник- Ссылка . Склады. В соответствии с этим планом обмена орга- низована распределенная информационная база, в кото- рой корневым узлом является центральный офис, а его подчиненными узлами — склады. У каждого из под- чиненных узлов плана обмена значение реквизита Склад установлено так, чтобы обозначать, какому складу соот- ветствует этот узел. Все документы РасходнаяНакладная должны присутствовать в корневом узле, а условием при- сутствия документов в подчиненных узлах является ра- венство значений реквизитов Склад в документе и узле плана обмена. В этом случае для того, чтобы документы РасходнаяНаклад- ная не попадали в те подчиненные узлы, куда они попадать не должны, обработчик события ПриОтправкеДанныхПодчинен- ному должен иметь следующий вид (листинг 15.56). Листинг 15.56. Процедура ПриОтправкеДанныхПодчиненному Процедура ПриОтправкеДанныхПодчиненномуОлементДанных, ОтправкаЭлемента) ТипДанных = ТипЗнч(ЭлементДанных); Если ТипДанных = ТипСДокументОбъект.РасходнаяНакладная") Тогда Если ЭлементДанных.Склад о Склад Тогда ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить; КонецЕсли; КонецЕсли; КонецПроцедуры В приведенном примере обработчика анализируется тип элемента данных, и если он равен ДокументОбъект.Расход- наяНакладная, то значение реквизита Склад документа срав- нивается со значением реквизита Склад узла плана обмена. Если значения реквизитов равны, то значение параметра ОтправкаЭлемента можно не изменять (при вызове пара- метр имеет значение Авто), При этом в сообщение будет
помещено XML-представление документа. Если же зна- чения реквизитов не равны, то параметру ОтправкаЭлемента присваивается значение Удалить. В этом случае в сообще- ние будет помещено XML-представление объекта Удале- ниеОбъекта, проинициализированного ссылкой на соответ- ствующий документ РасходнаяНакладная. Может показаться странным, что в случае неравенства значений реквизитов Склад, параметру ОтправкаЭлемента присваивается значение Удалить, а не Игнорировать, так как в случае значения Удалить XML-представление объекта УдалениеОбъекта будет помещаться в сообщения, отправ- ляемые всем подчиненным узлам, кроме того узла, в ко- торый будет отправлен сам документ. Таким образом, в значительной части случаев УдалениеОбъекта будет от- правлено тем узлам, где документа, который требуется удалить, никогда не было. Это действительно так, но в данном примере рассмотрен наиболее общий случай. Если же, например, известно, что значение реквизита Склад документа РасходнаяНакладная может быть установ- лено только при создании документа и в дальнейшем не может быть изменено, то параметру ОтправкаЭлемента в данном обработчике действительно могло бы быть при- своено значение Игнорировать. Если же значение реквизита Склад документа Расходная- Накладная может быть изменено в подчиненном узле, то в плане обмена необходимо определить обработчик события ПриПолученииДанныхОтПодчиненного следующего вида (лис- тинг 15.57). Листинг 15.57. Процедура ПриПолученииДанныхОтПодчиненного Процедура ПриПолученииДанныхОтПодчиненногоСЭлементДанных, ПолучениеЭлемента. ОтправкаНазад) ТипДанных = ТипЗнч(ЭлементДанных); Если ТипДанных = ТипС'ДокументОбъект.РасходнаяНакладная") Тогда Если ЭлементДанных.Склад <> Склад Тогда ОтправкаНазад = Истина; КонецЕсли; КонецЕсли; КонецПроцедуры В приведенном примере обработчика анализируется тип элемента данных, и если он равен ДокументОбъект.Расход- наяНакладная, то значение реквизита Склад документа срав- нивается со значением реквизита Склад узла плана обмена. Если значения реквизитов равны, то значения парамет- ров ПолучениеЭлемента и ОтправкаНазад можно не изменять, обеспечив этим поведение по умолчанию при приеме эле- мента данных. Если же значения реквизитов не равны, то параметру ОтправкаНазад присваивается значение Истина. Тем самым гарантируется, что изменения документа бу- дут зарегистрированы и при отправке сообщения под- чиненному узлу будет отправлено УдалениеОбъекта, если, конечно, реквизит Склад документа не будет изменен в главном узле так, что он окажется равен значению рекви- зита Склад соответствующего узла плана обмена. Если же значение реквизита Склад документа Расходная- Накладная не может быть изменено после создания доку- мента, то обработчик ПриПолученииДанныхОтПодчиненного мож- но не определять. Разрешение коллизий На основе отношения «главный-подчиненный» в распре- деленной информационной базе организована типовая процедура разрешения коллизий, автоматически выпол- няемая при приеме сообщения. Считается, что изменение элемента данных, произведенное в главном узле имеет высший приоритет по отношению к изменению, произве- денному в подчиненном узле. Таким образом, если сооб- щение, пришедшее от подчиненного узла, содержит эле- мент данных, изменения которого зарегистрированы для этого подчиненного узла, то никаких действий предпри- нято не будет, то есть этот элемент данных не будет поме- щен в базу данных и запись регистрации изменений не будет удалена. Если сообщение, пришедшее от главного узла, содержит элемент данных, изменения которого зарегистрированы для главного узла, то элемент данных будет записан в базу данных, а запись регистрация изменения будет уда- лена. В случае если данный сценарий не устраивает, можно реализовать прямо противоположный (принимаются из- менения из нижестоящей базы). Данный сценарий подразумевает, что для некоторых эле- ментов данных, для которых он реализуется, выполняет- ся следующее: ♦ каждое изменение элемента данных, произведенное в любом из узлов распределенной информационной базы, стремится распространиться по всем узлам; ♦ разрешение коллизий производится на основании от- ношения узлов «главный-подчиненный», но более вы- сокий приоритет имеет подчиненный узел. Для рассмотрения данного случая воспользуемся рас- смотренным выше примером с документом РасходнаяНак- ладная и планом обмена Склады. В данном случае требуется определить обработчики со- бытий ПриПолученииДанныхОтПодчиненного и ПриПолученииДан- ныхОтГлавного. Обработчик ПриПолученииДанныхОтПодчиненно- го будет иметь следующий вид (листинг 15.58). Листинг 15.58. Процедура ПриПолученииДанныхОтПодчиненного Процедура ПриПолученииДанныхОтПодчиненногоОлеиентДанных, ПолучениеЭлемента, ОтправкаНазад) ТипДанных = ТипЗнч(ЭлементДанных); Если ТипДанных = Тип("ДокументОбъект.РасходнаяНакладная") Тогда ПолучениеЭлемента = ПолучениеЭлементаДанных.Принять; КонецЕсли; КонецПроцедуры Приведенный обработчик весьма прост: проверяется тип элемента данных, и если элемент данных относится к ин- тересующему нас типу, то параметру ПолучениеЭлемента присваивается значение Принять, что приводит к безуслов- ному приему элемента данных, независимо от того, заре- гистрированы его изменения или нет. Обработчик события ПриПолученииДанныхОтГлавного выгля- дит следующим образом (листинг 15.59).
Листинг 15.59. Процедура ПриПолученииДанныхОтГлавного Процедура ПриПолученииДанныхОтГлавногоОлементДанных, ПолучениеЭлемента, ОтправкаНазад) ТипДанных = ТипЗнч(ЭлеиентДанных); Если ТипДанных = Тип("ДокументОбъект.РасходнаяНакладная") Тогда Если ПланыОбмена.ИзменениеЗарегистрированоССсылка, ЭлеиентДанных) Тогда ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать; КонецЕсли КонецЕсли; КонецПроцедуры Этот обработчик несколько сложнее. Если элемент данных относится к интересующему нас типу, то производится про- верка: зарегистрированы ли изменения элемента данных для узла-отправителя сообщения. Если изменения зарегистри- рованы, то параметру ПолучениеЭлемента присваивается зна- чение Игнорировать. В результате прочитанный элемент данных не записывается в базу данных, а регистрация из- менений сохраняется, что позволит поместить элемент данных в сообщение, отправляемое главному узлу. Восстановление узла распределенной информационной базы из резервной копии В случае возникновения ситуации, при которой необхо- димо восстановить резервную копию информационной базы, работающую в рамках распределенной информаци- онной базы, можно воспользоваться следующими реко- мендациями. Процедура восстановления информационной базы корневого узла Напомним, что корневым узлом считается информацион- ная база, у которой свойство ГлавныйУзел содержит значение Неопределено. Восстановление корневого узла сводится к восстановлению резервной копии информационной базы. После восстановления информационной базы корневого узла необходимо восстановить обмен данными в распре- деленной информационной базе. Для этого, над всеми ин- формационными базами — узлами распределенной ин- формационной базы — необходимо выполнить действия, аналогичные рекомендуемым при восстановлении ин- формационной базы подчиненного узла. Процедура восстановления информационной базы подчиненного узла Процедуру восстановления информационной базы под- чиненного узла можно разделить на несколько этапов: ♦ восстановление в информационной базе подчиненного узла конфигурации главного узла: ♦ отключение от распределенной информационной базы (осуществляется путем установки свойству ГлавныйУзел значения Неопределено) — ПланыОбмена.УстановитьГлавный- Узел(Неопределено); ♦ загрузка конфигурации главного узла (для восстанов- ления работы в распределенной информационной базе необходимо полное соответствие конфигураций глав- ного и подчиненного узлов). Для выполнения этого условия необходимо загрузить конфигурацию (из фай- ла *.cf), полученную из главного узла, в информацион- ную базу подчиненного узла (режим объединения кон- фигураций в данном случае использовать нельзя); ♦ синхронизация номеров сообщений между главным и подчиненным узлами. Для правильного обмена сооб- щениями в распределенной информационной базе не- обходимо, чтобы соблюдалось условие: номер при- нимаемого сообщения должен быть больше номера, записанного в реквизите НомерПринятого узла, соответст- вующего информационной базе — источнику сообще- ния. Номер сообщения получается путем добавления единицы к номеру последнего принятого сообщения (значение реквизита НомерОтправленного узла, соответст- вующего информационной базе — приемнику сообще- ния); ♦ подключение к распределенной информационной базе. Для подключения информационной базы подчиненно- го узла обратно в распределенную информационную базу необходимо установить свойству ГлавныйУзел преж- нее значение (листинг 15.60). Листинг 15.60. Установка свойства ГлавныйУзел ГлавныйУзел = ПланыОбмена.УдаленныеСклады.НайтиПоКоду("ЦентрОфис”): ПланыОбмена.УстановитьГлавныйУзел(ГлавныйУзел); ♦ синхронизация данных главного и подчиненного узлов. Синхронизация данных может выполняться в обе сто- роны: от главного узла в подчиненный и от подчинен- ного узла в главный. В обоих случаях достаточно лишь выполнить регистрацию требуемых данных в службе регистрации изменений (для этого можно воспользо- ваться соответствующим методом менеджера плана об- мена) (листинг 15.61). Листинг 15.61. Регистрация изменений для узла Узел = ПланыОбмена.УдаленныеСклады.НайтиПоКоду("Оптовый"): ПланыОбмена.ЗарегистрироватьИзменения(Узел. Неопределено): После выполнения описанных действий работа распре- деленной информационной базы может продолжаться в обычном режиме. Особенности использования последовательности документов в распределенной ИБ Для отслеживания правильного порядка проведения документов в 1 С: Предприятии служит механизм после-
довательностей документов. Этот механизм позволяет отслеживать порядок проведения документов и про- изводить восстановление этого порядка. Для того чтобы документ оказался в последовательности он должен заре- гистрироваться в последовательности, тогда механизм последовательностей будет учитывать его при своей ра- боте. При организации работы последовательности докумен- тов в распределенной информационной базе нужно учи- тывать, что участие документа в последовательности имеет смысл только в одном узле распределенной информаци- онной базы. Это может быть либо узел, в котором доку- мент был создан, либо другой узел, но узел должен быть один. Нарушение данного принципа может привести к различным проблемам в процессе работы с системой, на- пример, невозможности восстановления последователь- ности документов. Таким образом, документ, участвующий в последователь- ности, должен регистрироваться в последовательности только в одном узле информационной базы. Для этого до- кумент должен содержать информацию, по которой на момент записи документа можно сделать вывод, должен ли он в данном узле регистрироваться или нет. Для того чтобы документ мог это определить, все узлы информаци- онной базы должны иметь уникальную идентификацию. Например, документ может содержать реквизит, в качест- ве значения которого содержится код узла плана обмена его информационной базы. Коды узлов информационных баз должны быть в этом случае уникальными. Этого мож- но добиться организационными методами. Основываясь на информации принадлежности данному узлу распреде- ленной информационной базы, документ должен при за- писи либо очистить набор записей регистрации в после- довательности, либо наоборот его заполнить. Тем самым будет достигнута цель регистрации документа в последова- тельности только в собственном узле информационной базы. Пример очистки наборов записей в последовательностях (фрагмент кода размещается в обработке проведения до- кумента) приведен в листинге 15.62. Листинг 15.62. Пример очистки набора записей регистрации документа в последовательности Если Узел<>Планы0бмена.Расходные.ЭтотУзелО.Код Тогда Для Каждого НаборПоследовательности Из ПринадлежностьПоследовательностям Цикл НаборПоследовательности.Очистить(); КонецЦикла; КонецЕсли; Узел — реквизит документа, содержащий код узла, в кото- ром он должен регистрироваться в последовательностях. Как уже было сказано, документ может участвовать в по- следовательности только в одном узле информационной базы. Поэтому сами последовательности документов не должны участвовать в обмене данных. Иначе записи ре- гистрации документа будут переданы в другой узел ин- формационной базы, тем самым нарушив принцип реги- страции документа в последовательности только в одном узле информационной базы. Использование транзакций при организации обмена При реализации обмена как посредством универсального механизма обмена, так и с использованием механизма распределенных информационных баз одна из задач, ко- торые требуют решения, это обеспечение целостности и согласованности данных. Данная задача при использовании универсального обме- на может решаться с использованием транзакций (лис- тинг 15.63). Листинг 15.63. Пример использования транзакций НачатьТранзакциюО; // обработка данных ЗафиксироватьТранзакциюО; При выгрузке данных в механизме распределенных ин- формационных баз используется метод ЗаписатьИзмене- нияО менеджера планов обмена (листинг 15.64). Листинг 15.64. Пример использования метода ЗаписатьИзмененияО ПланыОбмена.ЗаписатьИзмененияСЗаписьСообщения. 0); Второй параметр метода указывает количество элемен- тов, записываемых в одной транзакции. Значение 0 ука- зывает на то, что запись всех изменений производится в одной транзакции. Такой подход (когда вся выгрузка или загрузка осущест- вляется в одной транзакции) обладает как определенны- ми преимуществами, так и определенными недостатками. Преимущества такого подхода заключаются в том, что, например, в файловом варианте работы действия, сгруп- пированные в одну транзакцию, выполняются значитель- но быстрее (до определенного предела). Кроме этого, при выгрузке данных использование одной транзакции по- зволяет избежать несогласованности выгружаемых дан- ных (например, когда после выгрузки документа, но до выгрузки наборов записей регистров, произошло пере- проведение документа). Минусами такого подхода является снижение параллель- ности работы пользователей, так как выгружаемые дан- ные будут заблокированы до окончания транзакции. Кроме этого, необходимо учитывать объем изменений, выполняемых в одной транзакции. Например, в файло- вом варианте все изменения, произведенные транзакци- ей, накапливаются в оперативной памяти, что при записи больших объемов данных может привести к исчерпыва- нию свободной памяти. В клиент-серверном варианте такой опасности нет, но все-таки записывать большие объемы данных в одной транзакции не рекомендуется (из-за проблем параллель- ности блокировки тоже требуют ресурса сервера баз дан- ных и т. п.).
При обмене большими порциями данных имеет смысл использовать несколько транзакций при загрузке или вы- грузке данных. Например, в алгоритме загрузки данных можно исполь- зовать следующий фрагмент кода, позволяющий разби- вать процесс загрузки на несколько транзакций по 1000 элементов данных (в данном случае величина 1000 — условная) (листинг 15.65). В случаях использования механизма распределенных информационных баз, количество объектов указывается вторым параметром метода ЗаписатьИзмененияО (лис- тинг 15.66). Следует отметить, что зачастую, в каждом конкретном случае необходимо искать компромисс между скоростью и параллельностью работы пользователей. Листинг 15.65. Пример использования нескольких транзакций при выгрузке данных Счетчик = 0; НачатьТранзакциюС); // обработка данных Если Счетчик = 1000 Тогда Счетчик = 0: ЗафиксироватьТранзакциюО; НачатьТранзакциюС): КонецЕсли; // обработка данных ЗафиксироватьТранзакциюС); Листинг 15.66. Пример указания количества элементов, записываемых в одной транзакции ПланыОбмена.ЗаписатьИзмененияСЗаписьСообщения, 1000); Методика включения в сообщение обмена дополнительной информации В некоторых случаях обмен данными должен сопровож- даться передачей в сообщении обмена служебной допол- нительной информацией. Передачу подобной инфор- мации можно осуществлять непосредственно в теле сооб- щения обмена. Дополнительную информацию можно размещать в теле сообщения, как при реализации универ- сального обмена, так и в случае работы с распределенны- ми информационными базами. При универсальном обмене это делается довольно про- сто. При выгрузке данных (в любой момент: в начале со- общения, в середине, в конце) можно записать в тело со- общения специализированный элемент XML (с нужным наполнением) (листинг 15.67). При чтении необходимо предусмотреть возможность чте- ния данного специализированного узла (листинг 15.68). При необходимости указания дополнительных данных при работе с распределенной информационной базой мож- но использовать следующий подход (листинг 15.69). Листинг 15.67. Пример записи служебной информации ЗаписьХМЕ.ЗаписатьНачалоЭлементаС"i nfo"): ЗаписьХМЕ.ЗаписатьАтрибутС"содержание", "Дополнительная информация"); ЗаписьХМЕ.ЗаписатьТекст("передаваемая информация"); ЗаписьХМЕ.ЗаписатьКонецЭлемента(); Листинг 15.68. Пример чтения служебной информации Если ЧтениеХМЕ.Имя="info” Тогда // Читаем текст xml - элемента ЧтениеХМЕ.Прочитать О; // Читаем конец элемента info ЧтениеХМЕ.Прочитать(); // Позиционируемся на начале элемента v8de:Changes ЧтениеХМЕ.Прочитать(); КонецЕсли; Листинг 15.69. Пример передачи дополнительной информации в сообщении распределенной информационной базы // Создаем объект записи XML ЗаписьХМЕ = Новый ЗаписьХМЕ; ЗаписьХМЕ.ОткрытьФайл("c:\out.xml"); ЗаписьХМЕ. ЗаписатьОбъявлениеХМЕО; // Создаем новое сообщение Узел=Планы0бмена.Магазины.НайтиПоКодуС"Магазин"); ЗаписьСообщения = ПланыОбмена. СоздатьЗаписьСообщенияО; ЗаписьСообщения.НачатьЗаписьСЗаписьХМЕ, Узел); //Пишем дополнительную информацию ЗаписьХМЕ.ЗаписатьНачалоЭлементаС"info”); ЗаписьХМЕ.ЗаписатьАтрибутС"содержание", "Код"); ВключитьСтроку=" |Событие=Документы.Событие.СоздатьДокумент(); |Событие.Дата=РабочаяДата; |Событие.0писаниеСобытия=""Сформировать внутренние заказы'"’; |//заполнение других реквизитов документа |Событие.Записать(); ”; ЗаписьХМЕ.ЗаписатьТекст(ВключитьСтроку); ЗаписьХМЕ.ЗаписатьКонецЭлемента(); //Пишем изменения ПланыОбмена.ЗаписатьИзменения(ЗаписьСообщения, 0); ЗаписьСообщения.ЗакончитьЗапись(); ЗаписьХМЕ.Закрытье); В результате выполнения получаем следующее сообще- ние (приведен начальный фрагмент) (листинг 15.70). Листинг 15.70. Фрагмент сообщения обмена <?xml version="1.0"?> <v8msg:Message xml ns:v8msg=”http://v8.lc.ru/messages"> <v8msg:Header> <v8msg:ExchangePlan>Mara3MHbi</v8msg:ExchangePlan> <v8msg;To>Mara3HH</v8msg:To> <v8msg:Егот>Центр0фис</у8т5д:From> <v8msg:MessageNo>l</v8msg:MessageNo> <v8msg:Recei vedNo>0</v8msg:Recei vedNo> </v8msg:Header>
<v8msg:Body xml ns: xsd="http: //мм. w3. org/2001/XMLSchema" xmlns:xs1="http://www.w3.org/2001/XMLSchema-i nstance" xmlns:v8="http://v8.lc.ru/data"> <info содержание="Код"> Событие=Документы.Событие.СоздатьДокумент(); Событие.Дата=РабочаяДата: Событие.ОписаниеСобытия= "Сфориировать внутренние заказы"; //заполнение других реквизитов документа Событие.ЗаписатьО; "; </info> <v8de:Changes xmlns:v8de=“http://v8.lc.ru/dataexchange/2005/02"> <v8de:S1gnature> 033clfla-8430-40bb-93fb-44b68fec09b6 </v8de:Signature> Чтение сообщения обмена, содержащего дополнитель- ную информацию, может быть выполнено так, как пока- зано в листинге 15.71 Листинг 15.71. Пример чтения сообщения обмена // Создаем объект чтения XML ЧтениеХМС = Новый ЧтениеХМС; ЧтениеХМС.ОткрытьФайл("с:\out.xml"): // Загрузка из найденного файла ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщенияО: ЧтениеСообщения.НачатьЧтение(ЧтениеХМС); // Читаем текст элемента xml ЧтениеХМС.Прочитать(); // Читаем конец элемента info ЧтениеХМС.Прочитать О; // Позиционируемся на начале элемента v8de:Changes ЧтениеХМС.Прочитать(); // Читаем изменения ПланыОбмена.ПрочитатьИз менения(ЧтениеСообщения); ЧтениеСообщения.ЗакончитьЧтениеС); ЧтениеХМС.Закрыть(): Обращаем ваше внимание на тот факт, что после начала чтения сообщения объект ЧтениеХМС уже позиционирован на начале элемента info (можно сразу производить выбор- ку атрибутов элемента). Следует отметить, что алгоритм как записи, так и чтения (в обоих вариантах обмена) зависит от структуры эле- мента, специализирующегося на «переносе» дополни- тельной информации. Организация одностороннего обмена В некоторых случаях нет необходимости организовывать полноценный обмен данными между двумя узлами — достаточно передавать данные в одном направлении (по- добная задача может возникнуть как при организации универсального обмена, так и в контексте распределен- ной информационной базы). Однако для правильного функционирования механизмов обмена и инфраструкту- ры сообщений в частности, необходимо получение ответ- ных сообщений — сообщений, содержащих квитанции о доставке данных. Все механизмы по реализации одностороннего обмена можно разбить на две большие группы: ♦ без ответных квитанций; ♦ с ответными сообщениями, содержащими только кви- танции. Для реализации одностороннего обмена без необходимо- сти получения ответных сообщений можно воспользо- ваться схемой обмена с гарантированной доставкой. Суть этой схемы в следующем: после формирования сообще- ния обмена производится удаление регистрации измене- ний. Этим действием подтверждается, что данные (запи- санные в только что сформированное сообщение) будут гарантированно доставлены адресату (листинг 15.72). Листинг 15.72. Пример удаления регистрации изменений Узел = ПланыОбмена.Магазины.НамтиПоКоду("Магазин"); ПланыОбмена.УдалитьРегистрациюИзменений(Узел); В случае если данный механизм используется в распреде- ленных базах данных, следует помнить, что метод Уда- литьРегистрациюИзмененийО, не очищает изменения, связан- ные со структурой конфигурации. То есть если конфигурация изменяется (и используется распределен- ная информационная база), отказаться от передачи ответ- ных квитанций не получится. Если рассматривать схемы, связанные с передачей ответ- ного сообщения (содержащего только квитанцию), то можно выделить следующие варианты решения: ♦ отсутствие регистрации изменений данных в информа- ционной базе, выступающей в роли узла-приемника, — сообщение обмена содержит только квитанцию о дос- тавке (данный вариант доступен только при реализа- ции универсального обмена); ♦ фильтрация выгружаемых данных из информационной базы, выступающей в роли узла-приемника, — сообще- ние обмена содержит только квитанцию о доставке (ре- комендуется в случае использования распределенных информационных баз, так как остается необходимость получать изменения метаданных) (листинг 15.73); Листинг 15.73. Процедура ПриОтправкеДанныхПодчиненному // В зависимости от направления можно использовать либо // событие ПриОтправкеДанныхПодчиненному. либо // ПриОтправкеДанныхГлавному Процедура ПриОтправкеДанныхПодчиненномуОлементДанных, ОтправкаЭлемента) ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить; КонецПроцедуры ♦ данные просто не включаются в сообщение (можно использовать в распределенных информационных ба- зах, для уведомления о приеме изменений конфигу- рации, в случае если в источнике используется при- нудительная очистка таблиц регистрации изменений) (листинг 15.74). В результате в файл обмена включает- ся только заголовок сообщения (листинг 15.75).
♦ фильтрация принимаемых данных от информацион- ной базы, выступающей в роли узла-приемника, - при приеме отрабатывается только квитанции о дос- тавке. Листинг 15.74. Пример записи сообщения обмена ЗаписьХМЕ = Новый ЗаписьХМЕ; ЗаписьХМЕ.ОткрытьФайл("с: \out. xml ’’); ЗаписьХМ!-. ЗаписатьОбъявлениеХМЕС); // Создаем новое сообщение Узел=Планы0бмена.Магазины.НайтиПоКодуС"Магазин"); ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщенияО; ЗаписьСообщения.НачатьЗапись(ЗаписьХМЕ, Узел): ЗаписьСообщения .ЗакончитьЗаписьО; ЗаписьХМС.Закрытье); Последний вариант является наименее предпочтитель- ным, так как предполагает передачу фактически ненуж- ных данных. Листинг 15.75. Фрагмент сообщения обмена «?xml version="1.0"?> «v8msg:Message xml ns:v8msg="http://v8.lc.ru/messages"> «v8msg:Header» «v8msg: ExchangePl an>Mar аз MHbi</v8msg: ExchangePl an> «v8msg:To>Mar a3HH«/v8msg:To» «v8msg: From»L|eHTpO<|)HC«/v8msg: From> «v8msg: MessageNo»6«/v8msg: MessageNo» «v8msg:ReceivedNo»0«/v8msg:ReceivedNo» «/v8msg:Header» <v8msg:Body/> </v8msg:Message> Примеры реализации автоматического обмена данными В процессе использования механизмов обмена данными часто возникает необходимость выполнять процедуру об- мена автоматически (например, каждую ночь в опреде- ленные часы). В данном разделе мы рассмотрим несколь- ко возможных вариантов организации автоматического обмена данными. Использование командной строки Данный способ требует обязательной поддержки со сто- роны конфигурации. Он основан на использовании клю- ча запуска командной строки (/С) платформы 1 (^Пред- приятия. Для облегчения процедуры разбора параметра запуска его значение представлено в формате XML. Данный фор- мат не является обязательным и используется только в демонстрационных целях. Главное, что какой формат па- раметра вы определите при запуске, такой вы и должны разбирать в процедуре обработки запуска. Строка, ука- занная после ключа «/С», будет передана в глобальное свойство ПараметрЗапуска. Определим смысловую нагрузку на элементы XML-доку- мента, представляющего собой параметр запуска (). Commands — элемент, обозначающий список команд за- пуска, может содержать различные команды, которые мо- гут быть обработаны данной конфигурацией; ReadChanges — команда чтения сообщения обмена; WriteChanges — команда записи сообщения обмена; ExchangePlan — имя плана обмена, для которого необходи- мо выполнить команду; Node — код узла плана обмена, для которого необходимо выполнить команду. Рассмотрим пример файла, содержащего строку запуска (листинг 15.76). Первой строкой указывается, что запускается информа- ционная база, расположенная в каталоге d:\DemoEchange. Последней строкой определяется, что весь процесс от- ражается в лог-файле c:\exchange.log. При возникнове- нии каких-либо ошибок они будут отражены в данном файле. Листинг 15.76. Пример файла, содержащего строку запуска /Fd:\DemoExchange /С "<Commands> <ReadChanges> «ExchangePlап»УдапенныеСклады«/ЕхсбапдеР1an> <Node>OnioBbM</Node> «/Readchanges» <Wr1teChanges> «ExchangePlап»УдаленныеСклады«/ЕхсбапдеР1an» «Node>OnioBbm«/Node> «/WriteChanges> «/Commands»" /Out c:\exchange.log Весь остальной текст файла содержит описание пользо- вательского параметра. После создания командного файла его выполнение необ- ходимо поставить в очередь планировщика (например, стандартного планировщика ОС Windows) (рис. 15.15). Task | Schedule | Settings | 1С Предприятие Рис. 15.15. Пример командной строки В процедуре обработки события ПередНачалоиРаботыСистеиы (листинг 15.77) следует проанализировать параметр запуска и, в случае, если он не пуст, передать его на обра- ботку. В данном случае обработка выполняется в проце- дуре модуля приложения ВыполнитьКомандыЗапуска (лис- тинг 15.78).
Листинг 15.77. Процедура ПередНачаломРаботыСистемы Процедура ПередНачаломРаботыСистемы(0тказ) Если ПараметрЗалуска <> '"' Тогда Попытка ВыполнитьКоиандыЗапуска(ПараметрЗапуска); Исключение Сообщить(ОписаниеОшибки()); КонецПопытки; // если вызов был сделан с параметрон - завершаем работу Отказ = Истина: КонецЕсли: КонецПроцедуры Листинг 15.78. Процедура ВыполнитьКомандыЗапуска Процедура ВыполнитьКонандыЗапуска(Паранетр) ПотокХМЕ = Новый ЧтениеХМЕ; ПотокХМЕ.УстановитьСтроку(ПараметрЗапуска); // Выполняем разбор параметра запуска ПотокХМЕ.Прочитать(): Если ПотокХМЕ.ТипУзла <> ТипУзлаХМЕ.НачалоЭлемента ИЛИ ПотокХМЕ.Имя о "Commands" Тогда ВызватьИсключение "Ошибка разбора списка команд: |ожидается элемент 'Commands'": КонецЕсли: // Читаем последовательно команды и исполняем их Пока ПотокХМЕ.Прочитать() Цикл Если ПотокХМЕ.ТипУзла = ТипУзлаХМЕ.КонецЭлемента И ПотокХМЕ.Имя = "Commands" Тогда // список команд закончился, прерываем цикл Прервать; КонецЕсли; Если ПотокХМЕ.ТипУзла <> ТипУзлаХМЕ.НачалоЭлемента Тогда ВызватьИсключение “Ошибка разбора списка команд: |очередная команда не обнаружена."; КонецЕсли; Если ПотокХМЕ.Имя = "ReadChanges" ИЛИ ПотокХМЕ.Имя = "WriteChanges" Тогда Команда = ПотокХМЕ.Имя; И Читаем параметры команды обмена данными ПотокХМЕ.Прочитать(); // Имя плана обмена Если ПотокХМЕ.ТипУзла <> ТипУзлаХМЕ.НачалоЭлемента ИЛИ ПотокХМЕ.Имя о "ExchangePlan" Тогда ВызватьИсключение "Ошибка разбора списка команд: |ожидается элемент 'ExchangePlan'"; КонецЕсли; // Читаем значение ИмяПланаОбмена = ПрочитатьХМЕСПотокХМЕ, Тип("Строка")); // Получаем менеджер плана обмена Если Метаданные.НайтиПоПолномуИмениС"ПланОбмена." + ИмяПланаОбмена) = Неопределено Тогда ВызватьИсключение "План обмена '" + ИмяПланаОбмена + '" не обнаружен."; КонецЕсли: ПланОбмена = ПланыОбмена[ИмяПланаОбмена]; // Для ПланаОбмена "Магазины" данные команды // не поддерживаем Если Метаданные.ПланыОбмена[ИияПланаОбмена] = Метаданные.ПланыОбмена.Магазины Тогда ВызватьИсключение "Автоматический обмен для плана обмена '" + ИмяПланаОбмена + '" не поддерживается."; КонецЕсли; // Код узла плана обмена Если ПотокХМЕ.ТипУзла <> ТипУзлаХМЕ.НачалоЭлемента ИЛИ ПотокХМЕ.Имя о "Node" Тогда ВызватьИсключение "Ошибка разбора списка команд: |ожидается элемент 'Node'": КонецЕсли; // Читаем значение КодУзла = ПрочитатьХМЕСПотокХМЕ, ТипС'Строка")): // Ищем узел плана обмена УзелСсылка = ПланОбмена.НайтиПоКоду(КодУзла): Если УзелСсылка.ПустаяО Тогда ВызватьИсключение "Узел план обмена '" + ИмяПланаОбмена + '" не обнаружен: '' + КодУзла; КонецЕсли: Узел = УзелСсылка.ПолучитьОбъектО; // Производим вызов команды Если Команда = "ReadChanges" Тогда // Выполняем чтение сообщения для указанного узла Узел.ПрочитатьСообщениеСИз мененияии(); Иначе // Выполняем запись сообщения для указанного узла Узел.ЗаписатьСообщениеСИз менениями(); КонецЕсли; Иначе ВызватьИсключение "Ошибка разбора списка команд, |неизвестная команда " + ПотокХМЕ.Имя + ..........; КонецЕсли; КонецЦикла; // все команды выполнены - завершаем работу Отказ = Истина; КонецПроцедуры Процедура ВыполнитъКомандыЗапускаО выполняет разбор переданной строки при помощи объекта ЧтениеХМЕ. По мере разбора получаемая информация анализируется, и распознанные команды выполняются. Приведенный об- работчик для проведения как выгрузки, так и загрузки использует процедуры ПрочитатьСообщениеСИзменениями и ЗаписатьСообщениеСИзменениями, которые должны быть определены в модуле соответствующего плана обмена с использованием ключевого слова Экспорт. Еще раз обращаем внимание на тот факт, что в случае если пользовательская команда определена отличным от приведенного в примере способом, реализация обработ- чика события также будет отличаться. Использование объекта СОМСоединение Автоматический обмен может быть реализован при по- мощи внешней программы, использующей возможности объекта СОМСоединение платформы ЮПредприятия. Дан- ный метод может быть использован в случае, когда изме- нение конфигурации (для внедрения кода поддержки
автоматического обмена) по каким-либо причинам невоз- можно или нежелательно. Для примера напишем программу на языке Visual Basic для выполнения обмена, аналогичного описанному в раз- деле «Использование командной строки», с. 603 (лис- тинг 15.79). Листинг 15.79. Пример процедуры обмена Dim connector = Create0bject("V8.C0MConnector") Dim connection = connector.connect("file=d:\DemoExchange") Dim nodeRef = connection.ПланыОбмена.УдаленныеСклады. НайтиПоКодуС"Оптовый") If (Not nodeRef.ПустаяО) Then Dim node = nodeRef.ПолучитьОбъектО node.ПрочитатьСообщениеСИзменениями() node.ЗаписатьСообщениеСИзмененияии() End If В данном примере используются те же процедуры узлов плана обмена УдаленныеСклады, что и в реализации обме- на с использованием командной строки. Полученный исполняемый модуль может быть поставлен в очередь планировщика. Пример на языке Javascript приведен в листинге 15.80. Листинг 15.80. Пример постановки задания в очередь Language=javascript t> <% entConn = new ActiveX0bject("v8.ComConnector"); conn = entConn.connect("file=d:\DemoExchange"); nodeRef = conn.ПланыОбмена.УдаленныеСклады. НайтиПоКодуС"Оптовый"); if (nodeRef.ПустаяО = false) { node - побеКеб.ПолучитьОбъектО: побе.ПрочитатьСообщениеСИзменениями(); node. ЗаписатьСообщениеСИзменениямиО ; } *> Данный код можно размещать в документах *.asp, *.aspx.
Глава 16. Web-расширение Роль Интернета в современной деловой и общественной жизни сложно переоценить. В связи с развитием интер- нет-технологий появились новые виды бизнеса (элек- тронные аукционы, интернет-магазины и т. и.). Фактиче- ски уже считается стандартом, что любая компания имеет некое свое «представительство» в Интернете, активно ис- пользует различные интернет-технологии для организа- ции как внутрикорпоративного взаимодействия, так и взаимодействия с огромной аудиторией клиентов, парт- неров по бизнесу. Большое количество бизнес-задач уже решается с актив- ным использованием этих технологий. С точки зрения автоматизации деятельности учета компаний, интернет- технологии позволяют организовать удобный процесс обмена данными, организовывать распределенные ин- формационные системы, реализовать механизмы доступа громадного количества пользователей к данным компа- нии. При разговоре о различных Интернет-технологиях очень часто встречаются следующие понятия: ♦ клиент' ♦ сервер', ♦ протокол. Под сервером понимается некий ресурс глобальной сети, к которому можно обратиться для получения какой-либо информации, осуществления обработки данных. Под кли- ентом обычно понимается программа, «обращающаяся» к серверу. Протокол — это правила, в соответствии с ко- торыми происходит «общение» клиента и сервера. Рассмотрим эти понятия несколько подробнее. Предпо- ложим, возникло желание просмотреть новости на каком- либо сайте в Интернете. С точки зрения пользователя Интернет-технологий мы для решения этой задачи вы- полняем следующую последовательность действий: ♦ запускаем программу, позволяющую просматривать страницы в Интернете (к примеру, это может быть Internet Explorer); ♦ в строке Адрес программы вводим «название» интере- сующего нас сайта (URL); ♦ в основном окне программы просматриваем получен- ные данные. А вот как этот процесс выглядит изнутри (напоминаем, что рассмотрение производится довольно упрощенно). Каждый компьютер в глобальной сети Интернет обладает неким уникальным адресом (IP). При организации любо- го взаимодействия учитываются IP-адреса как клиента, так и сервера. Кроме IP-адресов, дополнительно исполь- зуется такое понятие, как «порт». Рассматривая схему взаимодействия клиента и сервера, можно провести сле- дующую аналогию с реальной жизнью: на корабле нужно доставить груз в город N-ск. В общем случае довольно сложно представить себе корабль (если только это не судно на воздушной подушке), разгружающийся на центральной площади города. Для разгрузки судна (осуществления «взаимодействия» с городом) используется порт (некая точка взаимодействия). Саму разгрузку выполняет опре- деленная «служба» (бригада грузчиков, крановщиков и т. п.). При обслуживании используются определенные «команды», понятные как экипажу корабля, так и сотруд- никам порта (вира, майна). То же самое происходит и при обработке данных как кли- ентом, так и сервером. С «точки зрения» Интернета лю- бой компьютер в сети представляет из себя некий «черный ящик» с определенным набором точек взаимодействия (аэропорт, порт, ж/д вокзал и т. п.). Каждая такая точка работает по своим правилам (протоколам). Для обслужи- вания порта может использоваться специализированная программа (рис. 16.1). Рис. 16.1. Взаимодействие клиента и сервера Вернемся к получению данных с Интернет-сайта. В качестве клиента в данном случае выступает программа браузер (Internet Explorer). Когда пользователь вводит данные в поле Адрес, определяется IP-адрес компьютера, который содержит интересующий ресурс, то есть 1Р-ад- рес сервера (для этой цели в Интернете существует спе- циальная «служба»). Для просмотра Интернет-страниц используется протокол HTTP (протокол обмена гипер- текстом, также можно сказать, что это протокол обмена HTML-документами и их содержимым). По умолчанию работа в соответствии с этим протоколом ведется через порт с номером 80 (номер порта может быть изменен ад- министратором, в этом случае при обращении он должен указываться в явном виде). По полученному IP-адресу сервера (порт № 80) клиент формирует запрос на получение данных. Данный порт на сервере обслуживает специализированная программа: веб-сервер (к примеру, это может быть Internet Information Server, далее IIS). Эта программа получает за- прос, выполняет его (это может сопровождается выполнени- ем какого-либо специализированного кода, из которого про- изводится обращение к определенным базам данных).
Результат исполнения отсылает на IP-адрес клиента. По- лучив ответ, программа отображает его в виде, понятном пользователю. Следует отметить, что в данном примере не рассматрива- ется порядок работы через «промежуточные» службы (прокси-сервера, сервера защиты). До этого момента рассматривались только общие момен- ты, касающиеся работы глобальной сети Интернет. Пора вернуться к Web-расширению. Задача Web-расширения заключается в том, чтобы орга- низовать доступ к функциональности прикладных реше- ний ЮПредприятия через Интернет. Благодаря этому появляется возможность встраивать доступ к данным 1 С:Предприятия в существующие веб-сайты и создавать интернет-приложения, использующие данные информа- ционных баз ЮПредприятия. Общую схему взаимодействия клиента с информацион- ной базой 1С:Предприятия можно представить следую- щим образом (рис. 16.2). Web-расширение предоставляет как пользовательский, так и программный интерфейс к данным информацион- ной базы ЮПредприятия. Другими словами, можно сказать, что с помощью Web- расширения можно создавать веб-сайты (и т. п.), рабо- тая с которыми пользователь будет работать с информа- ционной базой ЮПредприятия, не имея «представле- ния» об этом. Работа будет вестись из программы по просмотру Интернет-страниц (например, IE), без уста- новленной на компьютере клиента платформы 1С:Пред- приятия. Рис. 16.2. Схема взаимодействия клиента с информационной базой ЮПредприятия Основные положения Web-расширение позволяет организовать доступ к ин- формационным базам (функциональности платформы) 1 С:Предприятия из веб-приложений и веб-сервисов, реа- лизованных на платформе .NET компании Microsoft. Основная идея, реализованная в данной платформе, — унифицировать работу распределенных вычислительных систем, сделать их независимыми от особенностей рабо- ты каждого отдельного приложения, сервиса. В данной платформе можно выделить две ее важных со- ставляющих: ♦ Visual Studio.Net — универсальная среда разработки для платформы .Net; ♦ .Net Framework — многоязыковая инфраструктура ис- полнения приложений для платформы .Net. В свою очередь, .Net Framework также состоит из двух ос- новных частей: ♦ FCL (.Net Framework Class Library) — библиотека клас- сов; ♦ CLR (Common Language Runtime) — среда исполнения управляемых приложений. Можно выделить две основные технологии, которые реа- лизуются классами FCL: ♦ ADO.NET (ActiveX Data Objects .Net) — помогает уста- навливать связь приложений с базами данных; ♦ ASP.NET (Active Server Pages .Net) — активные сервер- ные страницы .Net, помогает создавать веб-приложения и веб-сервисы на основе Web-форм. Постараемся показать взаимосвязь основных технологий, используемых Web-расширением, с помощью следующей схемы (рис. 16.3). Рис. 16.3. Взаимосвязь используемых технологий Библиотека FCL содержит более 7000 типов и разделена на различные модули, разделы (иерархические простран- ства имен). К примеру, в одном пространстве имен могут содержаться «кирпичики», с помощью которых можно работать с правами доступа, в другом — все необходимое для организации работы со специфическими элементами управления форм и т. п. Некоторые пространства имен могут подразделяться на более специфические простран- ства имен (так формируется их иерархия). Создание приложений с помощью .Net Framework озна- чает написание программы (в общем случае на любом языке, поддерживаемых системой) посредством исполь- зования библиотеки FCL. В данной главе код будет цели- ком написан на С#, и в нем повсеместно будут использо- ваться возможности .Net Framework.
Для того чтобы написанное на C# приложение могло быть выполнено, его код необходимо преобразовать в язык, понятный операционной системе. Подобное преоб- разование называется компиляцией программы и выпол- няется компилятором. В .Net этот процесс состоит из двух этапов (оба этапа реализуются CLR): ♦ компиляция в промежуточный язык MSIL (Microsoft Intermediate Language). Этот код не является специфи- ческим ни для какой операционной системы; ♦ компиляция в код, специфический для операционной системы и архитектуры используемого компьютера. Вы- полняется JIT-компиляторами (Just In Time, своевре- менный). В прошлом часто возникала необходимость транслировать написанную программу в несколько различных приложе- ний, каждое из которых предназначалось для конкретной операционной системы, архитектуры центрального про- цессора (одно приложение под Windows 9х, другое под Windows NT и т. п.). Сейчас такая необходимость исчез- ла. Существует несколько JIT-компиляторов, каждый из которых предназначается для определенного варианта архитектуры компьютера. Вызов нужного из них опреде- ляется условиями, в которых необходимо транслировать программу (из кода на языке MSIL) в машинный код. При таком подходе фактически можно забыть о систем- но-зависимых особенностях приложения и сконцентри- роваться на его функционале. Использование CLR (среда исполнения управляемых при- ложений) не ограничивается компиляцией программы на MSIL и компиляцией в машинный код с помощью како- го-либо JIT-компилятора. Код, написанный с помощью .Net Framework, является управляемым на этапе выпол- нения (runtime). Это означает, что CLR отслеживает вы- полнение приложений, управляя памятью, межъязыковой отладкой, обеспечением безопасности и т. п. Приложе- ния, выполняемые не под контролем CLR, называются неуправляемыми. Часто такую возможность используют для получения доступа к функциям нижнего уровня опе- рационной системы. В качестве обобщения можно рассмотреть последова- тельность действий, необходимых для создания и выпол- нения приложения: ♦ код приложения записывается на языке программиро- вания, совместимом с .Net; ♦ производится компиляция в промежуточный язык MSIL; ♦ перед выполнением код компилируется соответствую- щим JIT-компилятором; ♦ полученный машинный код исполняется. Если взглянуть на Web-расширение с точки зрения рас- смотренных технологий, то можно сказать, что оно фак- тически является расширением (дополнением) библио- теки FCL (добавляются компоненты как в ADO.NET, так и в ASP.NET). ADO.NET ADO.NET является технологией доступа к данным, по- зволяющей приложениям получить доступ к данным, хранящимся в различных источниках. Данная техноло- гия может применяться для доступа к данным не только в веб-приложениях, но и других приложениях, построен- ных на технологиях .NET. Основное ее отличие от множества аналогичных техноло- гий доступа к данным — это возможность работы с дан- ными без постоянного соединения с источником данных. Данные, полученные из базы данных, располагаются в объекте, известном как DataSet, после чего соединение с базой данных закрывается. Доступ и манипуляция дан- ными, находящимися в DataSet, возможна без «живого» соединения с базой данных. После того как произведены необходимые изменения, DataSet может быть синхрони- зирован с базой данных средствами ADO.NET одной транзакцией. Подобная способность работать без постоянного соедине- ния с базой данных является очень выгодной, эффектив- ной и часто востребованной при работе в распределенных средах, таких как веб-приложения. Благодаря этому не требуется прилагать огромное количество усилий по со- хранению соединения и сохранению полученных данных на сервере. К тому же, это позволяет создавать более мас- штабируемые и высокопроизводительные веб-прило- жения, так как минимизирует количество информации хранящейся на сервере и сервер более эффективно ис- пользует свои ресурсы. Основными классами FCL, реализующими технологию ADO.NET, являются классы Connection, Command, DataReader, DataAdapter и DataSet пространства имен System.Data. С по- мощью этого набора объектов осуществляется чтение, до- бавление, изменение и удаление данных. Объект Connection представляет собой соединение с ис- точником данных. Посредством него остальные объекты осуществляют доступ к источнику данных. В Connection указываются параметры соединения с источником дан- ных и сам источник данных. Для установления соеди- нения с источником данных нужно открыть соединение, после выполнения требуемых действий соединение за- крывается. Объект Command используется для извлечения и модифи- цирования данных, находящихся в источнике данных. Для указания, какие данные, и в каком виде следует из- влечь или изменить, используется текст команды. Обыч- но текст команды содержит запрос, написанный на со- ответствующем языке запросов. Для задания значений параметров запроса используются параметры команды. Параметры команды могут быть именованными или нет — это зависит от источника данных и языка запросов. Для указания источника данных, из которого следует из- влечь данные, команде устанавливается Connection. Ре- зультат исполнения команды может быть прочитан с по- мощью объекта DataReader. Объект DataReader предназначен для чтения результата исполнения команды. Данный объект и возвращается при ее выполнении. Кроме чтения данных результата запроса, DataReader позволяет получить информацию о структуре результата, то есть получить информацию о количестве и составе колонок результата запроса. DataAdapter служит для преобразования данных, получен- ных с помощью команды, и заполнения этими данными объекта DataSet. DataSet служит универсальным хранили- щем данных и играет ключевую роль при передачи дан- ных между различными компонентами системы. Поэтому
часто встает задача преобразования данных результата в DataSet и обратно. Эту задачу и решает DataAdapter. Этот объект содержит команды для чтения, добавления, изме- нения и удаления данных. Следует отметить, что после установки Web-расширения появляется возможность использования таких объектов как VBDbConnection, VSDbCommand, VSDataAdapter, V8DataReader, V8DbSelectCommand, V8DbUpdateCommand, V8DbDeleteCommand, V8Db- InsertCommand использование которых упрощает процесс обращения к данным информационной базы 1 С: Пред- приятие 8.0. Описание данных классов находится в про- странстве имен _lC.V8.Data. Примеры работы с этими объ- ектами будут рассмотрены позже. ASP.NET В самом начале данной главы рассматривалась последо- вательность действий, выполняемых при желании клиен- та просмотреть какую-либо html-страницу. Напомним эту последовательность: ♦ по уникальному адресу ресурса в Интернете клиентом (например, программой Internet Explorer) производит- ся запрос на получение данных (обращение идет к нуж- ному порту системы); ♦ этот порт на сервере обслуживает специализированная программа (веб-сервер), которая, приняв запрос, обра- батывает его; ♦ результат запроса в виде HTML-документа возвраща- ется браузеру и им отображается. Модель такого поведения называется «запрос-ответ», она является базовой в Интернете. Недостатком такой моде- ли является то, что общение клиента с сервером происхо- дит только в момент выполнения запроса (получения данных). После этого клиент живет «своей» жизнью, сер- вер — «своей». Технология ASP.NET позволяет использовать событий- но-ориентированную программную модель. Суть этой модели заключается в том, что сервер «знает», что делает клиент. Для того чтобы понять, как это работает и какие преимущества это дает, проведем краткий экскурс в исто- рию развития веб-технологий. Для размещения газетных публикаций в Интернете был разработан язык HTML (язык разметки гипертекста). Фактически его задачей было представление инфор- мации для пользователей Интернета с определенными функциями ее форматирования. Но страницы, описан- ные на этом языке, были статическими, никак не реаги- рующими на действия пользователя в программе-клиен- те. Если говорить о функциях веб-сервера, то он просто, получив запрос, «брал» готовый HTML-документ и отсы- лал его клиенту. Начиная с 4-й версии языка HTML (так называемый DHTML, динамический HTML) появилась возможность выполнять фрагменты кода (скрипты) на стороне клиен- та. Они имитировали нажатие на графические кнопки, с их помощью настраивалась анимация и т. д. В своей ра- боте эти языки использовали объектную модель клиент- ской программы (браузера). С их помощью также можно было программно формировать запросы к серверу (за- просы GET, когда параметры запроса отражаются в стро- ке url в формате иг1?параметр=значение). Ограничением этих языков было то, что они выполнялись на стороне клиента и естественно не обладали средствами по работе с базами данных на стороне сервера. Несколько позже (рассматриваем технологии компании Microsoft) появилась такая технология, как ASP (актив- ные серверные страницы). Суть этой технологии заклю- чалась в том, что у сервера (точнее у программы веб-сер- вера Internet Information Server) появилась возможность исполнять ASP-документы (документы, внутри которых находился код на каком-либо допустимом языке про- граммирования). Страницы «ожили». Появилась возмож- ность формировать ответы клиенту (результирующий HTML-документ) в зависимости от каких-либо условий, в том числе от состояния базы данных, расположенной на сервере. Таким образом, программный код стал испол- няться и на стороне сервера. Но серверный сценарий ни- как напрямую не мог контактировать с клиентским сце- нарием, и наоборот. По-прежнему общение клиента и сервера производилось при явном выполнении запроса или при отправке данных клиентом (в форме по кнопке Submit, 0k или т. п.). Сервер получал запрос (данные) от клиента, выполнял файл и отсылал результат обратно. По-прежнему не было информации о том, что происходит на клиенте. Разработ- чикам интернет-приложений приходилось принудительно (разными средствами) включать в запрос от клиента нуж- ные данные (полученные в результате действий пользо- вателя), потом (в случае возврата к ранее заполненным формам) определять механизмы восстановления введен- ных значений и т. п. С приходом технологии ASP.NET появились такие по- нятия, как веб-формы и серверные элементы управле- ния, элементы управления HTML. Суть в том, что если раньше (в технологии ASP) элементы управления созда- вались на стороне клиента (и модель их поведения так- же описывалась на стороне клиента), то теперь элемен- ты управления могут создаваться на стороне сервера. И на сервере появилась возможность отслеживать собы- тия (и как следствие выполнять их обработку), свя- занные с работой пользователя с этими элементами управления. Это фактически и есть событийно-ориенти- рованная модель. Следует отметить, что несмотря ни на что, событийная модель лежит «поверх» модели «запрос-ответ», она ее ис- пользует. Но запросы к серверу могут выполняться без явной команды пользователя. Рассмотрим на примере, как все это работает. В среде разработки Visual Studio .NET создадим новый проект (рис. 16.4). Qp»n ► If) Eile... Ctrl+N Close Blank Solution... Рис. 16.4. Создание нового проекта Далее будет предложено выбрать шаблон проекта. На бу- дущее (данная глава построена на сквозном примере) выберем шаблон V8 Web Application (хотя в данном слу- чае могли выбрать Web Application). Шаблоны V8 Web
Application и V8 Web Service появляются после установки Web-расширения (рис. 16.5). New Pi eject A project for cresting e V8 Web appkation Name |MySfte Location: | http://localhostjWySite ' Browse... j Project нЯ be created at http://bcalhost/My Site. «More | | OK Cancel | Help | Рис. 16.5. Создание нового приложения Отличием данного шаблона от Web application является то, что дополнительно в утилите импорта метаданных (она запускается автоматически) потребуется указать базу данных ЮПредприятия 8.0, которая будет использовать- ся в веб-приложении по умолчанию (с точки зрения дей- ствий, которые производятся при выборе данного шабло- на, отличий намного больше: копируются формы «по умолчанию», картинки, настраиваются ряд «конфигура- ционных» файлов и т. п.) (рис. 16.6). Рис. 16.7. Конструктор Web Form Рис. 16.8. Пример формы Start Page | WebForml.aspx LoginForm.o*px j Loginl Рис. 16.6. Окно конструктора приложения После выбора базы требуется указать пользователя, в кон- тексте которого будет осуществляться работа всего при- ложения с информационной базой ЮПредприятия. При обращении к объектам информационной базы (если ино- го не предусмотрено явным образом) будут использо- ваться права именно этого пользователя. В созданный проект добавим новую веб-форму (пункт меню Project ► Add New Item) (рис. 16.7). Используя панель инструментов Toolbox (группа Web Forms), разместим в диалоге формы четыре элемента управления TextBox, столько же элементов Label и две кнопки (эле- мент управления Button). Группы V8Web, V8Data появля- ются в данной панели инструментов после установки Web-расширения. Используя палитру свойств для каждого элемента управ- ления, можно добиться следующего вида формы (рис. 16.8). У создаваемой формы есть два режима просмотра: ♦ Design, показывается диалог формы таким, каким его будет видеть пользователь в программе клиенте; ♦ HTML, показывается исходный код формы (содержа- щийся в файле с расширением aspx). В режиме HTML код созданной страницы выглядит сле- дующим образом (листинг 16.1). Листинг 16.1. HTML-код созданной страницы «t@ Page language="c#" Codebeh1nd="LoginForm.aspx.cs" AutoEventWi reup="false" Inherits="V8WebBook.LoginForm" t> «iDOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN”> «HTML» «HEAD» «t i tle»Logi nForm</ti tle> <meta name=''GENERATOR" Content=''Microsoft Visual Studio .NET 7.1“> <meta name="CODE_LANGUAGE" Content="C#”> «meta name="vs_defaultClientScript" content”"JavaScript"» <meta name="vs_targetSchema" content”"http://schemas.microsoft.com/intellisense/ie5"> «/HEAD» «body MS POSITIONING="GridLayout"> «form id="Forml" method="post" runat="server"» <asp:TextBox id="TextBoxl" runat="server"»«/asp:TextBox» <asp:Button 1d="Button2" runat="server" Тех1="0чистить"» «/asp:Button» «asp:Button id="Buttonl" runat="server" Text=”OK"»«/asp:Button» «asp:Label id="Labe!4" runat=“server"»naponb«/asp:Label» <asp:Label 1d="Label3" runat=”server"»Серия </asp:Label» «asp:Label id="Labe!2" runat="server">J< паспортa«/asp: Label» «asp:Label id="Labell" runat="server"»HorHH«/asp:Label»
<asp:TextBox id='’TextBox4" runat=”server"></asp:TextBox> <asp:TextBox id="TextBox3" runat="server”>«/asp:TextBox> <asp:TextBox id="TextBox2" runat="server”>«/asp:TextBox> </form> </body> </HTML> Исходный текст формы включен не полностью, из него были удалены свойства элементов управления, связан- ные со стилем отображения (положение, шрифт и т. и.), но были оставлены все моменты, существенные с точки зрения рассматриваемого материала. Первые две строки (в исходном тексте это была одна строка) занимает директива, в которой указано, что ос- новным языком программирования для данной формы является язык С#, программная модель (исходный код формы) находится в файле LoginForm.aspx.cs. После этого до первого тега с префиксом asp (тегом назы- вается некое выражение, заключенное в угловые скобки) идет, казалось бы, обычный HTML. Отличие, про которое необходимо знать, заключается в том, что хотя сам язык HTML допускает наличие открывающего тега без закры- вающего, в данном случае желательно каждому откры- вающему тегу сопоставлять закрывающий тег. Закрываю- щий тег отличается от открывающего наличием символа «/» перед именем закрываемого тега. Обратите внимание на строку (листинг 16.2). Листинг 16.2. Фрагмент HTML-кода созданной страницы <form id="Forml" method="post" runat=”server"> Когда форма конструировалась в режиме Design, метод отправки для нее явно не определялся. Конструктор ав- томатически устанавливает метод отправки Post (данные формы отправляются во внутренних переменных запроса и не отображаются в строке URL браузера). Форма выпол- няется на сервере (обратите внимание на то, что для того, чтобы сделать форму клиентской, не надо писать runat= client, нужно просто убрать атрибут runat=”server”). Те, кто работал с HTML или ASP, обратили внимание на тот факт, что в данной форме не определен обработчик высы- лаемых ею данных, то есть после отправки данных на сер- вер они для обработки передаются этой же форме (произ- водится отсылка самой себе). Внутри формы с помощью тегов с префиксом asp (этот префикс указывается для серверных элементов управле- ния) определяются все визуально размещенные в них элементы управления. К примеру, в следующей строке указывается, что в форме определен элемент управления TextBox с уникальным идентификатором TextBoxl. Элемент управления являет- ся серверным (определяется наличием атрибута runat= server) (листинг 16.3). Листинг 16.3. Фрагмент HTML-кода созданной страницы <asp:TextBox id="TextBoxl" runat=”server">«/asp:TextBox> Для того чтобы посмотреть, как эта форма ведет себя в пользовательском режиме, следует выполнить команду меню Project ► Web Project ► Set As Start Page (в рамках дан- ного проекта страница станет стартовой). После этого нужно произвести компиляцию проекта и запустить его на исполнение. Это можно сделать единомоментно (дей- ствия выполнятся по очереди, но как бы в пакетном ре- жиме), запустив проект в режиме отладки (выполнив команду меню Debug ► Start). Внешний вид формы будет точно таким же, как и в режи- ме Design. Следует отметить, что при использовании брау- зеров старых версий или других производителей внеш- ний вид может отличаться. Кстати, одной из приятных особенностей ASP.NET является тот факт, что HTML- файл ответа, отсылаемый клиенту, подстраивается под возможности браузера клиента (для наиболее распро- страненных случаев). Если воспользоваться возможностью браузера просмот- реть исходный код (пункт меню Вид ► Источник) отобра- жаемого документа, то можно увидеть следующее (лис- тинг 16.4). Листинг 16.4. Исходный код страницы <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>LoginForm</title> «meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1"> <meta name=”CODE_LANGUAGE" Content=”C#”> <meta name=” vsdefaul tCl ientScri pt” content="JavaScri pt"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> </HEAD> «body MS_POSITIONING=”GridLayout”> <form name="Forml” method="post“ action-'LoginForm.aspx” id=”Forml"> «input type=”hidden" name="_VIEWSTATE" value= "dDwzMzkwMzkzMTY70z5XREZClCJcq60gjr2NGMikVs3uQ=’7> «input name=”TextBoxl” type="text" id="TextBoxl"/> «input type="submit” name=”Button2" уа1ие="0чистить" id=“Button2’7> «input type="submit" name="Buttonl” value="OK" 1d=”Buttonl" /> «span id="Label4”>naponb«/span> «span id="Label3">Серия </span> «span 1d="Label2">H" nacnopra«/span> «span id="Labell">HornH«/span> «input name="TextBox4" type="text” id=”TextBox4"/> «input name="TextBox3” type="text" id=”TextBox3"/> «input name="TextBox2” type=”text" id="TextBox2"/> «/form> «/body> «/HTML> Если сравнить с исходным текстом веб-формы, то можно сказать, что: ♦ представленный код является полностью «чистым» ко- дом HTML (без каких-либо директив, префиксов); ♦ при описании формы HTML (тег form) появилось яв- ное указание, что данные, в нее введенные, она же и бу- дет обрабатывать (action="LoginForm.aspx"); ♦ в данном тексте представлены обычные HTML-элемен- ты формы, создаваемые на стороне клиента; ♦ добавился тег input с типом hidden (скрытый) и «непо- нятным» значением. Фактически происходит следующее: при визуальном про- ектировании формы в ней размещаются серверные эле- менты управления. При обращении к данной форме для
каждого элемента управления создается его HTML-пред- ставление, которое и отправляется в браузер (на самом деле браузер и может отображать только код HTML, если бы ему был передан исходный код формы, то те фрагмен- ты, которые ему не «понятны», не отобразились бы). Рассмотрим назначение скрытого тега input. При работе с технологией ASP, при отправке данных из формы са- мой себе информация (состояние), введенная в элементы управления, сбрасывалась (форма как бы получалась за- ново и в нее передавались данные запроса). Для того что- бы оставить введенные данные на месте (восстановить состояния элементов управления), разработчикам прихо- дилось прописывать специфические механизмы. При ис- пользовании технологии ASP.NET в этом нет необходи- мости, рассматриваемое поле и содержит все состояния и значения элементов управления, представленных на форме. Теперь займемся программной моделью поведения веб- формы. Для начала определим обработчик события Нажа- тие на кнопку "Очистить". Для этого произведем двойной щелчок на кнопке Очистить. Откроется дополнительное окно, показывающее содержимое файла LoginForm.aspx.cs (исходный программный код формы). В представ- ленном коде уже будет сформировано определение функ- ции, обработчика события Button2_Click(object sender. System.EventArgs e). Текст, который нужно определить в обработчике, будет ниже выделен серым фоном, а по- ка ознакомимся со всем представленным кодом (лис- тинг 16.5). Листинг 16.5. Программный код формы using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; usi ng System.Web.UI.WebControls; usi ng System. Web. Ill. Html Control s; // новое пространство имен, совпадающее с именем проекта namespace V8WebBook { /// <summary> /// Summary description for LoginForm. /// </summary> public class LoginForm : System.Web.III.Page { protected System.Web.III.WebControls.TextBox TextBoxl; protected System.Web.III.WebControls.TextBox TextBox2; protected System.Web.III.WebControls.TextBox TextBox3; protected System.Web.III.WebControls.TextBox TextBox4; protected System.Web.III.WebControls.Label Labell; protected System.Web.UI.WebControls.Label Label2; protected System.Web.UI.WebControls.Label Label3: protected System.Web.UI.WebControls.Label Label4; protected System.Web.UI.WebControls.Button Buttonl; protected System.Web.UI.WebControls.Button Button2; private void PageLoadt object sender. System.EventArgs e) { 11 Put user code to initialize the page here } #region Web Form Designer generated code override protected void OnlnittEventArgs e) { // // CODEGEN: This call is required by the // ASP.NET Web Form Designer. // Ini 11 ali zeComponent(); base.Onlnit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponentO { this.Button2.Click += new System.EventHandler( this.Button2_Cli ck); this.Load += new System.EventHandler(this.Page Load): } #endregion private void Button2_Click(object sender. System.EventArgs e) { this.TextBoxl.Text="": this.TextBox2.Text="": this.TextBox3.Text='"'; thi s.TextBox4.Text=""; } } } Первоначально, с помощью оператора using, указываются используемые в данном коде пространства имен (каждое пространство имен содержит описание типов, решающее какую-либо определенную задачу). В новом пространстве имен определяется класс LoginForm, он наследуется от класса System.Web.UI.Page (базовый класс для любой веб-формы). Любой элемент управления опре- деляется как защищенный член создаваемого класса (из объявления видно, что определения серверных элементов управления находятся в пространстве имен System.Web. ULWebControls). При обращении к форме производится вызов функции OnlnittEventArgs е), из нее вызывается функция Initialize- ComponentO. В функции InitializeComponentO производит- ся определение обработчиков событий: ♦ начало загрузки страницы (Page_Load()); ♦ нажатие на кнопку Button2 (Button2_Click()). Для того чтобы функция могла выступать как обработчик события, она должна быть определена с двумя параметра- ми (листинг 16.6). Листинг 16.6. Пример определения функции private void Page_Load(object sender, System.EventArgs e) Параметр sender имеет тип object (базовый тип всех объ- ектов) и характеризует объект, событие которого обраба- тывается. Один обработчик события может обрабатывать однотипные события разных объектов, данный параметр может использоваться для «уточнения» или доступа к свойствам объекта-источника. Второй параметр позволяет получить более подробные данные о произошедшем событии. После отработки процедуры OnInit(EventArgs е) иниции- руется событие (соответствующая функция начинает вы- полняться) Page_Load.
После загрузки форма переходит к ожиданию отрабаты- ваемых событий. При нажатии на кнопку Очистить вызывается обработчик события Button2_Click, в котором очищаются все опреде- ленные в форме поля ввода (обращение производится к соответствующим защищенным членам класса). Что и происходит в пользовательском режиме. Изменим пример. Определим обработчик события для элемента управления TextBoxl (поле ввода, в которое пользователь вводит логин). Произведем двойной щел- чок на выбранном элементе управления (в режиме Design), в открывшемся модуле в созданном обработчике события определим следующий текст (листинг 16.7). Листинг 16.7. Пример обработчика события TextBoxl TextChanged private void TextBoxl_TextChanged(object sender. System.EventArgs e) { this.TextBox2.Text = "неизвестен"; this.TextBox3.Text = "неизвестен"; } Следует обратить внимание, что в функцию Initialize- Component() была автоматически добавлена строка (опре- деляющая, что добавленная функция будет являться об- работчиком события) (листинг 16.8). Листинг 16.8. Объявление функции InitializeComponentO private void InitializeComponentO { this.TextBoxl.TextChanged += new System.EventHandler( this.TextBoxlTextChanged); this.Button2.Click += new System.EventHandler( this.Button2_Cli ck); this.Load += new System.EventHandler(this.Page_Load): } Заметьте, несмотря на то, что событие TextChanged возни- кает при любом изменении в поле ввода TextBoxl, запус- тив веб-приложение в режиме отладки, мы этого не уви- дим. Какие бы данные ни вводились в поле TextBoxl, изменений значений (текста) в полях TextBox2 и TextBox3 производиться не будет. И только при нажатии на любую кнопку будет виден результат выполнения обработчика события TextChanged. Постараемся пояснить суть происходящего. Все события, которые происходят на форме, можно разделить на две большие группы: ♦ Пассивные (связанные с движениями мыши, нажатие на клавиши клавиатуры); ♦ Активные (нажатие на кнопки, изменение текста и т. и.). Пассивных событий формируется огромное множество, отрабатывать их на стороне сервера нет необходимости (и возможности). Их отработка возлагается на скрипты (сценарии) выполняемые на стороне клиента. Активные события отрабатываются на стороне клиента сервера (если для них определены обработчики собы- тий). Но при этом не всякое событие приводит к его не- медленной обработке на сервере. Часть событий может кэшироваться на клиенте. В нашем случае событие TextChanged кэшировалось. После того как произошло нажатие на любую кнопку, например на кнопку ОК, произошла отправка данных на сервер. Это можно увидеть, проанализировав текст источника HTML- кода в браузере. Кнопка определена следующим фрагментом кода (лис- тинг 16.9). Листинг 16.9. фрагмент кода «input type="submit" name="Buttonl" value="0K" id="Buttonl"/> Тип кнопки установлен в значение submit, это и определя- ет тот факт, что производится передача данных. В качест- ве получателя данных (для обработки) указана та же форма, это определено в теге form, в атрибуте action= "LoginForm.aspx" (листинг 16.10). Листинг 16.10. Фрагмент кода <form name="Forml" method="post" action="LoginForm.aspx" id="Forml"> После передачи данных на сервер обработчики событий выполняются в порядке их возникновения. Последним обрабатывается событие, вызвавшее процесс отправки данных серверу. В случае если необходимо, чтобы событие TextChanged обрабатывалось на сервере сразу после возникнове- ния, в палитре свойств серверного элемента управления TextBoxl свойство AutoPostBack (немедленная отправка) нужно установить в значение True (рис. 16.9). Т extBox 1 System.Web. UL WebControls. T extBox Рис. 16.9. Свойство AutoPostBack После установки данного свойства в исходном тексте формы (*.aspx) во фрагменте, описывающем серверный элемент управления, появился новый атрибут AutoPostBack="True" (листинг 16.11). Листинг 16.11. фрагмент кода <asp:TextBox id="TextBoxl" runat="server" AutoPostBack="True"></asp:TextBox> Изменения произошли и в HTML-документе, получае- мом программой-клиентом. Был добавлен сценарий, выполняемый на стороне клиен- та (листинг 16.12). Листинг 16.12. Сценарий, выполняемый на стороне клиента «script language="javascript"> <! - - function _____doPostBack(eventTarget. eventArgument) { var theform; i f (wi ndow.navi gator.appName.toLowerCaset). indexOf("netscape") > -1) { theform = document.forms["Forml"];
} else { theform = document.Forml; } theform.__EVENTTARGET.value = eventT arget.split("$").joi n: theform._EVENTARGUMENT.value = eventArgument; theform.submitO; } // --> </script> В области действия тега script определена функция __doPostBack(eventTarget eventArgument). Основная задача этой функции — вызвать принудительную отсылку дан- ных из HTML-формы на сервер. Вызов данной функции определен при описании HTML- элемента, ответственного за прием данных о логине (лис- тинг 16.13). Листинг 16.13. Фрагмент кода <input name="TextBoxl" type=”text" onchange="_doPostBackCTextBoxl', '')” 1 anguage="javascript" id="TextBoxl'7> To, что эта функция будет задействована, определяется тем, что ее вызов определен в свойстве onchange тега input. При возникновении необходимости определения собст- венных сценариев, выполняемых на стороне клиента, об- ращайте внимание на тот факт, что в зависимости от про- изводителя программы клиента (браузера) придется по разному отрабатывать какие-либо ситуации; реализация объектной модели браузера может различаться. Это на- глядно видно по функции, представленной выше. Объект, «форма», в случае если в качестве браузера выступает программа компании Netscape, получается с помощью следующей строки (листинг'16.14). Листинг 16.14. Пример для браузера Netscape theform = document.forms["Forml“]; В остальных случаях (Microsoft, Opera) он будет получен следующим образом (листинг 16.15). Листинг 16.15. Пример для браузеров Microsoft, Opera theform = document.Forml: В результате, казалось бы, незначительной манипуляции (установка свойства AutoPostBack в значение True) нуж- ный эффект был достигнут. После рассмотрения данного примера может возникнуть желание включать данное свойство для всех серверных элементов управления. На самом деле лучше этого не де- лать. Данное свойство стоит включать только в тех случа- ях, когда это действительно нужно, когда именно в этом и заключается функциональность элемента управления. Необоснованное включение может привести к падению производительности создаваемой веб-формы. При этом не стоит думать, что эта производительность зависит от скорости работы персонального компьютера или от ско- рости канала связи (хотя и не без этого). В первую оче- редь скорость выполнения запроса зависит от количества промежуточных узлов от клиента до сервера. Дело в том, что когда возникает необходимость отпра- вить данные на сервер, как правило, старое соединение уже разрушено. Если так, то вначале производится соеди- нение с сервером, затем отсылка заголовков сообщений. После того как клиент и сервер поняли, что соединились удачно, клиент отправляет данные. После обработки сер- вер инициирует обратный процесс... Очевидно, что де- лать все это без необходимости совершенно не стоит. Если вернуться к палитре свойств Toolbox становится оче- видным, что помимо серверных элементов управления, в диалоге можно размещать и обычные HTML-элементы. Это рекомендуется делать, если есть необходимость раз- местить какой-либо элемент и при этом нет смысла опре- делять его на стороне сервера (хоть не много, но позволит сэкономить ресурсы сервера). Кстати, в случае если при работе с серверными элемента- ми управления возникнет необходимость просмотреть, какие обработчики события для них определены, можно воспользоваться палитрой свойств, переключив ее в ре- жим просмотра событий (рис. 16.10). Рис. 16.10. Палитра свойств Конструкторы Web-расширения для веб-приложений С состав средств разработки, поставляемых вместе с Web-рас- ширением (помимо других средств), входят файлы шабло- нов для мастера MS Visual Studio Net 2003. Для знакомства с шаблонами, позволяющими создавать веб-приложения, не- обходимо первоначально создать новый проект, с выбором шаблона V8 Application. После выбора данного шаблона будет предложено выбрать информационную базу ЮПредпри- ятия. В качестве такой базы предлагаем выбрать демонстра- ционную конфигурацию Обмен данными, входящую в состав информационно-технологического сопровождения (ИТС). Перед использованием конфигурации желательно (это понадобится в дальнейшем) определить пользователя базы данных. Предварительно необходимо создать пол- ный набор прав и только после этого добавить пользова- теля (рис. 16.11). После добавления пользователя можно приступить к соз- данию нового веб-приложения. Для этого необходимо за- пустить среду разработки Visual Studio Net 2003 и соз- дать новый проект. При создании нового проекта (пункт главного меню File ► New ► Project) нужно выбрать шаблон
V8 Web Application. Данный шаблон доступен после уста- новки Web-расширения на компьютере разработчика (рис. 16.12). Рис. 16.11. Создание нового пользователя информационной базы ЮПредприятия После нажатия на кнопку ОК будет создан ряд файлов, не- обходимый для работы всего приложения в целом, и бу- дет открыта единственная (пустая) веб-форма (с именем WebForml.aspx). Просмотреть все созданные файлы можно, используя So- lution Explorer. Открыть его можно, используя команду глав- ного меню программы (View ► Solution Explorer) (рис. 16.14). ’ MySite - Mkiosoft Visual <> MET [design] Miew | Project guild Rebug Dgta Fie Edit iToofeox VSWeb veOata Data________ Web Forms | ^ Pointer A label Qode Designer Qpen Open With. tfTML Source Ctrl+PgDn Visible Borders Ctri+Q Detals Ctrl+Shtft+Q Synchronise Document Outline Solution Extforer CtrH-AJt+L Рис. 16.14. Вызов Solution Explorer New Project l$fl A project for creating a V8 Web application Name | ' Location: | http:/^ocahost/MySfte *| Browse... Project wl be created at http://localhost/MySite. »Mor£ I [~ OK 1 Cancel I Help В результате выполнения команды откроется окно сле- дующего вида (рис. 16.15). SijlptionE pli'jrer___________________________________ 1? X Рис 16.12. Создание нового веб-приложения В нижней части указывается путь к виртуальному ката- логу создаваемого веб-приложения (строку localhost тро- гать не нужно). После нажатия на кнопку ОК откроется окно утилиты генерации метаданных (запуск этой утили- ты является особенностью шаблона V8 Web Application) (рис. 16.13). В___________________________________ Solution 'МуSite' (1 project) В © MySfte (±J g) ^References] В Images Й assemblyinfo.es Def aultErrorForm. aspx -• DefaultFieldTreeForm.aspx — EH DefautFiterForm.aspx 1^1 DeFadtlmageForm.aspx DefaiMineForm aspx Ц] DefaultListForm.aspx DeFaultObjectForm.aspx DeFaultRecordForm.aspx DefaultReportPrint.aspx 0^1 Def aultTypeChoice. aspx Def aultTypelnfo. aspx DefaultValueslist.aspx ф Global.asax StyleSheet.css =* TableFormMap xml '4 TableFormMap.xsd Web.config ••• E3 WebForml.aspx Рис. 16.15. Окно Solution Explorer Рис 16.13. Окно конструктора приложения В окне утилиты необходимо выбрать конфигурацию (базу данных), которая будет основной у создаваемого веб-при- ложения, указать параметры доступа к ней (имя пользо- вателя и его пароль). Если рассмотреть содержимое указанного окна, то можно увидеть, что внутри группы Images находятся ссылки на картинки, используемые при оформлении форм. Внутри группы References находятся ссылки на dll-файлы, отве- чающие за реализацию ряда механизмов Web-расшире- ния. Кроме этого, там находится ссылка на файл lcv8.dll, в котором хранится информация о метаданных конфигу- рации, используемой веб-приложением. В корне MySite (так был назван виртуальный каталог при- ложения) определен ряд других файлов. Рассмотрим их назначение: ♦ DefaultErrorForm — форма, отображающая ошибки ис- полнения; ♦ DefaultFieldTreeForm — вызывается для отображения дос- тупных полей при работе с объектом V8ReportBuilder; ♦ DefaultFilterForm — вызывается для установки отборов в списке;
♦ DefaultlmageForm — вызывается для отображения карти- нок; ♦ DefaultLineForm — вызывается для редактирования стро- ки табличной части (если указан режим редактирова- ния в отдельной форме); ♦ DefaultListForm — вызывается для отображения формы списка, формы выбора, формы выбора групп; ♦ DefaultObjectForm — вызывается для отображения фор- мы объекта или группы справочника; ♦ DefaultRecordForm — вызывается для редактирования кон- стант и записи в списке регистра сведений с независи- мым режимом записи; ♦ DefaultReportPrint — используется для вывода отчета на просмотр и печать; ♦ DefaultTypeChoice — вызывается для выбора типа в поле ввода; ♦ DefaultTypelnfo — возвращает информацию о типах из метаданных; ♦ DefaultValueList — используется для формирования под- бора при вводе по строке; ♦ Global.asax — является как бы глобальным модулем веб- приложения, в нем можно определять ряд обработчи- ков событий; ♦ StyleSheet.css — содержит стили оформления, примени- мые к веб-формам; ♦ TableFormMap.xml — содержит описания основных форм объектов; ♦ Web.config — определяет настройки веб-приложения. Использование ряда этих файлов будет рассмотрено в сле- дующих разделах данной главы. в правой части диалога сразу же выделить интересующую категорию V8) (рис. 16.17). Рис. 16.17. Шаблон V8 List Form В нижней части диалога определяется имя создаваемой веб-формы. Данный шаблон может использоваться для создания веб- форм, которые по своей функциональности соответству- ют формам списка любых объектов 1С:Предприятие. После открытия (кнопка Open) выбранного шаблона не- обходимо из списка выбрать таблицу базы данных, кото- рая будет выступать источником данных для создаваемой веб-формы (рис. 16.18). Конструктор формы списка Имя таблицы V8 List Form Познакомимся с конструктором V8 List Form на примере создания в приложении веб-формы, позволяющей про- сматривать (и выполнять ряд других стандартных дейст- вий) список номенклатурных позиций подключенной ин- формационной базы. Для решения этой задачи включим в проект новый эле- мент (веб-форму). Сделать это можно, выполнив коман- ду главного меню программы (Project ► Add New Item...) (рис. 16.16). Поля для рази । Контрагент Склад Документ ПриходнаяНакладная ПланОбмена УдаленныеОфисы ПланОбмена УдаленныеСклады РегистрН акопления.УчетНоменклатуры РегистрСведений ЦеныН оменклатуры Справочник.Склады Справочник. Т ипыЦ ем Рис. 16.18. Выбор таблицы базы данных Bte Ed* JSew Project gufld pebug Dgjta Format I ► II Q | ® | Toolbox ® VSWeb ® Add Web Form... Add Web User Control. Add HTML Page.. Add Web Service... VSData Data Web Forms I Pointer ‘A to» tffi] Add Component... Add Class . AddNeffiItem.. Gri+Sbift+A [ filij Add Existing Item... Shif t+Alt+A Рис. 16.16. Команда Add New Item... Форму необходимо создать с использованием шаблона V8 List Form (для того чтобы не искать данный шаблон среди всех элементов пользовательского интерфейса, можно На этом же этапе конструктора можно определять состав полей, которые будут отображаться в создаваемой форме списка справочника (рис. 16.19). ВНИМАНИЕ Следует отметить тот факт, что при создании форм может возникнуть ситуация, когда имя реквизита совпадает с именем метода, существующего для объекта. К примеру, в справочнике может быть определен реквизит ПолноеНа- именование. При создании формы списка (для объекта с таким реквизитом) и ее использовании проблем возни- кать не будет, но при попытке из этой формы открыть фор- му элемента справочника может быть выдано сообщение Member not found (при создании нового элемента, сразу при открытии формы элемента, при изменении существую- щего элемента, при попытке сохранения сделанных изме- нений). Внизу открытого диалога автоматически проставляется флаг Записывать информацию в файл соответствия имен таб- лиц и форм. Если оставить этот флаг отмеченным, то тогда в файле проекта TableFormMap.xml будет размещен допол-
нительный элемент XML TableFormMap. Содержимое фай- ла приведено ниже (листинг 16.16). Рис. 16.19. Выбор состава полей Для просмотра созданной формы «в действии» ее можно определить как стартовую, используя команду главного меню программы (Project ► Web Project ► Set As Start Page) (рис. 16.21). ’ MySite Micibsoft Visual C- HET [design] nomenlist.aspx 0e Edit View Toofcox V8Web VSData Data__________ Web Forms | Pointer A Label TextBox И Button LinkButton Project ji Eutld Rebug Data Fgrmat Add Web Form... Add Web User Control... Add HTML Page... Add Web Service... Add Component . Table Frames Tools $|indo I Debu0 * й 13 Add Class... Add New Item... Ctrl+Shif t+A Add Existing Item... 5hif t+Ak+A % Wafa Project Copy Project... Exclude From Project Рис. 16.21. Команда Set As Start Page nomenhst.aspx | . ’S Перейти Пера; Colurn abc abc abc Set As Start gage Web Permissions. . Листинг 16.16. Содержимое файла TableFormMap.xml <?xml version=”1.0” encoding=”utf-B"?> <!-. Пример оформления <ТаЫ eFormMap xmlns="http://tempuri.org/TableFormMap.xsd"> <table паше="Документ.ИнвентаризацияТоваровНаСкладе"> <form type="Element">Invent.aspx«/form> <form type="List">InventList.aspx</form> </table> «/TableFormMap> «TableFormMap xmlns="http://tempuri.org/TableFormMap.xsd"> «table пате="Справочник.Номенклатура"> «form type="List”>nomenlist.aspx«/form> «/table> «/Tabl eFormMap> Элемент XML TableFormMap, представленный выше, опи- сывает, что для таблицы Справочник.Номенклатура опреде- лена форма списка с именем nomenlist.aspx. Это приведет к тому, что при возникновении необходимости работы со списком указанной таблицы пользователь будет работать не с формой списка по умолчанию (DefaultListForm.aspx), а с данной формой, если иное действие не определено разработчиком явным образом. Например, он может явно указать, что для подбора номенклатуры из какого-либо документа должна использоваться строго определенная форма и т. п. В результате добавления элемента по выбранному шабло- ну будет создана веб-форма следующего вида (рис. 16.20). После этого можно запустить приложение в режиме от- ладки (Debug ► Start) и проверить работу созданной формы. Следует отметить, что установка формы в качестве стар- товой действует только в режиме отладки. В готовом веб- приложении стартовая страница определяется в настрой- ках веб-сервера (рис. 16.22). Рис. 16.22. Указание стартовых страниц в настройках веб-сервера Для каждого веб-сервера эти настройки могут быть опре- делены индивидуально администратором сервера (напри- мер, программы Microsoft IIS). Подробное знакомство В результате работы конструктора в форме определено три объекта, их взаимосвязь можно показать схематиче- ски (рис. 16.23). Start Page | WebForml.aspx п т**мЬ«1.трм | ^Выбрать < М Перейти Иерархически Дейен CclumnO Columnl Column2 abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc VBListDataSource ListDataSource Рис. 16.20. Созданная веб-форма Рис. 16.23. Взаимосвязь объектов
Рассмотрение любой формы лучше начинать с источни- ков. Источником данных для данной формы является объект V8ListDataSource (ID — ListDataSource). Одно из свойств объекта содержит указание на используемую таб- лицу базы данных (Справочник.Номенклатура). Если веб- приложение работает с несколькими информационными базами 1 С:Предприятия, то псевдоним базы указывается в свойстве IBAlias (пустой псевдоним означает, что ис- пользуется база данных «по умолчанию», которая была указана при создании веб-приложения). В диалоге определен серверный элемент управления V8Grid (элемент, показывающий список). Этот элемент управле- ния связан с источником данных посредством свойства ListDataSource. Элемент управления V8CommandPanel (командная панель) свя- зан с нужным списком посредством свойства LinkedControl. Для просмотра кода созданной веб-формы (ее реализа- ции на языке С#) можно воспользоваться командой глав- ного меню программы View ► Code (рис. 16.24). а» в* I® Г-I Рис. 16.24. Команда Code Код формы выглядит следующим образом (листинг 16.17). Листинг 16.17 Код формы using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtrnlControls: using IC.VB.Data; using _lC.V8.WebControls; namespace MySite { public class nomenlist : System.Web.UI.Page { /// Заголовок страницы. protected Literal Title: protected V8Grid Grid: /// Источник данных. protected V8ListDataSource ListDataSource; III Командная панель. protected V8CommandPanel Panel: #region Web Form Designer generated code override protected void OnInit(EventArgs e) { InitializeComponentl); base.Onlnit(e); } /// Required method for Designer support - do not modify /// the contents of this method with the code editor. private void Initial izeComponentO { this.Load += new System.EventHandler(this.Page Load); this.Init += new System.EventHandler(this.Pagelnit); } #endregion private void Page_Init(object sender. System.EventArgs e) { // настройка командной панели string controlName = Request.Params["ControlName"]; if (controlName != null && controlName != string.Empty) { Grid.State = V8Grid.V8GridState.Select; // Если установлено имя ЗУ, значит, список // открыт для выбора. Добавляем колонку // Представление, так как при выборе // его нужно передавать в ЗУ Li stDataSource.Fi elds.Add( Li stDataSource.Metadata.TermStri ng( WebConsts.kPresentationPropTermString), false, false): Grid.PresentationField = Li stDataSource.Metadata.TermStri ng( WebConsts.kPresentationPropTermString); } else { foreach (V8CommandButton btn in Panel. Buttons. GetButtonsByType( V8CommandButtonType.Choice)) btn.Visible = false; } i f (Li stDataSource.CheckAccessRi ght( V8Rights.InteractiveDelete)) { const int ActionsBtn = 10; // для объектов команду удаления добавляем // в подменю "действия" V8CommandButton btn = new V8CommandButton(); Panel.Buttons[ActionsBtn].SubMenu.Add(btn); btn.CommandType = V8CommandButtonType.Delete: } V8WebUti1.SetButtonsStateByRi ght( ListDataSource, Panel.Buttons, V8CommandButtonType.Insert, V8Rights.Interactiveinsert); VBWebUt i1.SetButtonsStateByRi ght( ListDataSource, Panel.Buttons, V8CommandButtonType.InsertFolder. VBRights.Interactiveinsert); VBWebUt i1.SetButtonsStateByRi ght( ListDataSource, Panel.Buttons, V8CommandButtonType.Copy, V8Rights.Interactiveinsert); V8WebUti1.SetButtonsStateByRi ght( ListDataSource, Panel.Buttons, V8CommandButtonType.Deleti onMark, V8Rights.InteractiveSetDeletionMark); VBWebUti1.SetButtonsStateByRi ght( ListDataSource, Panel.Buttons, V8CommandButtonType.Delete, V8Rights.Interact!veDelete); } private void Page_Load(object sender. System.EventArgs e) { // проверка прав на просмотр таблицы if (!ListDataSource.CheckAccessRight(VBRights.View)) { VBWebUti1.Regi sterShowErrorScript( _1C.V8.Data.V8.GetString( "err_accessRightViolation"), this, true);
Response. EndO; return; } if (IIsPostBack) Title.Text = ListDataSource.Tableinfo.Presentation; } } } Прокомментируем данный код. Оператор using определя- ет пространства имен библиотеки классов, которые ис- пользуются в данной форме. Два последних из них: ♦ _lC.V8.Data; ♦ _lC.V8.WebControls. Они являются специфическими для Web-расширения. Пространство имен _lC.V8.Data содержит определения клас- сов, реализующих различные механизмы работы с инфор- мационными базами. Пространство имен _lC.V8.WebControls содержит определение элементов управления, специфи- ческих для Web-расширения, и их свойств. Далее в коде формы определяется пространство имен проекта MySite. В этом пространстве имен определяется единственный класс nomenlist, он наследуется от класса System.Web.UI.Раде (базового класса для веб-форм). В качестве защищенных членов класса определяются за- головок формы (Title) и все объекты, размещенные в диа- логе формы (источник, список, командная панель). Далее определяется функция инициализации класса (OnInit(EventArgs е)). В данном обработчике производится вызов функции InitializeComponentO, которая отвечает за определение функций (членов класса), как обработчиков каких-либо событий. Далее производится вызов метода Init базового класса (System.Web.UI.Page). Далее по коду определяются две функции, которые функ- цией InitializeComponentO были назначены как обработчи- ки события инициализации и загрузки формы. Следует отметить, что любой обработчик события явля- ется защищенным членом класса, функцией, которая не возвращает значения (void). У данной функции определено два параметра. Первый параметр — это элемент, с которого произошел вызов данной функции (объект, являющийся источником события), второй параметр содержит объект, описывающий «детали» возникшего события. В функции обработчике события Page_Init производится настройка командной панели, определенной в форме (опре- деляется состав кнопок). Первоначально анализируется воз- можный параметр запроса ControlName (Request.Params ["ControlName"]). В случае если в этом параметре определено значение отличное от null, это значит, что форма открывает- ся как форма выбора. Тогда для элемента управления уста- навливается режим выбора (при двойном щелчке форма будет закрыта и выбранное значение будет передано форме, из которой производился запрос), в источнике инициализи- руемой формы добавляется колонка Представление (для пе- редачи в элемент управления, в который производится вы- бор значения). В противном случае пытаемся найти кнопку выбора (в командной панели) и сделать ее невидимой. Остальные кнопки устанавливаются в соответствии с пра- вами пользователя, в контексте которого производится обращение к базе данных 1С:Предприятия. В обработчике события Page_Load производится проверка прав пользователя на просмотр списка (в противном слу- чае формируется сообщение о нарушении прав доступа). Далее проверяется свойство IsPostBack. Свойство позволя- ет отследить «первую загрузку» формы (форма загружает- ся не в связи с отработкой каких-либо «пользовательских» событий, то есть не «повторно»), В случае если форма за- гружается впервые, устанавливается заголовок формы. Следует обратить внимание на тот факт, что инициализа- ция формы и ее загрузка производятся каждый раз, как при ее первоначальной загрузке, так и при отработке ка- ких-либо событий на стороне сервера. Форма объекта, вызываемая по умолчанию Если при работе в ранее созданной форме списка номенк- латуры произвести двойной щелчок левой клавишей мыши, то откроется форма, содержащая данные о вы- бранном элементе справочника (рис. 16.25). Э Ни,... нк Uk ru-.uff hdeffiel F Fite Edit View Favorites Tools Help ©Back • ©' [J Q ©I ^Search фMedia ©j Я D Kt Address lahttp://locahost/My5ite/nomenlist.aspx g m 1g Перейти ▼ И Код 0000014 0000015 (полное наименовании | Indesit WS 105 ТХ A rd и TL 1000 Е: Добнови 1ание S 105 ТХ ооо е: :-1 Рис. 16.25. Форма элемента справочника
WebForml.aspx | nomenlist, aspx | nomenlist.aspx.es DefauftObjertFomr».a5pK* [ < l> ?- ......— ......................------------ ### mainTableCtrI System.Web.UI.WebControls. Table Рис. 16.26. Фрагмент диалога формы Это происходит несмотря на тот факт, что явно «форма элемента» справочника нами не создавалась. Дело в том, что в проект изначально включен набор форм «по умолчанию» (их перечень рассматривался ранее). И как раз в этом случае одна из этих форм и используется (DefaultObjectForm). Рассмотрим данный механизм более подробно. Начнем с самой формы DefaultObjectForm. В диалоге фор- мы определен источник данных, без указания таблицы, с которой он связан, и два элемента управления: ♦ таблица (обычный серверный элемент управления из пространства имен Sysytem.Web.UI.WebControls); ♦ командная панель (элемент управления, специфиче- ский для Web-расширения). Фрагмент диалога формы показан на рис. 16.26. В командной панели определены три кнопки (OK, Save, Close). Состав коллекции кнопок, возможные варианты настройки показаны на рис. 16.27. Рис. 16.27. Состав коллекции кнопок Программная реализация формы на языке C# приведена ниже (листинг 16.18). Следует отметить, что данный код приводится в качестве примера формы, определяемой программно (на основании переданных параметров). Ни- кто не гарантирует, что со временем реализация этой формы не будет меняться. Листинг 16.18. Программная реализация формы DefaultObjectForm using System; using System.Col lections; usi ng System.Col1ect1ons.Speci al1zed: using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.III; using System.Web.UI.WebControls; usi ng System.Web.UI.HtmlControls; using System.10: using _lC.V8.Data; using _lC.V8.WebControls; namespace _1C.VB.Forms { /// <summary> /// Форма объекта /// </summary> public class DefaultObjectForm : System.Web.UI.Page { protected _1C.V8.WebControls.V8CommandPanel menuPanel; protected _1C.VB.WebControls.V8CommandPanel mainPanel; protected System.Web.UI.WebControls.Table mainTableCtrl; protected Literal Title; protected _1C.VB.WebControls.V80bjectDataSource objectDS: public const string CssLabelClass = "labelltem"; public const string CssTextBoxClass = "textbox”; private void DefaultObjectForm lnittobject sender. System.EventArgs e) { if (Sessionf'Culture"] != null) System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.Culturelnfot (stri ng)Sessi on["Cuiture"]); string IBAlias = (string)Request.Params["IBAlias"]; if (IBAlias = null) IBAlias = string.Empty; objectDS.IBAlias = IBAlias: V8Metadata metadata = V8Metadata.GetMetadata(IBAlias); if (Request.Params["KeyType”] != null) { objectDS.TableName = metadata.TableNameByTypeName( Request.Paramsf"KeyType"]); } else if (Request.Params["TableName"] != null) { objectDS.TableName = Request.Params[”TableName"]; } else if (Request.Params["CopyKeyType"] != null) { objectDS.TableName = metadata.TableNameByTypeNamef Request.Paramsf"CopyKeyType"]); } else { throw new Exception(_lC.V8.Data.VB.GetString( "errWrongPageParameters")); } objectDS.ChecklsFolder(Request.Paramsf"IsFolder”], Request.Params["KeyValue"], Request.Params["CopyKeyValue"], Request.Paramsf"CopyKeyType"]): objectDS.SetTabularParts( objectDS.GetAl1TabularParts());
// Проверка на Redirect FormType formType = FormType.Element; if (objectDS.IsFolder) formType = FormType.ElementFolder; string url = V8Config.GetUrl(objectDS.IBAlias, objectDS.TableName, formType); if (url != string.Empty && url != WebConsts.DefaultForms.DefaultObjectFormName) Server.TransferCurl); Title.Text = objectDS.Tableinfo.Presentation; ConstructFormC); } private void DefaultObjectForm_Load(object sender. System.EventArgs e) { // проверка прав на просмотр таблицы if (!objectDS.CheckAccessRight(V8Rights.View)) { VBWebUti1.Regi sterShowErrorScri pt( _1C.V8.Data.V8.GetStri ng( "erraccessRightViolation"), this. true): Response.End(); return: } if (UsPostBack) { Regi sterResi zeScri pt(); } } #region Web Form Designer generated code override protected void OnlnitCEventArgs e) { InitializeComponentO; base.Onlnit(e); } private void InitializeComponentO { this.Load += new System.EventHandlerC this.DefaultObJectForm_Load); this.Init += new System.EventHandlerC this.DefaultObjectFormlnit); this.PreRender += new System.EventHandlerC this .Defaul tObjectFormPreRender); } #endregion /// <summary> /// Создать элементы управления формы /// </summary> protected void ConstructFormC) { bool enabled = objectDS.CheckAccessRi ght(V8Ri ghts.Edit): objectDS.Enabled = enabled: menuPanel.Buttons[0].Text = V8.Data.V8.GetString( “menureRead"); string presentationName = objectDS.Metadata.TermStri ng( WebConsts.kPresentationPropTermString); // создаем ЗУ для отображения и редактирования // полей тапки VBItemDSFieldCollection fields = objectDS.GetFieldsO: foreach (V8ItemDSField field in fields) { if ((field.Visible) continue; V8FieldInfo fieldinfo = objectDS.Tableinfo. FieldsInfoffield.NameJ; if (fieldinfo.Readonly) continue; // пропускаем хранилище значения if (fieldlnfo.TypeDomain.Types.C ount = 1 && string.CompareC fi eldlnfo.TypeDomai n.Types[0]. V8Consts.kValueStorageTypeString, true) = 0) { continue; } TableRow row = new TableRowO: mainTableCtrl.Rows.Add(row); TableCell cell = new TableCellO: row.Cells.Add(cell); Label label Ctrl = new Label(); cell.Controls.Add(labelCtrl); label Ctrl.Text = fieldinfo.Presentation; 1abelCtrl.CssClass = CssLabelClass; cell = new TableCellO; row.Cells.Add(cell); cell.Width = Unit.Percentage(lOO): V8TextBox textBoxCtrl = new V8TextBox(); textBoxCtrl.IBAlias = objectDS.IBAlias; cel 1.Controls.Add(textBoxCtrl): if (fieldinfo.PresentationLength = 0 || fieldlnfo.PresentationLength > 25) textBoxCtrl.Width = Unit.Percentage(lOO): else textBoxCtrl .Width = new Um't(27, UnitType.Ex); textBoxCtrl.ID = fieldinfo.Name; textBoxCtrl.CssClass = CssTextBoxClass; if (string.Equals(fieldlnfo.Name, objectDS.TableInfo.ParentField)) textBoxCtrl.ChoiceMode = Choi ceFoldersAndltems.Folders; textBoxCtrl.Type = fieldinfo.TypeDomain; if (fieldinfo.TypeDomain.Types.Count > 1) textBoxCtrl.ClearButton = true; bool existReference = fieldlnfo.ReferenceExist; bool existEnum = fieldlnfo.EnumExist || fi el dinfо.BoolExi st j| fi el dlnfo.EnumRefExi st; if (existReference) { textBoxCtrl.Sei ectButton = true; textBoxCtrl.OpenButton = true: textBoxCtrl.ClearButton = true: } else if (existEnum || fieldinfo.DateExist) { textBoxCtrl.SeiectButton = true; } else if (fieldinfo.TypeDescriptionExist) { textBoxCtrl.SeiectButton = true: textBoxCtrl.SeiectURL = WebConsts. DefaultForms. DefaultTypeChoi ceFormName; textBoxCtrl.AvailableTypes = fieldinfo. AvailableTypes; } textBoxCtrl.ItemDataSource = objectDS.UniquelD; textBoxCtrl.FieldName = fieldinfo.Name; } // создаем закладки для табличных частей V8ItemDSTabularPartCollection tabularParts = objectDS. GetAlITabularParts(); if (tabularParts.Count > 0)
{ mainTableCtrl.Height = Unit.Percentage(lOO): TableRow row = new TableRowO; mainTableCtrl.Rows.Add(row); TableCell cell = new TableCellO; row.Cells.Add(cell); cell.ColumnSpan = 2; cell.Height = Unit.Percentage(lOO); V8TabControl tabControl = new V8TabControl(); cel1.Controls.Add(tabControl); tabControl.Width = Unit.Percentage(lOO); tabControl.Height = Unit.Percentage(lOO): // для каждой табличной части создаем таблицу fbreach (V8ItemDSTabularPart tp in tabularParts) { V8Tab tab = new V8Tab(); tabControl.Tabs.Add(tab); tab.Text = objectDS. Metadata. TablesInfo[objectDS.TableName + + tp.Name]. Presentation: HtmlTable tabTable = new HtmlTableO: tab.Controls.Add(tabTable): tabTable.Width = "100Г; tabTable.Height = "1002": tabTable.CellSpacing = 0; tabTable.CellPadding = 0; HtmlTableRow tabRow = new HtmlTableRowO: tabTable.Rows.Add(tabRow); HtmlTableCell tabCell = new HtmlTableCellO: tabRow.Cel 1s.Add(tabCel1); tabCell.ColSpan = 2: VBCommandPanel panel = new V8CommandPanel(); tabCell.Controls.AddCpanel): panel.LinkedControl = "Table." + tp.Name; panel.ID = tp.Name + "Panel": V8CommandButton btn = new V8CommandButtonO: btn.CommandType = V8CommandButtonType.InsertRow: panel.Buttons.Add(btn); btn = new V8CommancButtonO: btn.CommandType = V8CommandButtonType.CopyRow: panel.Buttons.Add(btn); btn = new V8CommandButton(); btn.CommandType = V8CommandButtonType.DeleteRow: panel.Buttons.Add(btn); tabCel1.Controls.Add( new Literalcontrol( ₽"<div style='height:2px'><img src="' + WebConsts.Images.Emptylmage + /></div>")); tabRow = new HtmlTableRowO: tabTable.Rows.Add(tabRow): tabCell = new HtmlTableCellО: tabRow.Cel 1s.AddCtabCel1): tabCell.Width = "Ipx"; tabCel1.Controls.Add( new Literalcontrol( ₽"<div style='width:lpx;height:80px'>" + "<img src=’" + WebConsts.Images.Emptylmage + /></div>")): tabCell = new HtmlTableCellО: tabRow.Cel Is.AddCtabCel1): tabCell.Height = "1002"; tabCell .Width = "1002": Panel overPanel = new Panel О: tabCell.Controls.Add(overPanel); overPanel.Width = Unit.Percentage(lOO): overPanel.Height = Unit.Percentage(lOO): overPanel.Style.Add("overflow", "auto"); V8TableInfo subTableinfo = objectDS. Metadata. TablesInfo[objectDS.TableName + '.' + tp.Name]: V8EditGrid editGridCtrl = new V8EditGrid(); editGridCtrl.IBAlias = objectDS.IBAlias: editGridCtrl.ID = "Table." + tp.Name: overPanel.Controls.AddCeditGridCtrl); editGridCtrl.GridLines = GridLines.Horizontal: editGridCtrl.Borderwidth = Unit.Pixel(1): editGridCtrl.Borderstyle = Borderstyle.Sol id: editGridCtrl.BorderColor = Color.Gray; editGridCtrl.Width = Unit.Percentage(lOO); editGridCtrl.ItemDataSource = objectDS.UniquelD; editGridCtrl.DataMember = tp.Name: // создаем колонки по полям табличной части V8ItemDSFieldCollection tpFields = tp.GetFieldsO; foreach (V8ItemDSField field in tpFields) { if ((field.Visible) // T0D0 переделать на // невидимую колонку у грида continue: V8FieldInfo fieldinfo = subTableinfo. Fiel dsInfo[fi eld.Name]; if (fieldinfo.Readonly) continue: V8EditGridColumn column = new V8Edi tGridColumn(): editGridCtrl.Columns.Add(column): column.FieldName = fieldinfo.Name: column.HeaderText = fieldinfo.Presentation; column.Type = fieldlnfo.TypeDomain: if (field.Presentation) column.PresentationField = fieldinfo.Name + presentationName; if (fieldlnfo.TypeDomain.Types.Count > 1) column.ClearButton = true: bool existReference = fieldlnfo.ReferenceExi st: bool existEnum = fieldlnfo.EnumExist || fieldinfo.BoolExist || fieldlnfo.EnumRefExist: if (existReference) { column.ClearButton = true; column.OpenButton = true: column.SelectButton = true: } else if (existEnum || fieldinfo.DateExist) { column.SelectButton = true: } else if (fieldinfo.TypeDescriptionExist) { column.SelectButton = true: column.SeiectURL = WebConsts. DefaultForms. DefaultTypeChoi ceFormName; column.AvallableTypes = fieldinfo. AvailableTypes; }
} } } // Добавить дополнительные команды if (enabled && objectDS.Tableinfo.Helper 1= null && objectDS.Tableinfo.Helper.Actions != null) { ArrayList actions = objectDS. Tableinfo. Helper. Actions; int pos = mainPanel.Buttons.Count - 1; if (pos < 0) pos = 0; foreach (VBAction action in actions) { if ([action.Item) continue; V8CommandButton btn = new V8CommandButton(); btn.CommandType = V8CommandButtonType.Custom; btn.CommandName = action.Name; btn.Text = action.Presentation; btn.Hint = action.Presentation; mainPanel.Buttons.Insert(pos, btn); pos++; } } } protected void RegisterResizeScriptO { string s = "<script>ResizeWindow(500, 350):</script>"; Page.RegisterStartupScript("Resize", s); } private void DefaultObjectForm_PreRender(object sender. System.EventArgs e) { switch (objectDS.FormMode) { case V8ItemDataSourceMode.New : menuPanel,Buttons[l].Text = VB.Data.V8. GetStri ng( ’’V8ItemDataSourceMode. New”); break; case V8ItemDataSourceMode.Edit : menuPanel,Buttons[lJ.Text = VB.Data.V8. GetString("VBItemDataSourceMode.Edit"): break; case V8ItemDataSourceMode.Copy : menuPanel.Buttons[l].Text = V8.Data.V8. GetStri ng("VBItemDataSourceMode.Copy"); break; case VBItemDataSourceMode.InputOnBasis : menuPanel.Buttons[l].Text = V8.Data.V8. GetStri ng("V8ItemDataSourceMode. InputDnBasis"): break; } } } } Если рассмотреть представленный код, то можно отме- тить, что «структура» кода совпадает со структурой кода любой веб-формы (в том числе веб-формы, позволяющей работать со списком номенклатуры). Отличительной осо- бенностью является наполнение (код) обработчика со- бытия инициализации веб-формы (DefaultObjectForm lnit) и наличие «дополнительной» функции ConstructForm. Рас- смотрим их назначение и особенности функционирова- ния. Обработчик инициализации формы DefaultObjectForniJnit фактически производит настройку источника данных (V80bjectDataSource objectDS). Производится опрос воз- можных параметров запроса к данной форме. На случай, если веб-приложение работает с несколькими базами ЮПредприятия, проверяется значение парамет- ра IBAlias, полученное значение устанавливается в свой- ство объекта источника данных. Далее (в нашем случае в параметре КеуТуре, получаемом с помощью вызова Request.Params["KeyType"J) определяет- ся значение Справочник.Номенклатура (это значение в за- прос к форме включается автоматически). Значение по- лученного параметра устанавливается как имя таблицы источника данных. Далее по коду делается ряд проверок и осуществляется установка других (не менее важных) свойств источника. Практически в самом конце обработчика размещены сле- дующие строки (листинг 16.19). Листинг 16.19. Фрагмент кода string url = V8Config.GetUrl(objectDS.IBAlias, objectDS.TableName, formType): if (url != string.Empty && url != WebConsts.DefaultForms.DefaultObjectFormName) Server.Transfer(url); В первой строке производится попытка получения фор- мы, назначенной «основной» (используются данные, за- писанные в файле TableFormMap.xml). В случае если в ре- зультате выполнения метода GetUrlO не возвращается либо пустая строка, либо имя формы «по умолчанию», то производится переход на данную (специфическую) фор- му (Server.Transferor!)), путь к которой был получен. Если переход на другую форму не производится, то вы- зывается функция ConstructForm(). В тексте модуля дан- ной функции можно выделить несколько основных мо- ментов: ♦ в самом начале производится проверка на наличие прав на редактирование объекта; ♦ в соответствии с метаданными объекта создается набор элементов управления, связанных со свойствами редак- тируемого объекта; ♦ в соответствии с метаданными объекта создается набор элементов управления V8Edi tGrid, определяется состав колонок (в соответствии с набором реквизитов соотве- ствующих табличных частей). Связывание списков Поставим перед собой задачу: определить в веб-форме, позволяющей работать со списком номенклатуры, воз- можность просмотра и заполнения регистра сведений Це- ныНоменклатуры. Регистр сведений имеет два измерения: ♦ Номенклатура, тип СправочникСсылка.Номенклатура; ♦ ТипЦены, тип СправочникСсылка.ТипыЦен. Также регистр имеет ресурс Цена, тип Число. Регистр непе- риодический, режим записи Независимый.
Вернемся к форме nomenlist.aspx. Добавим в форму спи- ска новый источник (V8ListDataSource), в качестве табли- цы (свойство TableName) укажем таблицу РегистрСведений. ЦеныНоменклатуры (рис. 16.28). Properties VBListDataSourcel _1С. V8. WebControls. V8ListData5ource GMta: Wher eClause Wher eParameters AJowedData CholceMode Conditionclause Fields Hierarchical IBAlias InitByRequest OrderFieids PageSize TableName V8ListDataSourcel jTrue FoldersAndltems____ _ |(Cotection) j(Cofection) True _ 4------------------------------------- 20 ___________________________________ Регис трСве дений ДеныНоменк лату ры False Номенклатура =&Ссылка (Colection) Рис. 16.28. Свойства источника данных V8ListDataSource При настройке свойств нового источника в свойство WhereCl ause потребуется записать условие (можно сказать, что описание условия в данном свойстве равнозначно описанию условия в разделе ГДЕ при построении запроса к указанной таблице). Если необходимо определить усло- вие как параметр виртуальной таблицы, то в этом случае используется коллекция ConditionClause. Так же как и при описании запроса, параметр описывает- ся с помощью символа &, но в отличие от работы с объек- том Запрос 1С:Предприятия 8.0, параметр должен быть еще и определен (не путать с присвоением параметру зна- чения). Определение параметров происходит при на- стройке коллекции WhereParameters (необходимо просто создать новый параметр и указать его имя: Ссылка). После настройки нового источника необходимо добавить еще один серверный элемент управления V8Grid. В свой- ство ListDataSource определить имя добавленного источ- ника данных (рис. 16.29). Кроме этого, можно в свойство Width записать значение 100% (это приведет к тому, что ширина табличного поля будет совпадать с шириной открываемой формы). После размещения элемента в диалоге можно определиться с составом отображаемых им колонок. Для этой цели сна- чала нужно выполнить команду контекстного меню Fill columns (заполнить колонки) добавленного элемента управления V8Grid (рис. 16.30). После выполнения указанной команды будет автомати- чески (в соответствии с указанным источником) заполне- на коллекция Col umns табличного поля. Остается удалить из коллекции «не нужные» колонки (рис. 16.31). Properties ” Ц | VSGridi _1 С. V8. WebControls. V8Grid j ES 13 Appearance 13 haHor В Data (DataBindings) DataMember DataMemberParents DataSource IBAlias IsFolderField KeyFields V8ListDataSourcel PresentationField TableName Рис. 16.29. Установка свойства ListDataSource View HTML Source X Cut 111 Copy I Paste Paste as HTML X Delete Build Style . View in growser View Client Script ViewQode Synchronize Document Outline H columns Q Properties Рис. 16.30. Команда Fill columns Следующим действием будет назначение элементу управ- ления V8Grid, ответственного за список номенклатуры, об- работчика события SelectedlndexChanged (при изменении текущего индекса строки). Для этой цели в окне просмот- ра свойств необходимо переключиться в режим просмотра обработчиков событий (кнопка с «молнией»), установить курсор напротив события с именем V8Grid_SelectedIndex- Changed (рис. 16.32) и нажать кнопку Enter на клавиатуре. При этом выполнится два действия. Во-первых, в функции InitializeComponentO (ответственной за определение обработчиков событий) появится новая строка. Этой строкой новая функция Grid_SelectedIndex- Changed() назначается обработчиком события Selected- lndexChanged для элемента управления V8Grid («табличное поле», созданное конструктором формы и позволяющее работать со списком номенклатуры). Добавленная строка выделена серым фоном (листинг 16.20). V Ш j. I 1<К о I um n С о I le< tio и Е di to I Members: ПТ ТипЦен _1]Цена ТилЦен Properties: Columns Hierarchical HierarchyByElement OpenEnabled OpenFolderLkl OpenUrl Selectedlndex . State VBGridl (Collection) False False True 0 Browse Рис. 16.31. Настройка колонок списка
Рис. 16.32. Событие SelectedlndexChanged Листинг 16.20. Функция InitializeComponent private void Initial izeComponentO { this.Grid.SelectedlndexChanged += new System.EventHandler! this. GridSel ectedlndexChanged); this.Load += new System.EventHandler(this.Page Load): this.Init += new System.EventHandler(this.Pagelnit); } Во-вторых, в коде описан заголовок функции Grid_Selected- IndexChanged(). Остается определить внутри функции следующие строки кода (листинг 16.21). Листинг 16.21. Функция Grid SelectedlndexChanged private void Grid SelectedlndexChanged! object sender. System.EventArgs e) { V8ListDataSourcel.WhereParameters[0].Value = Gr i d.Iterns[Gri d.Seiectedlndex].KeyValues[0]; V8ListDataSourcel.First!): V8Gridl.DataBind(): } В данной функции производится получение ключевого поля (мы определили в качестве ключевого поля ссылку на номенклатуру) по текущему (новому) индексу записи в списке номенклатуры. Полученная ссылка устанавли- вается в значение первого параметра (обращение к пара- метрам производится по индексу, первый параметр, а он у нас и единственный в коллекции параметров, имеет ин- декс равный нулю). Далее источник V8ListDataSourcel (связанный с регистром сведений) принудительно перечитывает данные в соот- ветствии с новым значением параметра. После этого у табличного поля (V8Gridl) вызывается метод, иниции- рующий получение данных у источника. При проверке реализованного механизма можно убедить- ся, что требуемый результат достигнут (рис. 16.33). Схематически весь процесс можно представить следую- щим образом (рис. 16.34). Рис. 16.34. Схема взаимодействия связанных списков У рассмотренного механизма есть один недостаток. При первоначальном открытии окна табличное поле, связанное с регистром сведений (V8Grid) данными, не заполняется. Это происходит по той причине, что собы- тие SelectedlndexChanged не возникает при открытии формы. Для решения этой проблемы необходимо выполнить не- сколько действий. Сначала следует изменить обработчик загрузки веб-фор- мы (добавить строки) (листинг 16.22). Листинг 16.22. Обработчик события Page_Load private void Page_Load(object sender. System.EventArgs e) { // проверка прав на просмотр таблицы if (IListDataSource.CheckAccessRight(VBRights.View)) { VBWebUti1.Regi sterShowErrorScri pt( _1C. VB. Data. V8. GetStri ng! "erraccessRightViol ation”), this, true); Response.End!); return; } if (UsPostBack) { Title.Text = ListDataSource.Tableinfo.Presentation; Номенктатур* MiciAsoft Internet Exploiei Ffe Edit View Favorites Tods Help ©Back • 0 ’ [»Й | jPsearch «^Favorites ф Media © I Э D KL Address [ffi http://locafr)ost/MySite/riomenlist.aspx <b Go Links ** Перейти ▼ Иерархически Vx Действия ▼ ^Обновить |Й| ПП ПН IQ Код Наименование Пометка удаления ссылка Предопределенный Родитель Это группа Полное наименование D0DD014 Ardo TL 1000 EX-1 Ardo TL 1000 EX-1 Ardo TL 1000 EX-1 0000015 Indesit WS 105 TX Indesit WS 105 t:: Indesit WS 105 TX |ТипЦен Цена | основной 16000,00 | Рис. 16.33. Пример созданной формы
Коне труктор рмы > ieме нта l*J this.ListDataSource.FirstO; this.Grid.DataBindO; this.Grid_SelectedIndexChanged(Grid. null); } } При первой загрузке страницы производится программ- ное чтение данных в источник, связанный с номенклату- рой. Далее производится получение данных соответст- вующим «табличным полем» и после этого производится принудительный вызов функции — обработчика события SeiectedlndexChanged. Затем у обоих элементов управления, — источников дан- ных, — нужно установить свойство InitByRequest в значе- ние False (рис. 16.35). Имя таблицы: | Документ ПоступлениеТоваров Рис. 16.35. Свойство InitByRequest Записывать информацию в Файл соответствия имен таблиц и Фсм* Назад Вперед | | Готово | Отмена Рис. 16.37. Окно конструктора формы элемента Установка данного свойства необходима для исключения двойного считывания данных (так как теперь данные считываются и программно). V8ltemForm Для создания веб-формы, которая бы отображала данные какого-либо объекта (элемента справочника, документа и т. п.), необходимо выбрать шаблон V8 Item Form (рис. 16.36). Рис. 16.36. Шаблон V8 Item Form После определения имени создаваемой формы открыва- ем шаблон. Для начала необходимо определиться с объектом, для ко- торого будет создаваться веб-форма. Будем, считать, что необходимо создать форму документа Поступление това- ров (рис. 16.37). После выбора таблицы необходимо определиться с соста- вом реквизитов. Следует отметить, что в данном случае желательно выбирать все реквизиты (кроме предопреде- ленных), если только вы не создаете форму «только для просмотра»). После нажатия на кнопке Вперед необходимо будет вы- брать табличную часть, которая будет размещена в веб- форме, и определиться с составом отображаемых рекви- зитов табличной части документа. Заметьте, несмотря на то, что есть возможность для табличной части выбрать ссылку и номер строки, делать это совсем не обязательно (рис. 16.38). Рис. 16.38. Выбор реквизитов табличной части После нажатия на кнопку Готово интересующая нас фор- ма будет создана. Познакомимся с этой формой поближе. В рассматриваемой веб-форме можно увидеть несколько элементов управления: ♦ V80bjectDataSource — является источником данных (в его настройках указывается таблица, из которой будут из- влекаться данные для формы). В качестве ключевого поля данного элемента выступает ссылка на загружен- ный элемент; ♦ V8TextBox — предназначен для отображения (и обработ- ки) реквизитов шапки документа;
♦ V8EditGrid — предназначен для вывода табличной части документа (на каждую табличную часть по элементу); ♦ V8CommandPanel — реализует командную панель (как для экземпляра документа в целом, так и для каждой таб- личной части). Взаимосвязь элементов управления в упрощенном виде можно изобразить в виде следующей схемы (рис. 16.39). Рис. 16.39. Взаимосвязь элементов управления Внутри каждого объекта указаны свойства, посредством которых настраивается взаимосвязь указанных элемен- тов управления. Программная реализация веб-формы строится по «стан- дартной» схеме и имеет следующий вид (листинг 16.23). Листинг 16.23. Программная реализация веб-формы using System; using System.Col lections; using System.ComponentModel; using System.Data: using System.Drawing; using System.Web: using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls: using System.Web.UI.HtmlControls; using _lC.V8.Data; using 1C.V8.WebControls; namespace MySite { /// <summary> /// Summary description for docobj. /// </summary> public class docobj : System.Web.UI.Page { /// <summary> /// Заголовок страницы. /// </summary> protected Literal Title; /// <summary> /// Источник данных. /// </summary> protected V80bjectDataSource ItemDataSource; /// <summary> /// Командная панель. /// </summary> protected 1C.VB.WebControls.V8CommandPanel menuPanel; /// <summary> /// Командная панель формы. /// </summary> protected 1C.V8.WebControls.VBCommandPanel mainPanel; /// <summary> /// Редактирование полей /// </summary> protected System.Web.UI.WebControls.Label Labelflara; protected V8TextBox Дата; protected System.Web.UI.WebControls.Label LabelHoMep: protected V8TextBox Номер; protected System.Web.UI.WebControls.Label LabelКонтрагент; protected V8TextBox Контрагент; protected System.Web.UI.WebControls.Label LabelСклад; protected V8TextBox Склад; protected System.Web.UI.WebControls.Label LabelСсылка; protected VBTextBox Ссылка: protected System.Web.UI.WebControls.Label LabelПометкаУдаления; protected V8TextBox ПометкаУдаления; protected System.Web.UI.WebControls.Label LabelПроведен; /// <summary> /// Редактирование табличных частей /// </summary> protected V8TabControl VBTabControll; // Состав protected V8Tab V8Tabl; protected VBEditGrid VBEditGridl; protected _1C.V8.WebControls.V8CommandPanel V8CommandPanel3: #region Web Form Designer generated code override protected void OnlnitCEventArgs e) { Initial izeComponentO; base.Onlnit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponentO { this.Load += new System.EventHandler(this.Page Load); this.PreRender += new System.EventHandler( this. PagePreRender); } #endregion private void Page_Load(object sender. System.EventArgs e) { // проверка прав на просмотр таблицы if (!ItemDataSource.CheckAccessRight(V8Rights.View)) { V8WebUti1.Regi sterShowErrorScri pt( _1C. V8. Data. V8. GetStri ng( "erraccessRi ghtV i ol ati on"), this, true); Response. EndO; return; } if (UsPostBack) Title.Text = ItemDataSource.Tablelnfo.Presentati on; } private void Page_PreRender(object sender. System.EventArgs e) { switch (ItemDataSource.FormMode) { case V8ItemDataSourceMode.New : menuPanel.Buttons[l],Text = _lC.V8.Data.V8. GetStri ng("V8ItemDataSourceMode.New"); break;
case V8ItemDataSourceMode.Edit : menuPanel.Buttons[l].Text = _lC.VB.Data.VB. GetStri ng(”V8ItemDataSourceMode.Edit"): break; case VBItemDataSourceMode.Copy : menuPanel.Buttons[l].Text = _lC.V8.Data.V8. GetStri ng("V8ItemDataSourceMode.Copy"): break; case V8ItemDataSourceMode.Input0nBasis : menuPanel.Buttons[l].Text = _lC.V8.Data.V8. GetString("V8ItemDataSourceMode. InputOnBasis"): break; } } } } В пространстве имен проекта определяется новый класс. Все элементы управления определены как защищенные члены класса. Далее по коду определяются обработчики событий. Обработка строки табличной части При работе с документом, созданным в предыдущем раз- деле, становится очевидным одно неудобство: сумма по строке табличной части не считается, цена не подбирает- ся. Данные механизмы уже давно относятся к «обязатель- ным». Рассмотрим пример реализации расчета суммы по строке по введенному количеству и сумме. В самом начале потребуется включить в проект новую форму (используя шаблон Web Form). В диалоге размес- тить несколько элементов управления: ♦ V8LineDataSource (имя LineDS, в качестве источника ука- зана табличная часть документа); ♦ V8TextBox (по одному элементу управления на каждый реквизит табличной части); ♦ надписи (обычные HTML-элементы); ♦ V8CommandPanel, командная панель, связанная с объектом lineDS. Приблизительный вид формы (рис. 16.40). : Page | WebForml aspx | docBst.aspx | docobj.aspx | docobj.aspx.es bnedocaspK* | Snedoc.aspx.cs | DefaukL Цена [ fab (Номенклатура □ — ... р [Количество [ ^ibc LyMMa [ ш VBLmeDaiaSource' lineDS Рис. 16.40. Внешний вид веб-формы Для элементов управления V8TextBox, связанных с рекви- зитами табличной части Количество и Цена, можно опре- делить обработчик события ValueChanged. Текст всей фор- мы приведен ниже (листинг 16.24). Листинг 16.24. Программная реализация веб-формы using System; using System.Col lections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.Sessionstate; using System.Web.UI; using System.Web.UI.WebControls; us i ng System.Web.UI.HtrnlControls; using _lC.V8.Data; using 1C.VB.WebControls; namespace MySite { /// <summary> /// Summary description for linedoc. /// </summary> public class linedoc : System.Web.UI.Page { protected _lC.VB.WebControls.V8TextBox V8TextBoxl; protected _lC.VB.WebControls.VBTextBox V8TextBox2; protected _1C.V8.WebControls.V8TextBox V8TextBox3; protected _lC.V8.WebControls.VBLineDataSource lineDS; protected _lC.V8.WebControls.V8CommandPanel mainPanel; protected _lC.V8.WebControls.V8TextBox V8TextBox4; private void Page_Load(object sender. System.EventArgs e) { // получает список элементов thi s.1i neDS.SetColumns(); } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the // ASP.NET Web Form Designer. // Ini ti ali zeComponent(); base.Onlnit(e): } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponentO { this.V8TextBox2.ValueChanged += new 1C.V8.WebControls. VaiueChangedHandler( this.V8TextBox2_ValueChanged): this.Load += new System.EventHandler(this.PageLoad); #endregion private void VBTextBox2_ValueChanged( System.EventArgs eventArgs) { decimal Summa=O; Summa = Convert.ToDecimal(this.VBTextBox2.Value) * Convert.ToDecimal(this.V8TextBox3.Value); this.V8TextBox4.Value = Summa; } } } He следует забывать тот факт, что если не предпринимать никаких дополнительных шагов, обработка события (из- менения количества и цены) будет производиться только после явной отправки формы. Для того чтобы вызов функции происходил именно при изменении (а не кэши- ровался), необходимо свойство AutoPostBack установить
в значение True. Следует отметить, что не нужно (без осо- бой необходимости) устанавливать данное свойство для всех элементов управления. Рекомендуется это делать только в тех случаях, когда действительно нужна «немед- ленная» обработка данных (фактически после проведе- ния изменений производится отсылка формы серверу) (рис. 16.41). будут отображаться уникальные идентификаторы ссылок на объекты (что, скорее всего, «огорчит» пользователя). На следующем шаге необходимо предварительно нажать кнопку Заполнить (рис. 16.45). Add New Item MySite Categories: Templates: | V8TextBox2 _lC.V8.WebContro!s.V8TextBox ________________________________________________ UseLrstChoice False В tehavtor AccessKey True » - Г1 Web Project Items D UI О Code CJ Data О Utility Cl Resources |НН| V8 Chart Form V8 Item Form V8 List Form Enabled True EnableViewState True Tabindex 0 ToolTip Visible True В Data (DataBindings) AvailableTypes ChoiceMode FieldName IBAlias RemDataSource FoldersAndltems Количество hneDS Рис. 16.41. Свойство AutoPostBack A form for Web Applications Name: |nomenostaspx Open I Cancel I Help Рис. 16.43. Шаблон V8 Report Form Теперь, после того, как форма (ответственная за редакти- рование строки) готова, остается в веб-форме, ответст- венной за редактирование документа, установить нуж- ным образом свойства объекта V8EditGrid (рис. 16.42). Рис. 16.42. Свойство EditlnSeparateWindow Ko h< трукто p (f* рмы отче та V 0 | х Текст запроса: ВЫБРАТЬ Номенклатура КАК Номенклатура. ПРЕДСТАВЛЕНИЕ[Номенклатура) КАК. Товар. Склад КАК Склад ПРЕДСТАВЛЕНИЕ(Склад) КАК Местонахождение, КоличествоОстаток КАК Остаток ИЗ РегистрНакопления. У четНомемк латуры. Остатки ИТОГИ СУММА(Остаток) ПО Склад 1 Указывается, что редактирование строки табличной час- ти будет производиться в отдельном окне. И в качестве этого «окна» будет использоваться вновь созданная фор- ма строки табличной части. Назад I Вперед I | Готово I Отмена V8ReportForm При необходимости включения в создаваемое веб-прило- жение каких-либо отчетных форм можно воспользовать- ся шаблоном V8 Report Form. Создадим отчет, с помощью которого можно будет про- сматривать остатки номенклатурных позиций по складам. Для начала включим в проект новую форму. При созда- нии выбираем шаблон V8 Report Form (рис. 16.43). После открытия шаблона (указания имени создаваемой формы) определяем текст запроса (рис. 16.44). Следует отметить, что получаемая отчетная форма будет обладать функциональностью, похожей на функциональ- ность выходной формы, созданной с использованием воз- можностей построителя отчета. Исходя из этого, в тексте запроса в обязательном порядке должен быть определен раздел ИТОГИ. Кроме этого, важно в текст запроса включать поля представ- лений ссылочных полей, которые потом потребуется пока- зывать в отчете. Если этого не сделать, то в выходной форме Рис 16.44. Пример запроса Рис 16.45. Окно конструктора формы отчета
Конструктор формы отчета V8 |х При определении полей запроса поля представлений ав- томатически (по нажатию на кнопку Заполнить) не запол- няются. Их необходимо настроить (добавить) вручную. При этом форма конструктора должна выглядеть так же, как на рис. 14.45. Настройку списка выбранных полей не изменяем (не нужно вносить в этот список поля пред- ставлений, добавляемых в список полей запроса). Следующим шагом может быть определение группиро- вок строк и колонок. В нашем случае оставим все без из- менений (рис. 16.46). Рис. 16.46. Определение группировок строк и колонок На следующем шаге необходимо указать ряд настроек, важных с точки зрения размещения данных в отчетной форме (рис. 14.47). Рис. 16.47. Установка группировок Закладки на форме Р Выбранные поля Р Отборы Р Группировки р Порядок Рис. 16.49. Выбор состава закладок После последовательного выполнения всех указанных шагов будет создана необходимая веб-форма. Рассмотрим полученную веб-форму более подробно. Основу механизма веб-отчетов составляет элемент управ- ления V8ReportSource. Элемент управления содержит свой- ства, аналогичные свойствам построителя отчета 1 (^Пред- приятия 8.0: ♦ Order — порядок; ♦ Filter — управление отбором; ♦ ColumnGroup — измерения колонок; ♦ RowGroup — измерения строк; ♦ SelectedFields — выбранные поля. Эти свойства могут быть интерактивно настроены поль- зователем, для чего в форме на каждое свойство опреде- лено по элементу управления V8Edi tGrid (аналог таблич- ного поля ЮПредприятия). Для отображения результата запроса служит объект V8ReportViewer. Связанный с ним элемент управления V8CommandPanel позволяет осуществлять навигацию по по- лученному результату запроса (напоминаем, что в общем случае данные отображаются по указанному количеству строк). Состав и взаимосвязь элементов управления, располо- женных на форме можно схематически представить сле- дующим образом (рис. 16.50). Далее потребуется указать режим отображения отчета, определить количество строк, отображаемых на странице. Не рекомендуется делать данную величину очень боль- шой, так как это затрудняет как получение данных, так и их просмотр (рис. 14.48). Рис. 16.50. Взаимосвязь объектов формы Рис. 16.48. Настройка вывода отчета На последней странице конструктора отмечается необхо- димость размещения дополнительных закладок, сущест- венно расширяющих функциональность создаваемого веб-отчета. Можно сказать, что данные закладки реализу- ют такую же функциональность, как и табличные части построителя отчета в 1 С: Предприятие 8.0. Назначение «каждой закладки» совпадает с одноименны- ми табличными частями объекта ЮПредприятие 8.0 По- строительОтчета (рис. 14.49). Элемент управления V8ReportSource решает несколько задач; ♦ анализ текста запроса и выдача доступных полей для настроек параметров отчета; ♦ взаимодействие с кэшем отчета; ♦ разбиение результата отчета на группы и страницы. Можно сказать, что этот элемент управления является своего рода сервисной оболочкой, которая избавляет раз-
работника от работы с «деталями» реализации механизма веб-отчетов. Однако при желании можно отказаться от использования данного объекта и «воспроизвести» его функциональность, работая с его «составляющими». Дело в том, что объект V8ReportSource для своей работы использует несколько других объектов и механизмов. Ос- новными из них являются: ♦ V8ReportBuilder, используется для получения данных; ♦ V8ReportData, обработка полученных данных; ♦ механизм кэширования результата отчета; ♦ V8ReportFormatter, производит форматирование данных. В упрощенном виде взаимодействие перечисленных объ- ектов можно представить следующей схемой (рис. 16.51). Оба варианта реализуются с помощью свойств Details и FieldFormat объекта «VSReportSource. Какой вариант ис- пользуется, зависит от способа заполнения этих свойств. Рассмотрим их реализацию более подробно. Считаем, что настраиваем расшифровки у отчета, который создавался в предыдущем разделе. Простые расшифровки Добьемся того, чтобы после того, как отчет был сформи- рован, из него можно было открыть форму элемента как справочника Номенклатура, так и справочника Склады. Начать настройку расшифровок рекомендуется с настрой- ки свойства Details объекта VSReportSource. Необходимо создать новый элемент коллекции и настро- ить его так, как показано на рис. 16.52. Рис. 16.51. Взаимосвязь объектов V ро । tSo ui с eDetai Is <- о Нес tie n E dito i Товар Properties: "сж 1 Cancel I Help I —.......... ' 1 Л Коротко схему можно пояснить следующим образом. Эле- мент управления VSReportSource создает объект V8Report- Builder и передает ему все параметры и настройки, ука- занные пользователем (внесенные в соответствующие элементы управления VSEditGrid). В соответствии с этими параметрами (и текстом запроса отчета) объект VSReport- Builder извлекает данные из информационной базы ЮПредприятия 8.0 и возвращает их в виде объекта VBReportData. Эти данные помещаются в кэш отчета, осно- ванный на стандартном механизме кэширования ASP.NET. Из кэша данные извлекаются по мере необходимости, оформляются с помощью объекта V8ReportFormatter и пе- редаются элементу управления V8ReportViewer. Использование расшифровок В ряде случаев при работе с полученными отчетными данными может потребоваться получение дополнитель- ных (связанных с отображаемыми) данных. К примеру, при просмотре остатков товаров, открыть форму элемен- та справочника. Может потребоваться из одного отчета «перейти» в другой отчет. Например, работая с оборотно- сальдовой ведомостью, в которой каждая строка содер- жит данные об остатках по счету, приходу и расходу, по щелчку в строке желательно перейти в отчет, показываю- щий более детальную информацию по данному счету. Механизм получение таких «дополнительных» данных можно реализовать с помощью расшифровок. Расшиф- ровки можно разделить на два типа: ♦ простые — когда необходимо получить форму объекта по представляемой ссылке; ♦ сложные — когда из одного отчета необходимо перейти в другой отчет (с передачей нужных параметров). Рис. 16.52. Коллекция элементов свойства Details Коллекцию Detai IsParameters настраивать (для простых расшифровок) нет необходимости. В свойстве KeyField- ForElement выбирается поле (из полей отчета), которое со- держит ссылку объекта, форму элемента которого будем получать. В свойстве Name указываем имя расшифровки (его будем использовать при работе со свойством Field- Format). С помощью свойства URLTarget определяем вари- ант получения формы элемента. После настройки свойства Details переходим к опреде- лению свойства FieldFormat. Заполнение этого свойства приведет к тому, что данные, выводимые в указанном поле, будут представлены в виде гиперссылки. Это свой- ство необходимо заполнить, как показано на рис. 16.53. Рис. 16.53. Коллекция элементов свойства FieldFormat
В свойстве Details устанавливаем флаг использования расшифровки. В следующем поле из списка (предвари- тельно должно быть определено свойство Details объекта V8ReportSource) выбираем нужную расшифровку. Для ка- кого поля эта расшифровка определяется полем Name. Расшифровка (была показана настройка расшифровки по номенклатуре) готова, осталось только откомпилировать приложение. «Сложные» расшифровки Механизм «сложных» расшифровок позволяет настроить взаимосвязь существующих в веб-приложении отчетов. С его помощью можно значительно увеличить гибкость системы отчетности, используемой в приложении. Рассмотрим пример реализации связи отчета по остаткам товара с отчетом (его необходимо будет создать), показы- вающим движения выбранного товара понедельно. При создании нового отчета используется следующий за- прос (листинг 16.25). Листинг 16.25. Запрос, используемый для создания отчета о движениях товара ВЫБРАТЬ Период, Номенклатура, Представление(Номенклатура) Как Товар, КоличествоПриход Как Поступление, КоличествоРасход Как Продажа ИЗ РегистрНакопления.УчетНокенклатуры.Обороты! , , Неделя) Так же как и для «простых» расшифровок, определение «сложных» производится с помощью свойств Details и FieldFormat объекта V8ReportSource. Начнем с настройки свойства Details (рис. 16.54). Рис. 16.54. Коллекция Details В созданном элементе коллекции определяется его имя (оно будет использовано при определении свойства Field- Format). С помощью свойства URL указывается путь к фор- ме открываемого отчета. Для указания связи параметров вызывающего отчета с па- раметрами вызываемого используется свойство Detai 1s- Parametrs. Его настройка показана на рис. 16.55. Выбирается вариант сравнения Equal (равенство), опреде- ляется имя параметра отчета, значение выбирается из вы- падающего списка. VORepoi tSo и к eDetai kPa lametei Collection Editoi CK | Cancel Рис. 16.55. Коллекция DetailsParametrs Для того чтобы механизм заработал, остается настроить свойство FieldFormat (рис. 16.56). Рис. 16.56. Коллекция FieldFormat В свойстве Details устанавливаем флаг использования расшифровки. В следующем поле из списка (предвари- тельно должно быть определено свойство Detai 1 s объекта V8ReportSource) выбираем нужную расшифровку. Для ка- кого поля эта расшифровка определяется полем Name. Особенности реализации расшифровок Рассмотрим действие механизма расшифровок. Рассмат- ривать будем на примере «сложных» расшифровок, опре- деляемых в предыдущем разделе (реализация этого меха- низма как для простых, так и для сложных расшифровок строится по одному принципу). Сформируем отчет по остаткам номенклатуры (рис. 16.57). Отчет II Поля II Отбор | Группировки | Порядок I Сформировать | g) |7111 | (1) Перейти ГЯ |Й| | Печать Склад Номенклатура Остаток Стиральные машины 32 Стиральные машины Ardo TL 1000 EX-1 14 Стиральные машины Indesit WS 105 TX 18 Холодильники 29 Холодильники ELECTROLUX ER 9007 В 15 Холодильники Атлант МХМ 1704-00 14 Рис. 16.57. Пример отчета по остаткам номенклатуры
Товар в данном отчете отражается в виде гиперссылок. С точки зрения исходного HTML-кода каждая ячейка таблицы (в которой отражается номенклатурная пози- ция) имеет следующую реализацию (листинг 16.26). Листинг 16.26. Фрагмент HTML-кода < td class="Cel1 Detail fl ^Номенклатура fl (Номенклатура"> <div class="pointer" onclick="doDetai1sCl1ck('ReportViewer', ’Товар', '5'. Атлант МХМ 1704-00 </div> </td> При щелчке мышью по такой ячейке вызывается функ- ция javascript doDetailsClick, определенная в js файле. Под- ключение это файла определяется следующей строкой HTML-кода (листинг 16.27). Листинг 16.27. Фрагмент HTML-кода «script language='javascript’ src='/aspnetcllent71CV8/VBReportV1ewer.js'> </script> Сама функция имеет следующий вид (листинг 16.28). Листинг 16.28. Функция doDetailsClick function doDetailsClicktwcID. name, rowGroup, columnGroup) { if (rowGroup = null || columnGroup = null || name = null) return; __doPostBack(wcID, "Details;" + name + + rowGroup + + columnGroup); } В указанной функции производится проверка заполнен- ности необходимых параметров вызова и производится вызов функции______doPostBack, определенной в HTML-ко- де страницы (листинг 16.29). Листинг 16.29. Фрагмент HTML-кода «script language="javascript"> «!-- function ___doPostBack(eventTarget, eventArgument) { var theform; if (window.navigator.appName.toLowerCaseO. indexOfC'netscape") > -1) { theform = document.forms["Forml"]; } el se { theform = document.Forml; } theform._EVENTTARGET.value = eventTarget. spl i t ("$’’). jo1 n (":"); theform.__EVENTARGUMENT.value = eventArgument; theform.submit(); } // > «/script> Данная процедура на основании полученных через пара- метры данных «программно» генерирует запрос к серверу (для сервера формируется событие Details, которое им в дальнейшем и обрабатывается). V8ChartForm Табличные данные отчета могут быть представлены гра- фически, с помощью диаграмм. Для этого Web-расшире- ние предоставляет возможность создания веб-диаграмм, использующих в качестве своей основы механизм веб-от- четов. Шаблон V8 Chart Form как раз и предназначен для созда- ния веб-форм, показывающих данные в виде диаграммы. Последовательность выполняемых шагов при создании веб-диаграммы идентична последовательности (и особен- ностям заполнения) по созданию формы на основании шаблона V8 Report Form. Поэтому она в данном случае спе- циально не рассматривается. Единственной особенностью (кроме того факта, что вы- бирается другой шаблон) является необходимость выбо- ра вида диаграммы на одном из этапов создания формы (рис. 16.58). Рис. 16.58. Выбор вида диаграммы Основа механизма веб-диаграмм — элемент управления V8ChartSource. Свойства, управляющие настройкой запро- са, аналогичны свойствам V8ReportSource и табличным частям объекта ПостроительОтчета 1 С:Предприятие 8.0: ♦ Order — порядок; ♦ Filter — управление отбором; ♦ ColumnGroup — измерения колонок; ♦ RowGroup — измерения строк; ♦ SelectedFields — выбранные поля. Эти свойства могут быть интерактивно настроены поль- зователем в форме, для чего в ней располагается соответ- ствующее количество (на каждое свойство по одному) элементов управления V8EditGrid. Для отображения полученных данных служит элемент управления V8ChartViewer и связанный с ним элемент управления V8CommandPanel (позволяющий, в том числе, выбирать вид диаграммы). Взаимосвязь элементов управления, расположенных в форме веб-диаграммы, представлена на следующей схе- ме (рис. 16.59).
Рис. 16.59. Схема взаимодействия объектов формы Элемент управления V8ChartSource решает задачи, связан- ные с построением данных отчета: ♦ анализ текста запроса и выдача доступных полей для настроек параметров отчета (эта функциональность реа- лизована в базовом элементе V8ReportBuilder); ♦ формирование и кэширование изображения диаграм- мы. Также как и объект VSReportSource, объект V8ChartSource для своей работы использует ряд других объектов. В уп- рощенном виде их схема взаимодействия выглядит сле- дующим образом (рис. 16.60). При создании диаграммы элементу управления V8Chart- Source устанавливается: ♦ текст запроса; ♦ описание взаимосвязей полей запроса; ♦ отображаемый ресурс; ♦ серии — группировки строк; ♦ точки — группировки колонок; ♦ настройка упорядочивания и отбор; ♦ тип диаграммы; ♦ графический формат диаграммы; ♦ размер изображения. Элемент управления V8ChartSource, используя механизм отчетов, получает результаты выполнения запроса в объ- екте V8ReportData. С помощью объекта V8ChartFormatter, с учетом настроек оформления диаграммы, эти данные преобразуются в описание диаграммы. Это описание пе- редается объекту V8ChartImageCreator, который формирует изображение диаграммы. Сформированное изображение помещается в кэш диаграммы, основанный на стандарт- ном механизме кэширования ASP.NET. Для отображения диаграммы элемент управления V8Chart- Vi ewer размещает на веб-странице ссылку на форму по умолчанию для вывода изображений, которая извле- кает изображение диаграммы из кэша по идентификато- ру, полученному от V8ChartSource. Кроме этого, объект V8ChartImageCreator формирует карту областей изображе- ний (ImgMap), которая служит для поддержки механизма расшифровок и подсказок. Каждая область соответствует определенному элементу изображения (например, под- писи или сектору круговой диаграммы), к которому могут быть привязаны определенные параметры расшиф- ровки и подсказка. Расшифровки диаграммы определя- ются точно таким же образом, как и для отчета. Рис. 16.60. Схема взаимодействия объектов Доступ к данным через ADO.NET С помощью компонентов ADO.NET можно организовывать различную обработку данных: получение, изменение, уда- ление данных из информационной базы данных ЮПред- приятие 8.0. Рассмотрим эти возможности на ряде про- стых примеров. Необходимо помнить, что рассматриваемые объекты (по- средством которых будет организовываться доступ и модификация данных) в основном являются «специфи- ческими» для Web-расширения (определены в простран- стве имен _lC.V8.Data). Также следует отметить, что приводимые ниже примеры (после соответствующей корректировки) позволят адап- тировать уже готовые веб-формы (созданные без ис- пользования Web-расширения) к работе с информаци- онной базой 1 С:Предприятия 8.0 (по этой причине ни в одном из примеров не задействован ни один сервер- ный элемент управления из пространства имен _1C.V8. WebControls). Получение данных Получить данные из информационной базы ЮПредпри- ятие 8.0 (из веб-формы) можно двумя способами (на са- мом деле это просто два варианта определения одного и того же объекта V8DbSel ectCommand): ♦ по запросу; ♦ с указанием одной таблицы. Несмотря на наличие двух способов, общая схема (поря- док использования объектов) получения данных для них одна и та же. Ее можно представить в следующем виде (рис. 16.61).
Создание подключения к базе данных {объект V8D В Connection) Рис. 16.61. Алгоритм получения данных Для чтения в общем случае используются три объекта: ♦ V8DbConnection — предназначен для указания парамет- ров подключения к базе данных и проведения этого подключения; ♦ V8DbSel ectCommand — предназначен для указания пара- метров выборки и проведения выборки данных, полу- чения объекта V8DataReader; ♦ V8DataReader — предназначен для получения данных и их обхода. Перейдем к рассмотрению реальных примеров. Получение данных запросом Поставим перед собой задачу: получить (и отобразить в форме) остатки номенклатуры. Предварительно необходимо создать новую веб-форму. При создании выбрать шаблон Web Form. В диалоге формы необходимо разместить элемент управ- ления Table (он расположен в панели Toolbox в группе Web Forms). Из этой же группы необходимо добавить в диалог элемент управления Button (кнопку). В модуле формы необходимо добавить еще одно исполь- зуемое пространство имен — _lC.V8.Data. Остается следующим образом определить обработчик на- жатия на кнопку (следует отметить, что переход к обра- ботчику события кнопки можно осуществить по двойно- му щелчку по самой кнопке) (листинг 16.30). Листинг 16.30. Обработчик события Click private void Buttonl_C11ck(object sender. System.EventArgs e) { VBDbConnectlon connection = new VBDbConnectionO; connection.Database = "File= \“D:\\Конфигурации\\Типовые\\ОетоЕхсЬапде\”:”: connection.User = "web"; connection.Password = "1234”; V8DbSel ectCommand cmd = new VBDbSel ectCommandO: cmd.CommandType = CommandType.Text: cmd.CommandText = @"Выбрать Представление(Номенклатура) Как Наименование. КоличествоОстаток Как Остаток Из РегистрНакопления.УчетНоменклатуры.Остатки"; cmd.Connection = connection; TableRow row; TableCell cell; row = new TableRowO; cell = new TableCell(); cell.Text = "Номенклатура"; row.Cells.Add(cell); cell = new TableCelK): cell.Text = "Количество"; row.Cel 1s.Addlcel1); Tablel.Rows.Add(row); connection.OpenO; try { using(V8DataReader reader = (V8DataReader)cmd.ExecuteReader()) { while (reader.ReadO) { string номенклатура = reader.GetString(0); decimal количество = reader.GetDecimal(l); row = new TableRowO; cell = new TableCellO; cell.Text = номенклатура; row.Cel1s.Addlcel1); cell = new TableCellO; cell.Text = количество. ToStringO; row.Cells.Add(cell); Tablel.Rows.Add(row); } } } finally { connection.Close(); } Page.Controls.Add(Tablel); } При создании подключения (V8DbConnection) помимо пути к базе данных указывается имя и пароль пользователя, в контексте которого необходимо обращаться к базе дан- ных. В рассматриваемом случае эти данные указываются явно в коде формы (что не рекомендуется). Как это сде- лать по-другому, будет рассмотрено в следующем примере. При создании объекта VSDbSel ectCommand указывается тип команды: CommandType.Text. В этом случае в свойство Сот- mandText данного объекта можно записать текст запроса. При необходимости получить данные с каким-либо отбо- ром условие отбора определяется непосредственно в тек- сте запроса (параметр определяется с помощью символа «&»). При использовании параметров в условиях необхо- димо помнить: ♦ параметрам надо присваивать значения (<объект>. Parameters.Add(<HMB>, <3начение>); ♦ типы данных ЮПредприятия и .Net могут различаться и требовать явного преобразования; У созданного объекта V8DbSel ectCommand, через свойство Connection устанавливается созданный объект V8DbConnection.
Далее в коде производится работа с объектом Table. От- дельно создается строка табличной части (row), отдельно ячейка (cell). Манипулируя данными объектами, опреде- ляется объект таблица. Сам процесс получения данных начинается с установле- ния подключения (напомним, что одной из важных осо- бенностей ADO.NET является отсутствие необходимости поддерживать постоянное подключение). В конструкции try (попытка) производится получение данных. Причем при создании объекта V8DataReader (при выполнении метода ExecuteReaderO) используется конст- рукция using (по окончании блока кода все ресурсы будут гарантированно освобождены). Обход результата происходит в цикле. По окончании об- хода соединение закрывается. С помощью рассмотренной модели можно одновременно получать данные из разных таблиц, но полученные таким образом данные нельзя модифицировать. Указание одной таблицы Поставим перед собой задачу: отображать данные доку- мента Приходная накладная по введенному в форме номеру документа. Данный пример очень похож на предыдущий. Также нужно создать новую веб-форму. В диалоге формы необходимо разместить элемент управ- ления TextBox (он расположен в панели Toolbox в группе Web Forms). Из этой же группы необходимо добавить в диалог элемент управления Table (вывод данных будем производить именно в этот элемент управления) и Button (кнопка). В коде не забыть дописать использование пространства имен _lC.V8.Data. Обработчик события нажатия на кнопку будет уже опре- делен несколько по-иному (листинг 16.31). Листинг 16.31. Обработчик события Click private void Buttonl_Click(object sender. System.EventArgs e) { VBDbConnection connection = new V8DbConnection(): connecti on.Database= "File=\"D:\\KoH(|)MrypauMM\\TiinoBbie\\DenioExchange\”: connection.User=Session["UserName”].ToStringO; connection.Password=Session["UserPassword"].ToStringO: V8DbSel ectCommand and = new VBDbSelectCommandO; cmd.CommandType = CommandType.TableDirect; cmd.CommandText = "Документ.ПриходнаяНакладная": cmd.Connection = connection; cmd.Fields = @"Номер, Представление(Контрагент), Состав.(Представление(Номенклатура), Количество)"; cmd.WhereClause = "Номер=&Номер"; and.Parameters.Add("Номер", this.TextBoxl.Text.ToString()),- string номер; string контрагент,- TableRow row: TableCell cell; row = new TableRowO: cell = new TableCellO; cell.Text = "Номер/Номенклатура"; row.Cells.Add(cell); cell = new TableCellO; cell.Text = "Контрагент/Количество”; row.Cells.Add(cell); Tablel.Rows.Add(row); connection.OpenO; try { using(V8DataReader reader = (V8DataReader)cmd.ExecuteReader()) { while (reader.ReadO) { номер = reader.GetString(O); контрагент = reader.GetString(l); row = new TableRowO: cell = new TableCellO; cell.Text = номер.ToStringO; row.Cells.Add(cell): cell = new TableCellO; cell.Text = контрагент; row.Cells.Add(cell); Tablel.Rows.Add(row); using(V8DataReader Товары = (V8DataReader)reader.GetData(2)) { while (Товары.ReadO) { row = new TableRowO; cell = new TableCellO; cel 1 .Text=ToBapbi.GetString(0) ; row.Cells.Add(cell); cell = new TableCellO; cell.Text = Товары.GetDecimal(l).ToStringO; row.Cells.Add(cell); Tablet.Rows.Add(row); } } } } } finally { connect!on.Close(): } Page.Controls.Add(Tablel); } Рассмотрим отличия данного обработчика от приведен- ного ранее. При создании подключения имя пользовате- ля и его пароль не прописываются явно, а выбираются из параметров пользовательской сессии (объект Session<HMB параметра»]). За запись этих значений несет ответствен- ность сама система (но при желании подобную возмож- ность можно использовать и в своих целях, более подроб- но это освещено в разделе «Полезные средства .NET Framework», с. 647). У объекта V8DbSel ectConunand определен тип команды: CommandTуре. Tabl eDi rect. Исходя из этого, состав полей для выборки определен в свойстве Fields (указывается как реквизиты шапки документа, так и реквизиты вложенных таблиц). При необходимости наложить какой-либо отбор на данные, получаемые из таблицы, можно использовать свойство WhereClause (аналог раздела ГДЕ языка запросов 1 С:Предприятия).
Значение параметра берется из элемента управления TextBox (размещенного в диалоге). Следует обращать вни- мание на типы полей. В нашем случае документ Приход- ная накладная имеет строковый номер. При попытке пере- дать числовое значение ошибки бы не происходило, но к нужному результату (успешному нахождению докумен- та) это не приводило бы. Последней особенностью является открытие подчинен- ной выборки для обхода данных табличной части доку- мента. Добавление данных Поставим перед собой задачу: реализовать возможность добавления нового элемента в справочник Номенклатура. При добавлении данных работа ведется со следующими объектами: ♦ VBDbConnection — предназначен для указания парамет- ров подключения к базе данных и проведения этого подключения; ♦ VBDblnsertCommand - предназначен для указания добавляе- мых данных и проведения самой операции добавления. Перейдем к рассмотрению примера. Необходимо создать новую веб-форму (используя при этом шаблон Web Form). В диалоге формы необходимо разместить три элемента управления TextBox (для кода, наименования и закупочной цены номенклатуры). Также следует добавить в диалог кнопку (Button). При открытии формы необходимо заполнить текстовые поля и нажать на определенную кнопку. После добавления данные в текстовых полях должны очиститься. В код формы необходимо включить возможность исполь- зования пространства имен _lC.V8.Data. Для кнопки определим следующий обработчик события (листинг 16.32). Листинг 16.32. Обработчик события Click private void ButtonlClickfobject sender. System.EventArgs e) { VBDbConnection connection = new VBDbConnection!): connect!on.Database= 'Т11е=\"0:\\Конфигурации\\Типовые\\0етоЕхсЬапде\'':": connection.User=Session["UserName"].ToStringO: connection.Password=Session["UserPassword”].ToStringO: VBDblnsertCommand updCmd = new VBDblnsertCommand!): updCmd.CommandType = CommandType.TableDirect: updCmd.CommandText = "Справочник.Номенклатура": updCmd.Connection = connection; updCmd.Parameters.Add!"Код”, this.TextBoxl.Text.ToStringO); updCmd.Parameters.Add!"Наименование”, this.TextBox2.Text.ToStringO); updCmd.Parameters.Add!"ЗакупочнаяЦена". Convert.ToDeci mal!thi s.TextBox3.Text.ToStr1ng!))); connection.Open!); try { updCmd.ExecuteNonQuery!); } finally { connect1on.Close(): } 11 очищаем элементы управления this.TextBoxl.Text = this.TextBox2.Text = this.TextBox3.Text = } При создании объекта VBDblnsertCommand в качестве типа команды можно использовать только ConrnandType.TableDirect. В свойство Text записывается имя таблицы. Добавляемые данные должны соответствовать полям таблицы и опре- деляются как параметры. После установки подключения производится выполне- ние метода ExecuteNonQuery!) (метод ничего не возвра- щает). При успешном выполнении данные будут добавле- ны в базу данных 1С:Предприятия 8.0. Следует обратить внимание, что при обращении к эле- менту управления TextBox получаем значение типа Строка, для его преобразования к числу (для закупочной цены) используется объект Convert. В самом конце функции в текст полей ввода записывают- ся пустые строки. Следует обратить внимание, что в данной реализации полностью отсутствует реализация «защиты от дура- ка» (попытка добавить объект повторно, попытка до- бавить объект с незаполненными полями). В реальной жизни подобные проверки крайне желательно реали- зовывать. Изменение данных Поставим перед собой очередную задачу: необходимо «исправить» движения документа Приходная накладная (по указанному номеру документа) по регистру накопле- ния Учет номенклатуры. «Исправление» будет заключаться в том, что в ресурс количество будет записываться значе- ние единицы (независимо от реального наполнения доку- мента). Для изменения данных (а речь идет именно об изменении существующих данных) используются следующие объ- екты: ♦ VBDbConnection — предназначен для указания парамет- ров подключения к базе данных и проведения этого подключения; ♦ V8DbSel ectCommand — предназначен для указания пара- метров выборки и проведения выборки данных, полу- чения объекта V8DataReader; ♦ V8DataReader — предназначен для получения данных и их обхода; ♦ V8DbUpdateCommand — предназначен для выполнения об- новления данных. Схематично порядок работы при изменении данных мож- но показать следующим образом (рис. 16.62). Как и в предыдущих примерах, определим веб-форму. В диалоге разметим элемент управления TextBox (для вво- да номера документа), кнопку (для запуска процесса из- менения). Определяем возможность использования про- странства имен _lC.V8.Data. Обработчик нажатия на кнопку имеет следующий вид (листинг 16.33).
Рис. 16.62. Алгоритм изменения данных Листинг 16.33. Обработчик события Click private void Buttonl_Click(object sender. System.EventArgs e) { V8DbConnection connection = new V8DbConnection(); connecti on.Database= "File=\"D:\\KoH0MrypauMM\\TMnoBbie\\DemoExchange\"; ”; connection.User = "web": connection.Password = ”1234”: DataTable table = new DataTableO: table.Columns.Add("Период", typeof(object)); table.Columns.Add("Номенклатура", typeof(object)): table.Columns.Add("Склад", typeof(object)); table.Columns.Add("Количество”, typeof(decimal)); VBDbSelectCommand cmd = new VBDbSelectCommandO; cmd.CommandType = CommandType.TableDirect: cmd.CommandText = "РегистрНакопления.УчетНоменклатуры": cmd.Connection = connection: cmd.Fields = ^"Регистратор. Период. Номенклатура, Склад, Количество": cmd.WhereClause = "Регистратор.Номер=&Номер": cmd.Parameters.Add("Номер”, this.TextBoxl.Text.ToString()); ObjectRef регистратор = null; connecti on.Open(); try { using(VBDataReader reader = (V8DataReader)cmd.ExecuteReader()) { while (reader.ReadO) { регистратор = (ObjectRef)reader.GetValue(O): DataRow row = table.NewRowO; row[”nepHOfl"] = reader.GetValue(l): га«/["Номенклатура"] = reader.GetValue(2); row["Склад"] = reader.GetValue(3): row["Количество"] = 1: table.Rows.Add(row); } } } finally { connecti on.Close(); } V8DbUpdateCommand updCmd = new VBDbUpdateCommandO; updCmd.CommandType = CommandType.TableDirect; updCmd.CommandText = "РегистрНакопления.УчетНоменклатуры"; updCmd.Connection = connection; updCmd.Parameters.Add("Регистратор", регистратор); updCmd.Parameters.AddC'DataSet", table); connection.OpenO; try { updCmd.ExecuteNonQuery(); } finally { connection.CloseO; } } После создания объекта V8DbConnection производится оп- ределение и создание объекта DataTable. Дело в том, что изменения, которые по условию задачи необходимо про- вести, связаны с обработкой табличных данных (записей регистра накопления). В объекте DataTable будем накап- ливать набор записей, который в дальнейшем будет запи- сан в базу данных ЮПредприятия 8.0. Структура этого объекта совпадает с составом полей таблицы регистра на- копления УчетНоменклатуры. Не считая работы с объектом DataTable, первая часть об- работчика очень похожа на пример с получением данных. Оно и понятно, данные, перед тем как будут изменены, должны быть прочитаны. После того как будущий набор записей сформирован, создается объект V8DbUpdateCommand (возможен только тип команды: CommandType.TableDirect). При настройке пара- метров для набора записей регистра накопления (и ряда других регистров) необходимо обязательно указывать ре- гистратор. Опять же, для регистров добавляемый набор записей должен записываться в параметр с «предопреде- ленным» именем DataSet. С помощью вызова метода ExecuteNonQuery() соответст- вующей команды выполняется изменение данных. Удаление данных В рассматриваемом примере будем удалять элементы справочника номенклатура по введенному в текстовое поле коду. Функция, отвечающая за удаление элемента справочни- ка, имеет следующий вид (листинг 16.34). Листинг 16.34. Обработчик события Click private void Buttonl_Click(object sender. System.EventArgs e) { VSDbConnection connection = new V8DbConnection(); connect ion.Database- "Е11е=\"0:\\Конфигурации\\Типовые\\0етоЕхсЬапде\":"; connection.User = "web": connection.Password = "1234"; ObjectRef refer; VBDbSelectCommand cmd = new VBDbSelectCommandO; cmd.CommandType = CommandType.TableDirect; cmd.CommandText = "Справочник.Номенклатура"; cmd.Connection = connection; cmd.Fields = "Ссылка"; cmd.WhereClause = "Код=&Код"; cmd.Parameters.Add("Код", this.TextBoxl.Text);
connection.OpenO; try { refer = (ObjectRef)cmd.ExecuteScalarO; } V80bDeleteCommand delCmd = new V8DbDeleteCommand(); delCmd.Connection = connection; delCmd.CommandType = CommandType.TableDirect; delCmd.CommandText = "Справочник.Номенклатура"; delCmd.Parameters.Add("Ссылка", refer); connection.OpenO; try { delCmd.ExecuteNonQuery(); } finally { connection.Closed; } } После определения параметров подключения произво- дится получение данных. Важно при операции чтения (в рассматриваемом случае) получить ссылку на удаляе- мый объект. Так как ожидается получение одного значе- ния, оно получается выполнением метода ExecuteScalarQ. После получения ссылки создается и настраивается объ- ект V8DbDeleteCommand. Удаление производится при вызове метода ExecuteNonQuery. Следует отметить, что если объект, попытка удаления ко- торого производится, заблокирован, то выполнение мето- да приведет к ошибке. Веб-сервисы Отличие веб-сервиса от веб-приложения заключается в том, что веб-приложение предназначено для органи- зации пользовательского интерфейса с использованием веб-браузера, в то время как веб-сервис предназначен для организации программного доступа со стороны произ- вольных программных систем. С помощью веб-сервиса можно организовать доступ к механизмам 1С:Предпри- ятия, отсутствующим в других частях распределенной системы. С точки зрения использования, веб-сервис представляет собой некоторое множество методов, обращение к кото- рым может быть организовано из любой программной системы, которая выступает в качестве клиента веб-сер- виса. В принципе, создать на основе ASP.NET веб-сервис, осу- ществляющий доступ к информационной базе 1С:Пред- приятия 8.0, не слишком сложно. Но средства, предо- ставляемые Web-расширением, еще более упрощают эту задачу. Познакомимся с данной возможностью на примере созда- ния веб-сервиса, который возвращает сумму в рублях прописью, возвращает курс валюты по переданному коду валюты. Для начала создадим новый проект. При этом в качестве шаблона будем использовать V8 Web Service (рис. 16.63). Веб-сервис будет создан в виртуальном каталоге Му- Service. После нажатия на кнопку ОК автоматически стар- тует утилита загрузки метаданных (рис. 16.64). Рис. 16.64. Утилита импорта метаданных Hew PiojeU Project Types: ~VtsuaiC# Projects *' Q Visual C++ Projects Cj Setup and Deployment Projects 0? О Other Projects Q Visual Studio Solutions Templates: [88 fi® fej о * [vbJ V8 Web Windows Application Application 0 0 p Class Library Windows Smart Device Control Library Application A project for creating a V8 Web service Name |”~ч SwYve"" Location: | http://kxdhost/My Service iT| Browse... Project wl be created at http:/flocathost/MyService. »Morg OK I Cancel Рис. 16.63. Шаблон V8 Web Service Необходимо указать конфигурацию, которая будет ис- пользоваться сервисом, указать параметры доступа (имя пользователя конфигурации и его пароль). В результате работы конструктора по выбранному шаб- лону будет создан ряд файлов (просмотреть их можно ис- пользуя Solution Explorer). Файл, содержащий методы сервиса, имеет имя Servicel.asmx. Исходный программный текст этого файла приводится ниже (листинг 16.35). Листинг 16.35. Пример файла Servicel.asmx using System: using System.Col lections: using System.ComponentModel; using System.Data; using System.Diagnostics: using System.Web; using System.Web.Services: using _lC.V8.Data;
namespace MyService { III <summary> III Summary description for Servicel. Ill </summary> public class Servicel : System.Web.Services.WebService { public ServIcelO { //CODEGEN: This call is required by the // ASP.NET Web Services Designer Ini t i al 1zeComponent(); } #region Component Designer generated code //Required by the Web Services Designer private IContainer components = null: III <summary> III Required method for Designer support - do not modify III the contents of this method with the code editor. Ill </summary> private void InitializeComponentO { } III <summary> III Clean up any resources being used. Ill </summary> protected override void Dispose! bool disposing ) { 1f(d1spos1ng && components != null) { components.Dispose!): } base.Di sposefdi sposi ng); } #endregion [WebMethod] public string RublesInWordsidecimal sum) { using !V8DbConnection conn = new V8DbConnection!System. Configuration. Confi gurationSetti ngs. AppSetti ngs[V8Consts.Database], System. Configuration. Confi gurati onSett1ngs. AppSettings[V8Consts.UserName]. System. Configuration. ConfigurationSettlngs. AppSetti ngs[V8Consts.UserPassword])) { conn.Open!); string ret = !string)V8.Call! conn, conn.Connection. "ЧислоПрописью”, new object[] { sum. "L=ru_Rir, рубль, рубля, рублей, м, копейка, копейки, копеек, ж, 2" }): return ret; } } } } Метод Rubles InWords О получает в качестве параметра чис- ло. Далее с помощью обращения к методу ЧислоПрописью!) глобального контекста 1С:Предприятия 8.0 получает представление этого числа как суммы прописью в рублях на русском языке. Внутри самого метода первоначально производится ус- тановка соединения с базой данных. Вызов метода гло- бального контекста производится методом Call!). Па- раметры метода ЧислоПрописью!) передаются массивом, который создается и инициализируется прямо в методе Call!). Добавим в код реализацию метода, который будет по пе- реданному коду (в соответствии со стандартным класси- фикатором) возвращать курс валюты. Код метода приво- дится ниже (листинг 16.36). Листинг 16.36. Метод GetKursO public string GetKursiint code) { using !V8DbConnection conn = new VBDbConnection! System. Configuration. Confi gurati onSettIngs. AppSettings[V8Consts.Database]. System. Configuration. Con f1gurat1onSettIngs. AppSetti ngs[V8Consts.UserName]. System. Configuration. Confi gurationSettlngs. AppSett i ngs[VSConsts.UserPassword])) { conn.Open!); string ret = (string)V8.Call! conn. conn.Connection, "ПолучитьКурс”, code): return ret; } } Следует отметить, что функциональность метода основа- на на функции ПолучитьКурс(), определенной в модуле внешнего соединения информационной базы ЮПред- приятие 8.0 (листинг 16.37). Листинг 16.37. Функция ПолучитьКурсО Функция ПолучитьКурс!КодВалюты) Экспорт Валюта = Справочники.Валюты.НайтиПоКоду!КодВалюты); Отбор = Новый СтруктураС'Валюта", Валюта): Запись = РегистрыСведений.КурсыВалют.ПолучитьПоследнее! Отбор); Возврат(Запись.Курс); КонецФункции Перед тем как приступить к компиляции, рекомендуется определить пространство имен сервиса (листинг 16.38). Листинг 16.38. Определение пространства имен [WebServ1ce(Namespace = "http://name.name/WWWService/")] public class Servicel : System.Web.Services.WebService
Обращение к веб-сервису из веб-формы Для того чтобы получить возможность работать с веб- сервисом из создаваемого веб-приложения, необходимо первоначально добавить ссылку на данный сервис. Для этой цели необходимо выполнить команду главного меню Project ► Add Web Reference (рис. 16.65). Add Reference... Add Web Reference... Set ач StarH In Prniftrt Рис. 16.65. Команда Add Web Reference В открывшемся после этого окне указать путь к файлу сервиса (в данном случае указывается путь к сервису, су- ществующему на локальной машине). Далее следует на- жать на кнопку Go. Результат выполнения операции бу- дет выведен в ту же форму (рис. 16.66). В поле ввода Web Reference Name можно определить произ- вольное имя добавляемой веб-ссылки. Для обращения метода к сервису можно использовать код, подобный приведенному (листинг 16.39). Листинг 16.39. Пример обращения к веб-сервису private void Buttonl_Click(object sender. System.EventArgs e) { WebReference.WWWService ms = new WebReference.WWWServiceO; this.Labell.Text = ms.GetKurs(l): } Обращение к веб-сервису из ЮПредприятия 8.0 1С:Предприятие 8.0 не содержит встроенных средств для организации клиентского доступа к веб-сервисам. Одна- ко для доступа к веб-сервисам из конфигураций ЮПред- приятия может быть использован набор инструментов Microsoft SOAP Toolkit 3.0. Он является свободно рас- пространяемым и может быть загружен с сайта Microsoft. Ниже приведен фрагмент модуля на встроенном языке 1С:Предприятия 8.0, с помощью которого производится обращение к веб-сервису, который был создан ранее (листинг 16.40). Листинг 16.40. Пример обращения к веб-сервису Сумма = 1001; Сервис = Новый СОМОбъектСМЗЗОАР.SoapCIient30"); Сервис.MSSoapInitC "http://1ocalhost/TestService/Servicel.asmx’wsdl"); СуммаПрописью = Сервис.RublesInWords(CyMMa); Сообщить(СуммаПрописью); При организации взаимодействия с веб-сервисами следу- ет помнить, что есть достаточно серьезные ограничения по типам данных 1 С:Предприятия 8.0, которые могут быть использованы в качестве параметров и возвращае- мых значений. Фактически, без дополнительных преоб- разований, могут быть использованы следующие типы данных 1С:Предприятие 8.0: ♦ Булево; ♦ Число; ♦ Строка; ♦ Дата. Add Web Refeience Navigate to a web service URL (asmx or wsdl) and click Add Reference to add all the available services found at that URL. ©Back © | uri: iimiMMsi 1 Service Found: - Service! Web reference name: I WebReference Рис. 16.66. Добавление веб-ссылки Web services found at ths URL: | Add Reference ~~| Вызов процедур, функций Преобразование типов При создании (адаптации) веб-приложений и веб-серви- сов может возникнуть необходимость в использовании ряда ресурсов 1С:Предприятия 8.0. А именно: ♦ работать с глобальными переменными (определенными в модуле внешнего соединения с использованием клю- чевого слова Экспорт);
♦ осуществлять вызов процедур, функций, определенных с использованием ключевого слова Экспорт как в модуле внешнего соединения, так и в общих модулях (с уста- новленным флагом внешнее соединение). Следует помнить, что очень часто при использовании указанных ресурсов будет возникать необходимость в конвертации данных из типов .NET в типы ЮПредпри- ятия 8.0, и наоборот. Для осуществления преобразования можно использовать два метода (у каждого из них есть несколько вариантов вызова): ♦ ConvertValueNetToVe — преобразование типов .NET в типы ЮПредприятия 8.0; ♦ ConvertValueV8ToNet — преобразование типов ЮПред- приятия 8.0 в типы .NET. Предположим, что модуль внешнего соединения ЮПред- приятия выглядит следующим образом (листинг 16.41). Листинг 16.41. Пример модуля внешнего соединения Перен глПользователь Экспорт: Функция ПолучитьДанныеДляДок(Номенклатура, Цена) Экспорт Запрос = Новый Запрос; Запрос.Текст = ” ВЫБРАТЬ ЦеныНом ен клатуры.Цена ИЗ РегистрСведений.ЦеныНоменклатуры! Ноненклатура = &Нонен И ТипЦен = &ТипЦен) КАК ЦеныНоменклатуры" : Запрос.УстановитьПараметрС"Нонен", Ноненклатура): Запрос.УстановитьПараметрС"ТипЦен", Справочники.ТипыЦен.НайтиПоКодуС!)); Выборка = Запрос. ВыполнитьО.ВыбратьО; Если Выборка.СледующийО Тогда Цена = Выборка.Цена; ВозвратСИстина); Иначе Цена = 0; ВозвратСЛожь); КонецЕсли; КонецФункции Функция ВозвращаемСтрокуО Экспорт Возврате"Строка возврата"); КонецФункции глПользователь = "Некоторая переиенная”; Рассмотрим примеры обращения к переменным, функци- ям, объявленным в представленном модуле внешнего со- единения. Начнем с напоминания о том, что для обращения к базе дан- ных необходимо произвести подключение к ней. Это можно сделать, создав объект V80bConnection (листинг 16.42). Если в веб-форме определен какой-либо источник (спе- цифический для Web-расширения, например), то под- ключение может выглядеть следующим образом (лис- тинг 16.43). Следует отметить, что при знакомстве (через встроенную подсказку) с какими-либо методами нужно внимательно смотреть на тип используемого объекта connection. В ка- честве параметров может указываться connection с типом V8DbConnection и connection с типом ComObject. Листинг 16.42. Подключение к информационной базе ЮПредприятия V8DbConnection connection = new V8DbConnection(); connection.Database = "Е11е=\"0:\\Конфигурации\\Типовые\\0еп1оЕхсЬапде\":"; connection. User = Session["UserName"].ToStringO; connection. Password = Session["UserPassword''].ToStringO; // осуществление подключения connection.OpenО; Листинг 16.43. Установление соединения с информационной базой ЮПредприятия protected V8ListDataSource ListDataSource; // код формы connection = ListDataSource.Connection; // осуществление подключения connection.Open!); Можно сказать, что объект V8DbConnection определяет пара- метры подключения (и производит открытие подключения). У данного объекта существует свойство Connection, которое (после выполнения метода ОрепО) и содержит ComObject. Для чтения значения переменной модуля внешнего со- единения глПользователь можно использовать следующий метод (листинг 16.44). Листинг 16.44. Пример чтения значения переменной string currUser = (string)V8.Get( connection, connection.Connection. "глПользователь"); this.Label1.Text = currUser; Считаем, что в переменной connection находится объект типа V8DbConnection. Для обращения к функции ВозвращаемСтроку() можно ис- пользовать следующий код (листинг 16.45). Листинг 16.45. Пример обращения к функции object test = V8.Call(connection.Connection. "ВозвращаеиСтроку"); this. Label 2. Text = test.ToStringO; Рассмотренная ранее функция ВозвращаемСтроку() не имела параметров. В том случае, если они есть (и пара- метр не один), то для передачи значений в параметры можно использовать массив. Рассмотрим пример вызова функции, у которой определено два параметра (лис- тинг 16.46). Листинг 16.46. Пример вызова функции с двумя параметрами object[] args = {V8.ConvertValueNetToV8(NomenRef, connection), null): object test2 = V8.Call(connection.Connection, "ПолучитьДанныеДляДок", args); object ed = V8.ConvertValueVBToNet(args[l], connection): this.Label2.Text = V8.ConvertValueV8ToNet(args[l]. connection).ToString(); Первоначально формируется массив параметров args. При определении сразу же производится его инициали-
зация. Первым значением будет значение ссылки на но- менклатуру, преобразованное к типу 1С:Предприятия 8.0 (подобное значение можно получить при обращении к элементу управления V8TextBox с установленным соответ- ствующим типом). Второй элемент массива ничего не со- держит (null). Далее (с помощью метода Call О) производится вызов указанной функции (имя указывается вторым парамет- ром). Третьим параметром передается созданный ранее массив. Функция определена как возвращающая значение типа Булево (если цена номенклатуры найдена, то возвращает- ся значение Истина, не найдена Ложь). Кроме этого, возврат значения цены производится через массив параметров (параметры передаются по ссылке). После получения значения цены его необходимо преобразовать из типа 1С:Предприятия 8.0 в тип .NET. Полученное значение отображается в элементе управления Label2. Настройка прав доступа Для контроля прав доступа к данным информационной базы 1С:Предприятия предназначен класс VSRights про- странства имен _lC.V8.Data. Обращение к свойствам и методам данного класса позволяет проверить наличие разрешения на выполнение стандартных действий с дан- ными информационной базы. К примеру, такая проверка автоматически добавляется в функцию-обработчик загрузки формы, созданной на ос- нове шаблона V8 Item Form (листинг 16.47). Листинг 16.47. Обработчик события Page_Load private void Page_Load(object sender. System.EventArgs e) { // проверка прав на просмотр таблицы i f (!ItemDataSource.CheckAccessRight(V8Rights.View)) { V8WebUti1.Regi sterShowErrorScri pt( _1C. V8. Data. V8. GetStringC "erraccessRightViol ation"), this, true); Response. EndO: return; } if (HsPostBack) Title.Text = IterrtDataSource.Tableinfo.Presentation; } Следует отметить, что сами разрешения настраиваются в режиме конфигурирования информационной базы 1 С:Предприятие (настройкой ролей пользователей). Какие роли «действуют» — определяется пользователем, в контек- сте которого производится обращение к базе данных. Существует и более универсальная возможность про- верки прав пользователя. Она предоставляется мето- дом AccessRightO класса V8Right. В качестве параметров этому методу передаются строка с названием действия (например: Read, Edit, Posting и т. д.), таблица (объект V8TableInfo), в отношении которой предлагается выпол- нение действия, и соединение (объект V8DbConnection). Идентификация пользователя Информационная база данных 1 С:Предприятия 8.0 мо- жет не предусматривать никакой авторизации (что быва- ет, скорее всего, в исключительных ситуациях). В этом случае контроля прав доступа не производится, и задача идентификации пользователя на стороне веб-приложе- ния/сервиса, как правило, не возникает. В случае если авторизация в информационной базе при- сутствует, то с точки зрения веб-приложения/сервиса есть два варианта работы с ней; ♦ доступ к базе в контексте одного (как правило, специ- ально созданного) пользователя; ♦ каждый посетитель ресурса проходит авторизацию и, фактически, может работать под личным логином (с индивидуальным набором прав). Недостатком первого варианта является явное «обезли- чивание» (с точки зрения базы данных) всех пользовате- лей веб-приложения/сервиса. Второй вариант требует определения всех пользователей в самой информационной базе, что в случае большого ко- личества пользователей может быть неприемлемо. На практике могут использоваться смешанные варианты. Тогда ресурс делится на две части. К одной доступ осуще- ствляется в контексте какого-либо «общего» пользовате- ля, а к закрытой области (в которую может быть допуще- но намного меньше пользователей) требуется персональ- ная идентификация. Следует отметить, что при обращении к веб-сервисам мо- жет использоваться вариант, когда параметры доступа указываются в качестве параметров вызываемой функ- ции. Рассмотрим настройки веб-приложения/сервиса, связан- ные с правами доступа пользователей. Данные настройки распределены по нескольким файлам решения. Следует отметить, что при желании организовать иденти- фикацию на основе форм следует произвести настройку всех указанных файлов. Файл Web.config В случае если идентификация пользователей не произво- дится либо не используется принудительная авторизация на основе форм, то в этом файле определены следующие XML-элементы (листинг 16.48). В данном варианте к решению могут обращаться любые пользователи, к веб-серверу разрешен анонимный дос- туп. Но даже при анонимном доступе обращение веб-при- ложения к информационной базе может осуществляться в контексте одного или нескольких пользователей. Кон- троль прав доступа к информационной базе данных (при
необходимости) осуществляется обычно в обработчике события Load веб-форм. При этом проверяются права дос- тупа к запрашиваемым данным именно с точки зрения пользователя, параметры которого указаны в разделе appSetting (или явно определены другим образом). Листинг 16.48. Фрагмент файла Web.config «authentication mode="Windows" /> «authorization* «allow users="*” /> «!-- Allow all users --> «!-. «allow users=”[comma separated list of users]" roles="[comma separated list of roles]"/* «deny users="[comma separated list of users]” roles=”[comma separated list of roles]"/> «/authorization* Раздел appSettings имеет следующий вид (листинг 16.49). Листинг 16.49. фрагмент кода «appSettings* «add key=”Database” value='File="D:\Конфигурации\Типовые\ОетоЕхсЬапде";' /> «add key="UserName" value=”web"/> «add key="UserPassword” value=''1234"/> «add key="PoolCapacity” value="2"/> «/appSettings* Как видно, помимо имени пользователя и пароля в этом же разделе определен путь к информационной базе данных. В качестве отдельного варианта можно реализовать при- нудительную аутентификацию на основе форм. Особен- ность данного механизма заключается в том, что после его определения первое обращение к абсолютно любому ресурсу приведет к открытию формы, ответственной за идентификацию. Для того чтобы при таком варианте аутентификации организовать возможность гостевого входа (случайный пользователь тоже смог бы обратиться к ресурсу), непо- средственно в форме авторизации могут в явном виде прописывать гостевой логин. При настройке авторизации на основе форм разделы файла выглядят следующим образом (листинг 16.50). Листинг 16.50. Фрагмент кода «authentication mode="Forms"> «forms loginUrl="logon.aspx" name="AuthCookie” timeout=”60" path='7'7* «/authentication* В значение атрибута LoginUrl записывается путь к форме, которая будет вызываться для проведения аутентифика- ции пользователя (листинг 16.51). Листинг 16.51. фрагмент кода «authorization* «deny users="?'7> «/authorization* Обращаем внимание на тот факт, что для реализации аутентификации на основе форм недостаточно внести из- менения в файл web.config. Потребуется еще создать фор- му, в которой будет осуществляться аутентификация пользователя, и внести изменения в файл globaLasax. Файл global.asax Настройка данного файла (можно сказать, что он ис- пользуется в качестве «глобального модуля») необхо- дима в случае реализации механизма авторизации на ос- нове форм. Имеется в виду, что в других вариантах авторизации обычно этого не требуется (но работа с са- мим файлам может осуществляться для решения дру- гих задач). В определение используемых пространств имен следует добавить следующие строки (листинг 16.52). Листинг 16.52. Определение пространств имен using 1C.V8.WebControls; using System.Web.Security; using System.Security.Principal; Также следует определить обработчик события Authen- ticateRequest (листинг 16.53). Листинг 16.53. Обработчик события AuthenticateRequest protected void ApplicationAuthenticateRequest(Object sender, EventArgs e) { string cookieName = FormsAuthentication.FormsCookleName: HttpCookie authCookie = Context.Request.Cooki es[cooki eName]; if (authCookie — null) { return: } FormsAuthenticationTicket authTicket = null; try { authTicket = FormsAuthenti cation.Decrypt(authCooki e.Value); } catch { return: } if (authTicket = null) { return; } Formsldentity id = new Formsldentity(authTicket): GenericPrincipal princ = new GenericPrincipaKid, null); Context.User = princ; } При любом запросе будет вызываться вышеописанный обработчик события. В нем и производится проверка на предмет: была ли успешно осуществлена авторизация те- кущего пользователя или нет (используется механизм cookie — возможность сервера записывать на стороне клиента какие-либо значения, характеризуемые именем, сроком жизни и т. п.). Форма, используемая для авторизации «на основе форм» Предположим, что существует форма с именем logon.aspx (отвечающая за авторизацию пользователей). В форме определены два текстовых поля ввода (Text8ox) и кнопка,
по нажатию на которую производится проверка коррект- ности авторизации пользователя. Обработчик нажатия на кнопку имеет следующий вид (листинг 16.54). Листинг 16.54. Обработчик события Click private void Buttonl_Click(object sender. System.EventArgs e) { bool isLogin = false; using (VBDbConnection connection = new V8DbConnection( V8Metadata.GetDatabase(""). Name.Text, Password.Text ) ) { try { connection.OpenO; Session[WebConsts.UserName] = Name.Text; Session[WebConsts.UserPassword] = Password.Text; isLogin = true; } catch { } } if (isLogin) { FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket( 1. Name.Text, System.DateTime.Now, System.DateTime.Now.AddMi nutes(30), false, string.Empty ); string encTicket = FormsAuthenti cati on.Encrypt(authTi cket); Response.Cooki es.Add( new HttpCookie( FormsAuthent i cat i on.FormsCooki eName, encTicket ) ); Response.Redi rect( FormsAuthenti cati on. GetRedirectUrl(Name.Text,false) ): } el se { this.Label Info.Text = "Ошибка идентификации!"; } } Следует отметить, что в случае, если механизм авториза- ции на основе форм не используется (но все приложение работает в контексте одного пользователя), запись имени пользователя и его пароля в параметры объекта Session производится сервером автоматически. А если быть точ- нее, в файле global.asax определен следующий обработчик события, ответственный за это (листинг 16.55). Листинг 16.55. Обработчик события Start protected void Session_Start(Object sender, EventArgs e) { Session[WebConsts.UserName] = System. Configuration. Configurati onSetti ngs. AppSettings[V8Consts.UserName]: Session[WebConsts.UserPassword] = System. Configuration. ConfigurationSetti ngs. AppSetti ngs[V8Consts.UserPassword]; } Работа с метаданными Для того чтобы обрабатывать данные ЮПредприятия, Web-расширение строит структуру метаданных информа- ционной базы и создает описание типов, соответствующих данным, хранящимся в конкретной информационной базе. Этот процесс выполняется автоматически при создании нового проекта из шаблонов V8 Web Application или V8 Web Service. Если впоследствии конфигурация информацион- ной базы будет изменена, следует вручную запустить ге- нерацию метаданных для веб-приложения или веб-сервиса. Для этого используется команда главного меню Tools ► Импорт метаданных. После выполнения команды откроет- ся диалог следующего вида (рис. 16.67). В поле Каталог следует указать подкаталог /bin каталога, в котором находится веб-приложение. Результатом генерации метаданных является файл 1су8<псевдоним И Б>.сП1, содержащий описание типов, при- сущих конкретной информационной базе. Одно веб-приложение может использовать несколько ин- формационных баз. Каждая информационная база имеет в веб-приложении свой уникальный псевдоним. Именно он указывается в поле Псевдоним И Б при генерации мета- данных. Рис. 16.67. Импорт метаданных Эти псевдонимы также используются для указания связи с элементами управления, расположенными в форме (свойство IBAlias).
Доступ к структуре метаданных информационной базы предоставляется классом V8Metadata пространства имен _lC.V8.Data. Следует отметить, что метаданные конфигурации «по умолчанию» определяются в файл lcv8.dll. При работе с Visual Studio данная библиотека подгружается сис- темой. Если идет одновременная работа с разными проектами, но с одинаковыми именами данной биб- лиотеки (в каждом веб-приложении, построенном с по- мощью Web-расширения, обязательно будет библиотека с таким именем), может возникнуть «наложение» мета- данных, которое приведет к ошибкам в создаваемом при- ложении. В связи с этим при переходе от одного проекта (построен- ного на одних метаданных) к другому рекомендуется полностью закрывать предыдущий проект. Пул соединений В процессе обращения к данным информационной базы создаются COM-соединения с 1С:Предприятием. Это происходит при использовании элементов управления — источников данных или при непосредственной работе с объектом V8DbConnection. Создание каждого такого соеди- нения занимает определенную часть ресурсов сервера и требует некоторого времени. Поэтому для ускорения работы Web-расширение может поддерживать пул соединений, в котором будут нахо- диться уже открытые соединения. Разработчик имеет возможность настраивать пул соеди- нений, указывая максимальное количество соединений, одновременно находящихся в пуле, и период, в течение которого соединение будет удерживаться в пуле. Настройка (инициализация) перечисленных параметров выполняется в файле Global.asax (листинг 16.56). Листинг 16.56. Пример настройки пула соединений protected void Application_Start(Object sender, EventArgs e) { V8Metadata.SetDatabaseC System. Configuration. Configurationsettings. AppSettings[V8Consts.Database] ): string poolCapacityStr = System. Configuration. Configurationsettings. AppSettings[V8Consts.PoolCapacity]; if (poolCapacityStr != null) { try { int poolCapacity = 1nt.Parse(poolCapacityStr, Cultureinfo.Invariantculture); V8DbConnection.PoolCapacity = poolCapacity; } catch (FormatException) { } } string poolTimeoutStr = System. Configuration. Configurationsettings. AppSett i ngs[V8Consts.PoolTimeout]; if (poolTimeoutStr != null) { try { int poolTimeout = int.Parse(poolTimeoutStr. Cultureinfo.InvariantCulture); V8DbConnection.PoolTimeout = poolTimeout: } catch (FormatException) { } } string maxConnectionsStr = System. Configuration. Configurationsettings. AppSetti ngs[V8Consts.MaxConnections]; if (maxConnectionsStr != null) { try { int maxConnections = int.Parse(maxConnectionsStr, Cultureinfo.InvariantCulture); V8DbConnection.MaxConnections = maxConnections: } catch (FormatException) { } } V8Config.SetConfig("", V8Config.MapFileName); } Свойство PoolCapacity задает максимальное количество COM-соединений, одновременно находящихся в пуле. Значение данного свойства определяется в файле Web.config, в приведенном ниже разделе (листинг 16.57). Листинг 16.57. фрагмент файла Web.config <appSettings> <add key="Database" value='File="D:\Kon(|)urypauuu\TMnoBue\DemoExchange";’ /> <add key="UserName" value="web” /> <add key=”UserPassword" value="1234” /> <add key="PoolCapacity” value="2” /> </appSettings> Свойство PoolTimeout определяет период в секундах, в те- чение которого соединение будет удерживаться в пуле для возможного повторного использования. Алгоритм работы пула следующий: ♦ когда пользователь закрывает соединение с базой дан- ных, оно (в случае, если значение PoolCapacity отлича- ется от нуля) помещается в пул; ♦ если при этом пул был заполнен (в пуле находилось максимальное количество соединений), то будет вытес- нено то соединение, которое дольше всего находится в пуле; ♦ повторно использовать соединение может только тот же пользователь, в контексте которого оно было создано;
♦ по окончании времени существования в пуле (свойст- во Pool Timeout) соединение удаляется из пула (либо оно вытесняется каким-либо новым соединением). Следует отметить, что в данном случае, когда говорится о каком-либо пользователе, подразумевается пользователь, в контексте которого производится подключение к ин- формационной базе 1С:Предприятия 8.0. В связи с этим использование пула соединений особенно эффективно, когда все веб-приложение работает в контексте одного пользователя (указанного в файле web.config) Свойство MaxConnection определяет максимальное число одновременно существующих COM-соединений. Данное число соединений включает также число соединений, на- ходящихся в пуле. Значение по умолчанию равно 0 (без ограничений). Это свойство можно использовать при желании ограничить количество лицензий платформы ЮПредприятия 8.0, которые будут использоваться веб-приложением. Рассмотрим все это на примере. Пусть установлены сле- дующие значения свойств: ♦ MaxConnection = 4; ♦ Pool Timeout = 60; ♦ PoolCapacity = 2. При таком значении параметров, веб-приложение будет использовать макс шум 4 лицензии, при этом в пуле мак- симально будет находиться два соединения. Соединение из пула будет удаляться либо по истечении 60 секунд по- сле последнего его использования, либо при освобожде- нии другого (созданного позже) соединения, которое не расположено в пуле (оно вытеснит из пула самое «ста- рое» соединение). Полезные средства .NET Framework В данной главе рассмотрим ряд объектов (входящих в контекст ASP.NET), которые довольно часто использу- ются при создании как веб-приложений, так и веб-серви- сов. Данный раздел ни в коем случае не претендует на полное описание, при возникновении такой необходимо- сти рекомендуем обращаться к специализированной ли- тературе. Объект Response Данный объект позволяет серверу поддерживать связь с клиентом. Например, для включения в HTTP-вывод про- извольных данных (произвольного фрагмента HTML) можно использовать метод WtiteO (листинг 16.58). Листинг 16.58. Пример использования метода WtiteO Response.Write!"<Ь1>Здравствуй мир!! !</hl>"); Метод WtiteO в качестве параметра может принимать только строковые значения. С помощью объекта Response можно управлять буфериза- цией вывода данных. Поясним понятие буферизации. Веб-формы (файлы aspx) фактически представляют из себя программы, написанные (в нашем случае) на языке С#. При обращении к такой форме вызывается какая-ли- бо функция, в результате работы которой формируется HTTP-ответ клиенту. Так вот, при включенной буфери- зации ответ не будет отправлен клиенту, пока не закон- чится исполнение формы. При отключенной буфериза- ции данные отправляются по мере их формирования. Какой из вариантов использовать, определяется в каж- дом случае индивидуально. Для запрета буферизации можно использовать следую- щую конструкцию (листинг 16.59). Следует помнить, что в случае, если в HTTP-отклик уже помещены какие-либо данные, попытка отключения (или включения) буферизации приведет к ошибке. Методы объекта, позволяющие управлять буферизацией, перечислены в листинге 16.60. Листинг 16.59. Пример запрета буферизации Response.Buffer = false; Листинг 16.60. Методы, позволяющие управлять буферизацией // отсылает клиенту, все что на данный момент буферизировано Response.Flush!): // очищает все данные буфера Response.Clear!); // отсылает содержииое буфера, прекращает выполнение формы. // инициирует событие окончания запроса Response.End!): Объект может использоваться для перенаправления поль- зователей. К примеру, вы хотите, чтобы при первом обра- щении к ресурсу пользователь отправлялся на определен- ную стартовую страницу (независимо от запрашиваемого ресурса). С этой целью в файле globakasax можно опреде- лить обработчик события (листинг 16.61). Листинг 16.61. Пример перенаправления protected void Session_Start(Object sender, EventArgs e) { Response.Redirectturl); } Объект может использоваться для записи cookie (значе- ний, записываемых на стороне клиента) (листинг 16.62). Листинг 16.62. Пример использования cookie HttpCookie MyCookie = new HttpCookieC'LastVisit"); DateTime now = DateTime.Now; MyCookie. Value = now.ToStringO; MyCookie.Expires = now.AddHours(l); Response.Cookies.Add(MyCookie): Объект Request Данный объект позволяет поддерживать связь клиента с сервером. С помощью данного объекта можно произво- дить чтение значений cookie (листинг 16.63).
Листинг 16.63. Пример чтения cookie ПоследнийВизит = Request.Cookies["LastVisit"J; Также можно получать значения параметров, переданных в запросе. К примеру, обращение к ресурсу могло произ- водиться следующим образом (листинг 16.64). Листинг 16.64. Пример обращения к ресурсу Page.aspx’TableName = Справочник.Контрагенты Для извлечения значения параметра TableName можно ис- пользовать следующий подход (листинг 16.65). Листинг 16.65. Пример получения значения параметра ИмяТаблицы = Request.Params["TableName "]; Объект Session Данный объект предназначен для хранения «контекста» работы пользователя. Дело в том, что протокол HTTP не поддерживает возможности хранения состояния работы с пользователем (с его помощью нельзя хранить состояние пользовательской корзины, хранить значения, опреде- ляющие специфику работы данного пользователя и т. п.). Объект Session как раз и решает эти задачи. При первом обращении к любому ресурсу приложения для каждого пользователя создается объект сессии (каж- дый такой объект характеризуется неким уникальным идентификатором, защищенным от повторения). Как при старте сессии, так и при ее завершении инициируются события, обработчики которых могут быть определены в файле globaLasax. Завершение сессии (и освобождение всех занятых ее ре- сурсов) можно вызвать принудительно (листинг 16.66). Листинг 16.66. Пример завершения сессии Session.AbandonO; Также завершить сессию можно по истечении определен- ного промежутка времени после последнего запроса. Этот промежуток времени устанавливается в параметрах веб- сервера (рис. 16.68). Default Web Site Properties Directory Security | HTTP Headers |[ Custom Errors ]| Server Ex WebSite | ISAPI Filters f Home PC | Poet When Application Confirmation J Mappings] Options"] Debugging]________________________ Local Pat □ Script i Pl Read Application Configuration 0 Enable session state Session timeout: minutes Рис. 16.68. Настройка параметров веб-сервера Кроме этого, в объекте Session можно хранить значения, индивидуальные для каждого пользователя (листинг 16.67). Листинг 16.67. Пример записи и чтения значения // Запись значения: Session["UserName"J = "web": // Получение значения Значение = Session["UserName"J: Подготовка веб-приложения к работе До сих пор, для того чтобы проверить, как работает та или иная созданная веб-форма, рекомендовалось уста- новить ее как стартовую и запустить проект в режиме отладки. Когда все формы приложения будут готовы (а скорее всего намного раньше), необходимо поду- мать о навигации по созданному приложению. То есть должен быть определен механизм, позволяющий поль- зователю спокойно переходить от одной формы к дру- гой (без знания имен форм и путей до них). Реализа- ция подобного механизма может строиться по-разному. Но чаще всего в основе лежит возможность использова- ния гиперссылки. Примеры использования (код html) приведены в листин- ге 16.68. Листинг 16.68. Фрагмент HTML-кода «TABLE id=”Tablel" style="Z-INDEX: 102; LEFT: Ipx; WIDTH: 182px; POSITION: absolute: TOP: 44px; HEIGHT: 108px; BACKGROUND-COLOR: yel1ow" cell Spaci ng=’T" cellPadding="l" width="182" border="l"> <TR> <TD style=''HEIGHT: 13px"><STR0NG*CnpaBO4HHKH</STR0NG> </TD> </TR> <TR> <TD><A href="nomenlist.aspx">HoMeHKnaTypa</Ax/TD> </TR> <TR> <TD> <A href="DefaultLi stForm.aspx?TablеНате=Справочник. Контрагенты"* Контрагенты </A> </TD> </TR> </TABLE> Обращаем внимание на тот факт, что вторая гиперссылка определяет вызов формы списка справочника Контрагенты и при этом используется форма по умолчанию.
Состав файлов В ходе создания веб-приложения в виртуальном каталоге были созданы: ♦ каталог Images, он содержит картинки, используемые для оформления форм. Данный каталог необходимо ос- тавить в готовом решении; ♦ каталог bin, он содержит ряд файлов (этот каталог так- же в обязательном порядке должен включаться в рабо- тающее решение). В каталоге содержатся dll-файл про- екта и dll-файлы, содержащие описание метаданных используемых конфигураций; ♦ в корне виртуального каталога (если иное не опреде- лено явно) располагаются файлы *.aspx, *.aspx.cs. Файлы *.aspx.cs в рабочее решение можно не включать (но «терять» их не рекомендуется, так как они потре- буются в случае возникновения необходимости ис- правления функционала, перекомпиляции веб-прило- жения). Параметры автоформ Веб-приложение, созданное при помощи различных шаб- лонов в среде Visual Studio .NET, содержит несколько ав- тоформ (форм по умолчанию), которые используются приложением, когда происходит обращение к данным, для которых разработчик не создал собственных форм, при отработке некоторых стандартных действий. Управление работой автоформ осуществляется при по- мощи параметров, которые передаются либо в строке за- проса, либо как переменные формы. Разработчик веб-приложения может явно использовать автоформы для выполнения необходимых действий, оп- ределяемых логикой приложения. Указать, какие дейст- вия должна выполнить автоформа, можно при помощи ее параметров, передавая значения следующим образом (листинг 16.69). Листинг 16.69. Пример передачи параметров в автоформу чеЬТогт.а5рх?параметр1=ЗначениеПараиетра& параметр2=ЗначениеПараиетра Чтение переданных таким образом параметров осуществля- ется (в коде формы webform) с помощью объекта Request. Ниже приводится список параметров некоторых автоформ. Форма списка (DefaultListForm) DefaultListForm используется для отображения записей таб- лицы базы данных в виде списка. Также DefaultListForm применяется для выбора значений из списка записей. Эта форма имеет следующие параметры: ♦ IBAlias — имя информационной базы. Используется в том случае, если приложение работает с несколькими информационными базами данных. Значение по умол- чанию — пустая строка; ♦ TypeName — имя типа. Задает таблицу базы данных, кото- рая будет отображаться в списке. Вместо TypeName мо- жет использоваться параметр Tabl eName; ♦ Tabl eName — имя таблицы. Задает таблицу базы данных, которая будет отображаться в списке. Вместо Tabl eName может использоваться параметр TypeName; ♦ ChoiceMode — режим выбора для иерархических таблиц. Допустимые значения: " Items; " Folders; " FoldersAndltems. Если передано значение Folders, в списке будут отобра- жаться только группы элементов: ♦ Control Name — идентификатор элемента управления, вы- звавшего форму списка для выбора. Если передан пара- метр Control Name, форма переходит в режим выбора из списка; ♦ TypeDescriptionNeeded — указывает на необходимость счи- тывания описания типов для поддержки связи по типу. Возможные значения: " true; false; ♦ SelectionName<N>, SelectionValue<N>, SelectionType<N> — от- боры и параметры критериев отбора. В случае одного элемента отбора используется форма SelectionName, Selectionvalue, SelectionType. Если установлено не- сколько отборов, то они задаются в параметрах Selec- tionNamel, SelectionValuel, SelectionTypel, SelectionName2, SelectionValue2, SelectionType2 и т. д. Нумерация начи- нается с единицы. " SelectionName — имя поля; Selectionvalue — значение отбора; SelectionType — тип значения. Используется в случае составного типа; ♦ Assortment — задает режим подбора. В этом режиме по- сле выбора значения форма остается открытой, предо- ставляя возможность продолжения выбора. Должен быть задан параметр Control Name. Допустимое значение — true; ♦ Initial Value — начальное значение. Содержит значение ключа записи. Если параметр задан, то список позицио- нируется на переданное значение. Форма элемента объектной таблицы (DefaultObjectForm) DefaultObjectForm используется для добавления, редакти- рования, копирования или ввода на основании записи объектной таблицы.
Режим формы определяется следующим образом: ♦ если передан параметр KeyValue, то форма переходит в режим редактирования; ♦ если передан параметр CopyKeyValue и задаваемая им таб- лица совпадает с таблицей из параметра TableName (или КеуТуре), то форма переходит в режим копирования; ♦ если передан параметр CopyKeyValue и задаваемая им таблица не совпадает с таблицей из параметра TableName (или КеуТуре), то форма переходит в режим ввода на ос- новании; ♦ если параметры KeyValue и CopyKeyValue не заданы, то форма переходит в режим добавления записи. Эта форма имеет следующие параметры: ♦ IBAlias — имя информационной базы. Используется в том случае, если приложение работает с несколькими информационными базами данных. Значение по умол- чанию — пустая строка; ♦ КеуТуре — тип значения ключевого поля. Используется для определения таблицы, запись которой будет редакти- роваться (или в которую будет добавлена новая запись); ♦ KeyValue — значение ключевого поля. Задает значение ключа редактируемой записи; ♦ TableName — имя таблицы. Задает таблицу базы данных, запись которой будет редактировать в форме (будет до- бавлена при помощи формы). Вместо TableName может использоваться параметр КеуТуре; ♦ CopyKeyType, CopyKeyValue — тип значения ключевого поля и значение ключевого поля копируемой записи. Пере- дача этих параметров задает режим копирования; ♦ IsFolder — параметр «ЭтоГруппа». Определяет режим ре- дактирования (создания) группы; ♦ MasterName<N>, MasterValue<N>, MasterType<N> — предуста- новленные значения полей. Используется, например, для задания поля Владелец для подчиненных таблиц. В случае одного значения используется форма MasterName, Mastervalue, MasterType. Если передано несколько значе- ний, то они задаются в параметрах MasterNamel, Master- Valuel, MasterTypel, MasterName2, MasterValue2, MasterType2 и т. д. Нумерация начинается с единицы. " MasterName — имя поля; " MasterValue — значение; MasterType — тип значения. Используется в случае со- ставного типа; ♦ ControlName — идентификатор элемента управления, вы- звавшего форму. Используется для обновления списка записей после записи изменений в форме; ♦ Parent — значение поля Родитель для иерархических таблиц. Форма записи регистра (Default Record Form) DefaultRecordForm используется для редактирования, созда- ния новой или копирования существующей записи регистра. Режим формы определяется следующим образом: ♦ если передан параметр KeyValue<N>, то форма переходит в режим редактирования; ♦ если передан параметр CopyKeyValue<N>, то форма пере- ходит в режим копирования; ♦ если параметры KeyValue<N> и CopyKeyValue<N> не заданы, то форма переходит в режим добавления записи. Эта форма имеет следующие параметры: ♦ IBAlias — имя информационной базы. Используется в том случае, если приложение работает с несколькими информационными базами данных. Значение по умол- чанию — пустая строка; ♦ TableName — имя таблицы регистра. Задает регистр, за- пись которого будет редактировать в форме (будет до- бавлена при помощи формы); ♦ ControlName — идентификатор элемента управления, вы- звавшего форму. Используется для обновления списка записей после записи изменений в форме; ♦ KeyName<N>, KeyVal ue<N>, KeyType<N> — значения ключевых полей редактируемой записи. В случае одного значения используется форма KeyName, KeyValue, КеуТуре. Если для таблицы задано несколько ключевых полей, то их зна- чения задаются в параметрах KeyNamel, KeyVal uel, KeyTypel, KeyName2, KeyVal ue2, KeyType2 и т. д. Нумерация начинается с единицы. " KeyName — имя ключевого поля; " KeyValue — значение ключевого поля; " КеуТуре — тип значения ключевого поля. Использует- ся в случае составного типа; ♦ CopyKeyName<N>, CopyKeyValue<N>, CopyKeyType<N> — значения ключевых полей копируемой записи. В случае одного значения используется форма CopyKeyName, CopyKeyValue, CopyKeyType. Если для таблицы задано несколько ключевых полей, то их значения задаются в параметрах CopyKeyNamel, CopyKeyValuel, CopyKeyTypel, CopyKeyName2, CopyKeyValue2, CopyKeyType2 и т. д. Нумерация начинается с единицы. " CopyKeyName — имя ключевого поля; • CopyKeyVal ue — значение ключевого поля; " CopyKeyType — тип значения ключевого поля. Исполь- зуется в случае составного типа. Форма строки табличной части (DefaultLineForm) DefaultLineForm предназначена для редактирования (до- бавления) строки табличной части. Эта форма имеет сле- дующие параметры: ♦ IBAlias — имя информационной базы. Используется в том случае, если приложение работает с несколькими информационными базами данных. Значение по умол- чанию — пустая строка; ♦ TableName — имя табличной части; ♦ ColumnsList — разделенный точкой с запятой список отображаемых полей строки табличной части; ♦ HiddenColumnsList — разделенный точкой с запятой спи- сок неотображаемых полей строки табличной части; ♦ ControlName — идентификатор элемента управления, вы- звавшего форму для редактирования (добавления) строки табличной части. Используется для обновления отображе- ния табличной части после записи изменений в форме.
Глава 17. Поставка прикладных решений Выпуск тиражных прикладных решений влечет за собой целый ряд вопросов, которые обычно не возникают при создании заказных или индивидуальных систем. Если пользователь один, то разработчик может самостоятель- но установить у него прикладное решение и, при необхо- димости выполнить его обновление до новой версии. Теперь представим, что количество пользователей при- кладного решения исчисляется сотням и тысячами. Оче- видно, что «дойти» до каждого из них разработчик просто физически не сможет (особенно если пользователи нахо- дятся в другом городе или другой стране). Значит, не- обходимо готовить какой-то дистрибутив прикладного решения, который пользователь самостоятельно сможет запустить на своем компьютере и начать работать. Аналогично, требуется некий механизм для того, чтобы существовала возможность легко обновить прикладное решение пользователя до новой версии. Сложность этого действия применительно к системе 1 С: Предприятие за- ключается в том, что прикладные решения 1С:Предпри- ятия не являются закрытыми пользователь может моди- фицировать его под свои нужды. А это значит, что при обновлении возникнет необходимость совмещать измене- ния, выполненные пользователем, с изменениями, ко- торые произвел разработчик. При большом количестве изменений это может стать для пользователя очень слож- ной задачей. Система 1 С:Предприятие содержит два механизма, кото- рые в значительной степени автоматизируют описанные выше процессы. Во-первых, это механизм поставки и поддержки приклад- ных решений. Этот механизм позволяет разработчику из- менять прикладное решение, а пользователю автомати- чески или полуавтоматически принимать выполняемые изменения. Во-вторых, это механизм создания комплектов поставки. Этот механизм позволяет разработчику формировать ди- стрибутив, который, будучи запущен у пользователя, вы- полнит все необходимые действия самостоятельно. Совместное использование механизма поставки и под- держки и механизма создания комплектов поставки по- зволяет выполнять полный цикл поддержки прикладного решения у пользователя. В общем случае схема взаимо- действия разработчика с пользователем выглядит сле- дующим образом (рис. 17.1). Разработчик создает некоторое прикладное решение (вер- сия 1). Теперь ему нужно позаботиться о двух вещах. Во- первых, о том, чтобы пользователи, купившие это при- кладное решение, могли бы в дальнейшем легко обнов- лять его по мере выхода новых версий. Во-вторых, необ- ходимо создать некоторый исполняемый файл, который пользователь сможет запустить на своем компьютере, Рис. 17.1. Схема взаимодействия разработчика с пользователем
и этот файл выполнит установку всех файлов, необходи- мых для работы прикладного решения. Для решения первого вопроса разработчик использует механизм поставки и поддержки конфигурации, с помо- щью которого «сообщает» конфигурации о том, что она будет в дальнейшем получать обновления от этого разра- ботчика, а также сообщает конфигурации о том, в каких пределах она может быть изменена пользователем. Затем разработчик использует механизм создания комплектов поставки для того, чтобы создать дистрибутив версии 1. Дистрибутив может содержать не только непосредствен- но саму конфигурацию версии 1, но также и ряд других файлов, необходимых для установки на компьютере пользователя. Например, файл демонстрационной ин- формационной базы, сопроводительные файлы, файлы документации, обучающие файлы, рекламные материалы и т. д. Как правило, дистрибутив копируется на некото- рый физический носитель (например CD-ROM). Пользователь приобретает прикладное решение и запус- кает на своем компьютере программу установки, входя- щую в состав дистрибутива. Эта программа выполняет установку всех файлов, содержащихся в дистрибутиве. После того как установка закончена, пользователь может начать работу с прикладным решением и в том числе мо- жет модифицировать это прикладное решение под свои нужды. Благодаря механизму поставки и поддержки пользователь может изменить только те части конфигу- рации, для которых разработчик не запретил изменение. Таким образом, в общем случае через некоторое время пользователь будет иметь уже доработанное прикладное решение версии 1, которое больше или меньше (в зависи- мости от стараний пользователя) отличается от ориги- нального (версия 1) прикладного решения. К этому моменту разработчик, например, исправил ряд ошибок, обнаруженных в версии 1 прикладного ре- шения, и, используя возможности механизма создания комплектов поставки, выпустил обновление своего при- кладного решения, позволяющее перейти с версии 1 на версию 2. Это обновление разработчик записал на физический но- ситель, а также выложил на доступный всем пользовате- лям его прикладного решения FTP- или НТТР-ресурс. Предположим, пользователю нужно срочно получить об- новление своего прикладного решения, и он не может ждать, пока посылка с CD-ROM, содержащим обновле- ние, дойдет к нему по почте. В этом случае пользователь благодаря механизму поставки и поддержки может обра- титься к указанному FTP- или HTTP-ресурсу и обновить свое прикладное решение прямо с этого ресурса. Причем, если пользователь не вносил никаких изменений в при- кладное решение, обновление до версии 2 будет выполне- но полностью автоматически. Если же изменения вноси- лись, то механизм поставки и поддержки попросит пользователя указать, как поступить с теми объектами конфигурации, которые были изменены одновременно как разработчиком, так и пользователем. Механизм поставки и поддержки прикладных решений Суть механизма поставки и поддержки заключается в том, чтобы обеспечить автоматическую или полуавтомати- ческую возможность обновления прикладного решения у пользователя. Еще раз обратим внимание на то, что особен- ностью обновления прикладных решений ЮПредприятия является то, что прикладные решения, после того как они выпущены разработчиком, могут быть изменены пользова- телем. Таким образом, в момент обновления любого из рек- визитов объектов конфигурации может возникнуть одна из четырех ситуаций (табл. 17.1). и разработчиком, никакого однозначного решения о том, что же делать в данном случае, принять нельзя. Очевид- но, что только пользователь может решить, каким обра- зом его изменения должны сочетаться с изменениями, внесенными разработчиком. Поэтому одной из важных функций механизма поставки и поддержки является воз- можность автоматически определить такие свойства, и предоставить пользователю отфильтрованный их спи- сок, для того чтобы он указал правило объединения в ка- ждом конкретном случае. Таблица 17.1. Варианты действий разработчика и пользователя Разработчик Пользователь Не изменял Не изменял Не изменял Изменил Изменил Не изменял Изменил Изменил Таблица 17.2. Принятие решения о выполнении действий Разработчик Пользователь Действие Не изменял Не изменял Не изменять Не изменял Изменил Не изменять Изменил Не изменял Принять изменения разработчика Изменил Изменил ? Очевидно, что в трех перечисленных вариантах можно принять однозначное решение о том, какие действия нужно выполнить при обновлении прикладного решения (табл. 17.2). В последнем случае, когда один и тот же реквизит объек- та конфигурации был изменен как пользователем, так Чтобы сократить, по возможности, количество подобных объектов и облегчить тем самым обновление конфигура- ции, механизм поставки и поддержки позволяет задать для объектов конфигурации правила поставки и правила поддержки.
Правила поставки задает разработчик, а пользователь действует в соответствии с правилами поддержки и мо- жет изменять их (рис. 17.2). Рис. 17.2. Правила поставки и правила поддержки Для того чтобы конфигурация могла поддерживать дру- гие конфигурации, разработчик должен задать правила поставки. Правила поставки задаются разработчиком для каждого объекта конфигурации, и не могут быть измене- ны пользователем. Они служат для того, чтобы запретить пользователю изменение отдельных объектов, а для дру- гих объектов сообщить информацию о желательности или нежелательности внесения в них изменений. Прави- ла поставки задаются только для объектов верхнего уров- ня, таких как справочники, документы, регистры. Для объектов метаданных им подчиненных (таких как рекви- зиты, табличные части, формы, макеты) будут использо- ваться соответствующие правила родительских объектов. Существует три правила поставки: ♦ Изменения разрешены — означает, что пользователь может выполнять любые изменения этого объекта в своей конфигурации, то есть разработчик полагает, что изме- нения, выполняемые пользователем в этом объекте, не окажут значительного влияния на основную функцио- нальность прикладного решения. ♦ Изменения не рекомендуются — означает, что пользователь может изменять этот объект, но при внесении измене- ний он должен быть внимателен, так как это может по- влиять на значительную часть функциональности при- кладного решения. ♦ Изменения запрещены — означает, что пользователь не мо- жет выполнять изменения этого объекта. С точки зре- ния разработчика это правило означает, что объект на- столько важен для данного прикладного решения, что при любом его изменении пользователем разработчик не видит смысла в дальнейшей поддержке такого при- кладного решения. Правила поставки необходимы для того, чтобы в соответ- ствии с ними сформировать правила поддержки. Правила поддержки формируются всегда, но не всегда использу- ются. Это объясняется тем, что существует два режима поддержки конфигурации: ♦ полная поддержка; ♦ поддержка с возможностью изменения. Полная поддержка означает, что пользователю запрещено вносить изменения в конфигурацию. В том числе и добав- лять новые объекты. Поддержка с возможностью измене- ния означает, что пользователь может изменять конфигу- рацию в соответствии с правилами поддержки и при этом она продолжает находиться на поддержке поставщика. При первоначальной установке прикладного решения из дистрибутива создается конфигурация, находящаяся на полной поддержке. При желании пользователь может включить возможность изменения конфигурации — в этом случае начнут действовать правила поддержки, сформированные системой по умолчанию, на основании правил поставки. Существует три правила поддержки: ♦ Объект поставщика не редактируется — это правило означа- ет, что пользователь не может вносить изменения в этот объект. ♦ Объект поставщика редактируется с сохранениен поддержки — это правило означает, что пользователь может изменять объект и при этом конфигурация продолжает оставать- ся на поддержке поставщика. Однако удалить объект пользователь не может. ♦ Объект поставщика снят с поддержки — означает, что объект не может быть обновлен с использованием механизма поставки и поддержки. Иными словами, пользователь может вносить любые изменения в этот объект (в том числе и удалять), а механизм поставки и поддержки просто его «не видит». По умолчанию правила поддержки устанавливаются сле- дующим образом. Если разработчик установил правило поставки Изненения запрещены, то пользователю будет уста- новлено правило поддержки Объект поставщика не редакти- руется (рис. 17.3). Правила поставки Правила поддержи В этом случае пользователь не сможет изменять данный объект конфигурации и не сможет изменить правило под- держки. Если разработчик установил правило поддержки Изнене- ния не рекомендуются или Изненения разрешены, то соответст- вующими правилами поддержки, устанавливаемыми по умолчанию, будут Объект поставщика не редактируется и Объект поставщика редактируется с сохранениен поддержки (рис. 17.4). Правила поставки Правила поддержи Рис. 17.4. Установка правил поддержки
В дальнейшем пользователь сможет изменить при необ- ходимости, правило поддержки. Изменение режима поддержки Как уже было сказано выше, конфигурация пользователя может находиться либо на полной поддержке, либо на поддержке с возможностью изменения. Пользователь мо- жет самостоятельно перейти с одного режима поддержки на другой или вообще снять свою конфигурацию с под- держки поставщика. Начальный режим поддержки Установить полную поддержку конфигурации можно двумя способами: выполнить установку дистрибутива и создать новую информационную базу из шаблона, или выполнить загрузку файла поставки в существующую информационную базу. конфигурация снята с подарриги Рис. 17.5. Установка различных режимов поддержки конфигурации Также можно установить в качестве начального режим поддержки с возможностью изменения. Для этого нужно выполнить сравнение/объединение конфигурации с фай- лом поставки. Файл поставки представляет собой специ- альным образом подготовленный файл конфигурации, о котором подробнее рассказывается в разделе «Файл по- ставки», с. 668 (рис. 17.5). Полная поддержка — поддержка с возможностью изменения При желании пользователь может изменить режим под- держки конфигурации и включить возможность измене- ний. Для этого следует выполнить команду Конфигурация ► Поддержка ► Настройка поддержки и в открывшемся окне настройки поддержки нажать кнопку Включить возможность изменения: (рис. 17.6). В этом окне также, можно увидеть информацию о конфи- гурации поставщика, на поддержке которой находится данная конфигурация: название конфигурации, название поставщика и версию конфигурации поставщика. Кроме того, в этом окне отображаются правила поддерж- ки, которые начнут действовать при включении возмож- ности изменения конфигурации. Они установлены по умолчанию на основании правил поставки, заданных в конфигурации поставщика. Пользователь может сразу же (если это не запрещено поставщиком) настроить правила поддержки отличными от заданных по умолчанию или сделать это позже, в любое удобное время. Поддержка с возможностью изменения — полная поддержка Следует обратить внимание на то, что переход к поддерж- ке с возможностью изменения прост, в отличие от перехо- да в обратную сторону, к режиму полной поддержки кон- фигурации. Это обусловлено тем, что в режиме полной поддержки конфигурация пользователя представляет со- Рис. 17.6. Включение возможности изменения конфигурации
бой практически копию конфигурации поставщика. Об- новление конфигурации в режиме полной поддержки осуществляется полностью автоматически, на основании соответствия внутренних идентификаторов объектов ме- таданных конфигурации пользователя и конфигурации поставщика. При добавлении поставщиком нового объек- та в конфигурацию он будет добавлен в конфигурацию пользователя с тем же самым идентификатором (рис. 17.7). Конфигурация пользователя Конфигурация поставщика | Новый Объект (102) — —| НовыиОбъект (102) | | Старый Объект (1D1) [— — —[ Старый Объект (ID1) | Рис. 17.7. Обновление конфигурации, находящейся на полной поддержке В отличие от этой ситуации, при обновлении конфигура- ции, находящейся на поддержке с возможностью измене- ния, новый объект, добавленный в конфигурацию постав- щика, будет добавлен в конфигурацию пользователя уже с другим идентификатором, и соответствие этих двух идентификаторов будет запомнено, чтобы в дальнейшем однозначно связывать эти два объекта при обновлении (рис. 17.8). Рис. 17.8. Обновление конфигурации, находящейся на поддержке с возможностью изменения Теперь представим себе ситуацию, что для такой вот конфигурации пользователя неким гипотетическим способом снова установили режим полной поддержки. Тогда при очередном обновлении конфигурации прои- зойдет следующее: так как соответствие будет устанав- ливаться по внутренним идентификаторам, для объек- та конфигурации поставщика с идентификатором ID2 не будет найдено соответствия в конфигурации пользо- вателя, и в конфигурации пользователя будет создан еще один объект НовыйОбъект, но уже с идентификато- ром ID2 (рис. 17.9). Рис 17.9. Дублирование объектов в конфигурации пользователя В результате получим задвоение объектов в конфигура- ции пользователя, что совершенно недопустимо. Поэтому если конфигурация находится в режиме под- держки с возможностью изменения и в информационной базе присутствует некоторая непустая база данных, то для перехода к полной поддержке поставщика необходимо выполнить следующие действия: создать информацион- ную базу с пустой базой данных и конфигурацией, нахо- дящейся на полной поддержке, а затем программными средствами перенести в эту базу данные из прежней ин- формационной базы. Поддержка с возможностью изменения — снятие с поддержки Конфигурация, находящаяся в режиме поддержки с воз- можностью изменения, может быть полностью снята с поддержки. Для этого следует в окне настройки поддерж- ки нажать кнопку «Снять с поддержки». В результате конфигурация будет снята с поддержки поставщика и пиктограммы рядом с объектами конфигурации, обозна- чающие правила поддержки, исчезнут. Конфигурация, не стоящая на поддержке — поддержка с возможностью изменения Конфигурацию, которая не находится на поддержке мож- но снова поставить на поддержку с возможностью изме- нения. Для этого следует выполнить сравнение/объеди- нение этой конфигурации с файлом поставки. В начале сравнения будет выдано сообщение о том, что возможна постановка конфигурации на поддержку. При утверди- тельном ответе и выполнении сравнения и объединения с конфигурацией поставщика конфигурация пользователя будет поставлена на поддержку с возможностью измене- ния. При этом будут установлены правила поддержки ис- ходя из правил поставки, заданных в конфигурации по- ставщика. Изменение правил поддержки Пользователь может изменять правила поддержки в том случае, если для объекта заданы правила поставщика, от- личные от правила Изменения запрещены (рис. 17.10). Правила поддер*ги Рис 17.10. Изменение правил поддержки
Установка правил Объект поставщика редактируется с сохранением поддержки и Объект поставщика не редактируется Если для объекта установлено правило Объект поставщика не редактируется, то пользователь может изменить это пра- вило на любое из других правил поддержки (рис. 17.11): ♦ Объект поставщика редактируется с сохранением поддержки; ♦ Объект поставщика снят с поддержки. Рис. 17.11. Изменение правила поддержки Объект поставщика не редактируется Для установки правил поддержки Объект поставщика редак- тируется с сохранением поддержки и Объект поставщика снят с поддержки следует воспользоваться окном настройки поддержки (рис. 17.12). Установив курсор на нужный объект, следует открыть окно настройки правил поддержки, которое предложит выбрать правило поддержки (рис. 17.13). Рис. 9.13. Настройка правил поддержки Обратите внимание, что правило может быть установле- но рекурсивно, для всех подчиненных объектов. Таким образом, если одно и то же правило необходимо устано- вить, например, для всех справочников — необходимо первоначально установить курсор на ветку Справочники, если для всей конфигурации — то курсор нужно устано- вить на корень конфигурации. Установка правила Объект поставщика не редактируется Процесс возврата к запрету редактирования объекта по- ставщика является более сложным, чем, например, сня- тие запрета редактирования или снятие объекта с под- держки (рис. 17.14). Рис. 17.14. Установка правила поддержки Объект поставщика не редактируется Рис. 17.12. Изменение правила поддержки
Это связано с тем, что в то время, пока объекту было раз- решено редактирование, он мог быть изменен пользовате- лем. Поэтому для того, чтобы запретить редактирование объекта и тем самым снова разрешить его автоматическое обновление, сначала требуется выполнить сравнение/ объединение конфигурации пользователя с конфигура- цией поставщика. Если объект быть изменен, необходимо объединить его в режиме Взять из конфигурации поставщика. После того как объединение будет выполнено, следует запустить сравнение/объединение с конфигурацией по- ставщика еще раз и установить правило поддержки Объект поставщика не редактируется (рис. 17.15). Рис 17.15. Алгоритм установки правила Объект поставщика не редактируется При выборе в окне настройки поддержки правила Объект поставщика не редактируется будет предложено, прежде все- го, выполнить сравнение/объединение с конфигурацией поставщика. Для неизмененных объектов сразу же можно будет установить новое правило, нажав на кнопку Изме- нить, а для измененных объектов сначала нужно будет вы- полнить обновление (рис. 17.16). Следует учитывать также, что подобная смена правила поддержки не может быть выполнена для группы объек- тов или рекурсивно. Поэтому если, например, требуется установить это правило для всего справочника, следует отдельно устанавливать его для корня справочника, для каждого реквизита, для каждой табличной части, для ка- ждой формы и для каждого макета. Поддержка на разных языках Конфигурация поставщика может быть многоязычной, то есть содержать строки на разных языках. При вклю- ченной возможности изменений механизм поставки и поддержки позволяет осуществлять выборочную под- держку конфигурации пользователя только на одном или нескольких языках. В данном случае «выборочность» от- носится только к строкам на разных языках, которые со- держатся в конфигурации. Например, конфигурация поставщика содержит два язы- ка: Русский и Английский. Пользовательская конфигура- ция содержит только один язык, — Русский. В этом случае если установить режим поддержки только русского язы- ка, то строки, в которых значение на русском языке не из- менилось, не будут помечаться как различающиеся. Другая ситуация, в которой может использоваться под- держка только на некоторых языках — когда пользова- тель самостоятельно редактирует интерфейс на англий- ском, например, языке и хочет, чтобы при обновлении конфигурации строки интерфейса на английском языке оставались без изменений. Рис 17.16. Выполнение сравнения/объединения конфигураций и установка правила поддержки
Установить режим поддержки только выбранных языков можно из окна настройки поддержки по кнопке Языки поддержки (рис. 17.17). Рис. 17.17. Выбор языков, для которых будет осуществляться поддержка Кроме этого, пользователь может управлять выбором языков поддержки и непосредственно в ходе обновления прикладного решения из окна обновления основной кон- фигурации конфигурацией поставщика по кнопке На- стройка (рис. 17.18). Рис. 17.18. Выбор языков поддержки в процессе обновления конфигурации Особенности работы с конфигурацией в хранилище, если конфигурация стоит на поддержке Если конфигурация, находящаяся на поддержке постав- щика, модифицируется с использованием хранилища конфигурации, то следует учитывать некоторые особен- ности, накладываемые одновременным использованием этих двух механизмов. Подробнее про механизм группо- вой разработки прикладных решений можно прочитать в разделе «Групповая разработка прикладных решений», с. 690. Редактирование объектов Для того чтобы осуществить редактирование объекта конфигурации, необходимо не только захватить требуе- мый объект в хранилище, но и сделать его доступным для редактирования средствами механизма поддержки (то есть установить нужное правило поддержки). Настройка поддержки Для настройки поддержки необходимо захватить в хра- нилище корневой объект конфигурации. Вся настройка поддержки конфигурации хранится в корне конфигура- ции. Изменения, произведенные в параметрах поддерж- ки, станут доступны другим разработчикам данной кон- фигурации только после помещения корневого объекта в хранилище конфигурации. Обновление конфигурации Для выполнения обновления конфигурации настоятель- но рекомендуется захватывать в хранилище всю конфи- гурацию. Рис. 17.19. Настройка поставки
Настройка поставки Как уже говорилось в самом начале главы, перед тем как создать дистрибутив своего прикладного решения, разра- ботчику следует настроить правила поставки и некоторые другие свойства конфигурации, относящиеся к поставке. Все эти действия выполняются в окне настройки постав- ки (рис. 17.19), которое может быть открыто по команде Конфигурация ► Поставка конфигурации ► Настройка поставки. По умолчанию для любой конфигурации система назна- чает всем объектам правило Изменения разрешены. Разработ- чик при необходимости может изменить это правило. При этом следует учитывать, что правило поставки зада- ется не для каждого объекта конфигурации, который бу- дет анализироваться в процессе обновления, а только для прикладных объектов: справочников, документов, регист- ров и т. д. Правила для подчиненных объектов: реквизитов, табличных частей, форм, макетов и т. д. будут установлены такими же, какие установлены для родительского объекта. При настройке поставки также можно указать, включать или не включать тексты модулей конкретного объекта в конфигурацию поставщика. Если исходный текст модуля не включается, это означает, что в файл конфигурации поставщика будет включен скомпилированный образ мо- дуля. Такая возможность является элементом защиты ин- теллектуальной собственности поставщика и, возможно, элементом защиты логической целостности конфигура- ции от последующих модификаций пользователем. Влия- ния на быстродействие конфигурации это не оказывает. Также в диалоге настройки поставки присутствует флаг Файл поставки может использоваться для обновления. Смысл использования этого флага будет подробно рассмотрен в главе «Создание файла поставки», с. 669. Обновление конфигурации, находящейся на поддержке Обновление в автоматическом режиме Когда конфигурация находится на полной поддержке, об- новление выполняется в автоматическом режиме. От поль- зователя требуется только инициировать этот процесс — все остальные действия (поиск доступных обновлений, из- менение конфигурации) система выполнит самостоятельно. Обновление в режиме поддержки с возможностью изменения Если конфигурация находится на поддержке с возмож- ностью изменения, система пытается по максимуму, на основе имеющейся у нее информации, сформировать правила объединения. Наряду с этим она предоставляет разработчику возможность скорректировать те случаи, когда нельзя принять однозначного решения о том, каким же образом выполнять обновление. Этот процесс очень напоминает обычное сравнение/объединение конфигура- ций, но имеет некоторые особенности. Как говорилось в самом начале раздела, в общем случае существуют четыре ситуации, которые возникают при анализе изменений одного и того же объекта конфигура- ции, выполненных как пользователем, так и поставщиком: когда ни один из них не менял объект, когда объект изме- нен одним из них и когда они оба изменили объект. Кро- ме этого, в конфигурации пользователя существуют три правила поддержки, которые определяются разработчи- ком и могут быть дополнительно настроены пользовате- лем. В результате, при сравнении конфигураций могут возникнуть десять различных ситуаций, девять из кото- рых разрешаются однозначно (рис. 17.20). На приведенном рисунке показаны три правила поддерж- ки. Для каждого правила указаны возможные ситуации с изменением объекта: серый цвет обозначает кто (пользо- ватель или поставщик) вносил изменения в объект. Боль- шой прямоугольник снаружи показывает, чьи изменения будут в результате приняты по умолчанию. Если объект не изменялся или изменялся только в кон- фигурации пользователя (первая и вторая строки), тогда будет использовано правило объединения Взять из конфи- гурации пользователя. Если объект изменялся в конфигура- ции поставщика, то будет использовано правило Взять из новой конфигурации поставщика, за исключением случая, ко- гда объект снят с поддержки. В этом случае — Взять из конфигурации пользователя. Объект поставщика не редактируется I Плз Пет Объект Объект поставщика редактируется с сохранением поддержи Г—и Плз Пет Объект Объект поставщика снят с поддержи ; I Плз Пет Объект I —I Плз Пот Объект Плз Пет Объект Плз Об1 Плз Пет Объект Плз Пет Объект Плз Пет Объект Рис. 17.20. Варианты действий при обновлении конфигурации пользователя Если объект был изменен в обеих конфигурациях, но он снят с поддержки — тогда тоже будет использовано пра- вило Взять из конфигурации пользователя. Таким образом остается один спорный момент, когда объект был изменен в обеих конфигурациях и он нахо- дится на поддержке поставщика с возможностью обнов- ления. В этом случае по умолчанию устанавливается пра- вило обновления Взять из новой конфигурации поставщика. Для того чтобы пользователю было легче разобраться в о- тличиях, существующих в конфигурациях, окно объеди- нения конфигураций в этом случае имеет дополнитель- ные возможности (рис. 17.21).
Il Обновление Основная конфигурация Новая конфигурация поставщика _ □ х йб Новая конфигурация поставщ . Режим объединениям порядокподчине .. ч, В0Г31 УправлениеТоргоелей Ё 0JSI Справочники B0ft Банки Ё-0 Свойства ! Синоним ; Модуль объекта Ё Oft БанковскиеСчета В □ Свойства Ч- В‘1~ 3 УправлениеТорговлей Й Справочники В ft Банки Ё-Своистаа - Синоним L •• Модуль объек. Ё-ft БанковскиеСчета Ё Свойства Взять из новой конфигурации поставщ Статусы по соответствиям объектов------------------------------------------------------------------------------- [ ^Совпадающие | различающиеся | j |в основной новой конфигур. [И] Изменен порядок Статусы по истории объектов —....... — ......................................................-................ w »>< Ч Измененные 9 Н»олредоп»мы» + Дс£«вл»*<ые “ Удаленные И Изменен порядок | Действия^ 11 Фильтр ^ j Нестройна | Обновить | Выполнить j | ЗакрьтГ | [ справка Рис. 17.21. Окно объединения конфигураций Рис. 17.22. Настройка фильтров просмотра Прежде всего, это информация о статусах по истории объектов, представленная в виде пиктограмм. Эта инфор- мация помогает понять, какие изменения и в какой кон- фигурации были выполнены для данного объекта. На- пример, на приведенном рис. 17.21 видно, что модули объектов справочников Банки и БанковскиеСчета различа- ются. И пиктограммы статусов по истории объектов по- могают понять, что модуль объекта справочника Банки был изменен в новой конфигурации поставщика, а мо- дуль объекта справочника БанковскиеСчета был изменен в конфигурации пользователя. По умолчанию в этом слу- чае система не будет выполнять обновление модуля объ- екта справочника БанковскиеСчета. Но, возможно, измене- ния в это модуль были внесены ошибочно, и в этом случае разработчик может включить этот объект в число обновляемых объектов, и задать нужный режим объеди- нения. Кроме информации о статусах по истории объектов, разработчик имеет возможность подробно настраивать фильтр, позволяющий просматривать различные измене- ния и отличия в конфигурациях (рис. 17.22). Для того, чтобы понять назначение этого фильтра, забежим немного вперед и поясним что происходит при обновле- нии конфигурации, стоящей на поддержке. В процессе обновления конфигурации, находящейся на поддержке, помимо основной конфигурации и новой конфигурации поставщика, участвует также и старая конфигурация по- ставщика, которая хранится в информационной базе (рис. 17.23). В ходе обновления основной конфигурации новая кон- фигурация поставщика перезапишет собой старую кон- фигурацию поставщика. Таким образом, разработчик всегда имеет возможность сравнить основную конфигурацию с конфигурацией поставщика (Конфигурация ► Сравнить конфигурации). При выполнении обновления фильтр как раз и предо- ставляет возможность отобразить в различных сочетани- ях любые изменения, присутствующие в этих трех кон- фигурациях (рис. 17.24). Помимо ручной настройки фильтров для каждой пары сравниваемых конфигураций, настройка фильтров позво-
ляет использовать несколько готовых шаблонов, отобра- жающих следующие ситуации. Рис. 17.23. Конфигурации, участвующие в обновлении Рис. 17.24. Изменения, отображаемые с помощью фильтров просмотра Отличие основной и новой конфигурации поставщика от старой конфигурации поставщика. Этот шаблон фильт- ров позволяет понять, насколько изменения, вносимые в конфигурацию с обеих сторон, изменят предыдущую версию конфигурации поставщика (рис. 17.25). Рис. 17.26. Отличие основной конфигурации от новой конфигурации поставщика Отличие основной конфигурации от старой конфигурации поставщика. Этот шаблон фильтров позволяет понять, насколько конфигурация поставщика изменена пользо- вателем (рис. 17.27). Рис. 17.27. Отличие основной конфигурации от старой конфигурации поставщика Отличие новой конфигурации поставщика от старой кон- фигурации поставщика. Этот шаблон фильтров позволя- ет понять, какие изменения в конфигурацию внес постав- щик по сравнению с предыдущей версией (рис. 17.28). Рис. 17.28. Отличие новой конфигурации поставщика от старой конфигурации поставщика Рис. 17.25. Отличие основной и новой конфигурации поставщика от старой конфигурации поставщика Отличие основной конфигурации от новой конфигурации поставщика. Этот шаблон фильтров позволяет понять, как изменится основная конфигурация после обновления (рис. 17.26). При настройке фильтров просмотра пользователь может задать флаг Показывать только дважды измененные свойства. Назначение этого флага состоит в том, чтобы показать только те свойства, которые однозначно требуют ручной
Рис. 17.29. Отображение дважды измененных свойств настройки объединения. Как уже говорилось выше, в 9 слу- чаях из 10 механизм поставки и поддержки может одно- значно сформировать правила объединения конфигура- ций. Единственный случай, который требует вмешатель- ства человека, — это ситуация, когда один и тот же объект был изменен и в конфигурации пользователя, и в конфи- гурации поставщика. Для выделения только таких отли- чий и предназначен этот флаг. Среди прочих отличий они отображаются жирным шрифтом, а при установленном флажке — отображаются только эти свойства (рис. 17.29). Особенности обновления Добавление объектов поставщиком При выполнении сравнения конфигураций в процессе обновления выполняется установка соответствия объек- тов конфигурации поставщика объектам конфигурации пользователя. Это соответствие устанавливается по внут- ренним идентификаторам объектов, которые не доступны разработчику для редактирования. При первоначальной постановке конфигурации на поддержку конфигурация пользователя полностью соответствует конфигурации поставщика, в том числе и по идентификаторам объектов. При добавлении поставщиком нового объекта и после- дующем обновлении, этот объект будет создаваться также и в конфигурации пользователя, причем с тем же самым идентификатором, что и в конфигурации поставщика. Если пользователь включает возможность изменения, то начиная с этого момента идентичность идентификаторов объектов уже не обеспечивается. При добавлении постав- щиком нового объекта и последующем обновлении, этот объект так же будет создаваться в конфигурации пользо- вателя, однако с другим, уникальным идентификатором. При этом система запоминает такую пару идентификато- ров и при последующих обновлениях будет устанавли- вать соответствие между этими объектами. Удаление объектов поставщика пользователем Для того чтобы пользователь мог удалить в своей конфи- гурации объект поставщика, он должен предварительно снять его с поддержки, установив для него соответствую- щее правило поддержки. Причем снят с поддержки дол- жен быть как сам объект непосредственно, так и все его подчиненные объекты. Возврат к объекту поставщика Иногда требуется вернуться к тому объекту, который был удален. Рассмотрим следующую ситуацию: пользователь снял с поддержки и удалил объект поставщика. В этот момент он понял, что ошибся, и решил восстановить объ- ект поставщика обратно. В такой ситуации, в принципе, существует два возмож- ных решения: вернуться к конфигурации базы данных (Конфигурация ► Конфигурация базы данных ► Вернуться к конфигурации БД) и выполнить сравнение/объединение с конфигурацией поставщика (Конфигурация ► Сравнить, объединить с конфигурацией из файла). Правильным является возврат к конфигурации базы дан- ных, и вот почему. Перед удалением объекта ситуация выглядела следую- щим образом: во всех трех конфигурациях существовал один и тот же объект с одним и тем же идентификатором (например, ID1) (рис. 17.30). Рис. 17.30. Исходная ситуация После того как пользователь удалил объект в основной конфигурации, но не обновил конфигурацию базы дан- ных, этот объект все еще будет присутствовать в конфи- гурации базы данных (рис. 17.31). Рис. 17.31. Удаление объекта в основной конфигурации
Теперь пользователь решает сравнить/объединить основ- ную конфигурацию с конфигурацией поставщика, чтобы исправить свою ошибку. В результате этого объединения объект из конфигурации поставщика окажется новым для основной конфигурации и будет добавлен в нее, но уже с новым идентификатором (например, ID2). При этом система запомнит соответствие идентификаторов ID2-ID1 и при дальнейших обновлениях основной конфигурации конфигурацией поставщика будет считать, что это один и тот же объект (рис. 17.32). Рис. 17.32. Сравнение/объединение с конфигурацией поставщика Однако при обновлении конфигурации базы данных про- изойдет следующее: поскольку объекты имеют различные идентификаторы, они сопоставлены не будут (система бу- дет считать, что это разные объекты), и, соответственно, один из них будет удален, а другой добавлен, что может привести к потере данных (рис. 17.33). Рис. 17.33. Обновление конфигурации базы данных Поэтому, чтобы избежать такого результата, нужно ис- пользовать возврат к конфигурации базы данных. При этом объект в основной конфигурации будет создан с тем же самым идентификатором (рис. 17.34). Рис. 17.34. Возврат к конфигурации базы данных Удаление объектов поставщика поставщиком В процессе выпуска новых версий конфигурации по- ставщик может удалить некоторые объекты конфигура- ции, которые больше не предполагается использовать. Если конфигурация пользователя находится на полной поддержке, эти объекты будут автоматически удалены и в конфигурации пользователя. Если же конфигурация пользователя находится на под- держке с возможностью изменения, то эти объекты будут удалены только в том случае, если они идентичны объек- там поставщика, то есть если пользователь не изменял их в своей конфигурации. В противном случае они не будут помечены для участия в обновлении, но пользователь мо- жет установить эту пометку вручную при необходимости. Обновление модулей При обновлении конфигурации пользователя система никогда по умолчанию не устанавливает правило объеди- нения Объединять... Однако такое правило может быть ус- тановлено пользователем в том случае, когда, например, изменение модуля выполнялось как поставщиком, так и пользователем. О такой возможности надо помнить при модификации тиражных решений и соблюдать некоторые правила, ко- торые облегчат пользователю обновление конфигурации. Во-первых, нужно помнить о том, что при объединении модулей соответствие между процедурами и функциями устанавливается по именам, однако процедура по умолча- нию не будет сопоставлена функции, имеющей то же имя, и наоборот. Поэтому в ситуации, когда процедуру необ- ходимо преобразовать в функцию, следует изменять и имя новой функции. При этом старая процедура будет удалена, а новая функция (с новым именем) создана в конфигурации пользователя. В противном случае, если пользователь выберет режим Объединять... и не установит ручное соответствие процедур и функций, в результате объединения в модуле могут оказаться как старая проце- дура, так и новая функция с тем же именем, что нарушит работоспособность конфигурации. Во-вторых, если в конфигурации поставщика экспорти- руемая функция была перенесена из одного общего модуля в другой, то ей также следует дать новое имя. В против- ном случае, если пользователь редактировал эти модули и выбрал для них правило объединения Объединять..., то пе- ренесенная процедура после обновления, возможно, ока- жется в обоих модулях, что также нарушит работоспособ- ность конфигурации. Обновление конфигурации поставщика Иногда может потребоваться при обновлении конфигу- рации, стоящей на поддержке с возможностью измене- ния, обновить только старую конфигурацию поставщика, хранящуюся в информационной базе, не изменяя при этом основную конфигурацию. Такая возможность может понадобиться если конфигура- ция поставщика используется, например, в качестве некой справочной конфигурации, с которой постоянно выпол- няется сравнение, а изменения в основную конфигура- цию вносятся только вручную. В этом случае можно вы- полнить обновление конфигурацией поставщика и в окне сравнения с конфигурацией поставщика снять все флаж- ки участия в объединении. Тогда объединение с основной конфигурацией выполнено не будет, но новая конфигура- ция поставщика будет сохранена в информационной базе. Рекомендации по модификации конфигурации поставщика Модифицируя конфигурацию поставщика, всегда следу- ет соблюдать несколько рекомендаций, которые помогут упростить ее обновление в дальнейшем.
Снятие объектов с поддержки Без особой необходимости не рекомендуется снимать объекты с поддержки. Снятие объекта с поддержки на- верняка требуется в том случае, когда нужно удалить этот объект. Также снятие объекта с поддержки может потре- боваться, если дальнейшее развитие объекта предполага- ется производить собственными силами. В остальных случаях нормальным правилом для объекта является Обь - ект поставщика редактируется с сохранением поддержки. Удаление объектов поставщика К удалению объектов поставщика следует относиться ос- торожно, как к любому другому удалению. Алгоритмы конфигурации могут использовать эти объекты «для внут- ренних нужд», и их удаление может привести к нарушению логической целостности конфигурации. Перед удалением следует убедиться, что эти объекты действительно не за- действованы больше в логике конфигурации. Сортировка объектов метаданных Серьезное изменение порядка поддерева объектов может привести к тому, что выбор правила Порядок из конфигура- ции поставщика не гарантирует полного сохранения поряд- ка после объединения. Если сохранение данного порядка представляется критичным, можно после обновления кон- фигурации выполнить объединение с конфигурацией по- ставщика, вызываемое из диалога настройки поддержки (Конфигурация ► Поддержка ► Настройка поддержки... кноп- ка Сравнить, объединить). Повторное выполнение объеди- нения (после обновления) приведет к полному восста- новлению порядка. Сопоставление новых объектов Если есть необходимость, новым объектам поставщика можно поставить в соответствие объекты, существующие в конфигурации пользователя. Например, не дожидаясь выхода новой версии конфигурации, пользователь само- стоятельно добавил новый документ, который затем появил- ся в конфигурации поставщика. В этом случае при обнов- лении пользователь может сопоставить новый документ поставщика тому документу, который уже существует в его конфигурации. Однако следует очень аккуратно отно- ситься к этой процедуре, поскольку в последствии изме- нить данное соответствие будет невозможно. Переименование объектов Не рекомендуется без серьезной необходимости переиме- новывать объекты метаданных, процедуры и функции. Следует помнить, что имя, используемое в модуле для дос- тупа к какому-либо объекту, может формироваться дина- мически, и обнаружение и исправление таких мест может представлять собой сложную задачу. Объединение объектов Следует помнить, что действительное объединение таких объектов, как формы, макеты или интерфейсы, то есть ус- тановка для них правил Объединять с приоритетом..., являет- ся достаточно сложным процессом, и требует обязатель- ного ручного контроля результатов. Рекомендуется пользоваться средствами формирования визуального от- чета о сравнении таких свойств для анализа различий. Иногда может оказаться целесообразным отказаться от объединения и заново внести доработки в новую версию формы поставщика. Изменение общих модулей При разработке собственных универсальных процедур рекомендуется располагать их в новых модулях, а не по- мещать в модули поставщика. Если возникает необходи- мость модификации модулей поставщика, при обновлении следует помнить о возможности настройки объединения на уровне отдельных процедур. По аналогии с модификацией модулей, рекомендуется по возможности добавлять новые процедуры и функции, а не изменять существующие. Если подобное невозможно (например, требуется модификация обработчика собы- тия), следует оформлять добавляемый код в отдельную процедуру, а в процедуре поставщика вставлять только ее вызов. Использование буфера обмена Не следует обновлять объекты, используя копирование через буфер обмена. Это не только нарушит нормальное функционирование механизма поддержки, но может при- вести к нарушению логической целостности конфигура- ции и потере данных. Общие технологические сведения о поддержке Конфигурация, стоящая на поддержке, всегда содержит в себе конфигурацию поставщика. Если конфигурация находится на полной поддержке, это означает фактиче- ски, что конфигурация пользователя полностью совпада- ет с конфигурацией поставщика. В этом случае считается, что конфигурация, находящаяся на полной поддержке и является в то же время конфигурацией поставщика. Из этого также следует, что конфигурация, находящаяся на полной поддержке, может находиться на поддержке толь- ко у одного поставщика. Если пользователь включает возможность изменения, это означает, что конфигурация пользователя теперь может отличаться от конфигурации поставщика. Поэтому при включении возможности изменения конфигурация по- ставщика создается в явном виде и становится частью ос- новной конфигурации пользователя (рис. 17.35). Рис. 17.35. Хранение конфигурации поставщика в информационной базе После выполнения обновления конфигурации базы дан- ных конфигурация поставщика также будет присутство- вать и в конфигурации базы данных (рис. 17.36).
Рис. 17.36. Хранение конфигурации поставщика в информационной базе Очевидно, что это приведет к определенному росту объ- ема информационной базы. Также это приведет, напри- мер, к росту объема файла конфигурации (*.cf), посколь- ку фактически теперь будут выгружаться не одна, а две конфигурации: основная конфигурация и конфигурация поставщика (рис. 17.37). Конфигурация поставщика является неотъемлемой ча- стью основной конфигурации, и единственный случай, когда основная конфигурация будет отделена от конфи- гурации поставщика, — это формирование файла постав- ки. Поддержка конфигураций «не наследуется», поэтому если из конфигурации, стоящей на поддержке, будет сформирован файл поставки, то в него будет включена только основная конфигурация, без конфигурации по- ставщика (рис. 17.38). В общем случае, конфигурация может находиться одно- временно на поддержке нескольких конфигураций по- ставщиков. Это значит, что основная конфигурация будет хранить в себе также и конфигурацию каждого поставщи- ка, на поддержке которой она находится (рис. 17.39). Рис. 17.39. Хранение конфигураций поставщиков в информационной базе В информационной базе конфигурации поставщиков хранятся в сжатом виде, и при снятии конфигурации с поддержки соответствующая конфигурация поставщика удаляется из информационной базы. Однако особенность работы файловой базы данных 1 С:Предприятия заключается в том, что при этом размер файла *.1CD не уменьшается. Свободное место, появив- шееся в результате удаления конфигурации поставщика, будет использовано в дальнейшем, для размещения, на- пример, данных базы данных и для других целей. То, что объем конфигурации уменьшился, можно заметить по файлу выгрузки конфигурации (*.cf). Рис. 17.37. Конфигурация поставщика выгружается вместе с основной конфигурацией Рис. 17.38. Файл поставки не содержит конфигурацию поставщика
Сценарии поддержки Теперь рассмотрим несколько сценариев использования механизма поставки и поддержки прикладных решений. Вертикальная поддержка Сценарий вертикальной поддержки является одним из самых простых, и заключается в следующем. Поставщик 1 создает некоторое типовое решение. Поставщик 2 ставит свою конфигурацию на поддержку конфигурации постав- щика 1 (в возможностью изменения) и дорабатывает в со- ответствии с пожеланиями конечного пользователя. Ко- нечный пользователь работает в конфигурации, стоящей на полной поддержке поставщика 2 (рис. 17.40). Рис. 17.40. Вертикальная поддержка Типичный пример применения такого сценария: партнер поставляет пользователям доработанное типовое реше- ние фирмы «1С» (рис. 17.41). В этом случае партнер ставит свою рабочую конфигура- цию на поддержку типового решения фирмы «1С» и вно- сит в нее необходимые доработки. По мере готовности своих версий и релизов партнер формирует файлы об- новления для клиента. При выходе обновления типового решения фирмы «1С», партнер сначала обновляет свою рабочую конфигурацию, а затем из своей обновленной рабочей конфигурации формирует файл обновления для клиента. В силу своей простоты, такой способ поддержки является наиболее приемлемым для конечного пользователя: от конечного пользователя не требуется усилий по объеди- нению изменений, выполняемых каждым из поставщи- ков. От поставщика 2 он получает полностью готовое прикладное решение, которое обновляется в автоматиче- ском режиме, так как стоит на полной поддержке. С дру- гой стороны, такой сценарий поддержки удобен и для поставщика 2: поскольку пользователь не имеет возмож- ности вносить изменения в прикладное решение, постав- щик 2 может быть уверен, что у пользователя не возник- нет сложностей при его обновлении. Рис. 17.41. Пример использования «вертикальной» поддержки Потенциальным минусом такого сценария является необ- ходимость последовательного «спуска» изменений свер- ху вниз. Изменения, внесенные поставщиком 1, сначала должны быть приняты на более низком уровне — на уров- не поставщика 2, — и только после этого поставщик 2 сможет передать их на уровень пользователя. Очевидно, что если поставщик 2 внес значительные изменения в конфигурацию поставщика 1, то очередное обновление не всегда может быть выполнено достаточно оперативно. Последовательность установки вертикальной поддержки Для того, чтобы установить вертикальную поддержку для прикладного решения пользователя, нужно выполнить следующую последовательность действий (рис. 17.42). Рис. 17.42. Последовательность установки вертикальной поддержки
Поставщик 2 устанавливает у себя дистрибутив приклад- ного решения поставщика 1 и создает информационную базу с конфигурацией, стоящей на полной поддержке по- ставщика 1. После этого он переводит конфигурацию в режим поддержки с возможностью изменения и модифи- цирует прикладное решение. Затем поставщик 2 создает дистрибутив своей рабочей конфигурации, который и пе- редает пользователю. Горизонтальная поддержка Сценарий горизонтальной поддержки является более сложным для пользователя, но зато и более оперативным. Суть его заключается в том, что конфигурация пользова- теля находится на поддержке у двух поставщиков одно- временно (рис. 17.43). Рис. 17.43. «Горизонтальная» поддержка Сложность такой схемы для пользователя заключается в том, что его конфигурация может находиться только на поддержке с возможностью изменения. А это требует от него определенных усилий по правильной настройке пра- вил поддержки и непосредственного участия в процессе обновления, так как оно будет выполняться только в по- луавтоматическом режиме. Зато неоспоримым преимуществом является оператив- ность внесения изменений. В отличие от сценария верти- кальной поддержки, пользователю не нужно ждать, пока один поставщик внесет в свою конфигурацию изменения другого поставщика и сформирует для пользователя файл обновления. При горизонтальной поддержке поль- зователь может получать и устанавливать обновления от каждого из поставщиков независимо (рис. 17.44). Рис. 17.44. Обновление при горизонтальной поддержке Последовательность установки горизонтальной поддержки Для того чтобы установить горизонтальную поддержку для прикладного решения пользователя, нужно выпол- нить следующую последовательность действий (рис. 17.45). Рис. 17.45. Последовательность действий для установки горизонтальной поддержки Пользователь устанавливает у себя дистрибутив при- кладного решения поставщика 1 и создает информацион- ную базу с конфигурацией, стоящей на полной поддержке поставщика 1. После этого он переводит конфигурацию в режим поддержки с возможностью изменения. Затем он устанавливает дистрибутив поставщика 2 и выполняет сравнение/объединение текущей конфигурации с фай- лом поставки, содержащимся в дистрибутиве поставщи- ка 2. При выполнении сравнения/объединения будет за- дан вопрос о возможности постановки конфигурации на поддержку поставщика 2, на который нужно ответить ут- вердительно. После завершения сравнения/объединения текущая конфигурация будет находиться на поддержке двух поставщиков одновременно с возможностью изме- нения. Особенности горизонтальной поддержки Установка соответствия объектов Как правило, конфигурации поставщиков, на поддержку которых ставится текущая конфигурация, имеют логиче- ски совпадающие объекты. Поэтому важно убедиться, что они будут связаны с одним и тем же объектом текущей конфигурации. Особенность заключается в том, что при первичном выполнении сравнения/объединения с кон- фигурацией поставщика сопоставление объектов конфи- гураций будет выполняться только по именам объектов, которые в разных конфигурациях поставщиков могут различаться. Если это так, то следует выполнить ручную установку соответствий объектов конфигураций. Сделать это нужно именно при первичном объединении, посколь- ку в дальнейшем это соответствие изменить будет невоз- можно. Настройка поддержки Основной сложностью горизонтальной поддержки явля- ется то, что режим поддержки объекта задается относи- тельно каждой конфигурации поставщика, в которой он присутствует (рис. 17.46).
Настройка поддержки □ X Конфигурация находится на поддержке с аоаыомосты? изменения - Настройка правил поддержки объектов Сравнитъобъе^нить ]| Открыть ] [ Сохранить в файл ) | Закрыть || Справка Рис. 17.46. Настройка поддержки нескольких поставщиков Поддержка корневого объекта. Прежде всего нужно ре- шить, на поддержке какой конфигурации поставщика бу- дет находиться корневой объект текущей конфигурации. Соответственно, при первичном объединении с другими конфигурациями следует снимать флаг со свойств кон- фигурации и в дальнейшем устанавливать для корня кон- фигурации (отключив рекурсию) режим поддержки Снят с поддержки. Поддержка пересекающихся объектов. С большой до- лей вероятности часть объектов будет присутствовать од- новременно в нескольких конфигурациях поставщиков. В этом случае следует настроить правила поддержки ис- ходя из перечисленных вариантов: ♦ объект должен полностью соответствовать одной из конфигураций поставщика. В этом случае для данной конфигурации устанавливается правило поддержки Объект не редактируется, а для остальных — Объект снят с поддержки; ♦ объект должен редактироваться с сохранением под- держки одной из конфигураций. В этом случае для этой конфигурации устанавливается правило Объект редакти- руется с сохранением поддержки, а для остальных — Объект снят с поддержки; ♦ объект должен редактироваться и иметь возможность поддержки разных конфигураций. В этом случае для всех конфигураций устанавливается правило Объект ре- дактируется с сохранением поддержки; ♦ поддержка объекта не требуется. В этом случае для всех конфигураций устанавливается правило Объект снят с поддержки. При установке правил поддержки следует учитывать, что так как объект связан с объектами нескольких конфигу- раций поставщиков, то для того, что бы в одной из них ус- тановить правило Объект поставщика не редактируется, нуж- но сначала в остальных конфигурациях снять этот объект с поддержки. Механизм создания комплектов поставки Для того чтобы пользователь мог установить у себя при- кладное решение, разработчик должен передать ему необ- ходимые файлы. Состав этих файлов может быть самым разным, так же как и их назначение. Одни файлы могут предназначаться для того, чтобы обеспечивать обновле- ние или установку прикладного решения. Другие просто могут содержать справочную информацию и отображать- ся в специальных случаях. Третьи могут предназначаться для того, чтобы пользователь самостоятельно использо- вал их при необходимости. Механизм создания комплектов поставки позволяет ав- томатизировать работу по созданию наборов таких фай- лов и размещению их на компьютере пользователя. Основными файлами, участвующими в поддержке при- кладного решения пользователя, являются файл постав- ки и файл обновления. Файл поставки Файл поставки представляет собой файл конфигурации *.cf, сформированный специальным образом в информа- ционной базе разработчика. В общем случае файл постав- ки имеет два назначения: постановка конфигурации на поддержку и обновление конфигурации, стоящей на под- держке поставщика. Постановка конфигурации на под-
держку с помощью файла поставки возможна двумя спо- собами (рис. 17.47). Рис. 17.47. Постановка на поддержку с помощью файла поставки Во-первых, можно загрузить файл поставки в произволь- ную информационную базу командой Конфигурация ► За- грузить конфигурацию из файла... В этом случае текущая конфигурация информационной базы будет полностью заменена новой конфигурацией, которая стоит на полной поддержке конфигурации поставщика. Во-вторых, можно выполнить сравнение/объединение текущей конфигурации с файлом поставки. Полученная в этом случае конфигурация будет также стоять на под- держке конфигурации поставщика, но уже с возможно- стью изменения. Постановку на поддержку можно выполнить только с по- мощью файла поставки. Можно сказать, что файл постав- ки является основным инструментом, с помощью которого осуществляются действия по поддержке пользователь- ских конфигураций. Как уже говорилось, этот файл может быть использован не только для постановки на поддержку, но и для обновления конфигурации пользо- вателя, то есть для перехода с одной версии конфигура- ции, стоящей на поддержке, на версию файла поставки. Он содержит в себе полную конфигурацию поставщика и дополнительные данные, необходимые для поддержки. Поэтому обновление с помощью файла поставки возмож- но с любой версии конфигурации до версии файла по- ставки, в том числе с более поздней версии до более ран- ней (рис. 17.48). L. Файл поставки *.cf Версия 3 Рис. 17.48. Использование файла поставки Создание файла поставки Файл поставки формируется в информационной базе разработчика. Перед тем, как сформировать файл постав- ки, следует настроить поставку. Этот процесс подробно описан в разделе «Настройка поставки», с. 659. После этого нужно выполнить команду Конфигурация ► Поставка конфигурации ► Создать файлы поставки и обновления конфи- гурации... В открывшемся окне нужно указать имя и раз- мещение файла поставки и нажать кнопку Выполнить (рис. 17.49). Рис. 17.49. Создание файлов поставки и обновления Механизм поставки и поддержки обеспечивает опреде- ленную схему размещения файлов поставки и обновле- ния на диске. По умолчанию они располагаются в подка- талогах, имеющих имена, соответствующие свойству Версия конфигурации (рис. 17.50). Рис. 17.50. Структура каталогов поставки и обновления Корневой каталог поставки можно задать с помощью кнопки Каталог файлов поставки. Следует иметь в виду, что корневой каталог поставки не сохраняется внутри самой конфигурации и будет изменен, например, при переносе файла информационной базы *.lcd на другой компьютер. Также следует сделать дополнение к процессу настройки поставки, который описан в разделе «Настройка постав- ки», с. 659. В окне настройки поставки существует флаг Файл поставки может использоваться для обновления. По умолчанию этот флаг поднят, то есть по умолчанию с по-
мощью этого файла можно как поставить конфигурацию на поддержку, так и обновить конфигурацию, уже стоя- щую на поддержке до версии файла поставки. Однако есть случаи, в которых требуется использовать файл поставки, не допускающий выполнение обновле- ний. Подобные случаи возникают, когда переход на но- вую версию конфигурации требует сложной обработки базы данных. Рассмотрим одну из возможных ситуаций. Пусть при разработке очередной версии конфигурации было решено поменять тип реквизита РеквизитА справоч- ника СправочникА с типа Строка на тип ссылки на справоч- ник СправочникБ. Такую процедуру нельзя выполнить в рамках одного изменения структуры базы данных с пред- шествующим и/или последующим выполнением служеб- ной обработки. Требуется сначала переход к некоторой промежуточной конфигурации, выполнение служебной обработки, а затем уже переход к конфигурации новой версии. Переход на новую версию будет представлять со- бой следующую последовательность действий: ♦ создание справочника СправочникБ; ♦ создание в справочнике СправочникА нового реквизита РеквизитНовый с типом ссылки на справочник Справоч- никБ; ♦ выполнение в полученной промежуточной конфигура- ции служебной обработки, которая для каждого эле- мента справочника СправочникА создаст новый (или вы- берет существующий) элемент справочника СправочникБ, присвоит реквизиту РеквизитНовый ссылку на него, и очи- стит значение реквизита РеквизитА; ♦ удаление реквизита РеквизитА справочника СправочникА; ♦ переименование реквизита РеквизитНовый в РеквизитА. Таким образом, для выполнения этой последовательно- сти действий потребуется создание двух комплектов об- новления: для перехода к промежуточной версии и с про- межуточной на конечную версию. Кроме этого, очевидно, потребуется и файл поставки для установки новой вер- сии новыми пользователями. В этом случае такой файл поставки формируется со сброшенным флагом Файл по- ставки может использоваться для обновления, чтобы он слу- чайно не мог быть использован для обновления в данной ситуации. Однако следует учитывать недостаточную гибкость этого средства. При отключении этого флага пользователь не сможет при необходимости выполнить «обратное обнов- ление» с более поздней версии с помощью такого файла поставки. Файл обновления Файл обновления представляет собой специальный файл *.cfu, формируемый также в информационной базе разра- ботчика. Назначение файла обновления состоит лишь в том, чтобы выполнить обновление с некоторых опреде- ленных версий конфигурации до версии файла обновле- ния (рис. 17.51). В отличие от файла поставки, файл обновления позволя- ет выполнять обновления только с тех версий, которые были указаны при его формировании. Кроме того, файл обновления не позволяет выполнять обновление с более поздних версий до более ранних. Рис. 17.51. Использование файла обновления Это связано с тем, что файлы обновления включают в себя не всю конфигурацию, а только те изменения кото- рые существуют между версией файла обновления и вер- сиями, указанными при его формировании. За счет малого количества информации и дополнитель- ного сжатия данных, которое используется в файлах обновления, они оптимальны для доставки обновления пользователям по низкоскоростным каналам связи. Создание файла обновления Для формирования файла обновления необходимо от- крыть окно создания файлов поставки и обновления ко- мандой Конфигурация ► Поставка конфигурации ► Создать файлы поставки и обновления конфигурации. Создание фай- ла обновления требует обязательного указания файлов поставки предыдущих версий, для которых предназначе- но данное обновление (рис. 17.52). Рис. 17.52. Создание файла обновления Файлы поставки предыдущих версий можно добавить вручную, если они находятся в произвольном месте, или воспользоваться возможностью автоматического подбо- ра, исходя из структуры каталогов поставки. Для этого нужно нажать кнопку Добавить из предыдущих версий (рис. 17.53). Рис. 17.53. Добавление файлов поставки предыдущих версий
Технологические особенности использования файлов поставки и обновления Обновление конфигурации, стоящей на поддержке, мо- жет быть выполнено как с помощью файла поставки, так и с помощью файла обновления. Объем файла обновления меньше, чем объем файла по- ставки, но процесс обновления с помощью файла обнов- ления не может выполняться быстрее, чем с помощью файла поставки. Дело в том, что при использовании файла обновления сна- чала, на основе старой версии конфигурации поставщика и файла обновления, создается новая версия конфигура- ции поставщика. После этого выполняется сравнение/объ- единение текущей конфигурации с новой конфигурацией поставщика (рис. 17.54). При использовании файла поставки сразу же выполняет- ся сравнение/объединение. Поэтому в общем случае та- кой вариант обновления выполняется не медленнее, чем при использовании файла обновления (рис. 17.55). Рис. 17.54. Выполнение обновления с помощью файла обновления ------------------ Файл поставки (*.cf) Рис. 17.55. Выполнение обновления с помощью файла поставки При завершении процесса сравнения/объединения новая конфигурация поставщика замещает старую версию кон- фигурации поставщика. Если процесс сравнения/объеди- нения будет прерван, то старая конфигурация поставщи- ка не изменится. Файл информационной базы Может возникнуть ситуация, когда пользователю, для первоначальной установки прикладного решения, необ- ходимо передать не файл поставки, а непосредственно файл информационной базы *.lcd, содержащий, напри- мер, готовую к работе, но пустую базу данных. В этом случае можно создать пустую информационную базу в файловом режиме работы, загрузить в нее файл поставки (Конфигурация ► Загрузить конфигурацию из файла...) и пе- редать пользователю файл *.lcd (рис. 17.56). Файл выгрузки информационной базы В процессе поставки не исключена ситуация, когда, по- мимо файла поставки, пользователю понадобится и де- монстрационная информационная база, стоящая на под- держке поставщика. В этом случае можно использовать некоторую информационную базу, содержащую демонст- рационные данные. Конфигурация этой базы не обяза- тельно должна быть полностью идентична конфигурации разработчика, но расхождения между ними должны позво- лять производить обновление конфигурации базы данных (и самих данных) без проблем. Следует загрузить в эту базу файл поставки (Конфигурация ► Загрузить конфигурацию из файла...) и затем выгрузить информационную базу (Администрирование ► Выгрузить информационную базу...) (рис. 17.57). Рис. 17.56. Формирование файла информационной базы Рис. 17.57. Формирование файла выгрузки информационной базы
Шаблоны конфигураций Система ЮПредприятие предоставляет пользователю возможность самостоятельно создавать информационные базы, содержащие необходимые конфигурации. Для это- го ЮПредприятие поддерживает работу с каталогом шаблонов конфигураций. При создании новой информа- ционной базы пользователю открывается список шабло- нов. В этом списке он может выбрать один из имеющихся шаблонов, который будет использован при создании ин- формационной базы (рис. 17.58). Рис. 17.58. Список шаблонов Подобный подход позволяет создавать как пустые ин- формационные базы с требуемой конфигурацией, так и информационные базы, содержащие определенный со- став данных (например, демонстрационные базы). По умолчанию каталог шаблонов располагается в папке C:\Program Files\lcv8\tmplts, однако пользователь может настроить для работы и другой каталог шаблонов, если в этом есть необходимость. Это выполняется в диалоге настройки запуска, вызываемом по кнопке Настройка... в окне запуска (рис. 17.59). Рис. 17.59. Настройка расположения списка шаблонов Каталог шаблонов может иметь произвольную структуру, но рекомендуется придерживаться следующей иерархии подкаталогов (рис. 17.60). Например, реальный каталог шаблонов ЮПредприятия может выглядеть следующим образом (рис. 17.61). В корне каталога шаблонов находятся папки поставщи- ков. Каждый поставщик самостоятельно может выбрать имя для своего каталога, но для исключения повторений фирма «1С» регистрирует названия разработчиков — по- ставщиков прикладных решений (конфигураций). Реги- стрируется название для использования в наименованиях шаблонов конфигураций и название для использования в именах файловых каталогов. Рис. 17.60. Структура каталога шаблонов Рекомендуется выбирать имена каталогов в формате MS- DOS (8.3). Например, если организация поставщика на- зывается Фирма «Сервис», то каталог поставщика может иметь название Service. Каталог поставщика Фирма «1С» имеет название 1С. В каталоге поставщика могут быть расположены ката- логи, соответствующие прикладным решениям, выпус- каемым поставщиком. Каждый каталог имеет свое уни- кальное название. Например, если прикладное решение называется Издательство, то каталог этого прикладного решения может называться Publishing. В каталоге прикладного решения содержатся каталоги версий этого прикладного решения. Каждый каталог вер- сии имеет имя, формируемое на основе номера версии этого прикладного решения, в котором символы точка «.» заменяются символами подчеркивания «_». Например, каталог версии 1.0.6.1 может иметь имя 1_0_б_1. Внутри каталога версии может находиться набор файлов, которые имеют отношение к данной версии прикладного решения. Эти файлы, по сути дела, представляют собой набор файлов поставки и применительно к данной струк- туре называются шаблоном. В составе этих файлов есть файл *.mft, который называется манифестом и описыва- ет, каким образом система ЮПредприятие может ис- пользовать файлы, содержащиеся в шаблоне.
Рис. 17.61. Каталог шаблонов Возможны следующие способы использования: ♦ во-первых, файл поставки (*.cf) может быть использо- ван для создания новой информационной базы, с кон- фигурацией, стоящей на полной поддержке постав- щика. Для этого он должен быть соответствующим образом описан в манифесте; ♦ во-втпорых, файл выгрузки базы данных (*.dt) может быть использован для создания демонстрационной ин- формационной базы, с конфигурацией, стоящей также на полной поддержке поставщика. Для этого он должен быть соответствующим образом описан в манифесте; ♦ в-третъих, файл обновления (*.cfu) может быть ис- пользован системой для автоматического (или полуав- томатического) обновления прикладного решения. Для этого в каталоге шаблонов, где находится файл обнов- ления, должен существовать манифест, содержащий определенную информацию. Остальные файлы (кроме *.cf, *.cfu и *.dt), содержащиеся в шаблоне, предназначены для ручного использования — они могут содержать дополнительную информацию об устанавливаемой версии, вспомогательные файлы и об- работки и т. д. Манифест Файл манифеста используется системой ЮПредприятие при формировании списка шаблонов и при поиске дос- тупных обновлений прикладного решения. Файл мани- феста может иметь произвольное имя и расширение mft. Манифест является текстовым файлом, использующим кодировку UTF-8 для поддержки нескольких языков. Структура манифеста включает использование зарезер- вированных параметров и секций. В общем виде манифест имеет следующую структуру: Vendor=... Name»... Version»... [Configl] Catalog»... Destination»... Source»... [ConfigZ] В начале манифеста содержатся три параметра: ♦ Vendor — имя поставщика. Совпадает со значением свойства конфигурации Поставщик; ♦ Name — наименование прикладного решения. Совпадает со значением свойства конфигурации Имя; ♦ Version — версия конфигурации. Совпадает со значени- ем свойства конфигурации Версия. За этими параметрами могут следовать одна или несколь- ко секций, имеющих стандартные имена Configl, Config2 и т. д. Каждая из этих секций, в свою очередь, описывает для 1 С:Предприятия отдельный шаблон, который может быть использован пользователем при создании новой ин- формационной базы (рис. 17.62). Бухгалтерия презриятия Бухгалтерия предприятия (демо) \ Ш1 0.61 > ^1:51.27 Н О Создать пустую информационную Вазу «Назад ] Далее» | Отмена | Рис. 17.62. Файл манифеста
Например, на рис. 17.62 видно, что секция Configl исполь- зуется для описания шаблона версии 1.5.1.27 Бухгалтерии предприятия, а секция Config2 описывает шаблон де- монстрационной базы Бухгалтерии предприятия версии 1.5.1.27. Каждая секция содержит три параметра. Catalog — определяет наименование прикладного реше- ния в списке шаблонов. В наименовании прикладного ре- шения указывается полное название (с учетом иерархии) ветки списка шаблонов, в которой будет располагаться данный шаблон. Название одного уровня иерархии отде- ляется от названия другого уровня иерархии символом «/». Например, название 1С: Бухгалтерия предприятия/Бух- галтерия предприятия означает, что в папке 1С:Бухгалтерия предприятия будет отображаться папка Бухгалтерия пред- приятия, в которой уже и будет находиться шаблон ука- занной версии прикладного решения (рис. 17.63). Рис. 17.63. Отображение прикладного решения в списке шаблонов В общем случае параметр Catalog имеет синтаксис Catal од_«суффикс языка>. Например, Catalog_ru или Catalog_en. Задание суффикса языка используется для того, чтобы отображать название прикладного решения на языке интерфейса платформы 1С:Предприятия. Если суффикс языка не указан, то значение этого параметра использует- ся для всех языков интерфейсов платформы, кроме тех, для которых в данной секции указан параметр Catalog с нужным суффиксом. Например, в предыдущем примере в секцию Configl мож- но добавить параметр Catalog_en (рис. 17.64). Г IcvB.mft Notepad Xj Fife Edit Format View Help Vendor-Фирма "1C" A Name-Бухга л терияПред приятия Verslon=l.5.1.27 [Configl] Catalog^! С:Бухгалтерия предприятия /Бухгалтерия предприятия Catalogen-1 C.'Accounting /Accounting Destination^! CyUxounting Source=1Cv8.cf (Config?] СаГа1од=1С:Бухгалтерия предприятия/Бухгалтерия предприятия (демо] Destination-1 C\DemoAccountlng Source=l CvB.dt < > .K| Рис. 17.64. Использование параметра Catalog для разных языков Тогда при работе с английским языком интерфейса плат- формы список шаблонов будет выглядеть следующим об- разом (рис. 17.65). Рис. 17.65. Вид списка шаблонов при запуске с английским языком интерфейса платформы Для указанной нами версии прикладного решения будет выведено ее английское название, в то время как для ос- тальных версий будут использованы русские названия, указанные в параметрах Catalog соответствующих мани- фестов. На момент написания данной книги 1С:Предприятие ис- пользует следующие суффиксы языков (табл. 17.3). Таблица 17.3. Языки интерфейса платформы Язык интерфейса Суффикс языка Английский Еп Болгарский Bg Грузинский Ка Казахский Кк Латышский Lv Литовский Lt Немецкий De Румынский Ro Русский Ru Украинский Uk Точный список доступных кодов языков интерфейса на- ходится в файле в Locllnfo.txt. По умолчанию файл распо- ложен в каталоге C:\Program Files\lcv8. Destination — рекомендуемый подкаталог, в котором бу- дет создаваться новая информационная база на основа- нии данного шаблона. По умолчанию система 1 (^Пред- приятие предлагает создавать новые информационные базы в каталоге C:\Documents and Settings\<Karanor локаль- ного пользователя>\Му Documents\. Параметр Destination определяет дальнейшую структуру подкаталогов относи- тельно этого каталога. Параметр Desti nation рекомендуется указывать в формате «каталог разработчика* \ «каталог информационной базы*, на- пример Service\Publish для прикладного решения Изда- тельство разработчика Фирма «Сервис». Если в процессе создания новой информационной базы выяснится, что такой каталог уже существует, то к ука- занному имени автоматически будет добавлен символ «1», затем «2» и т. д. (Service\Publishl, Service\Publish2,...).
Source — имя файла поставки (*.cf) или файла выгрузки информационной базы (*.dt). Эти файлы должны нахо- диться в том же каталоге, что и манифест. При формиро- вании списка шаблонов система проверяет наличие файла, указанного в параметре Source. Если такой файл отсутст- вует, соответствующая этой секции ветка в списке шабло- нов не отображается. Использование манифеста для автоматического поиска обновлений Файлы обновления (*.cfu) не описываются в манифесте, так как вся информация, необходимая собственно для об- новления, может быть получена непосредственно из са- мого файла обновления. Однако для того, чтобы система ЮПредприятие отобразила файл *.cfu как доступное об- новление, в каталоге шаблонов должен обязательно при- сутствовать манифест, со значениями параметров Vendor, Name и Version, совпадающими со значениями, указанными в файле обновления. Не обязательно файл обновления и соответствующий манифест должны находиться в одной и той же папке каталога шаблонов, но такое размещение рекомендуется. Кроме этого, манифест должен обязательно содержать одну секцию с параметрами Catalog, Destination и Source. Из параметра Catal од будет взято отображаемое название обновления, параметры Destination и Source в данном случае использоваться не будут, но должны быть заданы (можно задать произвольные значения), иначе об- новление не будет найдено автоматически. Кроме этого, при обновлении прикладного решения систе- ма может использовать специальный файл, содержащий дополнительную информацию о данном обновлении. Та- кой файл имеет стандартное имя lcv8upd и одно из четы- рех расширений: *.htm, *.html, *.txt или *.mxl. Этот файл будет отображен при нажатии кнопки Информация об об- новлении в диалоге обновления конфигурации (рис. 17.66). При выполнении обновления прикладного решения поль- зователю предоставляется возможность выбрать один из двух вариантов выполнения этого действия: автоматиче- ский поиск обновлений и указание нужного файла обнов- ления вручную (рис. 17.67). Рис. 17.67. Выбор источника обновления Если пользователь выбирает автоматический поиск об- новлений, то система будет выполнять поиск (по умолча- нию) в нескольких каталогах (рис. 17.68). Для того чтобы система отобразила находящиеся в них файлы обновле- ния, они должны быть сформированы по правилам, опи- санным в предыдущем разделе. Обновление конфигурации X Выберите область поиска файлов обновлении 0 Искать в текущем каталоге шаблонов и обновлений. c:\Program Ftes\1cv8'tmpHs 0 Искать обновления в каталогах «’V 0 http .//downloads v8.1c.ruftmplts/ О a\ (дискета) 0e \v8updates (CD-ROM) ||сЦ1айлОтПостаещика1 ,cf Информация об обновлении [ < Назад"| Отмена ~ | [ справка | Рис. 17.68. Выбор области поиска обновлений | < Назад ] Р Готово | Отмена [справка Рис. 17.66. Диалог обновления конфигурации Файл lcv8upd.* должен находиться в том же каталоге, что и соответствующий файл обновления. Удаленный каталог шаблонов Обновление конфигурации, стоящей на поддержке по- ставщика, выполняется с помощью команды Конфигура- ция ► Поддержка ► Обновить конфигурацию. Все представленные на этом рисунке каталоги можно разделить на две группы: простые каталоги, содержащие обновления, и каталоги шаблонов. К простым каталогам относятся каталог а:\ (дискета) и e:\v8updates (CD-ROM). Кроме указанных пользователь имеет возможность до- бавлять и другие каталоги, в которых могут находиться обновления. Наряду с этим механизм поставки и поддержки позволя- ет выполнять полностью автоматический поиск обновле- ний, при котором от пользователя не требуется указания даже местонахождения файлов обновления. Для этого ис- пользуются локальный и удаленный каталоги шаблонов. Путь к локальному каталогу шаблонов берется из настро- ек системы, и по умолчанию флаг поиска в локальном каталоге шаблонов установлен. Таким образом, все под- ходящие обновления, которые были получены пользова- телем в процессе установки дистрибутивов прикладных решений, будут найдены в локальном каталоге шаблонов.
Кроме того, в свойстве поставляемой конфигурации Адрес каталога обновлений разработчик может указать адрес уда- ленного каталога шаблонов (FTP- или НТТР-ресурс), в котором система также будет выполнять поиск доступ- ных обновлений. Благодаря этому поддерживается воз- можность удаленного обновления прикладного решения у пользователя: при формировании комплекта поставки разработчик указывает в нем адрес удаленного каталога обновлений и передает пользователю логин и пароль для этого ресурса. В дальнейшем пользователь при необходи- мости, выполняет команду Конфигурация ► Поддержка ► Обновить конфигурацию, вводит логин и пароль и система выполняет автоматическое (если конфигурация находит- ся на полной поддержке) или полуавтоматическое обнов- ление прикладного решения. Файл списка шаблонов Особенностью удаленного каталога шаблонов является наличие файла списка шаблонов. Этот файл должен рас- полагаться в корне удаленного каталога и содержать опи- сание всех шаблонов, находящихся в этом удаленном ка- талоге. Как правило, для создания удаленного каталога шабло- нов используется следующая последовательность дейст- вий. Сначала структура папок и файлов удаленного ката- лога создается на локальном компьютере. После этого открывается окно редактирования каталога шаблонов кон- фигураций (Конфигурация ► Поддержка ► Шаблоны конфи- гураций и обновлений). В этом окне открывается корень структуры каталога шаблонов, который мы готовим на локальном компьютере, и в нем создается файл списка шаблонов (Действия ► Создать файл списка шаблонов). В кор- не каталога шаблонов будет создан файл v8cscdsc.lst — это и есть файл списка шаблонов. После этого вся созданная локально структура каталогов и файлов копируется на удаленный ресурс. Создание комплектов поставки Как говорилось в начале главы, механизм создания ком- плектов поставки позволяет автоматизировать процесс подготовки всех необходимых файлов для передачи поль- зователю. Кроме этого, он позволяет создать из этих фай- лов дистрибутив — файл архива lcv8.efd и инсталлятор setup.exe. Пользователь запускает инсталлятор, и все файлы, содержащиеся в архиве, устанавливаются в ло- кальный каталог шаблонов. Для того, чтобы формирование комплекта поставки мож- но было выполнять неоднократно, все информация о ком- плекте поставки хранится в файле описания комплекта поставки. Такой файл имеет расширение .edf. При созда- нии нового комплекта поставки разработчик создает но- вый файл описания этого комплекта поставки, который затем может сохранить на диске и использовать в дальней- шем для редактирования состава комплекта поставки или для формирования новых версий файлов поставки. Для создания нового комплекта поставки следует выпол- нить команду Конфигурация ► Поставка конфигурации ► Комплект поставки.... Система предложит открыть один из сохраненных фай- лов описания комплекта поставки, или создать новый (рис. 17.69). Рис. 17.69. Выбор описания комплекта поставки Когда создается новый комплект поставки, нужно ука- зать наименование будущей поставки и наименование поставщика (рис. 17.70). Рис. 17.70. Ввод наименования поставки и поставщика По умолчанию система указывает в этих полях значения свойств Синоним и Поставщик текущей конфигурации, однако совсем не обязательно, что именно они и должны быть за- даны для формируемого комплекта поставки. Во-первых, создание, редактирование файлов описания комплектов поставки может выполняться, вообще говоря, в любой произвольной информационной базе, поэтому наимено- вание поставляемого прикладного решения может отли- чаться от того, которое содержится в текущей информа- ционной базе. Во-вторых, комплект поставки может включать в себя шаблоны разных прикладных решений, поэтому название комплекта поставки может быть вооб- ще не связано с конкретным прикладным решением. На следующем шаге создания описания комплекта по- ставки предоставляется возможность использовать теку- щую информационную базу в качестве «источника дан- ных» для создаваемого комплекта (рис. 17.71). Создание описания комплекта поставки Укажите параметры шаблона й Определять параметры по текущей конфигурацию Поставщик: Имя Версия Путь Фирма "Сервис" Издательство 1.4.2.2 | КаталогПоставщика~ Параметры шаблона записываются в манифест шаблона, входящего в комплект поставки I с Ыиад 1Г Г отово Отмена j | Сгуавка | Рис. 17.71. Указание параметров шаблона
Эта возможность также не является обязательной, но по умолчанию она включена. Этой возможностью удобно пользоваться, например, когда нужно быстро создать комплект поставки для текущего прикладного решения. Тогда значения свойств Поставщик, Имя и Версия текущей конфигурации будут использованы как значения пара- метров Vendor, Name и Version создаваемого манифеста. Од- нако если комплект поставки будет содержать шаблоны нескольких прикладных решений, тогда в остальных шаблонах эти значения нужно будет изменить вручную, в процессе редактирования файла описания комплекта поставки. Также на этом шаге создания описания комплекта по- ставки можно задать путь, по которому будут установле- ны файлы комплекта поставки (то есть папка каталога шаблонов, в которую будут помещены файлы комплекта поставки у пользователя). Если в поставке будет содер- жаться несколько прикладных решений, то для осталь- ных этот путь можно будет также отредактировать вруч- ную. Следующий шаг создания описания поставки предлагает использовать файлы текущей конфигурации в создавае- мом комплекте поставки (рис. 17.72). Рис. 17.72. Подбор файлов шаблона Опять же, это не обязательно, но удобно, если комплект поставки формируется только для текущего прикладного решения. В этом случае автоматически в комплект по- ставки можно включить следующие файлы. Файл текущей конфигурации (*.cf) можно включить как в виде просто файла конфигурации (для использования «как есть»), так и в виде файла поставки (для создания конфигурации, стоящей на поддержке или для обновле- ния версий). Файл выгрузки информационной базы (*.dt) тоже можно включить «как есть» или в виде выгрузки информацион- ной базы, конфигурация которой стоит на полной под- держке текущей конфигурации. Кроме этого, в поле Каталог дополнительных файлов можно указать каталог, файлы которого будут включены в ком- плект поставки (например, каталог с файлами сопроводи- тельной документации). После нажатия кнопки Готово открывается окно редакти- рования описания комплекта поставки (рис. 17.73). Описание комплекта поставки состоит из четырех со- ставляющих: шаблоны конфигураций, варианты постав- ки, базовые каталоги и языки. Рис. 17.73. Редактирование комплекта поставки Общие свойства описания комплекта поставки Сам по себе комплект поставки обладает тремя свойства- ми, которые отображаются в палитре свойств: Наименова- ние, Поставщик и Описание (рис. 17.74). D ADistributelPacklKoMnnerr поставки? edf _ П х Действия» “d Щ * Создать комплект Создать файлы комплекта В--Л Шаблоны конфигурации Ё-Л Издательство (Фирма "Сервис", версия 1 4.2 НЙЗ Файл выгрузим информас^онной базы '--ULI Файл конфигурации Варианты поставки Полный - Базовые каталоги В-’ЙЬ Языки «С _ -~в По умолчанию Рис. 17.74. Свойства комплекта поставки Свойства Наименование и Поставщик используются про- граммой установки для отображения наименования при- кладного решения и наименования поставщика в процессе установки прикладного решения. Программа установки, исходя из настроек операционной системы, выбирает один из возможных языков интерфейса платформы для отображения наименования и поставщика. Поэтому для каждого из этих свойств может быть задано значение на соответствующем языке (рис. 17.75). Рис. 17.75. Ввод наименования и описания на разных языках В результате если установка дистрибутива, сформиро- ванного из этого комплекта поставки, будет выполняться в операционной системе с украинскими региональными настройками, то программа установки будет иметь сле- дующий вид (рис. 17.76).
Рис. 17.76. Окно программы установки Свойство Описание предназначено исключительно для раз- работчика и может содержать некоторую служебную ин- формацию, относящуюся к данному описанию комплекта поставки. Шаблоны конфигураций Комплект поставки может содержать один или несколько шаблонов конфигураций. Каждый шаблон описывается отдельной веткой в дереве описания комплекта поставки. Если поставляется одна версия прикладного решения, то, как правило, описание комплекта поставки содержит один шаблон. Несколько шаблонов могут использовать- ся, например, когда поставляется несколько различных прикладных решений или несколько версий одного и того же прикладного решения. Каждое описание шаблона содержит перечень файлов, входящих в этот шаблон. Разработчик имеет возмож- ность добавлять и удалять шаблоны, добавлять и удалять файлы шаблонов. При добавлении файлов в шаблон система, помимо соб- ственно указания добавляемого файла или добавляемого каталога файлов, предоставляет возможность добавить также файл текущей конфигурации и файл выгрузки те- кущей информационной базы (рис. 17.77). Рис. 17.77. Добавление файлов в шаблон Свойства шаблона Для каждого шаблона, содержащегося в описании ком- плекта поставки, могут быть заданы следующие свойства (рис. 17.78). Рис. 17.78. Свойства шаблона Свойства Поставщик, Имя и Версия задают те значения, ко- торые будут указаны в параметрах Vendor, Name и Version создаваемого манифеста. Флаг Текущая конфигурация позволяет взять значения этих свойств из текущей конфигурации или задать вручную. Свойство Размещение манифеста определяет папку катало- га шаблонов, в которую будет установлен манифест и все файлы, содержащиеся в данном шаблоне. Свойства файлов комплекта поставки В общем случае, для файла содержащегося в шаблоне описания комплекта поставки, могут быть заданы сле- дующие свойства (в зависимости от вида файла, некото- рые свойства могут быть недоступны) (рис. 17.79). Рис. 14.79. Свойства файлов комплекта поставки В свойстве Наименование задается представление этого файла, отображаемое в описании комплекта поставки. Оно помогает разработчику понять назначение каждого файла, входящего в шаблон. В свойстве Данные задается вид файла: Файл, Текущая кон- фигурация или Текущая информационная база. Значение Текущая информационная база указывает, что в шаблон должен быть включен файл выгрузки текущей информа- ционной базы (*.dt). Значение Текущая конфигурация ука- зывает, что в шаблон должен быть включен файл конфи- гурации текущей информационной базы (*.cf). Значение Файл указывает, что в шаблон должен быть включен ука- занный файл. Свойство Базовый каталог определяет каталог, относи- тельно которого указываются пути к файлам, входящим в комплект поставки. Подробнее о базовых каталогах напи- сано в разделе «Базовые каталоги», с. 679.
Флаг Поставить на поддержку доступен только для видов файлов Текущая конфигурация и Текущая информационная база и означает, что должны быть сформированы соответ- ственно файл поставки и файл выгрузки информацион- ной базы с конфигурацией, стоящей на поддержке теку- щей конфигурации. Группа свойств Шаблон также доступна только для фай- лов вида Текущая конфигурация и Текущая информационная база. Флаг Включать в манифест определяет, что для данного файла должна быть создана соответствующая секция в манифесте. В противном случае информация об этом файле не будет отображаться в списке шаблонов ЮПред- приятия. Свойство Наименование в шаблоне содержит значение, ко- торое будет присвоено параметру Catalog манифеста. При- чем если описание шаблона содержит несколько языков, это свойство будет представлять собой строку на разных языках, которая позволяет задать значение для каждого языка отдельно. В таком случае эти значения будут уста- новлены соответствующим параметрам Са1а1од_<суффикс языка> манифеста. Флаг Наименование для обновлений указывает, по сути, ка- кая из секций данного шаблона будет идти первой. Этот флаг может быть установлен только у какого-либо одного файла вида Текущая конфигурация или Текущая информаци- онная база, входящего в данный шаблон. В случае если ма- нифест используется системой при автоматическом поис- ке обновлений (*.cfu), именно из параметра Catalog этой секции (свойство Наименование в шаблоне в описании комплекта поставки) будет браться наименование обнов- ления. Базовые каталоги Базовые каталоги предназначены для удобства указания путей к файлам в описании комплекта поставки. Например, разработчик может иметь для каждого при- кладного решения одинаковую структуру каталогов, в ко- торой хранятся файлы, используемые в поставке. Тогда, задавая в описании комплекта поставки базовые катало- ги, он может легко создать из описания поставки одного прикладного решения описание поставки другого, просто указав в нем другой базовый каталог в путях к файлам. Или другой пример: путь к каталогам, в которых находят- ся исходные файлы, может быть очень длинным и «не чи- табельным». В этом случае его также можно задать как базовый каталог описания комплекта поставки, а пути к используемым файлам указывать относительно базового каталога. Варианты поставки Описание каждого комплекта поставки может содержать несколько вариантов поставки. По умолчанию всегда су- ществует вариант поставки Полный, включающий в себя все файлы, перечисленные в описании комплекта постав- ки. Наряду с этим разработчик может определить допол- нительно необходимое количество других вариантов по- ставки и для каждого из них задать состав файлов, входящих в тот или иной вариант. В общем случае, для варианта поставки могут быть зада- ны следующие свойства (в зависимости от вида варианта поставки, некоторые свойства могут быть недоступны) (рис. 17.80). Рис. 17.80. Свойства варианта поставки Наименование — это представление данного варианта по- ставки в описании комплекта поставки. Свойство Поставляемые файлы содержит список фай- лов, которые включаются в данный вариант поставки (рис. 17.81). Рис. 17.81. Список файлов, включаемых в вариант поставки В свойстве Описание версии указывается один из файлов, включаемых в комплект поставки. Этот файл будет от- крыт после завершения установки дистрибутива на ком- пьютере пользователя (рис. 17.82). Рис. 17.82. Использование описания версии
Так как программа установки выбирает один из языков интерфейсов платформы при своей работе, то и файл описания версии можно указывать свой для каждого из возможных языков интерфейса (рис. 17.83). Рис. 17.83. Использование файлов описания для разных языков Группы свойств Комплект поставки и Набор файлов поставки предназначены для указания каталогов по умолчанию, в которых будет выполняться сохранение соответственно дистрибутива поставки и набора файлов поставки при их формировании из описания комплекта поставки. Языки В описании комплекта поставки может быть задано не- сколько языков, которые будут использоваться при фор- мировании представления файлов шаблона в списке шаб- лонов. По сути языки, задаваемые в описании комплекта поставки, определяют суффиксы языков, которые будут использоваться в параметрах Са1а1од_<суффикс языка> ма- нифестов. Для каждого языка задается его представление в описании поставки и его суффикс (рис. 17.84). Рис. 17.84. Свойства языка Создание комплекта поставки Комплект поставки может быть создан в виде дистрибу- тива (Создать поставку) и в виде отдельных файлов (Соз- дать файлы поставки). Результатом создания дистрибутива будут являться два файла: setup.exe, содержащий программу установки, и lcv8.efd, содержащий архив файлов поставки. Результатом создания файлов поставки будет структура каталогов, указанная в свойствах шаблонов описания комплекта поставки Размещение манифеста. В каждой вет- ке будут содержаться файлы соответствующего шаблона и сформированный файл манифеста. Типичные сценарии создания комплектов поставки Прежде чем приступить к рассмотрению нескольких ти- повых сценариев создания комплектов поставки следует заметить, что, несмотря на то, что механизм создания комплектов поставки позволяет прямо из рабочей инфор- мационной базы формировать файлы поставки (*.cf), настоятельно рекомендуется создавать и хранить отдель- но готовые файлы поставки для каждой версии приклад- ного решения. В дальнейшем это упростит создание об- новлений и комплектов поставки, так как не всегда «под рукой» может быть рабочая информационная база нуж- ной версии, а выбрать нужный файл поставки из сохра- ненных гораздо проще. К тому же, если возникнет необхо- димость сформировать комплект поставки, содержащий разные прикладные решения или несколько версий одно- го прикладного решения, то без соответствующих файлов поставки просто не обойтись. Поэтому в дальнейшем будем исходить из предположе- ния, что у разработчика на диске D: существует некоторая структура каталогов (рис. 17.85). S £3 Distribute £3 1.4.2.1 £3 1.4.2.2 В Раск В AddFiles £2) Distr В DistrFil Рис. 17.85. Структура рабочих каталогов В этой структуре каталог D:\Distribute используется как каталог файлов поставки в механизме поставки и под- держки. Таким образом он содержит структуру каталогов версий прикладного решения с соответствующими им файлами поставки и обновления. Эти файлы формиру- ются по мере выпуска очередных версий прикладного ре- шения с помощью механизма поставки и поддержки (Конфигурация ► Поставка конфигурации ► Создать файлы по- ставки и обновления конфигурации.... Кроме этого, для удобства формирования комплектов по- ставки в этом же каталоге содержится папка Раск, в кото- рой в папке AddFiles находятся сопроводительные файлы (описания поставки на нужных языках, описания измене- ний и пр.). Также в каталоге Раск находятся папки Distr и DistrFil для соответственно готовых дистрибутивов и файлов ком- плекта поставки. Создание комплекта поставки версии прикладного решения Сформулируем задачу: необходимо создать описание комплекта поставки, с помощью которого сформировать два дистрибутива нашего прикладного решения — рус- скоязычный и англоязычный. Часть необходимых файлов подготовлена заранее: файлы описания версии прикладного решения (на русском и на английском языках), файл поставки англоязычной вер- сии (*.cf) и файл выгрузки демонстрационной англо- язычной базы (*.dt). Мы находимся в конфигураторе демонстрационной рус- скоязычной информационной базы, содержащей постав- ляемую версию конфигурации. Создаем новый комплект поставки в процессе создания указываем каталог размещения файлов в каталоге шабло- на пользователя (Service/Publishing) (рис. 17.86).
Создание описания комплекта поставки Укажите параметры шаблона 0 Определять параметры по текущей конфигурации скольку этот файл будет присутствовать только в рус- скоязычной поставке, наименование на английском язы- ке можно не задавать (рис. 17.90). Поставщик: Имя Версия- Путь. Фирма "Сервис" Из дате-. 1 4.2.2 | Service/Publishing X DADistributeXPack’iKoMnneKT поставки! edf Действия * Й Создать комплект Создать файлы комплекта Параметры шаблона записываются в манифест шаблона, входящего в комплект поставки. | < Назад j| Далее > |f~ Готово )| Отмена 11 Справка [ Рис. 17.86. Указание каталога размещения файлов Задаем наименование комплекта поставки и наименова- ние поставщика на английском языке (рис. 17.87). Комплект поставки Е Л. Шаблоны конфигураций Й- Л, Издательство (Фирма "Сервис", версия 1 4 2.2) Ш Файл выгрузки инфорыаэомэй базы L1.I Файл конфигурации Mt Варианты поставки Полный г1 Базовые каталоги гД в,с — «Ь Языки п»с „ • По умолчанию ..• Английским Рис. 17.87. Указание наименований на разных языках Рис. 17.89. Добавление файла описания поставки Рис. 17.90. Наименование в шаблоне _ П X Добавляем английский язык с суффиксом еп (рис. 17.88). Рис 17.88. Добавление английского языка На этом языке будет отображаться наименование конфигу- рации в списке шаблонов при использовании англоязыч- ного интерфейса платформы ЮПредприятия. В осталь- ных случаях по умолчанию название будет отображаться на русском языке. В русскоязычный дистрибутив добавляем файл описания поставки на русском языке (рис. 17.89). Задаем наименование в шаблоне конфигураций для фай- ла выгрузки русскоязычной демонстрационной базы. По- Также задаем желаемый каталог, в котором будет создана новая информационная база на компьютере пользователя из этого шаблона — Service/PublishingDemo (рис. 17.91). Рис. 17.91. Размещение информационной базы Аналогичным образом задаем наименование в шабло- не и размещение для русскоязычного файла поставки (рис. 17.92). Добавляем новый шаблон в описание комплекта постав- ки для перечисления англоязычных файлов (рис. 17.93).
Свойства Файл конфигурации Ф X Основные: Наименование [файл конфигурации » Источник: Данные [текущая конфигурация [" Базовый каталог <Не использоватъ> Файл/каталог Поставить на подарржку Е 0_______________________________ [сервис Издательство/Издатвльстео Включать в манифест Наименование в шаблоне ♦ Шаблон Наименование для обновлений 0 Рис. 17.92. Свойства файла поставки D \Distnbute\Pack\KoMnneKT поставки! edf * Действия» Создать комплект Создать файлы комплекта □ Л. Шаблоны конфигураций Й- Л. Издательство (Фирма “Сервис", версия 1 4.2.2) j ' I* ReadMetxt г Й.1 Файл выгрузки инЗ><м«и»*«»> базы • L&I Файл конфигурации Варианты поставки Полный Базовые каталоги Е) -ф Языки м« „ • По умолчанию - нс —© Английский Рис. 17.93. Шаблон для файлов англоязычной поставки В англоязычный шаблон добавляем файл описания по- ставки на английском языке (рис. 17.94). X D:\Distribute\Pack\KoMnneKT поставки! edf П X Действия Создать комплект Создать файлы комплекта Е© Комплект поставки □ Л. Шаблоны конфигураций В Л Издательство (Фирма "Сервис", версия 1 4.2.2) ReadMetxt Файл выгрузки информационной базы 5--£Й Файл конфигурации Е Л> Издательство (англ) (Фирма "Сервис", версия 1 4.2.2) El Bap^"*'-’'"-' L -Ifit Полный |- “ j, Базовые каталоги д, *»* ~ □ ©Л Языки I- « I По умолчанию Английский Рис. 17.94. Файл описания поставки на английском языке В англоязычный шаблон добавляем файл выгрузки анг- лоязычной демонстрационной базы, задаем его название в файле описания комплекта поставки и указываем, что этот файл должен быть включен в шаблон (рис. 17.95). X DADistributeXPackXKoMnneKT поставки! edf * _ О X Действия » Создать комплект Создать файлы комплекта Е ' Комплект поставки Ё-Л* Шаблоны конфигурации |=|-Ла Издательство (Фирма "Сервис", версия 1 4.22) |~ReadMe.txt I-W Файл выгрузки инфсры«4«мой базы 5-Ж1 Файл конфигурации Ё-Ль Издательство (англ) (Фирма “Сервис", версия 1 4 2.2) ...... =..* ReadMe_en.txt Б Варианты поставки Полный Базовые каталоги „ *»’ — В ©fc Языки H-U* По умолчанию <2® - !- © Английским Рис. 17.95. Англоязычная демонстрационная база Задаем наименование этого файла в шаблоне на русском и на английском языке. Наименование на русском языке скорее всего, использоваться не будет, так как мы предпо- лагаем, что англоязычную версию поставки будет исполь- зовать клиент, работающий с английским интерфейсом платформы. Однако лучше его задать как наименование по умолчанию, потому что в противном случае, если кли- ент запустит ЮПредприятие с любым другим интерфей- сом, в списке шаблонов наименование нашего прикладно- го решения будет отображено пустой строкой (рис. 17.96). Рис. 17.96. Наименование файла в шаблоне Задаем желаемый каталог, в котором будет создана новая информационная база на компьютере пользователя из этого шаблона — Service/PublishingDemo (рис. 17.97). Аналогичным образом добавляем англоязычный файл поставки и задаем для него наименование в шаблоне и размещение (рис. 17.98). Создаем вариант поставки Русскоязычный (рис. 17.99). Определяем состав файлов, входящих в этот вариант по- ставки (рис. 17.100). Задаем файл описания варианта поставки. При любых уста- новках операционной системы пользователя будет исполь- зоваться русскоязычное описание поставки (рис. 17.101).
Рис. 17.97. Размещение информационной базы Рис. 17.101. Файл описания русскоязычного варианта поставки Создаем вариант поставки Англоязычный и определяем со- став поставляемых файлов (рис. 17.102). Рис. 17.98. Свойства англоязычного файла поставки Рис. 17.102. Состав файлов англоязычного варианта поставки Задаем файл описания варианта поставки. При русско- язычных установках операционной системы пользовате- ля будет использоваться русскоязычное описание, в ос- тальных случаях — англоязычное описание (рис. 17.103). Рис. 17.99. Вариант поставки Русскоязычный Рис. 17.103. Файлы описания англоязычного варианта поставки Рис 17.100. Состав файлов русскоязычного варианта поставки Сохраняем файл описания комплекта поставки (Файл ► Сохранить). Формируем русскоязычный дистрибутив (Создать комплект ► Русскоязычный). Формируем англоя- зычный дистрибутив (Создать комплект ► Англоязычный). Создание комплекта поставки обновления для удаленного каталога шаблонов Сформулируем задачу: необходимо создать набор файлов поставки, который позволит выполнить только обновле- ние прикладного решения с использованием удаленного каталога шаблонов. Заранее подготовлен файл описания обновления (lcv8upd.txt). Мы находимся в конфигураторе рабочей информационной базы, содержащей поставляемую версию конфигурации. Создадим файл обновления (*.cfu) с нужной версии на- шего прикладного решения. Для этого выполним команду
Конфигурация ► Поставка конфигурации ► Создать файлы по- ставки и обновления конфигурации.... Откажемся от созда- ния файла поставки, а для файла обновления выберем файл поставки предыдущей версии. Таким образом, соз- даваемое нами обновление позволит пользователю пе- рейти с версии 1.4.2.1 на версию 1.4.2.2 (рис. 17.104). Рис. 17.104. Создание файла обновления Рис. 17.107. Файлы в описании шаблона Для файла конфигурации зададим наименование в шаб- лоне и размещение (рис. 17.108). Создадим новое описание комплекта поставки. Зададим путь в каталоге шаблонов — Service/Publishing (рис. 17.105). Создание описания комплекта поставки Укажите параметры шаблона 0 Определять параметры по текущей конфигурации Поставщик: Имя Версия. Путь: Фирма "Сервис" Издательство 1.4.2.2 Рис. 17.108. Свойства файла конфигурации |service/Publishing| Параметры шаблона записываются в манифест шаблона, входящего в Комплект постам Создадим вариант поставки Обновление и зададим состав поставляемых файлов (рис. 17.109). | < Назад ~~|| Далее > || Готово |[~ Отмена ][ Справка j Рис. 17.105. Описание комплекта поставки На следующем шаге откажемся от включения в комплект поставки файла информационной базы. По большому счету и файл конфигурации нам также не будет нужен, однако мы оставим его для того, чтобы была сформирова- на одна секция в манифесте. В дальнейшем мы исключим этот файл из числа поставляемых файлов (рис. 17.106). Создание описания комплекта поставки X Выберите файлы шаблоне [^Текущая конфигурация Файл с текущей конфигурацией может использоваться для создания новой инфсрмжцо^а* базы, не содержащей данных О((е*3й4кая мм «• i '••••" ?. база; Файл с текущей ин базой может использоваться для создания новой информационной базы как копии текущей. □ Каталог дополнительных файлов. Дополнительно в шаблон могут быть включены файлы, находящиеся в указанном каталоге и подеаталог ах этого каталога Готово || Отмена | [ Справка | Рис. 17.106. Состав файлов шаблона Добавим в описание шаблона сформированный ранее файл обновления и файл lcv8upd.txt (рис. 17.107). Рис. 17.109. Состав файлов варианта поставки Обновление Создадим комплект файлов обновления (Создать файлы комплекта ► Обновление). В результате создастся структу- ра каталогов Service — Publishing, в которой будут содер- жаться файлы обновления (рис. 17.110). Name л. Й ICvB.cfu в} IcvB.mft © lcv8upd.txt Рис. 17.110. Состав файлов обновления При этом файл манифеста будет иметь следующее содер- жание (рис. 17.111). Создадим файл списка шаблонов. Для этого откроем окно редактирования каталога шаблонов конфигураций (Конфигурация ► Поддержка ► Шаблоны конфигураций и обнов-
лений...). Выберем корень созданной структуры каталогов (Service). В окне будут отображены обновления, содержа- щиеся в созданном нами каталоге (рис. 17.112). Г 1cv8.mft - Notepad ' |- ||П|[Х| Fife Edit Format View Help Vendor-фирма “Сервис*' Name-Издательство Version=1.4.2.2 [Configl | Са1а1од-Сервис:Издательство/Издательство Destination=Service/Publishing Source=1Cv8.cf Рис. 17.111. Содержание файла манифеста Рис. 17.112. Создание файла списка шаблонов Выполним команду Действия ► Создать файл списка шабло- нов. В результате в корне нашего каталога шаблонов бу- дет создан файл v8cscdsc.lst (рис. 17.113). Name £3) Publishing Г=1 vBcscdsc.lst Рис. 17.113. Файл списка шаблонов Теперь эту структуру каталогов можно выложить на ftp- или http-pecypc, являющийся удаленным каталогом шаб- лонов для данной конфигурации. В результате при об- новлении прикладного решения пользователю будет ото- бражена следующая информация (рис. 17.114). Рис 17.114. Окно обновления конфигурации При нажатии кнопки Информация об обновлении будет от- крыт файл lcv8upd.txt. Создание файлов поставки и обновления из командной строки Система 1С:Предприятие может быть запущена в режиме Конфигуратор из командной строки. Такой режим запуска позволяет выполнять различные действия, в том числе и создание файлов поставки и обновления. Для этого в строке запуска используется параметр Create- DistributionFiles и ключи cffile и cfufile. Для создания файла поставки следует использовать пара- метр CreateDistributionFiles с ключом cffile, после которо- го указывается имя создаваемого файла *.cf (листинг 17.1). Листинг 17.1. Пример создания файла поставки /CreateDistributionFiles -cffile D:\Publishing.cf Для создания файла обновления следует использовать параметр CreateDistributionFiles с ключом cfufile, после которого указывается имя создаваемого файла *.cfu. Кро- ме этого необходимо задать также и файлы поставки пре- дыдущих версий, для которых будет формироваться об- новления. Это можно сделать двумя способами. Во-первых, с помощью явного указания пути к файлу по- ставки предыдущей версии в этом случае для указания имени файла используется ключ f (листинг 17.2). Листинг 17.2. Пример создания файла обновления (текст команды должен быть записан в одну строку) /CreateDi stri buti onFi1es -cfufile D:\Publishing.cfu -f D:\Distribute\l.4.2.l\lCv8.cf Во-вторых, задать нужные файлы поставки предыдущих версий можно указанием их версии. В этом случае систе- ма будет использовать каталог файлов поставки, назна- ченный в данной конфигурации, и брать файл поставки из папки с указанным номером версии. Для указания но- мера версии используется ключ v (листинг 17.3). Листинг 17.3. Пример создания файла обновления /CreateDi stri buti onFi1es -cfufi1e D:\Publishing.cfu -v 1.4.2.1 Если файл обновления формируется для нескольких пре- дыдущих версий, то в командной строке должно быть указано соответствующее количество ключей f или v. В следующем примере для информационной базы в фай- ловом режиме создается файл поставки и файл обновле- ния с предыдущей версии. Результаты выполнения со- храняются в файле Report.txt (текст примера должен быть записан в одну строку) (листинг 17.4). Листинг 17.4. Пример создания файлов поставки и обновления "C:\Prograni Files\lcv8\bin\lcv8.exe” CONFIG /F “C:\Documents and Settings\User\ Му Documents\InfoBase24" /N Administrator /Р Password /CreateDistributionFiles -cffile D:\Publishing.cf -cfufile D:\Publishing.cfu -f D:\Distribute\1.4.2.1\lCv8.cf /Out D:\Report.txt
Глава 18. Методология разработки «Жизненный цикл» прикладного решения Технологическая платформа 1С:Предприятия 8.0 позво- ляет разрабатывать прикладные решения самого разного масштаба. Это могут быть как несложные решения для одного или нескольких пользователей, так и сложные многопользовательские тиражные решения, обладающие широкой функциональностью и обрабатывающие боль- шие объемы данных. Важным моментом является то, что состав задач, решаемых разработчиком в одном и другом случае, существенно отличается. При реализации слож- ных многофункциональных проектов на первый план выходит целый ряд задач, которые для простых конфи- гураций не являются критичными и решаются обычно, минимальными производственными затратами. Чтобы лучше понять особенности индустриальной разра- ботки, рассмотрим полный «жизненный цикл» приклад- ного решения (рис. 18.1). Рис. 18.1. «Жизненный цикл» прикладного решения Проектирование Можно сказать, что собственно создание будущего при- кладного решения начинается с его проектирования. Предполагается, что к этому моменту задача, стоящая перед будущим прикладным решением, уже полностью сформулирована: проведено обследование заказчика, фор- мализованы требования, выработано техническое зада- ние и получена полная информация, которая необходима для того, чтобы начать непосредственное создание кон- фигурации. Уже на этом этапе начинаются серьезные отличия. При создании простых прикладных решений, собственно про- цесс проектирования может зачастую вообще отсутство- вать. Это связано с тем, что структура объектов метадан- ных позволяет разработчику мыслить не таблицами и полями, а объектами, описывающими сущности конкрет- ной прикладной области. Поэтому зачастую термины предметной области однозначно и полностью могут быть перенесены в структуру метаданных. Например, если за- казчик использует каталог товаров и два документа, кото- рые регистрируют поступление и расход товаров, то ровно таким же образом эта структура может быть перенесена и в прикладное решение: один справочник и два документа. Если требуемая функциональность решения невелика, то разработчик вполне может держать структуру метадан- ных «в голове» и запись ее «на бумаге» может потребо- ваться лишь для отражения в документации. Совершенно другая картина возникает, когда начинается разработка крупного проекта. Здесь уже требуются уси- лия нескольких человек, как для постановки задачи, так и для проектирования. Причем в процессе проектирова- ния приходится решать ряд дополнительных задач. Прежде всего, это решение вопроса о том, каким образом будет реализовываться та или иная функциональность будущей системы. В крупных решениях, как правило, всегда присутствует большое количество функциональ- ности, которая не может быть реализована только каким- либо одним объектом конфигурации. Возникает необхо- димость задействовать несколько различных объектов, причем далеко не всегда можно однозначно, без внима- тельного рассмотрения, сказать, какие именно объекты конфигурации лучше использовать в данном случае. Одна и та же задача, в принципе, может быть решена с ис- пользованием различных объектов конфигурации, поэто- му вопрос правильного выбора используемых объектов и построения эффективной структуры метаданных при- обретает первостепенное значение. Если бы важность правильного выбора объектов мета- данных была бы обусловлена только этой причиной — одно это явилось бы достаточно серьезным поводом, чтобы уделить процессу проектирования значительное внимание. Однако есть еще целый ряд факторов, кото- рые еще больше поднимают значимость этапа проекти- рования.
Если в простой конфигурации при проектировании мета- данных будет допущена ошибка, то это, конечно, непри- ятный факт, но не катастрофический. При определенных условиях даже полная переделка всего прикладного ре- шения может быть выполнена в разумные сроки и разум- ными средствами. Однако если ошибка в проектировании метаданных будет допущена в крупном проекте, это мо- жет стать полной катастрофой, поскольку потребует ог- ромных ресурсов для ее исправления и «встраивания» новых объектов и новых алгоритмов в уже существующее прикладное решение. Другим важным аспектом правильного проектирования структуры метаданных является производительность системы. Производительность простых прикладных ре- шений, как правило, «непроизвольно» тестируется самим разработчиком в процессе проверки правильности реали- зуемых алгоритмов. Таким образом, он сразу видит, на- пример, что тот или иной отчет работает медленно и мо- жет, как уже говорилось, даже изменить структуру метаданных без особых затрат времени и сил. В отличие от этой ситуации, большие проекты, как правило, рассчи- таны на интенсивную многопользовательскую работу, поэтому, помимо собственно быстродействия, они долж- ны обеспечивать также высокую параллельность работы пользователей. А значит, при проектировании метадан- ных следует внимательно анализировать создаваемую структуру на предмет возникновения «узких мест» при одновременной работе большого количества пользовате- лей. Как говорится, «гладко было на бумаге, да забыли про овраги». Это тем более важно, поскольку быстродей- ствие системы, которое видит разработчик в процессе от- ладки создаваемых алгоритмов, совершенно не имеет ни- чего общего с реальным быстродействием системы при полной нагрузке. Простой пример: разработчик создал документ и убедился, что он проводится быстро и пра- вильно. Но когда несколько пользователей стали одно- временно интенсивно создавать эти документы, выясни- лось, что их одновременная работа просто невозможна, поскольку структура объектов метаданных, задейство- ванных в алгоритме проведения, такова, что, проводя эти документы, пользователи блокируют одни и те же записи в таблицах базы данных. Разработка После того как проектирование будущего прикладного решения завершено, начинается этап разработки, на кото- ром создаются объекты метаданных и описываются алго- ритмы функционирования. На этом этапе главной осо- бенностью разработки больших проектов является то, что решение создается не одним разработчиком, а группой параллельно работающих сотрудников. А это выдвигает на первый план необходимость согласованного внесения изменений в создаваемое прикладное решение, обеспече- ния конкурентного доступа к произвольным частям кон- фигурации, необходимость хранения и отслеживания различных версий создаваемой конфигурации, возмож- ность «отката» к произвольной версии и целый ряд дру- гих задач. Платформа ЮПредприятия 8.0 содержит специальный механизм, обеспечивающий групповую разработку при- кладного решения, о котором более подробно рассказано в разделе «Групповая разработка прикладных решений», с. 690. И если один разработчик может использовать этот механизм «по желанию» (например, для того, чтобы иметь возможность версионирования своей разработки), то для группы разработчиков этот механизм становится просто необходимым. Функциональное тестирование Этап функционального тестирования, так или иначе, присутствует при разработке прикладного решения лю- бой сложности. В самом простом варианте функциональ- ное тестирование прикладного решения выполняется разработчиком в процессе создания отдельных алгорит- мов. Функциональное же тестирование больших проек- тов представляет собой отдельную задачу, для реализа- ции которой требуется целый ряд мероприятий: создание тестовых баз, разработка тестов, анализ получаемых ре- зультатов и т. д. Такое тестирование выполняется уже группой сотрудников, и каждый, как правило, тестирует лишь отдельную часть или подсистему прикладного ре- шения. Нагрузочное тестирование Этап нагрузочного тестирования, как правило, отсутству- ет при создании простых прикладных решений. Это свя- зано с тем, что технологические возможности платформы в подавляющем большинстве случаев обеспечивают нуж- ную производительность и параллельность работы при небольшом количестве пользователей даже тогда, когда решение спроектировано неоптимальным образом. Ис- ключение составляют лишь случаи, когда разработчиком допускаются грубые ошибки проектирования. Если же создается тиражируемое решение, предполагаю- щее одновременную работу большого количество пользо- вателей, то нагрузочное тестирование по своей важности становится в один ряд с задачей правильной реализации функциональности. В самом деле, какую ценность для пользователя будет иметь замечательная, функциональ- ная, удобная программа, если он просто не сможет в ней работать из-за постоянных блокировок или очень боль- шого времени реакции системы на его действия? Поэтому нагрузочное тестирование призвано, прежде все- го, дать оценку производительности системы при одновре- менной работе большого количества пользователей и вы- явить «узкие места» системы, снижающие параллельность работы. Более подробно о нагрузочном тестировании рас- сказано в разделе «Оптимизация производительности на уровнях автоматизируемых процессов предприятия и ав- томатизированных рабочих мест», с. 711. Внедрение Процесс внедрения простого прикладного решения сво- дится, как правило, к созданию информационной базы и краткому инструктажу пользователя. При наличии под- робной справки и документации пользователь может ос- воить работу в прикладном решении и самостоятельно,
без посторонней помощи. Можно сказать, что в большин- стве случаев внедрение является завершающим момен- том в разработке, не требующим каких-то особенных за- трат сил и средств. Это, своего рода, «точка», которую ставит разработчик. Все, работа выполнена, пользователь доволен. Для крупных проектов все обстоит с точностью до на- оборот. Наибольшее количество сложностей и проблем возникает именно на этапе внедрения проекта у заказ- чика. Причем эти трудности, в подавляющем большин- стве, не относятся к конкретному внедряемому реше- нию, а имеют общий характер, одинаковый для разных решений и для разных заказчиков. Необходимость по- этапного внедрения, обучение большого количества но- вых пользователей в короткое время, согласованный перенос данных и параллельная работа с существую- щей системой автоматизации, преодоление сознатель- ного и подсознательного противодействия внедрению новой системы, получение адекватной оценки резуль- татов внедрения — вот лишь неполный список задач, которые приходится решать при любом крупном вне- дрении. Очевидно, что для успешного выполнения за- дачи требуется уже не просто настойчивость и умение, а владение отлаженной технологией внедрения, в кото- рой задействовано большое количество специалистов различного профиля. Сопровождение Процесс сопровождения прикладного решения также значительно отличается в одном и другом случае, вплоть до того, что простое прикладное решение может вообще не требовать какого-либо сопровождения. Оно просто и понятно в использовании, обладает необходимой функ- циональностью и полностью устраивает пользователя. Если же мы говорим о крупном решении и тем более о ре- шении тиражном, подразумевающим продажу большого количества копий, то здесь вопрос качественного сопро- вождения выпущенного прикладного решения становит- ся одним из важных факторов, который будет обеспечи- вать дальнейший рост продаж. Пользователь должен иметь возможность самостоятельно установить приклад- ное решение. Для этого платформа 1С:Предприятия 8.0 содержит инструмент создания дистрибутивов. Затем нужно обеспечить обновление существующих у пользо- вателя версий прикладного решения на новые, которые будут выпускаться по мере необходимости. Для этих це- лей платформа также содержит механизм поддержки прикладных решений, который позволяет пользователю обновлять версию своего прикладного решения как в руч- ном, так и автоматическом режиме. Выводы Прежде чем перейти к более подробному рассмотрению возможностей системы, обеспечивающих индустриаль- ную разработку прикладных решений, хочется еще раз акцентировать внимание на том, что разработка крупных решений требует не только умения пользоваться соответ- ствующими механизмами и инструментами платформы, но и гораздо более взвешенного, внимательного и тща- тельного подхода к вопросу разработки вообще. Это объясняется тем, что платформа обладает довольно широкими возможностями, которые, однако, надо ис- пользовать «с умом». Например, система позволяет раз- работать очень сложный, но эффективный запрос и в то же время допускает создание простого, но очень не эф- фективного запроса. Предоставив разработчику большую свободу для творчества, система уже не может однознач- но определить, является ли данное решение, принятое разработчиком, ошибочным, или наоборот, это сознатель- ное использование некоторой конкретной возможности системы. Поэтому вопросам проектирования структуры метаданных, параллельности работы, эффективности за- просов, способов реализации функциональности следует уделять больше внимания, по сравнению с предыдущими версиями платформы, а при разработке крупных реше- ний — особенно. Проектирование структуры метаданных Как уже говорилось выше, этап проектирования структу- ры метаданных имеет одно из первостепенных значений при разработке крупных прикладных решений. Однако и для более простых решений создание правильной струк- туры объектов является важным и ответственным этапом разработки. От правильно принятого решения зависит не только удобство разработки и производительность созда- ваемого прикладного решения, но и возможность его раз- вития и адаптации к возможным изменениям состава ре- шаемых задач. В большинстве случаев выбор подходящего объекта кон- фигурации не представляет большой сложности, так как для каждого вида объекта конфигурации определено ос- новное назначение и имеется достаточно примеров, как в методических материалах, так и в типовых конфигураци- ях. Однако, разумеется, состав видов объектов конфигу- рации, предоставляемый платформой, как любая класси- фикация не может однозначно определять выбор подхо- дящего объекта во всех случаях. Поэтому в спорных си- туациях, когда выбор вида объекта конфигурации не очевиден, нужно внимательно проанализировать все осо- бенности устройства и поведения объектов соответст- вующего вида. Выбор между объектными и необъектными данными Например, одним из типичных вопросов, возникающих в сложных случаях, является выбор между объектными и необъектными данными. Чаще всего это выбор между справочником и регистром сведений. Здесь рекомендует-
ся, прежде всего, обратить внимание на природу данных предметной области. Если сами данные являются, по сути, перечнем уникальных объектов, то рекомендуется исполь- зовать объектные данные. Подробно особенности исполь- зования тех и других данных описаны в разделах «Объект- ные данные», с. 36 и «Необъектные данные», с. 44. Важным моментом проектирования структуры метадан- ных является то, что выбор вида объекта конфигурации не может производиться для каждой сущности предмет- ной области отдельно. Необходимо обязательно анали- зировать всю совокупность сущностей, отражаемых в конфигурации на текущий момент, а также учитывать возможное включение новых сущностей в дальнейшем. Поэтому о правильности принятия решения можно гово- рить только с учетом состава задач, решаемых при разра- ботке конкретной конфигурации. Например, в одном прикладном решении состав сотруд- ников организации будет правильно отражаться в справоч- нике, так как с точки зрения этой конфигурации сотруд- ник является объектом. Однако в другой конфигурации, содержащей более широкую функциональность (напри- мер, многофирменность), может быть принято решение в справочнике отражать такую сущность, как физические лица, как более общее понятие. А информация о сотруд- никах в этом случае может храниться в регистре сведе- ний. Фактически регистр сведений будет отражать факт работы конкретного физического лица в конкретной ор- ганизации, реализуя, таким образом, связь «многие ко многим». Но может быть принято решение в пользу хра- нения и в этом случае сотрудников в справочнике, факти- чески отражая в справочнике в качестве объектов не физическое лицо, а трудовой договор, в котором указыва- ется физическое лицо и организация. В этом случае спра- вочник будет не просто связывать физические лица и ор- ганизации, а описывать объекты — трудовые договоры, имеющие свойство уникальности в пространстве и времени. Таким образом, при проектировании состава объектов конфигурации, разработчику очень важно четко пред- ставлять какую сущность предметной области будет от- ражать конкретный объект. Анализ логики работы прикладных объектов с данными Важно учитывать, что объекты конфигурации того или иного вида описывают не просто таблицы базы данных с некоторым набором полей, а обеспечивают определенную логику работы с данными. Эта логика определяет и со- став возможностей, автоматически предоставляемых раз- работчику, и набор ограничений, и параметры производи- тельности тех или иных операций с данными. Типичной ошибкой, например, является использование регистра сведений в качестве простой таблицы для запи- си некоторых данных. Регистр сведений предназначен для хранения сведений, соответствующих определенным комбинациям значений измерений. Соответственно, од- ним из основных его свойств является обеспечение уни- кальности записей по составу измерений и периоду (для периодического регистра). Поэтому при каждой запи- си регистр сведений выполняет в обязательном порядке удаление существующих записей с такой комбинацией значений измерений или проверку уникальности (в зави- симости от способа записи). Если при этом выполняется добавление одиночных записей с помощью менеджера за- писи, то такая операция будет приводить к достаточно большим накладным расходам, особенно если имеется большое количество измерений. Таким образом, если от- ражаемая сущность предметной области не подходит по своей природе под регистр сведений, то следует рассмот- реть целесообразность использования регистра сведений (особенно с учетом предполагаемого объема хранимой информации). Анализ производительности Еще одним аспектом, который следует рассматривать при выборе вида объекта конфигурации, является необходи- мость учета технологических особенностей работы плат- формы с данными, поддерживаемыми этим объектом. Состав прикладных объектов конфигурации должен мак- симально соответствовать реальному составу сущностей предметной области, однако при его проектировании не- обходимо рассматривать и технологические вопросы. В не- которых случаях даже в правильно спроектированную структуру объектов необходимо внести коррективы, дик- туемые технологическими особенностями. Например, если в составе информации об объекте необ- ходимо хранить большие объемы бинарных данных (кар- тинки, файлы и т. д.), то для этой цели рекомендуется заводить отдельные объекты метаданных (справочники или регистры сведений), связанные с данным объектом, чтобы исключить обязательное считывание больших объ- емов информации при считывании объекта. Если речь идет о структурах данных, предполагающих хранение большого объема информации или интенсивное использование, то для оценки эффективности принятого решения можно рекомендовать провести эксперименты, в которых на объемах данных, сопоставимых с реальными, сравнить производительность одних и тех же операций с разными вариантами структуры. Анализ возможностей использования обмена данными В качестве еще одной рекомендации можно предложить учитывать в процессе проектирования возможное ис- пользование в данной конфигурации механизмов обме- на данными. Хотя такая потребность не всегда определе- на заранее, но можно предположить, что она может возникнуть в ходе эксплуатации системы. Поэтому по- лезно при проектировании основных объектов конфигу- рации подумать о возможных вариантах обмена с точки зрения принимаемых решений по организации структу- ры данных. Например, следует учитывать, что табличная часть объ- екта является его неотъемлемой частью при всех опера- циях добавления, записи и удаления. Соответственно, при организации распределенной системы обмен дан- ными объекта будет происходить, включая все его таб-
личные части. С другой стороны, данные регистров и подчиненных справочников участвуют в обмене само- стоятельно, что позволяет управлять их миграцией не- зависимо от объектов, с которыми они связаны. Напри- мер, может передаваться элемент справочника, но не передаваться регистр сведений, хранящий связанную с ним информацию. Анализ параллельности работы Параллельность работы пользователей — важный вопрос при создании многофункциональных прикладных реше- ний. На этапе проектирования закладывается база для эффективной и успешной работы прикладного решения в многопользовательской среде. Поэтому следует внимательно относиться к алгоритмам взаимодействия различных объектов конфигурации, ко- торые планируется реализовывать. Надо помнить о том, что такой алгоритм может выполняться одновременно несколькими пользователями. Это поможет избежать возникновения узких мест прикладного решения в ре- зультате неудачного взаимодействия объектов конфигу- рации между собой. Также следует уделять достаточное внимание вопросам оптимального индексирования объектов конфигурации, поскольку это позволяет в дальнейшем существенно со- кратить диапазон блокировок и вероятность возникно- вения взаимных блокировок при конкурентной работе пользователей. Групповая разработка прикладных решений Рост функциональности создаваемого прикладного реше- ния приводит к тому, что требуется одновременная рабо- та нескольких разработчиков для того, чтобы прикладное решение было создано в разумные сроки. При этом каж- дый из разработчиков, как правило, создает отдельную, функционально законченную часть прикладного реше- ния, которая взаимодействует с другими частями при- кладного решения, созданными другими разработчиками. Сложность организации подобного процесса разработки заключается в том, что, как правило, одни и те же объекты конфигурации задействованы в различных функциональ- ных частях прикладного решения. Поэтому изменения, вносимые разными разработчиками в одни и те же объек- ты, должны быть очень хорошо согласованы между собой, иначе неизбежно появление большого количества ошибок. Для того чтобы упростить и автоматизировать процесс разработки прикладного решения коллективом разработ- чиков, платформа ЮПредприятия содержит специаль- ный механизм, позволяющий вести групповую разработ- ку решений. Используемая терминология Прежде чем перейти к дальнейшему рассмотрению мето- дики работы с хранилищем конфигурации, следует опре- делиться с терминами, которые будут использоваться в ходе изложения. Режим работы с подключением к хранилищу — это основ- ной способ работы с хранилищем конфигурации, при ко- тором в информационной базе сохраняется информация о подключении к хранилищу, а в хранилище сохраняется информация о подключении информационной базы. Этот режим может быть завершен только в результате выполнения команды отключения от хранилища; закры- тие окна конфигуратора не приводит к отключению от хранилища. Таким образом, редактирование конфигура- ции может выполняться и без непосредственной связи с хранилищем конфигурации. В этом режиме доступны все операции с хранилищем конфигурации. Режим работы без подключения к хранилищу — это вспо- могательный способ работы с хранилищем конфигурации, при котором можно выполнять все действия, за исключе- нием захвата, получения и помещения объектов в храни- лище. Для завершения этого режима можно выполнить команду закрытия хранилища или просто закрыть окно конфигуратора. Работа в этом режиме возможна только при непосредственной связи с хранилищем конфигура- ции. Этот режим предназначен в основном для того, чтобы иметь возможность выполнять административные и неко- торые другие действия с хранилищем на любом компьюте- ре, на котором установлено 1С:Предприятие. Подключение к хранилищу — это процесс, в результате ко- торого информационная база, которая еще не подключе- на к хранилищу конфигурации, подключается к нему в режиме работы с подключением. Отключение от хранилища — это процесс, позволяющий завершить режим работы с подключением к хранилищу. Информационная база снова становится не подключен- ной к хранилищу конфигурации. Соединение с хранилищем — процедура соединения ин- формационной базы, ранее подключенной к хранилищу конфигурации, с хранилищем конфигурации. Эта проце- дура выполняется системой как отдельно (например, по- сле открытия в конфигураторе информационной базы, подключенной к хранилищу), так и в процессе подключе- ния к хранилищу конфигурации. Открытие хранилища — это процесс, позволяющий со- единиться с хранилищем конфигурации в режиме работы без подключения к хранилищу. Закрытие хранилища — это процесс, позволяющий завер- шить режим работы без подключения к хранилищу. Общие сведения о хранилище конфигурации Основу механизма групповой разработки составляет хра- нилище конфигурации. Хранилище создается на каком-
либо общем сетевом ресурсе и в него помещается конфи- гурация, которую предполагается разрабатывать. Каж- дый из разработчиков создает на своей рабочей станции тестовую информационную базу и подключает ее к хра- нилищу. При подключении к хранилищу конфигурация тестовой базы автоматически заменяется конфигурацией, содержащейся в хранилище, и все объекты метаданных становятся недоступными для редактирования. Таким образом, каждый из разработчиков имеет возможность тестировать и отлаживать текущую разрабатываемую конфигурацию на своей рабочей станции и на своих тестовых данных, независимо от других разработчиков (рис. 18.2). Рис. 18.2. Использование хранилища конфигурации Ключевым моментом здесь является то, что, не предпри- няв специальных действий, разработчик не имеет воз- можности редактировать объекты конфигурации. Дальнейшая работа строится следующим образом: если разработчику необходимо изменить какой-либо объект конфигурации, он захватывает его в хранилище, вно- сит изменения и затем помещает обратно в хранилище (рис. 18.3). Таким образом, обеспечивается блокировка одновре- менного изменения объекта несколькими разработчика- ми: разработчик может захватить в хранилище только те объекты, которые не захвачены другими пользователя- ми. Другими словами, захват объектов в хранилище вы- полняется эксклюзивно, и, захватив объект, разработчик может быть уверен, что этот объект не будет изменен другими разработчиками до тех пор, пока он не поместит его в хранилище и/или не отменит захват в хранилище (рис. 18.4). Помимо обеспечения захвата и блокировок объектов кон- фигурации, хранилище предоставляет целый ряд сервис- ных функций, которые упрощают ведение разработки и делают ее более автоматизированной. Прежде всего, это возможность версионирования раз- работки и ведения истории изменения версий. Храни- лище позволяет не только просматривать список вер- сий, но и выводит отчеты в различных разрезах: по версиям, по объектам разработки, по комментариям к версиям. Захват сСъактое в хранилище объектов в отладочной базе и отладоа Помещение в хранилище и т < объектов Рис. 18.3. Захват и помещение объектов в хранилище Рис. 18.4. Монопольный захват объектов в хранилище Поддерживается возможность отката назад и удаления ненужных версий, опубликованных в хранилище, а также возможность удаления самых ранних ненужных версий путем сокращения до нужной версии. Также хранилище позволяет разработчику просмотреть любую из версий, находящихся в хранилище, сравнить различные версии, загрузить выбранную версию в ло- кальную отладочную базу, с которой работает разработ- чик, или сохранить в файл на диске.
Создание хранилища конфигурации Процесс создания хранилища конфигурации подробно описан в документации и не представляет сложностей. Стоит лишь заметить, что хранилище может располагать- ся как на том же компьютере, который используется раз- работчиком (в случае, если хранилище используется только одним разработчиком) (рис. 18.5), так и на общем сете- вом ресурсе, если хранилище используется группой раз- работчиков (рис. 18.6). Рис. 18.5. Расположение хранилища на рабочей станции Рис. 18.6. Расположение хранилища на общем сетевом ресурсе лищем конфигурации. Существуют три права: админист- ративные функции, изменение состава версий и захват объектов. ♦ Право Административные функции позволяет создавать, изменять и удалять пользователей хранилища, отклю- чать пользователей, подключенных к хранилищу, и от- менять захват объектов хранилища, выполненный дру- гими пользователями. ♦ Право Изменение состава версий позволяет выполнять откат, сокращение и объединение версий конфигура- ций в хранилище. ♦ Право Захват объектов захватывать объекты в хранили- ще и вносить изменения в конфигурацию хранилища. Все эти права связаны друг с другом. Установка права Ад- министративные функции подразумевает, что пользователь может выполнять любые действия с хранилищем, поэто- му при установке этого права устанавливаются также и права Изменение состава версий и Захват объектов. Установка права Изменение состава версий требует, чтобы пользователь имел возможность захвата и изменения объектов, поэтому вместе с этим правом устанавливается и право Захват объектов. Таким образом, возможны четыре различных сочетания прав (табл. 18.1). Таблица 18.1. Сочетания прав пользователей хранилища Установленные права Действия пользователя Административные функции Изменение состава версий Захват объектов Пользователь может выполнять любые действия с хранилищем Изменение состава версий Захват объектов Пользователь может выполнять любые действия, кроме административных Захват объектов Пользователь может выполнять только захват, изменение объектов, помещение их в хранилище и отказ от захвата объектов Нет установленных прав Пользователь может только просматривать объекты хранилища Пользователи хранилища Хранилище конфигурации позволяет определить необхо- димое количество пользователей хранилища, задать имя пользователя, пароль и определить права пользователя. При создании хранилища система обязательно создает пользователя хранилища, обладающего полным набором прав, и предлагает задать имя пользователя (по умолча- нию Администратор) и пароль. Права пользователей Каждому пользователю хранилища может быть назначен индивидуальный набор прав, определяющий действия, которые данный пользователь может выполнять с храни- Подключение к хранилищу Процесс подключения информационной базы к хранили- щу заключается в том, что между информационной базой и хранилищем устанавливается связь, которая будет под- держиваться до тех пор, пока база не будет отключена от хранилища. Информация о подключении хранится как в подключаемой базе, так и в хранилище. Профиль инфор- мационной базы хранит информацию о местонахождении хранилища, и пользователе хранилища, от имени которо- го выполняется подключение. В свою очередь в хранили- ще для данного пользователя записывается информация о подключенной информационной базе и ее расположе- нии (рис. 18.7).
Рис. 18.7. Подключение к хранилищу Такой способ установки связи определяет некоторые осо- бенности работы с хранилищем. Так, например, для каждо- го пользователя хранилища в каждый момент времени мо- жет быть подключена только одна информационная база. С другой стороны, если информационная база была под- ключена к хранилищу от имени некоторого пользователя, то каждый раз при открытии ее в конфигураторе система будет предлагать соединиться с хранилищем от имени этого пользователя. Если по каким-либо причинам требу- ется выполнить соединение от имени другого пользовате- ля, то сначала нужно отключить базу от хранилища (при этом в хранилище для данного пользователя будет очи- щена информация о подключении), а затем уже выпол- нить новое подключение от имени другого пользователя хранилища. Смена пользователя, от имени которого вы- полняется подключение, «на лету» не поддерживается. При подключении информационной базы к хранилищу выполняется аутентификация пользователя в хранилище конфигурации и затем, возможно, выполняется непосред- ственно процедура подключения информационной базы к хранилищу. При этом возможны две ситуации. ♦ Ситуация первая: аутентификация пользователя хра- нилища выполнена (рис. 18.8), но для этого пользовате- ля нет информации о подключенной базе. В этом слу- чае производится подключение и устанавливается связь (рис. 18.9). ♦ Ситуация вторая: аутентификация пользователя храни- лища выполнена, но для данного пользователя хранили- ща уже имеется информация о подключенной информа- ционной базе (например, этот пользователь пытается подключиться с другой рабочей станции) (рис. 18.10). В этом случае еще на этапе аутентификации проверяется наличие соединения данного пользователя с хранили- щем. Если соединения нет, то система предоставляет воз- можность подключиться, предупреждая, однако, о том, что для данного пользователя хранилища уже имеется информация о другой подключенной информационной базе. Если в этом случае разработчик все равно решит подключиться, то система выполнит новое подключе- ние, и в хранилище изменится информация о подключен- ной информационной базе для данного пользователя (рис. 18.11). Подключение информационной базы 1 к хранилищу Информационная базе 1 Хранилище конфигурации Пользователь 1 Пользователь 1 Рис. 18.8. Подключение к хранилищу После выполнения подключения сохраняется информация о подключении Рис. 18.9. Подключение к хранилищу выполнено Хранилище конфигурации Пользователь 1 Путь к ИБ1 Подключение ин базы 2 к хранилищу Рис. 18.10. Подключение к хранилищу с другого компьютера После подключения информация в хранилище изменится для этого пользователя Рис. 18.11. Выполнено подключение со второго компьютера
Это приведет к тому, что при открытии в конфигураторе старой информационной базы система предложит соеди- ниться с хранилищем конфигурации, основываясь на той информации, которая хранится в этой базе (рис. 18.12). И Б1 будет пытаться подключиться к хранилищу, но безуспешно, тк. информация о подключении не совпадает Рис. 18.12. Попытка соединения прежней информационной базы с хранилищем При этом будет запрошен диалог аутентификации, одна- ко соединиться с хранилищем уже не удастся. Как гово- рилось выше, смена пользователя «на лету» не поддержи- вается, поэтому необходимо сначала отключить базу от хранилища, а затем произвести повторное подключение, если в этом есть необходимость (рис. 18.13). После отключения ИБ1 от хранилища, информация о подключении будет очищена и базу можно подключить заново Рис. 18.13. Состояние после отключения от хранилища Действия, выполняемые системой при подключении к хранилищу При подключении к хранилищу конфигурации система получает из хранилища конфигурацию, заменяет основ- ную конфигурацию информационной базы на ту конфи- гурацию, которая получена из хранилища, и сохраняет основную конфигурацию информационной базы. После этого выполняется процедура соединения с хранилищем конфигурации. Действия, выполняемые системой при соединении с хранилищем В процессе соединения с хранилищем аутентифицирует- ся пользователь хранилища, проверяется соответствие информации о подключении в информационной базе и в хранилище конфигурации. Затем выполняется проверка информации о захвате объектов в хранилище и в инфор- мационной базе. Если выясняется, что информация не синхронизирована (например, объект захвачен в хра- нилище, но в информационной базе нет информации о захвате этого объекта), то выполняется синхронизация этой информации на основании того, какое состояние объекта указано в хранилище конфигурации. Если в хра- нилище объект захвачен, он будет помечен как захвачен- ный и в информационной базе. Если в хранилище объект не захвачен в информационной базе будет сброшена от- метка о захвате этого объекта. Отображение состояния объектов конфигурации Для выполнения операций с хранилищем конфигурации предназначено окно хранилища конфигурации. Из этого окна можно выполнить все операции, доступные с храни- лищем конфигурации. Кроме этого, большой ряд опера- ций с хранилищем доступен и из окна конфигурации. Для того чтобы разработчик мог видеть текущее состоя- ние объектов конфигурации, и в том и в другом окне вы- водится информация о состоянии объектов в виде пикто- грамм. — закрытый замок синего цвета обозначает объект, который не захвачен ни одним пользователем хранили- ща. Разработчик не может редактировать такой объект, но может выполнить захват такого объекта, после чего ре- дактирование станет возможным. % ¥ — открытый замок синего цвета с отметкой красного цвета обозначает объект, который захвачен разработчи- ком. Такой объект разработчик может редактировать, но другие разработчики, подключенные к хранилищу, захва- тить этот объект не могут. — закрытый замок синего цвета с пиктограммой жел- того цвета обозначает объект, который захвачен другим пользователем хранилища. Разработчик не может редак- тировать этот объект, но при необходимости может полу- чить этот объект (например, если ему необходимо видеть текущую версию этого объекта, находящуюся в хранили- ще конфигурации). — отметка красного цвета обозначает объект, который добавлен разработчиком в отладочной конфигурации, но еще отсутствует (не помещен) в хранилище конфигура- ции. Также этой пиктограммой обозначается объект, ко- торый удален из хранилища, но еще присутствует в отла- дочной конфигурации разработчика.
Кроме перечисленных пиктограмм для обозначения со- стояния объектов конфигурации используются еще четы- ре похожие пиктограммы, имеющие меньший размер и дополнительное изображение дерева рядом с пиктограм- мой) (рис. 18.14). Рис. 18.14. Пиктограммы подчиненных объектов Эти пиктограммы имеют тот же самый смысл, что и пере- численные выше, но присутствуют у тех объектов конфи- гурации, которые не могут быть захвачены в хранилище самостоятельно, а только в составе родительского объек- та. Такими объектами являются, например, реквизиты, табличные части, реквизиты табличных частей, значения перечислений, измерения, ресурсы и некоторые другие объекты конфигурации. Формы и макеты могут быть за- хвачены самостоятельно. Просмотр состояния объектов Зачастую возникает необходимость просмотреть, какие объекты захвачены в хранилище и какой пользователь выполнил захват. Для этого можно использовать различ- ные способы. Прежде всего, можно использовать окно конфигурации и посмотреть на пиктограммы, которые показывают со- стояние объектов конфигурации. Если объект захвачен другим пользователем хранилища, то при наведении курсора на пиктограмму система выведет подсказку с подробной информацией о пользователе, дате и време- ни захвата объекта, компьютере, с которого выполнен захват, и пути к отладочной базе разработчика (рис. 18.15). ¥ X Конфигурация Действия- t UI [j в Й-Д* Общие Константы ФЗ Справочники Й J Документы | Нумераторы I Й Последовательности i АВСКлассификацияПокупателей : Ер <§} АвансовыйОтчет Й- ^1 АккредитивПереданный = Й g] АккредитивПолученный Й gl ВводНачальныхОстатковНДС i Й-\gj ВнутреннееПеремещениеНалич. Й g] ВнутреннийЗаказ : Й g] Возврат! оваровОтПокупателя gj ВозвратТоваровПоставщику g| ВозвратТоваровПоставщикуИз. g] ВосстановлениеНДС g| ВычетНДСПоПриобретеннымЦе. g| ВычетНДССАванса g] ГТДИмпорт g| ДенежныйЧек • g] Доверенность g] ЗаказПокупателя g| ЗаказПоставщику fi fi 0 ф- Й ф- Й й Й 0- Ф' 0 Объект захвачен другим пользователем в хранилище конфигурации Пользователь. Иванов Дата захвата: 25.03.200414 26 42 Компьютер: КОСЫ база. CADocumenls and Settings\kochk\My Documents\lnfoBase2 Рис. 18.15. Состояние захваченного объекта Такой способ может быть удобен для небольших конфи- гураций, однако если конфигурация содержит большое количество объектов, то найти нужный среди нескольких сотен объектов бывает нелегко. В этом случае можно использовать другой способ, кото- рый предоставляет окно хранилища конфигурации. Это окно по умолчанию отображает конфигурацию в виде де- рева с отключенным отбором. Для удобства следует пере- ключить представление данных в этом окне с дерева на список (команда меню Вид ► Список), а затем установить отбор Все захваченные (команда меню Действия ► Отбор) (рис. 18.16). Рис. 18.16. Просмотр захваченных объектов в окне хранилища конфигурации В результате будет отображен список всех объектов, ко- торые захвачены пользователями хранилища с указанием имени пользователя, даты и времени захвата, имени ком- пьютера, с которого произведен захват, и пути к отладоч- ной базе (на рисунке колонки Дата, Компьютер и Информа- ционная база скрыты). При необходимости можно детализировать список захва- ченных объектов и вывести объекты, захваченные только одним из пользователей. Для этого нужно установить со- ответствующие параметры отбора списка (рис. 18.17). Рис. 18.17. Отбор объектов хранилища Обновление информации о состоянии объектов конфигурации При выполнении разработчиком действий с хранилищем (например, захват, помещение объектов и др.) информа- ция о состоянии объектов конфигурации, отображаемая в открытых окнах его отладочной базы, обновляется авто- матически, после выполнения каждого действия, так как в этот момент выполняется обмен информацией с хра- нилищем. В остальное время непосредственная связь с хранилищем не требуется, и разработчик работает авто- номно. Поэтому, изменения, производимые в это время другими пользователями хранилища, автоматически не отображаются. Для того чтобы получить актуальную информацию о захвате объектов конфигурации, следу- ет использовать команду меню Действия ► Обновить ста- тусы, которая обновляет информацию о захваченных объектах.
Захват и помещение объектов в хранилище Как уже упоминалось в начале этой главы, для того что- бы изменить объект конфигурации, разработчику необ- ходимо выполнить следующую последовательность дей- ствий: ♦ захват объекта; ♦ изменение объекта; ♦ помещение объекта в хранилище. Однако в процессе разработки могут возникать различ- ные промежуточные ситуации, которые требуют получе- ния актуальных данных из хранилища, или управления захватом и освобождением объектов. Поэтому кроме команд Захватить в хранилище и Поместить в хранилище существуют еще две команды: Отменить захват в хранилище и Получить из хранилища. Рассмотрим каждую из этих команд более подробно. Захват в хранилище Команда Захватить в хранилище позволяет разработчику захватить объект, который еще не был захвачен други- ми разработчиками. Захват может быть осуществлен как в окне конфигурации, так и в окне хранилища кон- фигурации. Выбор того или иного способа — дело вкуса разработчика, однако захват объектов в окне хранили- ща конфигурации позволяет выполнить множествен- ный захват объектов, чего нельзя сделать в окне конфи- гурации. В ходе выполнения команды Захватить в хранилище систе- ма выводит список захватываемых объектов. Остановим- ся подробнее на информации, которая содержится в этом списке (рис. 18.18). Рис. 18.18. Захват объектов в хранилище конфигурации В первой колонке указывается признак получения объек- та из хранилища. По умолчанию для всех захватываемых объектов будет выполняться получение этих объектов из хранилища. Вторая колонка списка отображает состояние объекта. Возможны четыре состояния (табл. 18.2). Состояние Объект не будет изменен говорит о том, что объ- ект, захватываемый в хранилище, совпадает с объектом, находящимся в отладочной базе. Состояние Объект будет изменен говорит о том, что объект, захватываемый в хранилище, отличается от объекта, на- ходящегося в отладочной базе. Такая ситуация может возникать, например, когда после того, как разработчик поместил объект в хранилище, этот объект был захвачен, изменен и помещен в хранилище другим разработчиком. Тогда при новом захвате этого объекта система сообщит разработчику, что объект, находящийся в его отладочной базе, отличается от того, который находится в храни- лище. Таблица 18.2. Состояния объектов Состояние Пиктограмма Описание Объект не будет изменен Нет пиктограммы Объект не будет изменен в отладочной конфигурации Объект будет изменен Объект в отладочной конфигурации будет изменен Объект будет добавлен Объект будет добавлен в отладочную конфигурацию Объект будет удален i"".l Объект будет удален из отладочной конфигурации Состояние Объект будет удален говорит о том, что объект, который разработчик хочет захватить, отсутствует в кон- фигурации хранилища. Например, он был удален другим разработчиком, который посчитал этот объект лишним. Состояние Объект будет добавлен говорит о том, что из хра- нилища будет получен объект, который отсутствует в от- ладочной конфигурации. Здесь следует объяснить одну особенность захвата и помещения объектов. Помимо не- посредственно тех объектов, которые указывает разработ- чик для захвата (или помещения в хранилище), система будет анализировать также необходимость выполнения этой операции и над другими объектами, связанными с указанными явным или неявным образом. Например, если другой разработчик добавил новую форму к спра- вочнику, то при захвате этого справочника система предложит также получить и добавленную форму этого справочника, которая отсутствует в отладочной конфи- гурации, но которая непосредственно связана с захва- тываемым справочником. И в этом случае для формы и будет как раз указано состояние Объект будет добавлен (рис. 18.19). Захват объектов в хранилище конфигурации L.. .... ..... .................... ... 0 411 Справочник Ин формационные Карты_______________________________________ 0 0 + С] Справочник. Ин формационные Карты Форма Форма Выбора Группы Q Выполнять рекурсивно Д Разрешать получать захваченные ОК 11 Отмена"] | Справка"] Рис. 18.19. Захват связанных объектов Третья колонка показывает полное имя объекта метадан- ных, а в четвертой колонке отображается признак захвата объекта в хранилище конфигурации. Он также установ- лен по умолчанию (в большинстве случаев), однако раз- работчик может и сбросить его, если, например, требуется только получить объект из хранилища, а изменять его он не собирается.
Также в диалоге захвата объектов хранилища разработ- чику предоставляется возможность определить два свой- ства, относящиеся ко всем захватываемым объектам. Выполнять рекурсивно — указывает, что помимо тех объек- тов, которые перечислены в списке, следует также захва- тить и все их подчиненные объекты, которые могут быть загружены независимо (подчиненные объекты, которые не могут быть загружены независимо от родительского объекта, всегда будут получены вместе с родительским объектом). Например, если при захвате справочника не выполнять загрузку рекурсивно, то из подчиненных объектов будут захвачены только реквизиты и табличные части справоч- ника (рис. 18.20). Конфигурация <•> ¥ X к-**, t Ю I Й-Л ФильтрыДл я Электронных Писем S 2 Реквизиты — ОперацияУсловия £ i । ; • — порядок | | — Использование Ё ?.:^ Табличные части Ё УсловияФильтра ! — ОтрицаниеУсловия j. I } ' — Условие '<- ЗначениеУсловия j, Ё «И ДействияФильтра | г — ДействиеФильтра - — Группа Писем Ё Q Формы С Форма С писка g О Форма Элемента g -О ФормаВыбора g Q Макеты Рис. 18.20. Захват без рекурсивной загрузки Если же выполнить захват рекурсивно, то также будут за- хвачены и те объекты, подчиненные справочнику, кото- рые могут быть захвачены отдельно от него: формы и ма- кеты (рис. 18.21). Рис. 18.21. Захват с рекурсивной загрузкой Флаг Разрешать получать захваченные позволяет при загрузке получить и те объекты, которые захвачены данным пользо- вателем. Такая возможность может потребоваться, напри- мер, когда нужно вернуться к состоянию хранилища, не от- меняя захват объекта, а продолжая его редактирование. Однако использовать этот флаг нужно внимательно, по- скольку среди объектов, получаемых из хранилища, мо- гут оказаться объекты, захваченные самим разработчи- ком ранее и уже измененные им в своей отладочной конфигурации. В этом случае изменения таких объектов, сделанные разработчиком в своей отладочной конфигу- рации, будут потеряны. Рассмотрим возможную ситуацию. Разработчик захватил и редактирует справочник СправочникА. Он добавляет в него реквизит, ссылающийся на справочник СправочникБ (рис. 18.22). Пользователь Хранилище Рис. 18.22. Действия первого пользователя В это время другой пользователь также редактирует кон- фигурацию и решает удалить справочник СправочникБ. После этого помещает выполненные изменения в храни- лище (рис. 18.23). Эфанилище Пользователь СправочникА Рис. 18.23. Действия второго пользователя Теперь первый пользователь решает поместить измене- ния справочника СправочникА в хранилище. Ему не удаст- ся этого сделать, поскольку система попросит его помес- тить в хранилище и справочник СправочникБ, так как иначе в хранилище окажется ссылка на справочник, кото- рый там отсутствует. Поэтому система предложит поль- зователю захватить корень конфигурации, чтобы полу- чить из хранилища нужные данные. Однако так как в хранилище уже отсутствует справочник СправочникБ, то система будет требовать получения и данных справочни- ка СправочникА, иначе в конфигурации пользователя ока- жется ссылка на несуществующий справочник Справоч- никБ. В этом случае и потребуется установка флага Разрешать получать захваченные. Однако при этом измене- ния, внесенные пользователем в справочник СправочникА, будут потеряны.
Помещение в хранилище Процесс помещения объектов в хранилище прямо проти- воположен захвату их в хранилище. В ходе выполнения команды Поместить в хранилище выдается аналогичный диалог, за тем лишь исключением, что первая колонка яв- ляется признаком помещения объекта в хранилище, по- следняя колонка отсутствует (Захватить), и нет флага Раз- решать получать захваченные. Однако в диалоге присутствует другой флаг — Оставить захваченными, который позволяет не «расставаться» с объектами, перечисленными в списке, а лишь поместить их в хранилище. Таким образом, например, другие разра- ботчики смогут получить эти объекты, чтобы узнать их актуальное состояние, а данный разработчик сможет про- должить их модификацию, не выполняя заново их захват в хранилище. Версии конфигурации Если в результате выполнения команды Поместить в хра- нилище объекты хранилища были изменены, создается новая версия конфигурации в хранилище. Для иденти- фикации каждой версии конфигурации в хранилище со- храняется следующая информация: ♦ Порядковый номер версии — генерируется системой автоматически; ♦ Версия конфигурации — значение свойства «Версия» конфигурации; ♦ Дата — дата и время публикации изменений в хранили- ще конфигурации; ♦ Пользователь — имя пользователя, внесшего измене- ния; ♦ Комментарий — комментарий к выполненным измене- ниям; ♦ Метка — краткое описание некоторого крупного этапа разработки конфигурации (например, выпуск новой версии, подготовка поставки и т. д.); ♦ Комментарий метки — расширенное описание, коммен- тирующее метку. Методология использования хранилища конфигурации предполагает, что каждая версия должна содержать ка- кое-либо одно цельное изменение конфигурации. Напри- мер, исправление одной ошибки или одну доработку. В этом случае комментарий к этой версии будет описы- вать одно изменение, и это описание будет относиться ко всем объектам, измененным в данной версии. Такой по- рядок работы позволяет получить стройную и понятную структуру версий конфигурации, с которой в дальнейшем будет легко работать. Рекомендуется каждое такое изменение (все захваченные объекты метаданных) помещать в хранилище за один прием, создавая только одну новую версию конфигура- ции. Если все же приходится помещать такие изменения в несколько приемов (создавая несколько версий), жела- тельно указывать полностью идентичный комментарий ко всем таким изменениям. При написании комментария к версии следует учиты- вать, что этот комментарий может быть использован при подготовке документации к очередной версии разрабаты- ваемой конфигурации, в частности выведен отчет по вер- сиям хранилища. Если в комментариях к версиям при- сутствует служебная информация, то ее лучше распола- гать после символов // (два слэша). В дальнейшем, при формировании отчета эту информацию можно будет ав- томатически исключить из отчета. Если с символов // начинается строка, то вся эта строка может быть исключена из отчета. Если символы // распо- лагаются в середине строки, то можно исключить часть строки, начиная с символов // и до конца строки. Отмена захвата Команда Отменить захват в хранилище позволяет освобо- дить объект в хранилище и получить из хранилища теку- щую версию объекта. Эта возможность может потре- боваться, например, когда разработчик окончательно запутался в изменениях, которые он вносил в объекты, и хочет просто «отпустить» захваченные объекты, не из- меняя их в хранилище, чтобы начать работу заново или чтобы другие разработчики могли внести в них измене- ния. Получение объекта из хранилища Команда Получить из хранилища позволяет получить объ- ект, не осуществляя его захват. Такая возможность может понадобиться, например, для того, чтобы посмотреть ак- туальное состояние объекта, который изменяется (или изменялся) другим разработчиком. Обновление конфигурации из хранилища Обновление конфигурации из хранилища — это получе- ние изменений всех объектов из хранилища (за исключе- нием захваченных данным пользователем). Эта команда является сервисной, реализована для более удобной син- хронизации конфигурации отладочной базы с последней версией конфигурации хранилища и позволяет в ряде случаев обойтись без дополнительного подтверждения получения объектов из хранилища. Действия, выполняемые при обновлении конфигурации из хранилища, аналогичны действиям, выполняемым при получении объектов из хранилища. Если сравнивать эту команду с получением объектов из хранилища, то можно сказать, что обновление конфигурации из хранилища приведет к тем же самым результатам, что и получение корневого объекта конфигурации с установленным при- знаком Выполнять рекурсивно. Администрирование хранилища Администрирование хранилища конфигурации может быть выполнено как в режиме работы с подключением, так и в режиме работы без подключения (естественно, если пользователь хранилища обладает административ- ными правами). Для этого используется команда Действия ► Администри- рование хранилища.
В результате выполнения этой команды открывается окно администрирования хранилища, которое позволяет выполнять три группы действий: ♦ просмотр, создание, изменение и удаление пользовате- лей хранилища; ♦ просмотр подключений, зарегистрированных в храни- лище, и отключение информационных баз от храни- лища; ♦ просмотр объектов, захваченных в хранилище другими пользователями, и отмена захвата объектов. Администрирование пользователей хранилища подробно описано в документации и не требует отдельных поясне- ний. Поэтому остановимся подробнее на просмотре под- ключений и захваченных объектов. На закладке Подключения система выводит список поль- зователей хранилища, для которых есть информация о подключенных информационных базах. Список содер- жит имя пользователя, имя компьютера, с которого осу- ществлено подключение к компьютеру, и путь к информа- ционной базе. Подключения, активные в данный момент (то есть те информационные базы, которые открыты поль- зователями в конфигураторе), выделяются жирным шрифтом. Администратор хранилища имеет возмож- ность отключить выбранную информационную базу от хранилища, но лишь при том условии, что эта база не от- крыта в данный момент в конфигураторе. То есть отклю- чить можно только те подключения, которые не выделе- ны жирным. На закладке Отмена захвата отображается список объек- тов, захваченных конкретным пользователем. Здесь ад- министратор хранилища также имеет возможность отме- нить захват каждого из объектов, но лишь в том случае, если отладочная база разработчика, захватившего данный объект, не открыта в режиме конфигуратора. Такое от- ключение может понадобиться, например, если разработ- чик, уходя в отпуск, забыл поместить захваченные объек- ты в хранилище. В этом случае команда разработчиков, отменив захват его объектов, все же сможет продолжить работу с этими объектами. Также есть одна особенность отображения захваченных объектов на этой закладке: отображаются только объек- ты, захваченные другими пользователями. Объекты, за- хваченные текущим разработчиком, не отображаются. То есть просматривать и отменять захват «своих» объек- тов можно в окне хранилища конфигурации или в дереве конфигурации. Сравнение и сохранение текущей конфигурации хранилища Конфигурацию отладочной базы можно сравнить/объе- динить с текущей конфигурацией хранилища, можно сравнить текущую конфигурацию хранилища с конфигу- рацией из файла, а также можно сохранить текущую кон- фигурацию хранилища в файл. Все эти действия доступны как в режиме работы с под- ключением, так и в режиме работы без подключения к хранилищу. Также следует отметить, что хранилище позволяет срав- нивать не только конфигурацию целиком, но и отдельные объекты хранилища с объектами конфигурации. Для это- го используется команда Действия ► Сравнить с объектом конфигурации. Выполнение этой команды сводится к по- лучению отчета о сравнении конфигураций по выбранно- му объекту. В процессе выполнения этой команды разра- ботчик может открыть или не открывать стандартный диалог сравнения/объединения конфигураций. Работа с версиями хранилища конфигурации Как уже говорилось ранее, при помещении измененных объектов в хранилище система создает новую версию конфигурации хранилища, которую можно сопроводить дополнительной информацией. Состав сопроводительной информации был описан в разделе «Версии конфигура- ции», с. 698. Для работы с версиями конфигурации следу- ет выполнить команду Действия ► История хранилища. Сис- тема откроет окно истории хранилища конфигурации, в котором будет представлена информация об имеющих- ся версиях (рис. 18.24). Рис. 18.24. История хранилища Хочется обратить внимание, что в состав информации, отображаемой для каждой версии, входит комментарий к версии, комментарий к метке, а также состав объектов, измененных в этой версии. Метка предназначена для ука- зания крупных этапов разработки и имеет поле коммен- тария к метке для расширенного описания каждого этапа. Список измененных объектов содержит пиктограммы, которые позволяют определить состояние измененных объектов (был ли объект просто изменен, добавлен или удален). Контекстное меню позволяет открыть указанную версию объекта для просмотра, просмотреть историю из- менения объекта за все время или только за указанный период, а также сравнить версию объекта с текущей вер- сией хранилища. Текущей версией хранилища является последняя версия в списке (имеющая максимальный номер).
Для удобства можно выделить одновременно несколько версий — тогда будут показаны все объекты, измененные в этих версиях, а в поле Комментарий выведены коммен- тарии ко всем выделенным версиям. Для каждой версии можно изменить некоторую инфор- мацию о версии: метку, комментарий и комментарий метки. Каждую версию можно открыть для просмотра, загрузить в отладочную базу, сравнить/объединить с конфигураци- ей отладочной базы, сравнить с конфигурацией из файла или сохранить в файл. Любые две версии хранилища можно сравнить между со- бой. Установка отбора в окне истории хранилища Версии, отображаемые в окне истории, могут быть ото- браны по различным критериям (рис. 18.25). Рис. 18.25. Отбор версий хранилища Например, можно выполнить отбор по одному или не- скольким пользователям хранилища. В этом случае будут отображены только те версии, которые создавались вы- бранными пользователями. Также можно установить отбор по определенным объек- там конфигурации. В этом случае будут показаны те вер- сии, которые содержат изменения выбранных объектов. Кроме этого, можно ограничить диапазон отображаемых версий как в терминах версий, так и в терминах календар- ных дат. Флаг Выводить метки позволяет отображать версии, отме- ченные метками. Если этот флаг сбросить, то будут пока- заны только те версии, которые не отмечены метками. Флаг Выводить только метки позволяет отображать только версии, отмеченные метками. Если оба флага установле- ны, то будут показаны только те версии, которые отмече- ны метками. В поле Версия конфигурации можно указать нужную вер- сию (колонка Версия конфигурации), и тогда будут отобра- жены только те версии конфигурации хранилища, для которых значение этого поля соответствует указанному. Откат к предыдущей версии Хранилище предоставляет возможность откатиться от те- кущей версии к любой предыдущей. При этом из храни- лища удаляются все версии конфигурации, расположен- ные после указанной. Такая возможность может понадобиться, если в храни- лище были опубликованы ненужные версии конфигура- ции. Сокращение до выбранной версии Хранилище конфигурации можно сократить до любой выбранной версии. В этом случае из хранилища удаляют- ся все версии конфигурации, расположенные ранее ука- занной. Такая возможность может понадобиться, когда ранние версии конфигурации становятся ненужными. Объединение версий Несколько последовательных версий хранилища могут быть объединены в одну. В результате будет сформирова- на одна сводная версия, включающая в себя изменения всех выбранных версий. Отчеты по истории хранилища Хранилище конфигурации позволяет выполнять несколь- ко видов отчетов по истории хранилища. Такие отчеты имеют двоякое назначение: с одной стороны, они могут использоваться для внутренних целей (например, для от- слеживания хода разработки), а с другой — для формиро- вания сопроводительной документации к выпускаемым версиям конфигурации. Создать отчет по истории хранилища можно при помо- щи команды Действия ► Отчет по истории хранилища (рис. 18.26). Рис. 18.26. Отчет по истории хранилища
Отчет по версиям хранилища Отчет по версиям хранилища показывает информацию о версиях в хронологическом порядке, включая коммен- тарии к версии и перечень измененных объектов, с указа- нием их статуса (добавлены, удалены и т. д.). Отчет по объектам разработки Отчет по объектам разработки показывает объекты кон- фигурации в алфавитном порядке, включая комментарии к версиям, в которых эти объекты изменялись. Отчет по комментариям к версиям хранилища Отчет по комментариям к версиям хранилища показыва- ет комментарии к версиям в хронологическом порядке версий, включая перечень измененных объектов, с указа- нием их статуса (добавлены, удалены и т. д.). Существует возможность выводить перечисленные отчеты, как в текстовый, так и в табличный документ, скрывать служебные комментарии (начинающиеся с //), исклю- чать версии с пустыми комментариями и устанавливать отбор версий, по которым будет строиться отчет. Уста- новка отбора аналогична тому, как устанавливается отбор версий в окне истории хранилища конфигурации (см. раздел «Работа с версиями хранилища конфигу- рации», с. 699). Использование отчетов по истории хранилища Отчеты по истории хранилища могут использоваться как для внутренних служебных целей, так и в качестве источ- ника информации при формировании файлов, включае- мых в поставку прикладного решения. В качестве примера можно привести выдержку из стан- дарта подготовки версий конфигураций фирмы «1С» (пол- ностью со стандартами разработки фирмы «1С» можно ознакомиться на сайте фирмы «1С» по адресу http:// partners.v8.1 c.ru). При подготовке версий конфигураций ЮПредприя- тия 8.0 готовятся следующие дополнительные файлы: ♦ описание изменений в версии; ♦ отчет по измененным объектам; ♦ отчет по комментариям; ♦ lcv8upd.htm — включается описание порядка обнов- ления предыдущей (предыдущих) версии на текущую; ♦ ReadMe.txt — включает дополнительную информацию. Подготовка отчета по измененным объектам. Отчет по измененным объектам содержит для каждого объекта конфигурации, в которые вносились изменения с момен- та выпуска предыдущей версии конфигурации, с описа- нием всех внесенных в этот объект изменений. Отчет по измененным объектам является «зеркальным» по отно- шению к отчету по комментариям. Получение отчета по измененным объектам. Для получе- ния отчета с группировкой «по объектам» формируется отчет по истории хранилища с параметрами: ♦ Отчет по — Объектам разработки. ♦ Выводить в — Табличный документ. ♦ Не выводить строки комментария, начинающиеся с «//..» - Да. ♦ В диалоге «Отбор версий хранилища» указывается: Диапазон версий хранилища: С версии <начальный номер> по версию <конечный номер>. Выводить метки — Нет. Оформление отчета по объектам. Полученный отчет со- храняется с именем «Название конфигурации». Версия «номер версии без номера сборки>. Измененные объекты.mxl Например: Управление торговлей. Версия 10.2.3. Измененные объекты.mxl Из отчета убирается служебная информация: ♦ путь к хранилищу; ♦ дата и время формирования отчета. Вместо них в файл помещаются строки с указанием на- звания конфигурации и номера версии в виде: 1С:Предприятие 8.0 Конфигурация «Название конфигурации>, редакция «номер редакции> Версия «номер версии без номера сборки> Например: 1С:Предприятие 8.0 Конфигурация Управление торговлей, редакция 10.2 Версия 10.2.3 Подготовка отчета по комментариям. Отчет по коммен- тариям представляет собой описание изменений, внесен- ных в конфигурацию с момента выпуска предыдущей версии, с перечислением для каждого изменения объек- тов конфигурации, которые были изменены. Отчет по комментариям является «зеркальным» по отношению к отчету по измененным объектам. Получение отчета по комментариям. Для получения от- чета с группировкой «по комментариям» формируется отчет по истории хранилища с параметрами: ♦ Отчет по — Комментариям к версиям хранилища. ♦ Выводить в — Табличный документ. ♦ Не выводить строки комментария, начинающиеся с «//..» - Да. ♦ В диалоге «Отбор версий хранилища» указывается: Диапазон версий хранилища: С версии <начальный номер> по версию <конечный номер>. Выводить метки — Нет. Оформление отчета по комментариям. Полученный от- чет сохраняется с именем «Название конфигурации». Версия «номер версии». Изменения в версии.mxl Например: Управление торговлей. Версия 10.2.3. Изменения в версии.mxl Из отчета убирается служебная информация: ♦ путь к хранилищу; ♦ дата и время формирования отчета.
Вместо них в файл помещаются строки с указанием на- звания конфигурации и номера версии в виде: 1С:Предприятие 8.0 Конфигурация «Название конфигурации:», редакция <нонер редакции» Версия «номер версии без номера сборки» Например: 1С:Предприятие 8.0 Конфигурация Управление торговлей, редакция 10.2 Версия 10.2.3 Варианты использования хранилища конфигурации Поскольку разработка прикладного решения — процесс творческий, различные группы разработчиков могут ор- ганизовывать свою совместную работу над проектом со- вершенно по-разному. Рассмотрим несколько вариантов использования хранилища конфигурации разработчи- ками. Локальная группа разработчиков Наиболее типовой и наиболее распространенной схемой работы с хранилищем является схема, при которой хра- нилище расположено в локальной сети, к нему подключе- на группа разработчиков и периодически выполняется архивирование хранилища (рис. 18.27). Рис. 18.27. Локальная группа разработчиков Каждый разработчик действует по следующей схеме: за- хватил объекты — внес изменения — поместил объекты в хранилище. С нужной периодичностью выполняется архивирование хранилища конфигурации. Для этого файл хранилища lcv8ddb.lCD просто копируется в архив, расположенный, как правило, на другой рабочей станции или на сменном носителе. В случае каких-либо сбоев в работе хранилища с помощью утилиты ChDBFL, входящей в комплект постав- ки 1С:Предприятия, можно проверить файл хранилища на наличие ошибок. Однако выполнять исправление хра- нилища с его помощью не рекомендуется, поскольку при этом логическая целостность данных хранилища может быть нарушена, что приведет к потере его работоспособ- ности. Для восстановления хранилища конфигурации следует использовать резервные копии хранилища. После того как разработка прикладного решения завер- шена, на основе текущей версии хранилища создается комплект поставки (дистрибутив) решения. Более подроб- но процесс создания комплектов поставки описан в раз- деле «Механизм создания комплектов поставки», с. 668. Один разработчик Хранилище конфигурации, как механизм, автоматизи- рующий процесс разработки прикладного решения, мо- жет быть использован не только группой разработчиков, но и одним разработчиком, который полностью самостоя- тельно ведет разработку (рис. 18.28). Рис. 18.28. Один разработчик В этом случае, очевидно, возможности разделения досту- па к редактируемым объектам использованы не будут, од- нако все остальные функции хранилища (версиониро- вание разработки, возможность формирования отчетов и т. д.) будут полезны для контроля процесса разработки. Разработка конфигурации должна вестись по правилам работы с хранилищем (захват объектов, изменение, поме- щение в хранилище), но так как других пользователей, работающих с хранилищем, нет, то при помещении объ- ектов в хранилище можно всегда устанавливать признак Оставить захваченным. Удаленные разработчики Хранилище конфигурации позволяет работать без непо- средственной с ним связи. Основная суть данной методи- ки в том, чтобы предварительно произвести захват нуж- ных объектов конфигурации. После этого захваченные объекты можно редактировать, не соединяясь с хранили- щем (рис. 18.29). Рис. 18.29. «Оффлайновые» разработчики Таким образом, возможна следующая схема работы: раз- работчик подключается к хранилищу, захватывает нуж- ные ему объекты, а работает с ними или дома, или на вы- зове у клиента с локальным ключом. Потом возвращается
в свой офис, соединяется с хранилищем, помещает в хра- нилище захваченные им объекты и получает из хранили- ща объекты, измененные другими разработчиками. Преимущество данной методики в том, что разработчик забирает «свою» часть объектов и работает с ней, гаран- тированно не пересекаясь с коллегами. В этом же заключается и недостаток подобного подхода: необходимо заранее знать, в какие объекты конфигура- ции предстоит вносить изменения, что возможно далеко не всегда. Разработка на территории заказчика Зачастую завершающая часть разработки прикладного решения (а иногда и вся разработка целиком) выполняется непосредственно на территории заказчика. В этом случае для упрощения процесса обновления информационной базы клиента, она может быть подключена непосредст- венно к хранилищу конфигурации (рис. 18.30). Рис. 18.31. Удаленный заказчик Таким образом, заказчик имеет возможность выполнять тестирование разрабатываемой конфигурации, а разра- ботчики могут выполнять удаленное обновление конфи- гурации заказчика. Рис 18.30. Разработка на территории заказчика При этом, как правило, создается специальный пользова- тель хранилища, имеющий права только на чтение и по- лучение данных из хранилища. Под этим пользователем рабочая база клиента подключается к хранилищу. «Удаленный» заказчик Зачастую возникает необходимость взаимодействовать с заказчиком, который расположен на другой территории (например, на другом конце города или в другом городе). В этом случае для обновления рабочей конфигурации за- казчика можно использовать механизм поставки и под- держки конфигураций (подробнее об этом механизме можно прочитать в разделе «Механизм поставки и под- держки прикладных решений», с. 652) (рис. 18.31). Последовательность взаимодействия с заказчиком в этом случае заключается в следующем: на определенном этапе разработки создается комплект поставки, который пере- дается заказчику, и заказчик устанавливает его у себя (создается рабочая база заказчика). Конфигурация, уста- новленная у заказчика, стоит на полной поддержке, и по мере необходимости разработчиками формируется ком- плект обновления на основании текущей версии конфи- гурации. Этот комплект обновления выкладывается на ftp- или http-pecypc, с которого заказчик самостоятельно в автоматическом режиме выполняет обновление своей рабочей конфигурации. Работа с хранилищем конфигурации из командной строки Система 1 С:Предприятие может быть запущена в режиме Конфигуратор из командной строки. Такой режим запуска позволяет выполнять различные действия, в том числе и выгрузку, и обновление версий конфигурации в хранили- ще. Для соединения с хранилищем используются параметры DepotF, DepotN и DepotP, задающие, соответственно, каталог хранилища, имя пользователя и пароль. Для сохранения версии конфигурации хранилища в файл используется параметр DepotDumpCfg с ключом v. Ключ v задает номер версии, которая должна быть выгружена из хранилища. Если ключ v не задан или его значение равно -1, тогда будет сохранена текущая версия хранили- ща (листинг 18.1). Листинг 18.1. Сохранение версии конфигурации хранилища в файл /DepotDumpCfg D:\l\Publishing.cf -v 9 Для обновления конфигурации информационной базы из хранилища используется параметр DepotUpdateCfg с клю- чами v и revised. Ключ v задает номер версии, которая должна быть использована для обновления. Ключ revi sed позволяет получать захваченные объекты, если это требу- ется (листинг 18.2). Листинг 18.2. Обновление конфигурации информационной базы из хранилища /DepotDumpCfg D:\l\Publishing.cf -revised Следует учитывать, что если конфигурация подключена к хранилищу, то ключ v будет проигнорирован, так как в этом случае возможно обновление только текущей вереи-
ей конфигурации хранилища. Также, если конфигурация не подключена к хранилищу, то будет проигнорирован ключ revi sed, так как в режиме работы без подключения к хранилищу, захват и получение отдельных объектов не- возможны. Обновление конфигурации из хранилища может быть ис- пользовано, например, для того, чтобы затем сформиро- вать файлы поставки и обновления. Подробнее о форми- ровании файлов поставки и обновления из командной строки см. с. 685. Производительность прикладного решения Общее понятие производительности прикладного решения Производительность прикладного решения на платфор- ме ЮПредприятия 8.0 является комплексным поня- тием, включающим в себя несколько различных состав- ляющих. Можно выделить следующие составляющие производительности: прикладное решение, технологи- ческая платформа, сервер баз данных и оборудование (рис. 18.32). Рассмотрим каждую из перечисленных составляющих более подробно. Прикладное решение Непосредственно само прикладное решение, созданное разработчиками, является одной из важнейших состав- ляющих, оказывающих влияние на производительность системы. Например, грамотное проектирование структу- ры метаданных и решение вопросов индексирования по- зволяет существенно сократить диапазон блокировок и вероятность возникновения взаимных блокировок. В то же время неграмотно написанный запрос при неблаго- приятном стечении обстоятельств способен «замучить» сколь угодно мощный сервер приложений или сервер баз данных. Или другой пример: транзакция, надолго забло- кировавшая какой-либо общий ресурс, может сделать не- возможной работу большинства пользователей системы. Технологическая платформа Поскольку любое прикладное решение (конфигурация) всегда выполняется под управлением технологической платформы ЮПредприятия, то производительность платформы также оказывает непосредственное влияние на общий результат. Как показывает практика, в подав- ляющем большинстве случаев при крупных внедрениях используется трехуровневая архитектура системы (вари- ант работы клиент — сервер). В таком варианте работы на компьютерах пользователей исполняется клиентская часть системы, которая взаимодействует с сервером ЮПред- приятия. Сервер ЮПредприятия обеспечивает взаимо- действие клиентских приложений с сервером баз данных и кроме этого выполняет еще ряд служебных задач. Очевидно, что от быстродействия платформы также в значительной степени зависит производительность сис- темы. Важным моментом здесь является то, что если на другие составляющие производительности разработчик может повлиять непосредственно (например, проведя ди- агностику и оптимизацию), то на производительность платформы разработчик повлиять не может, он использу- ет ее «как есть». Сервер баз данных В качестве сервера баз данных ЮПредприятие может ис- пользовать SQL Server. Как показывает практика, негра- мотное или пренебрежительное отношение к настройке и обслуживанию этого продукта может привести в некото- рых случаях к существенному падению производительно- сти системы. В то же время соблюдение рекомендаций и выполнение регламентных процедур значительно увели- чивают стабильность и скорость работы прикладного ре- шения. Например, поддержание индексов и статистики SQL Server в актуальном состоянии позволяет вырабаты- вать оптимальный план выполнения запросов, а своевре- менная очистка журнала транзакций позволяет избежать неконтролируемого роста его размера и затрат ресурсов SQL Server. Оборудование Оборудование обеспечивает функционирование всех вы- шеперечисленных составляющих. Здесь самое значитель- ное влияние на производительность оказывает, прежде всего, конфигурация аппаратных средств: количество и быстродействие процессоров, количество и быстродейст- вие дисков, объем оперативной памяти, пропускная спо- собность сетевого интерфейса и т. д. Взаимное влияние составляющих производительности Все перечисленные составляющие существуют не сами по себе, а оказывают влияние друг на друга.
Например, от производительности технологической плат- формы напрямую зависит, с какой скоростью будет вы- полняться тот или иной участок кода, содержащегося в модуле. Также от платформы зависит, например, на- сколько быстро и правильно запрос, написанный на язы- ке запросов ЮПредприятия, будет преобразован в за- прос на языке Transact SQL, передан SQL Server, получен от него обратно и обработан (например, построены итоги в соответствии с инструкциями в тексте запроса). В свою очередь, производительность платформы также зависит от производительности SQL Server, поскольку многие действия системы сводятся к выполнению раз- личных запросов SQL Server. Поэтому правильная на- стройка и своевременное выполнение регламентных опе- раций на SQL Server могут иметь значительное влияние на производительность, как платформы, так и всего при- кладного решения в целом. И, наконец, фундаментальной, можно сказать, состав- ляющей производительности является оборудование, ко- торое непосредственно влияет как на производительность платформы, так и на производительность SQL Server. Как бы хорошо ни было написано прикладное решение, какие бы возможности масштабирования ни были зало- жены в платформу, как бы хорошо ни обслуживался SQL Server, — все это может быть «загублено» недостаточной производительностью дисковой подсистемы SQL Server, или недостаточной объемом оперативной памяти, кото- рую может использовать SQL Server. Последовательность решения задач оптимизации Описанное взаимное влияние определяет последователь- ность решения любых задач, связанных с повышением производительности. Прежде всего необходимо обес- печить достаточную производительность используемого оборудования и правильную настройку операционной системы. После этого следует настроить SQL Server и ор- ганизовать регулярное выполнение регламентных опера- ций по его обслуживанию. Необходимая производитель- ность технологической платформы заложена в нее при разработке и не может быть изменена прикладным разра- ботчиком, поэтому единственным способом увеличить производительность платформы является использование последней ее версии, поскольку от версии к версии вы- полняется оптимизация различных механизмов и устра- нение обнаруженных ошибок. И наконец, заключитель- ной и наиболее сложной задачей является обеспечение производительности собственно прикладного решения (кон- фигурации), созданного прикладными разработчиками. Изменение производительности во времени При анализе и оптимизации производительности систе- мы нужно рассматривать все перечисленные составляю- щие в комплексе. Однако кроме этого следует понимать, что производительность не является неким статическим неизменным результатом. Основная особенность заклю- чается в том, что она может меняться с течением времени. Поэтому в общем случае производительность следует рассматривать в виде матрицы, одним из измерений кото- рой является время (рис. 18.33). Разработка ! Внедрение Эксплуатация Прикладное решение Клиентская часть Сервер 1 С. Предприятия 8 0 SQL Server 2000 Оборудование Рис. 18.33. Изменение производительности во времени Как видно из приведенной схемы, при решении вопросов производительности имеют значение не абсолютные вре- менные показатели, а качественные: этапы «жизненного цикла» прикладного решения. Любое прикладное реше- ние «переживает» как минимум три этапа: разработка, внедрение и эксплуатация. Разработка На этапе разработки основное влияние на производи- тельность оказывает прикладное решение. Основная за- дача, решаемая на этом этапе, заключается в обеспечении некоторого «типового» уровня производительности, до- статочного для подавляющего большинства внедрений (исходя из среднестатистических представлений о воз- можных внедрениях). Внедрение Задача, решаемая на этапе внедрения, является более конкретной и в то же время более ответственной — необ- ходимо обеспечить требуемый заказчиком уровень про- изводительности исходя из условий конкретного внедре- ния. В этой ситуации одинаково пристальное внимание должно быть уделено уже всем составляющим произво- дительности, так как недочеты в любой из этих состав- ляющих могут привести к серьезным проблемам в бу- дущем. Эксплуатация Казалось бы, что на этапе внедрения и заканчивается ре- шение вопросов производительности: система внедрена, заказчик доволен, пользователи работают... Однако, на самом деле, в процессе эксплуатации также требуется анализировать производительность системы и поддержи- вать ее на требуемом уровне. Прикладное решение не является статичным, оно разви- вается, и в процессе эксплуатации на систему действует целый ряд различных факторов, которые могут снизить уровень производительности, достигнутый на момент внедрения системы. Основными из таких факторов являются: ♦ увеличение количества пользователей системы; ♦ увеличение объема хранящейся в системе информа- ции; ♦ пиковая нагрузка, например, в конце отчетного периода;
♦ усложнение функциональности; ♦ доработка прикладного решения без обеспечения над- лежащего контроля качества. Увеличение количества пользователей Количество пользователей имеет тенденцию расти. Это очевидный и естественный процесс, понятный еще на этапе внедрения. Собственно целью автоматизации и яв- ляется возможность дальнейшего развития, поэтому в процессе эксплуатации к системе подключаются все но- вые пользователи, что увеличивает общую нагрузку на систему и может привести к снижению производитель- ности. Как правило, уровень производительности, достигнутый на этапе внедрения, не является критическим: всегда име- ется определенный запас, позволяющий системе разви- ваться. При постепенном увеличении количества поль- зователей этот запас «выбирается» в течение довольно продолжительного времени и поэтому проблемы произ- водительности можно диагностировать и устранить еще на ранних этапах. Гораздо более опасной является ситуация скачкообраз- ного увеличения количества пользователей (например, открытие крупного филиала, значительное расширение компании, поглощение конкурирующей фирмы). В этом случае нагрузка на систему значительно возрастает в очень короткий срок и может превысить существующие возможности системы. Поэтому подобные изменения следует планировать (а возможно, даже и моделировать) заранее и при необходимости принимать меры для увели- чения производительности системы. Увеличение объема информации Увеличение объема хранящейся информации также яв- ляется естественным процессом, который может значи- тельно повлиять на производительность прикладного ре- шения. Самым очевидным проявлением этого может являться увеличение времени работы отчетов, замедле- ние работы некоторых интерфейсных механизмов (на- пример, форм подбора) и т. д. Пиковые нагрузки Для многих прикладных решений характерной является ситуация, когда нагрузка на систему имеет явно выра- женные «пики», возникающие с определенной периодич- ностью. Наиболее распространенной является наличие циклической пиковой нагрузки, например, в конце отчет- ного периода, поскольку в это время выполняется подго- товка большого количества сводных данных, выполняют- ся расчеты, перерасчеты и пр. Как уже говорилось ранее, скачкообразные увеличения нагрузки являются наиболее опасными и требуют особого внимания и по возможно- сти, прогнозирования. Усложнение функциональности В ходе эксплуатации, как правило, прикладное решение дорабатывается, приобретает новую функциональность или расширяются возможности существующих механиз- мов, реализованных в конкретном решении. Подобные изменения также могут привести к снижению производи- тельности. Например, документ, который раньше прово- дился по пяти регистрам, теперь должен формировать движения в десяти регистрах, причем по довольно слож- ному алгоритму. Очевидно, что время проведения этого документа возрастет. Некачественные доработки Отдельно следует выделить ситуации, когда в уже рабо- тающее прикладное решение вносятся доработки без над- лежащего анализа их влияния на производительность системы. Конфигурации 1 С: Предприятия являются, по своей идеологии, открытыми и доступными для модифи- кации. С одной стороны, это является очень большим преимуществом, позволяющим легко и быстро подстраи- вать их под нужды конкретного заказчика. В том числе и без непосредственного участия разработчиков. Средства разработки входят в стандартную поставку прикладного решения, поэтому специалисты заказчика могут само- стоятельно внести нужные им изменения в прикладное решение. С другой стороны, внося изменения, специали- сты заказчика заботятся в большей степени о реализации некоторой функциональности, нежели о том, какое влия- ние это может оказать на производительность системы в целом. В конце концов, они просто могут не иметь доста- точного опыта и знаний для адекватной оценки последст- вий подобных модификаций. Цикл поддержания производительности Как уже было сказано, в процессе эксплуатации приклад- ного решения необходимо постоянно контролировать и поддерживать уровень производительности, который был достигнут при внедрении системы. Для этого, прежде всего, на этапе внедрения следует сформировать набор эталонных показателей производи- тельности системы и зафиксировать значение каждого показателя, достигнутое при внедрении. Это позволит в дальнейшем получать не качественные («что-то програм- ма работает медленно»), а количественные оценки изме- нения производительности. Реализовать это можно различными способами. Напри- мер, в процессе работы прикладного решения можно автоматически регистрировать некоторые показатели производительности системы, например, в журнале реги- страции. Или периодически проводить нагрузочное тес- тирование (если существует такая возможность) с целью получить текущие значения показателей производитель- ности. В качестве эталонных могут быть выбраны различные показатели, например, относительное время проведения «тяжелых» документов, среднее относительное время проведения документов при некотором количестве одно- временно работающих пользователей, среднее относи- тельное время, требуемое для выполнения некоторого вида работ (например, расчета зарплаты) и т. д. По мере эксплуатации прикладного решения состав этих показателей может изменяться и дополняться с тем, что- бы иметь возможность более точно анализировать произ- водительность системы и диагностировать возникающие проблемы. Анализ производительности требуется выполнять перио- дически, в процессе эксплуатации, для того чтобы ви- деть динамику изменения производительности, иметь возможность прогнозировать возможную нагрузку на систему и на ранних этапах выявлять узкие места, кото- рые могут привести к проблемам при дальнейшем увели- чении нагрузки.
Уровни функционирования прикладного решения Работу прикладного решения ЮПредприятия услов- но можно разбить на несколько логических уровней (рис. 18.34). Уровень О Автоматизируемые процессы предприятия Уровень 1 Автоматизированное рабочее место Уровень 2 Конфигурация Уровень 3 Платформа ЧС Предприятия Уровень 4 СУБД Операционная система и оборудование Рис. 18.34. Логические уровни прикладного решения Уровень б Нулевой уровень — это автоматизируемые процессы пред- приятия, то есть непосредственная деятельность, которой занимается организация. Первый уровень — это автоматизированное рабочее место, за которым трудится конечный пользователь системы. Можно сказать, что первый уровень включает в себя ин- терфейс пользователя и прикладную логику. Второй уровень — это конфигурация. Она включает в се- бя структуру метаданных, свойства объектов метаданных, модули, которые содержат, в том числе, алгоритмы и об- работчики событий, написанные на встроенном языке, а также запросы, написанные на языке запросов ЮПред- приятия. Третий уровень — это платформа 1 С: Предприятия, кото- рая собственно и обеспечивает исполнение конфигурации. Четвертый уровень — система управления базой данных. В случае использования файлового варианта это собст- венный движок базы данных ЮПредприятия, а в кли- ент-серверном варианте это SQL Server. Пятый уровень — это уровень операционной системы и оборудования. Взаимодействие уровней Все перечисленные уровни существуют не обособленно друг от друга, а взаимодействуют как сверху вниз, так и снизу вверх. Взаимодействие сверху вниз выражается в том, что верхний уровень «управляет» нижним — пере- дает команды на выполнение определенных действий. Взаимодействие снизу вверх заключается в том, что верх- ний уровень получает в ответ результаты выполнения пе- реданных команд. Несмотря на то что уровни взаимодействуют друг с дру- гом, существует определенная изоляция одного уровня от другого. Вышестоящий уровень «не знает» о том, каким именно образом будет выполняться его команда ниже- стоящим уровнем. Например, находясь на уровне автома- тизированного рабочего места (фактически, на уровне пользовательского интерфейса), невозможно точно ска- зать, какие действия будут выполнены при нажатии на ту или иную кнопку. Для того чтобы узнать это, необходимо спуститься на один уровень вниз (на уровень конфигура- ции) и посмотреть текст обработчика нажатия этой кноп- ки. С другой стороны, нижележащий уровень знает, что и как ему нужно делать (исходя из полученной команды), но «не понимает» этого действия в терминах вышестоя- щего уровня. Естественно, самому уровню и не надо «знать», как будет выполнять его команду нижележащий уровень или зачем вышестоящему уровню понадобилось послать именно та- кой запрос. Однако такое понимание требуется от челове- ка, который анализирует производительность системы и должен для этого отслеживать выполнение команды на разных уровнях (то есть переходить с уровня на уровень), и следовательно, преодолевать эту изоляцию. Важно помнить, что кроме команды, полученной «свер- ху», каждый уровень использует некоторые дополнитель- ные данные, существующие непосредственно на этом уровне. На основании команды и своих собственных дан- ных, уровень формирует свое представление команды, то есть осуществляет ее «трансляцию» в свои термины. Цикл оптимизации производительности Для диагностики и оптимизации производительности при- кладного решения в общем случае необходимо выполнить как минимум три действия. Прежде всего, нужно диагно- стировать проблему. Предположим, что диагностика вы- полняется на некотором уровне X, на котором эта проблема себя проявляет. Затем нужно понять причину проблемы, то есть найти ее источник, локализовать. Пусть локализация выполняется на некотором уровне Y. В заключение нужно выполнить оптимизацию, внести определенные исправле- ния. Пусть это происходит на уровне Z. Особенность описанного процесса заключается в том, что уровни X, Y и Z, как правило, не совпадают, а уровень Z к тому же приходится выбирать из нескольких возможных. Рассмотрим простой пример. Допустим, что пользователь недоволен тем, что у него недостаточно быстро проводится документ. Это диагностирование проблемы на уровне 1 — уровне пользовательского интерфейса (рис. 18.35). Причиной медленной работы документа может являться, например, то, что в ходе выполнения запроса SQL Server составляет неправильный план запроса. Таким обра- зом, локализация проблемы выполняется на уровне 4 (рис. 18.36). Управлять тем, как SQL Server составляет план запроса, мы не можем, поэтому необходимо изменить текст запро- са ЮПредприятия таким образом, чтобы SQL Server стал составлять правильный план запроса. Это оптимиза- ция на уровне 2 (рис. 18.37).
Автоматизируемые процессы предприятия Уровень О Уровень 1 Автоматизированное рабочее место Диагностика недостаточно быстро Уровень х проводится документ Уровень 3 Уровень 4 Конфигурация Платформа 1С Предприятия СУБД Операционная система и оборудование Уровень б -------------------------------------- Рис. 18.35. Диагностика на уровне пользовательского интерфейса Уровень О Автоматизируемые процессы предприятия Автоматизированное рабочее место Уровень X Уровень 1 Конфигурация Диагностика недостаточно быстро проводится документ Уровень 2 Платформа 1 С: Предприятия Уровень 3 СУБД Уровень Y Уровень 4 Локализация SQL Server 2000 составляет неправильный план запроса Операционная система и оборудование Уровень б --------------------------—------------ Рис. 18.36. Локализация на уровне СУБД Уровень 1 Автоматизируемые процессы предприятия Автоматизированное рабочее место Уровень X Диагностика недостаточно быстро проводится документ Конфигурация Уровень Z Оптимизация изменить текст запроса Уровень 2 Уровень 3 Платформа 1С Предприятия СУБД Уровень Y Уровень 4 Локализация SQL Server 2000 составляет неправильный план запроса Операционная система и оборудование Уровень 5 --------------------------------------- Рис. 18.37. Оптимизация на уровне конфигурации
Ключевым моментом оптимизации производительности прикладного решения является то, что три перечислен- ные этапа, — диагностика, локализация и оптимизация — выполняются последовательно, в цикле, до тех пор, пока не будет получен требуемый или ожидаемый результат (рис. 18.38). Рис. 18.38. Цикл оптимизации производительности Независимо от того, на каком логическом уровне произ- водится оптимизация, цикл выполняемых действий все- гда будет одним и тем же. Первоначально выполняется сбор данных, которые слу- жат отправной точкой для начала процесса оптимизации. Затем выполняется анализ этих данных и выявляются узкие места системы. После того, как узкие места выявлены, необходимо их ранжировать, то есть определить, какие из этих узких мест влияют на снижение производительности больше, а какие — меньше. Сначала следует оптимизировать те места, которые оказывают наиболее сильное влияние на снижение производительности. Можно сказать, что здесь работает правило 20/80: 20% усилий по оптимизации дают 80% прироста производительности. Поэтому лучше потратить силы на устранение двух наиболее узких мест и получить 80% прирост производительности, чем опти- мизировать 8 «мелких» и получить прирост производи- тельности всего на 20%. Найденные узкие места системы обрабатываются после- довательно, одно за другим. Это связано с тем, что после устранения очередного узкого места необходимо оценить, какое влияние оказали на систему выполненные измене- ния. Нет гарантии, что производительность системы обя- зательно улучшится. Она, например, может не изменить- ся, или даже ухудшиться. Дело в том, что некоторые способы оптимизации имеют свою «цену» — улучшение производительности в одном месте достигается за счет ухудшения ее в другом. Например, создание индекса уве- личивает скорость чтения данных и в то же время замед- ляет скорость их записи. Поэтому если внести в систему сразу большое количество изменений («устранить» сразу несколько узких мест), то очень сложно будет опреде- лить, какое же из внесенных изменений дало негативный эффект. Итак, для каждого узкого места выполняется его локали- зация, то есть определяется, какой элемент системы при- водит к снижению производительности. После того как «виновный» определен, принимается решение о том, ка- ким образом и на каком логическом уровне вносить изме- нения. Как уже говорилось выше, этот выбор далеко не всегда бывает однозначным и, что не менее важно, не всегда его можно реализовать. Например, в результате анализа может оказаться, что единственным способом решения данной проблемы является модернизация оборудования, на которую в данный момент нет средств. В таком случае работа с данным узким местом завершается и переходят к следующему. Если же оптимизация возможна, то вносятся соответст- вующие изменения и после этого снова выполняется сбор данных для того, чтобы определить, насколько измени- лось поведение системы. Как уже говорилось, нет 100 % гарантии, что производительность улучшится. Если про- изводительность не изменилась или ухудшилась, необходи- мо понять причину. Возможно, узкое место было определе- но неправильно. Возможно, узкое место ликвидировано, но внесенные изменения оказали отрицательное влияние на другие элементы системы. Если же в результате внесенных изменений произво- дительность улучшилась, необходимо оценить степень улучшений. Возможно, что требуемый уровень произво- дительности достигнут и этого достаточно для решения поставленных задач. В этом случае ликвидацию осталь- ных узких мест можно провести позже. Если производительность улучшилась, но не достигла требуемого уровня, следует перейти к следующему узко- му месту и повторить весь цикл еще раз. Два вида проблем с производительностью Говоря о проблемах производительности, следует разли- чать два вида этих проблем: недостаточная производи- тельность системы и неоптимальная работа системы. Диагностирование проблем недостаточной производитель- ности системы возможно только при сопоставлении про- изводительности системы на уровне 1 (автоматизирован- ное рабочее место) с требованиями уровня 0 (автомати- зируемые процессы предприятия). Дело в том, что только на уровне 0 существуют объективные критерии оценки производительности. А именно: производительность сис- темы должна быть достаточной для того, чтобы обеспе- чить выполнение требований бизнес-логики. Например, регламентная операция, которая должна выполняться ежедневно, не должна длиться более чем 24 — Продол- жительность рабочего дня> часов. Или проведение доку- мента не может занимать больше времени чем: Продол- жительность рабочего дня>/<количество документов в день> — <время ручного ввода документам На остальных уровнях можно диагностировать только признаки неоптимальной работы системы. Эти признаки не могут однозначно свидетельствовать о недостаточной производительности, поскольку четких критериев на этих уровнях не существует. Но они могут говорить, на- пример, о возможности оптимизировать систему, то есть повысить ее производительность. Кроме этого, они могут говорить о потенциальной опасности того, что со време- нем проблема перейдет в первую категорию и станет при- чиной неработоспособности системы. Это может про- изойти при любом изменении ситуации, в том числе, например, при масштабировании системы (то есть при
увеличении числа одновременно работающих пользовате- лей или размера информационной базы), при изменении аппаратной конфигурации системы или при перераспреде- лении нагрузки с одних функций системы на другие. Поэтому не следует пренебрегать проблемами, связанны- ми с неоптимальной работой системы. Сегодня они могут не оказывать влияния на работу системы, но проявятся при ее изменении или дальнейшем развитии. Следует проводить периодический мониторинг этих проблем, оценивать степень их критичности и принимать решение относительно необходимости их исправления. Общие сведения об оптимизации производительности Прежде чем перейти к подробному рассмотрению опти- мизации производительности на различных уровнях при- кладного решения, сформулируем общий подход к реше- нию вопросов производительности: ♦ оптимизация производительности прикладного реше- ния возможна на различных уровнях; ♦ большая часть проблем решается при помощи: следования рекомендациям по выбору оборудования; следования рекомендациям и стандартам разработки; нагрузочного тестирования в процессе разработки; оптимизации алгоритмов на уровне конфигурации; ♦ в редких случаях требуется оптимизация производи- тельности на уровне СУБД; ♦ оптимизация производительности на уровне СУБД до- вольно сложна и требует специальных знаний. Теперь рассмотрим каждый из перечисленных пунктов подробнее, чтобы описанный подход к оптимизации про- изводительности стал полностью понятен. Следование рекомендациям Как ни странно, но большого количества проблем произ- водительности можно избежать, просто следуя рекомен- дациям. Это касается и выбора оборудования, и написа- ния прикладного кода, и собственно самой разработки прикладного решения. Рекомендации по выбору оборудования опубликованы в открытом разделе сайта v8.lc.ru (http://v8.lc.ru/overview/ recomendations.htm). Естественно, эти рекомендации яв- ляются базовыми и не могут использоваться как «истина в последней инстанции». Нужно анализировать особен- ности каждого конкретного внедрения и вносить соответ- ствующие коррективы... Однако следование этим реко- мендациям позволит в большинстве случаев избежать серьезных проблем с производительностью оборудования. Рекомендации и стандарты разработки также опублико- ваны на сайте V8, но в разделе, доступном партнерам. Кроме того, большое количество материалов, описываю- щих методику и особенности использования тех или иных механизмов платформы, публикуются в информационно- технологическом сопровождении (ИТС). Следование стандартам разработки и методически правильное ис- пользование механизмов платформы также позволяет избежать многих проблем на этапе разработки конфигу- рации и написания прикладного кода. Нагрузочное тестирование Нагрузочное тестирование является наиболее эффектив- ным способом оптимизации производительности при- кладного решения и дает наиболее понятные конечному пользователю результаты. Нагрузочное тестирование по- зволяет провести сразу несколько важных исследований. Прежде всего это исследование производительности. На- грузочное тестирование позволяет оценить, как будет вести себя система в определенных условиях, под опреде- ленной нагрузкой. То есть проведя нагрузочное тестиро- вание, мы можем сказать, что на таких компьютерах, при таком количестве пользователей и с таким объемом дан- ных расчет заработной платы, например, будет выпол- няться за такое количество времени, отчет об остатках будет формироваться столько-то минут, а при одновре- менном вводе приходной накладной таким-то количест- вом пользователей она будет проводиться столько-то се- кунд без возникновения конфликта блокировок. Также нагрузочное тестирование позволяет провести ис- следование масштабируемости системы. Исследование масштабируемости имеет важное значение, поскольку дает ответ, например, на следующие вопросы: ♦ при каком максимальном количестве пользователей система будет обеспечивать приемлемый уровень про- изводительности; ♦ какой максимальный объем данных сможет обрабаты- вать система на существующем оборудовании; ♦ как увеличится производительность системы при мо- дернизации аппаратных средств (увеличении памяти, увеличении числа процессоров); ♦ когда при текущем росте бизнеса клиента понадобится модернизация аппаратных средств. Результаты исследования производительности и масштаби- руемости, безусловно, важны для конечного пользователя, но еще более важны они для разработчика. Анализируя эти результаты, разработчик имеет возможность определить узкие места прикладного решения и оптимизировать их. Оптимизация на уровне конфигурации Как уже говорилось, следование рекомендациям и стан- дартам разработки позволяет избежать многих проблем с производительностью, однако ни один стандарт не может учесть все возможные ситуации. Поэтому оптимизация на уровне конфигурации также является одним из важ- ных этапов оптимизации производительности приклад- ного решения. Кроме того, подавляющее большинство уз- ких мест, выявляемых при нагрузочном тестировании, оптимизируются именно на уровне конфигурации. Оптимизация производительности на уровне СУБД Случаи, когда может потребоваться оптимизация произ- водительности на уровне СУБД, редки.
Во-первых, вести речь об оптимизации на уровне СУБД можно только в клиент-серверном варианте работы, по- скольку в файловом варианте используется собственный движок базы данных ЮПредприятия не нуждающийся, и не имеющий инструментов для оптимизации. Файло- вый вариант работы ЮПредприятия рассчитан на персо- нальную работу одного пользователя или работу неболь- шого количества пользователей в локальной сети. В этом случае, как правило, объем обрабатываемых данных не- велик, и производительность файловой базы данных ЮПредприятия вполне достаточна для эффективной ра- боты прикладного решения. Во-вторых, в 90% случаев достаточно правильно настро- ить выполнение регламентных операций на сервере баз данных для того, чтобы решить проблемы с его неэффек- тивной работой. Оптимизация на уровне СУБД, требующая специальных знаний Оптимизация производительности на уровне СУБД — кропотливое и непростое дело, требующее хорошего зна- ния принципов работы SQL Server и уверенного владе- ния такими инструментами, как SQL Profiler, SQL Query Analyzer и Index Tuning Wizard. Поэтому заниматься та- кой оптимизацией рекомендуется тогда, когда это дейст- вительно оправдано реальными задачами, например, при разработке оригинального тиражного прикладного реше- ния, рассчитанного на работу под серьезной нагрузкой (большое количество конкурирующих пользователей, большие объемы данных и пр.). Оптимизация производительности на уровнях автоматизируемых процессов предприятия и автоматизированных рабочих мест Проблемы недостаточной производительности системы могут диагностироваться только на уровнях 0 и 1 (авто- матизируемые процессы предприятия, автоматизирован- ное рабочее место). При отсутствии полноценного нагру- зочного тестирования приложения есть опасность, что большая часть таких проблем проявится только во время эксплуатации приложения в реальных условиях. Цена вопроса в этом случае может быть существенно выше, чем при обнаружении проблемы во время разработки системы. Диагностика проблем производительности на уровне 0 и 1 является наиболее плодотворным подходом к опти- мизации прикладного решения и заключается в нагрузоч- ном тестировании системы. Нагрузочное тестирование является методом, при кото- ром тестовые задания имитируют нагрузку на инфор- мационную систему, подобную той, которая создается реальными пользователями. Нагрузочное тестирование преследует следующие цели: определение нагрузочной способности системы, исследование масштабируемости системы и обнаружение и устранение узких мест. Нагрузочное тестирование позволяет оценить поведение системы в различных режимах работы. Например, режим работы, при котором ресурсы используются на 80 и более процентов, принципиальным образом отличается от обыч- ного режима работы. Это позволяет выявить узкие места и ошибки, которые в обычных условиях не проявляют себя. В двух словах, нагрузочное тестирование заключается в том, что с помощью определенных тестовых инструмен- тов реализуется один и тот же сеанс тестирования с опре- деленным шагом увеличения интенсивности нагрузки от реализации к реализации. Увеличение интенсивности нагрузки может заключаться, например, в увеличении количества пользователей или увеличении объема обрабатываемых данных. Таким об- разом, имея некоторые фиксированные показатели быст- родействия системы (например, время отклика системы или время выполнения одной или ряда операций), можно определить предельно допустимое количество одновре- менно работающих пользователей или предельный объем обрабатываемой информации. Тестовые задания, как правило, имитируют основные сценарии работы пользователей в наиболее критичных, с точки зрения производительности, вариантах работы системы. Например, это многопользовательская работа или выполнение регламентных операций с базой данных. Одним из вариантов, который используется наиболее часто для целей тестирования, является ввод и проведе- ние документов в различных режимах, из которых самым критичным в плане производительности является много- пользовательский режим. Основным критерием оценки производительности в этом режиме является пропускная способность системы — ко- личество документов (или строк документов), обработан- ных системой в единицу времени. Процесс нагрузочного тестирования состоит из несколь- ких этапов. Описание модели Прежде всего описывается модель системы. Модель сис- темы включает в себя несколько составляющих. Требования к системе — требования к системе определя- ют те действия, которые должна выполнять система. Критерии работоспособности — критерии работоспособ- ности определяют те пределы, в которых функциониро- вание системы считается нормальным. Пределы масштабируемости — параметры, описывающие возможное изменение системы с течением времени, на- пример, что количество пользователей системы должно увеличиться в два раза в течение года. Формирование исходных данных Исходя из созданной модели системы генерируется тес- товая база с заданными параметрами. Тестовая база должна быть максимально похожа на реальную базу дан- ных, которая будет существовать, например, через какой- то промежуток времени.
Существует ряд моментов, на которые нужно обратить внимание при формировании тестовой базы. Учет особенностей тестируемых режимов При формировании исходных данных следует учитывать особенности тестируемых режимов, производительность которых планируется оценивать. Например, очень часто используется довольно прямолинейный подход, когда бе- рется демонстрационная конфигурация и прямо на ней выполняется тестирование. Другим, не менее распро- страненным случаем, является размножение некоторых документов (или одного документа) копированием и дальнейшая попытка получить какие-то данные о произ- водительности и на их основании принять решение о том, какое оборудование необходимо, или о том, подходит ли данная система вообще или нет. Очевидно, что приведенные примеры никоим образом не учитывают какую-либо специфику и особенности ре- жимов, которые предполагается тестировать, а значит, не- возможно говорить о достоверности результатов, полу- ченных в результате такого тестирования. Они могут оказаться как заниженными, так и завышенными, что одинаково плохо, поскольку не дает оценить реальную ситуацию. Перечислим особенности, которые обязательно должны быть учтены при подготовке исходных данных для любо- го тестирования. Период тестовых данных Прежде всего, следует обеспечить, чтобы период, за кото- рый сформированы тестовые данные, охватывал бы пол- ный технологический цикл тестируемого прикладного решения. Типичной ошибкой является формирование всех тестовых данных одним днем. Такой подбор тесто- вых данных может серьезно повлиять на то, какой план запроса, например, будет выбран SQL Server при выпол- нении запроса 1С:Предприятия, в результате чего данные тестирования не будут отражать реальной картины. Движения по всей номенклатуре Другой важной особенностью является необходимость формирования движений по всей номенклатуре. Если, например, тестовые данные получены простым копирова- нием одного и того же документа, то очевидно, что такие данные никак не помогут получить реальную картину ра- боты прикладного решения, а лишь серьезно исказят ее. В результате, например, блокировки SQL Server, возни- кающие в процессе тестирования, будут значительно от- личаться от тех, которые возникают при реальной работе (чем меньше данных, тем больше вероятность возникно- вения конфликтов блокировок). Распределение данных Также необходимо заботиться о том, чтобы распределе- ние тестовых данных отражало реальный документооборот предприятия. Это касается как «разнообразия» докумен- тов, так и их количества. Использование недостаточного объема тестовых данных особенно сильно влияет на рабо- ту в клиент-серверном варианте. Те операции, которые быстро выполняются на малых объемах данных, могут существенно медленнее выполняться при больших объе- мах данных. Расчет итогов Немаловажное значение имеет также необходимость рас- чета итогов за весь используемый при тестировании период. Пересчет итогов, выполняемый в процессе тести- рования, может существенно исказить результаты, по- скольку, например, при построении отчетов за прошед- шие периоды остатки будут получаться дольше. Выполнение регламентных операций Следует также не забывать о том, что до начала тестиро- вания должны быть выполнены все необходимые регла- ментные операции (например, проведение по партиям, расчет себестоимости и пр.). Регламентные операции с базой данных После того как исходные данные сформированы, следует обратить внимание на саму базу данных и выполнить в ней требуемые регламентные операции для того, чтобы приблизить ее к состоянию реальной базы данных. Прежде всего необходимо выполнить дефрагментацию файлов базы данных. Дело в том, что процесс формирова- ния тестовых данных довольно длительный и интенсив- ный с точки зрения модификации данных. Поэтому в ре- зультате этих действий создается база данных достаточно большого объема и велика вероятность фрагментации файлов базы данных. Если этого не сделать, то некоторые файловые операции могут быть существенно замедлены. Также необходимо переиндексировать таблицы базы дан- ных. В процессе формирования тестовых данных выпол- няется активное массированное добавление информации в базу данных, и существующие индексы уже не отра- жают реальное распределение данных в таблицах базы. Несмотря на то что SQL Server имеет средства для авто- матического поддержания актуальности статистики рас- пределения данных в индексах, при интенсивной моди- фикации данных этих средств оказывается недостаточно, так как статистики рассчитываются в свободное время, которого может не быть из-за сильной загрузки SQL Server. В результате может сложиться ситуация, когда выполнение тестов будет осуществляться исходя из уста- ревшей информации об индексах, что приведет к замед- лению работы. Кроме этого, необходимо также обновить статистическую информацию, используемую SQL Server при выполнении запросов. Если этого не сделать, то оптимизатор SQL Server может, например, использовать неоптимальный план при выполнении запросов, что приведет к увеличе- нию времени выполнения операции и количества блоки- ровок. Сценарий тестирования Следующим шагом в подготовке нагрузочного тестирова- ния является создание сценария тестирования. Сценарий тестирования описывает способы, виды и критерии тес- тирования для всех требований, а также необходимые ре- сурсы и порядок выполнения тестирования. Он включает в себя несколько составляющих: Во-первых, это описание виртуальных пользователей, имитирующих работу реальных пользователей сис- темы.
Во-вторых, это действия виртуальных пользователей (например, создание документов, выполнение отчетов и т. д.). В-третьих, это описание показателей производительно- сти, измеряемых во время выполнения действий. Как правило, используются два основных показателя произ- водительности: время выполнения действия и относи- тельное время выполнения действия (время выполнения в пересчете на единицу информации). Например, если го- ворить о проведении документа расчета зарплаты, то кро- ме собственно абсолютного времени проведения доку- мента, особенно интересно знать и относительное время проведения документа (в пересчете на одного работника). В-четвертых, сценарий тестирования содержит описание критериев для каждого показателя производительности, то есть диапазона значений, в котором показатель счита- ется «нормальным». Эти критерии должны определяться, в первую очередь, бизнес-логикой приложения. Напри- мер, при определении критериев выполнения некоторой регламентной операции нужно исходить из того, что дли- тельность этой операции не может превышать 12-14 ча- сов, так как она должна выполняться каждый день в ноч- ное время. В противном случае операция просто не будет выполнена к началу следующего рабочего дня. Также не менее важным моментом при определении кри- териев показателей производительности является то, что относительное время выполнения действия на одной и той же базе не должно увеличиваться при изменении не- которых факторов. Например, может наблюдаться такая ситуация, что для небольшого документа относительное время выполнения невелико, а для большого документа оно вдруг увеличивается. Это говорит о том, что налицо явная неоптимальность в работе системы. При нормаль- ной ситуации с производительностью относительное вре- мя выполнения документа должно уменьшаться или, в крайнем случае, не изменяться при увеличении объема документа. Это справедливо для тех объемов документов, которые реально используются. Возможно, на очень больших объемах, которые в реальной жизни никогда не используются, относительное время выполнения будет увеличиваться, но все равно это увеличение должно быть плавным, а не резким. Другим важным моментом для определения критериев производительности является то, что относительное вре- мя выполнения действия должно увеличиваться незначи- тельно, с ростом самой базы данных. То есть некий рост, конечно, наблюдаться должен, но непропорциональный росту объема базы данных. Например, при росте базы данных в 100 раз производительность расчета уменьшает- ся в 2 раза — это вполне нормальная ситуация. Выбор параметров нагрузки Следующий аспект нагрузочного тестирования, на кото- рый хотелось бы обратить внимание, — это правильный выбор параметров нагрузки. При моделировании нагруз- ки следует учитывать ограничения используемого для этих целей оборудования и не запускать слишком боль- шого количества сессий на одном компьютере. Как пра- вило, практически невозможно разработать некий сце- нарий тестирования, посадить за компьютеры большое количество пользователей и провести тестирование. Это очень сложный и плохо воспроизводимый процесс. По- этому для целей нагрузочного тестирования, как правило, используется несколько рабочих станций, на которых за- пускаются нагрузочные сессии. Поэтому для определе- ния допустимого количества сессий для одного компью- тера следует использовать стандартные методики оценки загруженности оборудования, о которых подробнее мож- но прочитать в разделе «Оптимизация производительно- сти на уровне оборудования», с. 729. Если этот момент не проконтролировать, то нагрузка, создаваемая этими сес- сиями, будет существенно ниже планируемой, что приве- дет к завышенной оценке производительности системы. При выборе параметров нагрузки следует учитывать, что количество активных сессий, создающих эту нагрузку, является существенным фактором при проведении тести- рования. В общем случае, одно и то же количество документов, проведенных десятью сессиями, создаст существенно мень- шую нагрузку на систему, чем то же количество докумен- тов, но проведенное ста сессиями. В случае ста сессий значительную роль в уменьшении пропускной способно- сти будут играть блокировки. Также следует учитывать, что частота ввода и проведе- ния, например, документов одной сессией должна отра- жать реальное время, затрачиваемое пользователем на эту операцию. Учет этого фактора особенно важен при тестировании производительности в многопользователь- ском режиме. Без учета этого фактора смоделированная нагрузка на систему может оказаться существенно выше, чем реальная, что приведет к получению неверных ре- зультатов и, как следствие, неверной оценке произво- дительности системы или формированию завышенных требований к производительности используемого обору- дования Следующим важным фактором для формирования пара- метров нагрузки является то, что выбор состава таблич- ной части документов, используемых при тестировании, существенно зависит от целей тестирования. При оценке производительности оборудования необходимо выбирать неконкурирующий состав табличной части документа, поскольку в противном случае блокировки могут не по- зволить оценить реальную производительность исследуе- мого оборудования. Нагрузка на оборудование будет су- щественно ниже планируемой. Для оценки производительности системы в условиях, максимально близких к реальным, состав и объем таблич- ной части документа и его реквизитов должен подбирать- ся таким образом, чтобы соответствовать среднестатисти- ческому документу, использующемуся для подобных задач. Однако не следует всегда подбирать состав табличной части документа случайным образом, поскольку это не позволит повторить этот тест в тех же условиях для срав- нения производительности системы на разных видах обо- рудования. В то же время, если тест должен быть реали- стичен, то, напротив, в данных должен быть элемент случайности, который есть в реальной работе предпри- ятия. Выбор условий тестирования Выбор оборудования для проведения нагрузочного тес- тирования может оказать существенное влияние на ре- зультаты. Необходимо выбирать максимально сбаланси-
рованное по производительности отдельных подсистем оборудование, так как наличие узкого места не позволит получить реальной оценки производительности приклад- ной системы Производительность используемого оборудования долж- на соответствовать масштабу исследуемой системы и уров- ню создаваемой нагрузки. Например, использование мало- мощных компьютеров в качестве серверов недопустимо. При проведении тестирования необходимо контролиро- вать ключевые показатели загруженности основных под- систем используемого оборудования, чтобы иметь воз- можность правильно оценить полученные результаты. Например, если целью тестирования является выбор обо- рудования, то эта информация поможет определить узкое место и скорректировать требования к производительно- сти оборудования. Если же целью тестирования является оценка производи- тельности и масштабируемости всей системы, то эта ин- формация позволит правильно оценить полученные ре- зультаты. Приведем простой пример: предположим, что при увеличении количества пользователей, вводящих документы, время проведения документа увеличилось. Если при этом степень загрузки оборудования далека от предельной и не увеличивается, то проблема, скорее все- го, кроется в прикладном решении — блокировки не до- пускают параллельного выполнения операций, и увели- чение мощности оборудования не решит проблему. Если же какая-либо из подсистем используемого оборудова- ния перегружена, то масштабируемость системы ограни- чена производительностью используемого оборудования, и для решения проблемы необходима модернизация этой подсистемы. Выполнение тестов и сохранение результатов После того как подготовлены все необходимые инстру- менты для проведения нагрузочного тестирования, мож- но приступать собственно к выполнению тестов. Для этого, как правило, используются различные обработки, кото- рые запускаются на нескольких компьютерах в рамках локальной сети. В заключение тестирования следует сохранить и проана- лизировать значения показателей производительности, полученные во время тестирования. Оптимизация производительности на уровне конфигурации Оптимизация производительности на уровне конфигура- ции (уровень 2) заключается в основном в визуальном контроле прикладного кода. Как уже говорилось ранее, следование рекомендациям и стандартам разработки по- могает избежать многих проблем с производительностью на этом уровне. Однако в дополнение к этому можно провести, при необ- ходимости, и дополнительную оптимизацию производи- тельности. Для локализации проблем производительно- сти на уровне конфигурации используются два основных инструмента: режим замера производительности ЮПред- приятия и журнал регистрации. Подробнее о том, как использовать эти инструменты, рассказано в разделах «Режим замера производительности ЮПредприятия», с. 736, и «Журнал регистрации ЮПредприятия», с. 734. Симптомы проблем с производительностью на этом уровне следующие: неоправданно большое время выполнения отдельных операций, сообщения об ошибках (timeout и deadlok) и большое время отклика системы. В качестве примерного сценария оптимизации произво- дительности существующего прикладного решения мож- но привести следующие рекомендации по настройке параллельности работы пользователей и производитель- ности прикладного решения в целом. Оптимизация параллельности работы пользователей с прикладным решением Рассмотрим последовательность действий, которую необ- ходимо предпринять для того, чтобы обеспечить макси- мальную пропускную способность прикладного решения при параллельной работе пользователей. Выделить оперативные данные При оптимизации прикладного решения с точки зрения параллельности работы пользователей следует понимать, что пропускная способность системы уменьшается, когда увеличивается продолжительность и количество блоки- ровок, накладываемых на данные. Это происходит в ос- новном при модификации каких-либо данных. Таким образом, прежде всего, необходимо выделить те виды информации, которые будут вводиться одновремен- но большим количеством пользователей. Как правило, это будут один или несколько документов, которые чаще всего используются при одновременной работе большого количества пользователей. Именно этим документам, а точнее действиям, выполняемым при проведении этих документов, следует уделить основное внимание. Убедиться, что бизнес-логика проведения документа содержит только оперативные операции Для каждого из выбранных документов следует провести анализ действий, выполняемых при проведении, и убе- диться, что выполняются только те действия, которые НЕОБХОДИМО выполнить. Надо отдавать себе отчет в том, что «нельзя объять необъ- ятного». При конкретных характеристиках используемо- го оборудования и производительности технологической платформы всегда существует предел в составе и количе- стве действий, которые можно выполнить при проведе- нии документа, если документы проводятся одновремен- но некоторым количеством пользователей. Поэтому чаще всего приходится искать компромисс между функцио- нальностью операций и пропускной способностью систе- мы в оперативном режиме. В данном случае под оперативным режимом понимается не режим оперативного проведения документа, а работа пользователя «в данный момент, прямо сейчас». В отли- чие от оперативного режима, регламентный режим под-
разумевает выполнение действий не «прямо сейчас», а позже, в моменты минимальной нагрузки на систему (например, когда с системой работает небольшое количе- ство пользователей, или, например, в ночное время, когда работающих пользователей нет совсем). Подход к проектированию прикладных решений, рассчи- танных на одновременную работу большого количества пользователей, в корне отличается от разработки неболь- ших решений, рассчитанных на одновременную работу нескольких человек. Для внедрений с небольшим количеством одновременно работающих пользователей или небольшим документо- оборотом, в общем случае, не требуется обеспечение мак- симальной пропускной способности. На первый план вы- ходят задачи обеспечения требуемой функциональности операций, максимально комфортной работы пользовате- лей и минимизация административных действий с систе- мой. В таких решениях увеличение функциональности операций, которые выполняются в оперативном режиме, не приводит к неприемлемому увеличению времени вы- полнения этих операций. Основным критерием, который ограничивает объем используемых регламентных опера- ций, в этом случае служит сохранение приемлемого вре- мени выполнения этих операций. Для внедрений с большим количеством одновременно работающих пользователей или большим документообо- ротом основным критерием становится обеспечение мак- симальной пропускной способности системы. На первое место выходят критерии обеспечения требуемой произ- водительности, а не «бухгалтер хочет видеть проводки». Здесь необходимо максимально снизить нагрузку на сис- тему при выполнении операций в оперативном режиме, максимально уменьшить время выполнения операций. Все, что может увеличить длительность операции, следу- ет выносить за рамки оперативного режима и выполнять в период минимальной активности пользователей. Например, в оперативном режиме выполнять проведение только по регистрам управленческого учета, а по регист- рам бухгалтерского и налогового учета — регламентной обработкой, во время минимальной активности пользова- телей. Следует отметить, что «отложенные» расчеты являются общепринятым способом обеспечения требуемых пара- метров производительности в оперативном режиме, ис- пользуемым в аналогичных системах других производи- телей. Все внимание уделить оперативному режиму Итак, предположим, что разделение на оперативные и регламентные операции выполнено. Теперь нужно про- анализировать, какие действия выполняются в оператив- ном режиме. Далее будут представлены обзорные сведения, которые помогают выполнить такой анализ. Эти сведения носят упрощенный характер и не охватывают абсолютно все си- туации, возникающие при параллельной работе пользо- вателей. Прежде всего, для анализа параллельности работы поль- зователей нужно понимать, что параллельность заканчи- вается там, где две или более сессий 1С:Предприятия пы- таются с одними и теми же данными одновременно вы- полнить операции, блокирующие друг друга. Таких операций немного, это: ♦ чтение вне транзакции; ♦ чтение в транзакции; ♦ чтение с опцией ДЛЯ ИЗМЕНЕНИЯ; ♦ запись. В сводном виде информация о блокировках, возникаю- щих при одновременном выполнении операций над одни- ми и теми же данными, представлена в табл. 18.3. Таблица 18.3. Возможность выполнения совместных действий над данными Сессия 2 Чтение вне транзакции Чтение в транзакции Чтение ДЛЯ ИЗМЕНЕНИЯ Запись Сессия 1 Чтение вне транзакции + + + + Чтение в транзакции + + + - Чтение ДЛЯ ИЗМЕНЕНИЯ + + - - Запись + - - - Из представленной таблицы видно, что чтение данных вне транзакции не блокирует другие операции. Чтение данных в транзакции блокирует запись этих же самых данных другой сессией. Чтение с опцией ДЛЯ ИЗМЕНЕНИЯ блокирует чтение этих данных с опцией ДЛЯ ИЗМЕНЕННИЯ и их запись. И наконец, запись данных блокирует все опе- рации, кроме нетранзакционного чтения их другой сессией. В части, касающейся чтения данных, эта информация очень важна при анализе запросов, выполняемых в опера- тивном режиме, так как при этом разработчик знает те поля и таблицы, к которым он обращается. Что касается записи данных, эта операция в 1 (^Предпри- ятии может быть выполнена только в объектной технике. Как видно из приведенной выше таблицы, невозможно одновременно модифицировать одни и те же записи таб- лиц базы данных. Сложность состоит в том, что на при- кладном уровне разработчик оперирует не понятиями за- писей таблиц, а понятиями объектов встроенного языка, объектов конфигурации и их реквизитов. Различные объ- екты конфигурации создают разные структуры таблиц для хранения своих данных и используют разные алго- ритмы их заполнения. По этой причине разные объекты конфигурации допускают различную параллельность при записи объектов встроенного языка, модифицирую- щих их данные. Например, два разных элемента справочника Номенклату- ра всегда могут быть записаны параллельно, в то время как два набора записей регистра бухгалтерии, принадле-
жащие различным регистраторам, допускают параллель- ную запись не всегда. Сразу следует оговориться, что речь идет о клиент-сер- верном варианте работы. В файловом варианте работы эта параллельность отсутствует, так как блокируются таблицы объектов конфигурации целиком. Для того чтобы понять, к каким именно таблицам выпол- няются обращения при работе в объектной технике, нуж- но хорошо знать структуру объектов конфигурации. Под- робнее об этом можно прочитать в соответствующих главах этой книги. Но чтобы не держать в голове структуру каждого из объ- ектов конфигурации, можно воспользоваться сводными данными о параллельности работы в различных режимах и с различными объектами конфигурации, которые при- ведены далее. Эти данные приведены в терминах при- кладных объектов и их реквизитов и расположены в по- рядке возрастания параллельности записи. Эти сведения не охватывают все ситуации, но позволяют оптимизиро- вать подавляющее число проблем, возникающих при па- раллельной работе пользователей. Последовательная запись Константа. Запись двух разных констант может выпол- няться только последовательно. Формирование сообщений обмена. Выгрузка измене- ний, зарегистрированных для некоторого объекта конфи- гурации (например, справочника Номенклатура), и моди- фикация данных этого объекта конфигурации (например, запись элемента справочника) может выполняться толь- ко последовательно. Регистр расчета (с использованием фактического пе- риода действия). Если запись наборов записей регистра расчета приводит к изменению фактического периода действия, то такие наборы могут быть записаны только последовательно. Последовательность. Документы, перемещающие грани- цу одной и той же последовательности, могут быть прове- дены только последовательно. Параллельность по набору измерений Несмотря на приведенные ниже сведения о параллельно- сти записи, в некоторых случаях возможны блокировки за счет того, что блокируются записи, соседние с диапазо- ном модифицируемых записей. Регистр бухгалтерии. Возможна параллельная запись набо- ров записей, которые не содержат записей с одинаковыми значениями периода, счета и измерений, причем под перио- дом понимается не конкретная дата, а месяц, которому при- надлежит значение периода. Например, следующие набо- ры записей могут быть записаны параллельно (табл. 18.4). Обратите внимание, что следующие наборы записей мож- но записать только последовательно, так как значения поля Период выделенных записей принадлежат одному и тому же месяцу, а значения счета и организации совпа- дают (табл. 18.5). Регистр накопления (остатков), Регистр сведений (не- зависимый непериодический). Возможна параллельная запись наборов записей, которые не содержат записей с одинаковыми значениями всех измерений (табл. 18.6). Таблица 18.4. Наборы записей, которые могут быть записаны параллельно Регистратор Период Счет Организация Набор записей 1 Регистратор! 15.10.2004 50.1 ООО «Алеф» Регистратор! 15.10.2004 62.1 ООО «Алеф» Набор записей 2 Регистратор2 15.10.2004 50.1 ЗАО «Беркут-М» Регистратор2 15.10.2004 60.1 ЗАО «Беркут-М» Таблица 18.5. Наборы записей, которые нельзя записать параллельно Регистратор Период Счет Организация Набор записей 1 Регистратор! 15.10.2004 50.1 ООО «Алеф» Регистратор! 15.10.2004 62.1 ООО «Алеф» Набор записей 2 Регистратор2 27.10.2004 50.1 ООО «Алеф» Регистратор2 27.10.2004 60.1 ООО «Алеф» Таблица 18.6. Наборы записей, которые могут быть записаны параллельно Регистратор Номенклатура Склад Набор записей 1 Регистратор! Телевизор Розничный Регистратор! Печь СВЧ Розничный Набор записей 2 Регистратор2 Телевизор Оптовый Регистратор2 Утюг Розничный Обратите внимание, что следующие наборы записей мож- но записать только последовательно, так как они содер- жат записи с одинаковыми значениями всех измерений (табл. 18.7). Таблица 18.7. Наборы записей, которые нельзя записать параллельно Регистратор Номенклатура Склад Набор записей 1 Регистратор! Телевизор Розничный Регистратор! Печь СВЧ Розничный Набор записей 2 Регистратор2 Телевизор Розничный Регистратор2 Утюг Розничный
Регистр накопления (оборотов). Возможна параллель- ная запись наборов записей, которые не содержат записей с одинаковыми значениями периода и всех измерений, причем под периодом понимается не конкретная дата, а месяц, которому принадлежит значение периода. На- пример, следующие наборы записей могут быть записаны параллельно (табл. 18.8). за счет того, что блокируются записи, соседние с диапазо- ном модифицируемых записей. Регистр расчета (без использования фактического пе- риода действия), Регистр сведений (подчиненный реги- стратору). Возможна параллельная запись наборов запи- сей, принадлежащих разным регистраторам (табл. 18.11). Таблица 18.8. Наборы записей, которые могут быть записаны параллельно Регистратор Период Номенклатура Склад Набор записей 1 Регистратор! 15.10.2004 Телевизор Розничный Регистратор! 15.10.2004 Печь СВЧ Оптовый Набор записей 2 Регистратор2 01.11.2004 Телевизор Розничный Регистратор2 01.11.2004 Утюг Розничный Таблица 18.11. Наборы записей, которые могут быть записаны параллельно Регистратор Номенклатура Склад Набор записей 1 Регистратор! Телевизор Розничный Регистратор! Печь СВЧ Розничный Набор записей 2 Регистратор2 Телевизор Розничный Регистратор2 Утюг Розничный Обратите внимание, что следующие наборы записей мож- но записать только последовательно, так как значения поля Период выделенных записей принадлежат одному и тому же месяцу, а значения номенклатуры и склада сов- падают (табл. 18.9). Таблица 18.9. Наборы записей, которые нельзя записать параллельно Регистратор Период Номенклатура Склад Набор записей 1 Регистратор! 15.10.2004 Телевизор Розничный Регистратор! 15.10.2004 Печь СВЧ Оптовый Набор записей 2 Регистратор2 27.10.2004 Телевизор Розничный Регистратор2 27.10.2004 Утюг Розничный Регистр сведений (периодический). Возможна парал- лельная запись наборов записей, которые не содержат за- писей с одинаковыми значениями периода и измерений (табл. 18.10). Таблица 18.10. Наборы записей, которые могут быть записаны параллельно Регистратор Период Номенклатура Склад Набор записей 1 Регистратор! 15.10.2004 Телевизор Розничный Регистратор! 15.10.2004 Печь СВЧ Оптовый Набор записей 2 Регистратор2 27.10.2004 Телевизор Розничный Регистратор2 27.10.2004 Утюг Розничный Параллельность по регистратору Несмотря на приведенные ниже сведения о параллельно- сти работы, в некоторых случаях возможны блокировки Полная параллельность Данные следующих объектов конфигурации могут быть записаны параллельно (например, запись двух различ- ных элементов справочника или двух различных доку- ментов): ♦ Справочник; ♦ Документ; ♦ План видов характеристик; ♦ План счетов; ♦ План видов расчета; ♦ Бизнес-процесс; ♦ Задача. Исходя из информации о параллельности работы в раз- личных режимах и с различными объектами конфигура- ции, следует, прежде всего, исключить из оперативного режима те действия, которые могут выполняться только последовательно. Если исключить такие действия невоз- можно, то следует попытаться реализовать их с использо- ванием объектов конфигурации, допускающих большую параллельность работы. После этого главное внимание следует уделить тем объ- ектам, которые допускают самую меньшую параллель- ность работы, и, в последнюю очередь, проанализировать действия с объектами, данные которых могут модифици- роваться независимо. Выполнить анализ используемых регистров Убедиться в правильности проектирования измерений Следует убедиться, что измерения регистров спроектиро- ваны правильно, то есть позволяют обеспечить парал- лельность работы, требуемую прикладной логикой. Например, если требуется, чтобы разные пользователи могли одновременно записывать данные в регистр накоп- ления для разной номенклатуры и/или разного склада, то такой регистр накопления должен иметь измерения Но-
менклатура и Склад, так как регистр накопления допускает параллельную запись наборов записей, отобранных по уникальному сочетанию значений всех измерений. По- этому если, например, регистр накопления будет иметь только одно измерение Номенклатура, то необходимой па- раллельности не удастся достичь в принципе, так как это- го не позволит сделать сама логика работы регистра накопления. Убедиться в правильности индексирования измерений и реквизитов регистра Главной особенностью получения данных из базы дан- ных является то, что при этом блокируются не те записи, которые возвращает запрос, а те, которые он обработал при обращении к базе данных. Поэтому основная опасность отсутствия подходящих ин- дексов заключается в том, что в этом случае будут блоки- роваться избыточные записи, так как из-за отсутствия индекса запрос вынужден обработать диапазон записей больший, чем следует, и затем последовательно переби- рать их, выбирая нужные. Поэтому надо проанализировать используемые запросы и убедиться, что структура регистров и варианты индек- сирования, указанные для реквизитов, соответствуют условиям используемых запросов. Для всех условий за- просов должен быть подходящий индекс. Подробнее об индексах таблиц базы данных можно прочитать в разделе «Индексы таблиц базы данных», с. 788. Для того чтобы провести такой анализ следует взять текст запроса, определить используемые таблицы и выде- лить те поля, которые используются в условиях запроса. Затем надо сравнить их с индексами, которые создает система для таблиц данного регистра. При необходимости следует создать дополнительные ин- дексы с помощью свойства Индексировать. Например, есть регистр накопления с измерениями Но- менклатура и Склад. Свойство Индексировать этих измере- ний установлено в значение Не индексировать. К этому ре- гистру выполняется следующий запрос (листинг 18.3). Листинг 18.3. Пример запроса ВЫБРАТЬ РегистрНакопленияОстатков.Период. РегистрНакопленияОстатков.Регистратор. РегистрНакопленияОстатков. ВидДвижения. РегистрНакопленияОстатков.Номенклатура, РегистрНакопленияОстатков.Остаток. РегистрНакопленияОстатков.РеквизитДвижения ИЗ РегистрНакопления.РегистрНакопленияОстатков КАК РегистрНакопленияОстатков ГДЕ РегистрНакопленияОстатков.Склад = &ВыбранныйСклад Так как для указанного регистра накопления в таблице движений будут созданы индексы Период + Регистратор + НомерСтроки и Регистратор + НомерСтроки то выполнение такого запроса приведет к тому, что будут выбраны все записи движений регистра (так как не суще- ствует подходящего индекса), а затем, путем перебора этих записей, будут получены только записи по выбран- ному складу. В результате все записи движений регистра окажутся заблокированными. Для того чтобы избежать этой ситуации, для измерения регистра Склад нужно установить свойство Индексировать в значение Индексировать. В этом случае в таблице движе- ний регистра будет создан дополнительный индекс ИзмерениеСклад + Период + Регистратор + НомерСтроки. Таким образом, при выполнении указанного запроса бу- дут заблокированы только записи, относящиеся к указан- ному складу. Аналогичным образом следует внимательно относиться и к наложению условий на измерения регистров в пара- метрах виртуальных таблиц. Для получения данных вир- туальные таблицы могут использовать итоговые таблицы регистров, которые также имеют определенные наборы индексов. Например, для регистра накопления остатков, физиче- ская таблица итогов всегда будет содержать индекс Период + Измерение! + ... + Измерением и дополнительно будут создаваться индексы Период + ИзмерениеК, если ИзмерениеК — не первое в дереве метаданных и для него свойство Индексировать установлено в значение Индек- сировать. Поэтому если требуется отбирать итоги по сочетанию значений измерений, следует помнить, что индексы будут использованы эффективно только в том случае, когда ин- декс покрывает условие, то есть с самого начала содержит без пропуска поля, на которые накладываются условия. Например, можно выполнять эффективный отбор по по- лям Период, Измерение! и Измерение?, однако отбор по по- лям Период, Измерение! и ИзмерениеЗ не будет эффектив- ным, так как не существует индекса, начинающегося с полей Период + Измерение! + ИзмерениеЗ. Если требуется получать итоги по одному измерению, ко- торое не является первым, — следует его проиндексиро- вать. Состав измерений, на которые накладываются условия, важен не только при работе с виртуальными таблицами. Например, он важен для регистра сведений, который не содержит итоговых таблиц, но индексы, создаваемые для таблицы записей этого регистра, также содержат поля из- мерений в том порядке, как они указаны в метаданных. По возможности исключить использование пустых регистров Следует избегать ситуаций, при которых регистр может оказаться пустым, но задействованным в логике опера- тивного режима работы. Пустой регистр — потенциаль- ный источник избыточной блокировки, так как при обра- щении к записям этого регистра будет блокироваться вся таблица регистра. Например, документ в оперативном режиме не выполня- ет движения по одному виду учета, но для этого докумен- та указано свойство автоудаления движений. Таким обра- зом, при проведении документа в оперативном режиме один или несколько регистров, относящихся к неисполь- зуемому виду учета, не будут содержать записей. В ре- зультате каждый раз при записи этого документа система будет выполнять обращение ко всем регистрам, по кото-
рым этот документ может делать движения (в том числе и к пустым). Таблицы пустых регистров будут блокиро- ваться целиком, что приведет к невозможности парал- лельной работы с этими документами. Поэтому если в прикладном решении существуют пустые регистры, прежде всего, нужно проанализировать необхо- димость их использования и, возможно, удалить из кон- фигурации. Если эти регистры все же должны присутствовать в кон- фигурации, то следует отключить свойство автоудаления у документов, которые могут выполнять движения по этим регистрам, и выполнять удаление движений средст- вами встроенного языка, не обращаясь к этим регистрам в случаях, когда точно известно, что документ не содер- жит движений по этим регистрам. Исключить обращение к неактуальным итогам регистров Если при работе в оперативном режиме выполняется по- лучение итоговых значений регистров на указанную дату, вместо обращения к актуальным итогам, это может при- вести к дополнительным блокировкам таблиц движений этих регистров, так как виртуальные таблицы будут ис- пользовать досчет итогов до указанной даты с исполь- зованием таблицы движений регистра. В результате окажется заблокированным диапазон записей движений регистра. Подробнее о работе виртуальных таблиц можно прочи- тать в разделах «Получение данных из регистров накоп- ления», с. 198 и «Построение виртуальных таблиц регист- ра бухгалтерии», с. 309. Использовать автоматический режим записи движений документа Если в этом нет специальной прикладной необходимости, не следует выполнять запись движений регистра в явном виде (с использованием метода Записать!) набора записей регистра) в обработке проведения. Все наборы записей движений, модифицированные на момент записи доку- мента, будут записаны автоматически при выходе из об- работчика проведения. При этом для различных доку- ментов, использующих одни и те же регистры, запись наборов записей будет производиться в одной и той же последовательности, которую обеспечивает платформа. Это позволит избежать конфликтов блокировок при про- ведении таких документов. Подробнее можно прочитать об этом в разделе «Единый порядок доступа к ресурсам», с. 725. Оптимизировать действия, выполняемые в транзакции Как уже было показано ранее, чтение, выполняемое в транзакции, устанавливает блокировки на прочитанные данные, которые не позволят модифицировать прочитан- ные записи другими сессиями. Поэтому важно мак- симально оптимизировать все действия, выполняемые в транзакции. Использовать транзакцию следует только в том случае, когда это действительно необходимо, например, когда с точки зрения бизнес-логики необходимо изолировать по- следовательность действий с данными от вмешательства со стороны параллельно работающих пользователей. При работе в транзакции следует избегать чтения ненуж- ных данных, так как все прочитанные данные будут за- блокированы от записи. Недопустимо использовать в транзакциях интерактив- ные операции, требующие ответной реакции пользовате- лей (предупреждения, вопросы и т. д.). Также очень внимательно нужно отнестись к эффектив- ности ограничений доступа, накладываемых на уровне таблиц и записей базы данных, так как они выполняются при любых обращениях к базе данных. Оптимизировать запросы После выполнения всех перечисленных действий следует выполнить оптимизацию запросов. Прежде всего нужно обратить внимание на использование опции ДЛЯ ИЗМЕНЕНИЯ, а затем выполнить рекомендации по запросам, описанные в следующем разделе («Оптимизация различных режи- мов работы прикладного решения»). Правильно использовать опцию ДЛЯ ИЗМЕНЕНИЯ Эту опцию следует использовать в тех случаях, когда вы- полняется чтение данных регистра и последующая моди- фикация данных этого же регистра. В этом случае опция ДЛЯ ИЗМЕНЕНИЯ поможет избежать конфликтов блокировок при параллельном проведении таких документов. Поэтому опцию ДЛЯ ИЗМЕНЕНИЯ следует указывать только при чтении тех таблиц, которые будут затем изменены в этой же транзакции. Не следует использовать эту опцию «на всякий случай», так как ее использование снижает параллельность обраще- ния к регистру (устанавливается блокировка на чтение). Также очень осторожно следует использовать открытую форму этой опции, без указания списка таблиц, так как в этом случае блокируются все таблицы, используемые в запросе. Подробнее об использовании опции ДЛЯ ИЗМЕНЕНИЯ можно прочитать в разделе «Использование в запросах операто- ра ДЛЯ ИЗМЕНЕНИЯ», с. 726. Оптимизация различных режимов работы прикладного решения Оптимизация производительности прикладного решения является не менее важной задачей, чем оптимизация па- раллельности работы пользователей. При этом речь идет уже не о возможности многих пользователей выполнять некоторый набор действий одновременно, а непосредст- венно о времени выполнения отдельных операций, вре- мени получения отчетов, открытия списков и т. д. При оптимизации производительности прикладного решения справедливо все, сказанное выше про оптимизацию па- раллельности работы пользователей. Дополнительно к этому следует обратить внимание также и на другие мо- менты, которые перечислены ниже. Не использовать запросы в цикле Многократное выполнение одного и того же или похожих запросов в цикле занимает гораздо больше времени, чем выполнение одного запроса, возвращающего аналогич- ную совокупность данных.
Например, в следующем фрагменте кода выполняется многократное выполнение запроса в цикле для каждого значения номенклатуры (листинг 18.4). Листинг 18.4. Пример неоптимального запроса Для Каждого Номенклатура Из МассивНоненклатуры Цикл Запрос = Новый Запрос; Запрос.Текст = " ВЫБРАТЬ РегистрНакопленияОстатковОстатки.Склад, РегистрНакопленияОстатковОстатки.ОстатокОстаток ИЗ РегистрНакопления.РегистрНакопленияОстатков.ОстаткиС , Номенклатура = 4йы'раннаяНоменклатура) КАК РегистрНакопленияОстатковОстатки” Запрос.УстановитьПараметрС'ВыбраннаяНоменклатура". Номенклатура); Результат = Запрос.ВыполнитьО; КонецЦикла; В результате запрос будет выполнен столько раз, сколько элементов содержится в массиве номенклатуры. Такой фрагмент следует переписать следующим образом (лис- тинг 18.5). Листинг 18.5. Пример оптимального запроса Запрос = Новый Запрос; Запрос.Текст = " |ВЫБРАТЬ | РегистрНакопленияОстатковОстатки.Склад. | РегистрНакопленияОстатковОстатки.ОстатокОстаток |ИЗ РегистрНакопления.РегистрНакопленияОстатков.Остатки(, j Номенклатура В (&МассивНоменклатуры)) КАК РегистрНакопленияОстатковОстатки” Запрос.УстановитьПараметрС"МассивНоненклатуры". МассивНоненклатуры); Результат = Запрос.ВыполнитьО; В результате один запрос со сложным условием отбора будет выполнен гораздо быстрее, чем несколько запросов с простыми условиями. Иногда возникает ситуация, когда требуемое условие за- проса, позволяющее отказаться от выполнения в цикле, сформулировать затруднительно или очень сложно. В этом случае как минимум нужно вынести создание запроса за пределы цикла, а в цикле изменять только па- раметры запроса. Это позволит избежать многократной синтаксической проверки текста запроса (листинг 18.6). Листинг 18.6. Пример запроса Запрос = Новый Запрос; Запрос.Текст = " ВЫБРАТЬ РегистрНакопленияОстатковОстагки.Склад. РегистрНакопленияОстатковОстатки.ОстатокОстаток ИЗ РегистрНакопления.РегистрНакопленияОстатков.ОстаткиС, Номенклатура = &ВыбраннаяНоменклатура) КАК РегистрНакопленияОстатковОстатки" Для Каждого Номенклатура Из МассивНоненклатуры Цикл Запрос.УстановитьПараметрСВыбраннаяНоменклатура". Номенклатура); Результат = Запрос.ВыполнитьО; КонецЦикла; Использовать параметры виртуальных таблиц Следует максимально использовать параметры виртуаль- ных таблиц, если это не искажает суть выполняемых дей- ствий. Например, в следующем запросе условие на отбираемые данные накладывается в секции ГДЕ (листинг 18.7). Листинг 18.7. Пример неоптимального запроса ВЫБРАТЬ Номенклатура, КоличествоОстаток ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки() ГДЕ Номенклатура = &Номенклатура Такой вариант является неоптимальным, так как сначала виртуальная таблица выберет все записи из таблицы ос- татков, а затем уже на полученную выборку будет нало- жен отбор по значению номенклатуры. Для оптимального выполнения подобного запроса следу- ет ограничивать объем выбираемых данных в самой вир- туальной таблице (листинг 18.8). Листинг 18.8. Пример оптимального запроса ВЫБРАТЬ Номенклатура, КоличествоОстаток ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки( , Номенклатура = (^Номенклатура) При этом не следует забывать о логике выполнения за- проса. Например, запрос, представленный в листинге 18.9, и за- прос, представленный в листинге 18.10, вернут различ- ные результаты. Листинг 18.9. Пример запроса ВЫБРАТЬ Валюта, Курс ИЗ РегистрСведений.КурсыВалют.СрезПоследних() ГДЕ Источник = &ВыбранныйИсточник Листинг 18.10. Пример запроса ВЫБРАТЬ Валюта. Курс ИЗ РегистрСведений.КурсыВалют.СрезПоследнихС . Источник = & ВыбранныйИсточник) Первый запрос вернет записи, в которые не попадут ва- люты, у которых последний курс установлен не по вы- бранному источнику. Во втором случае будут выбраны последние курсы всех валют, у которых хоть раз курс устанавливался по вы- бранному источнику. Подробнее о виртуальных таблицах регистра сведений можно прочитать в разделе «Получение данных из перио- дических регистров сведений», с. 123
Исключить получение поля Ссылка через точку Не следует получать поле Ссылка через точку от другого поля, так как при этом будет создаваться дополнительное соединение, которое замедлит выполнение запроса. Например, в следующем запросе поле Ссылка получается через точку от поля Контрагент (листинг 18.11). Листинг 18.11. Пример неоптимального запроса ВЫБРАТЬ РасходнаяНакладная.Дата, РасходнаяНакладная.Номер ИЗ Документ.РасходнаяНакладная КАК РасходнаяНакладная ГДЕ РасходнаяНакладная.Контрагент.Ссылка = &Контрагент В результате будет создано совершенно ненужное в дан- ном случае соединение с таблицей Контрагенты, и, как следствие, выполнение запроса замедлится. Такой запрос следует переписать следующим образом (листинг 18.12). Листинг 18.12. Пример оптимального запроса ВЫБРАТЬ РасходнаяНакладная.Дата, РасходнаяНакладная.Номер ИЗ Документ.РасходнаяНакладная КАК РасходнаяНакладная ГДЕ РасходнаяНакладная.Контрагент = &Контрагент Использовать операцию ВЫРАЗИТЬ для ограничения количества таблиц Если ссылка ссылается на несколько таблиц, то будет произведено соединение со всеми таблицами, в которых присутствует данное поле. Если ссылка является любой ссылкой, то возможно появ- ление соединений со всеми таблицами. Если четко известно, что поле составного типа является ссылкой на конкретную таблицу, то желательно исполь- зовать операцию ВЫРАЗИТЬ для ограничения количества таблиц (листинг 18.13). Листинг 18.13. Пример оптимального запроса ВЫБРАТЬ ВЫРАЗИТЬ (Продажи.Регистратор КАК Документ.РасходнаяНакладная).Номер, ВЫРАЗИТЬ (Продажи.Регистратор КАК Документ.РасходнаяНакладная).Дата, Продажи.Контрагент, П[юдажи. Сумма ИЗ РегистрНакопления.Продажи КАК Продажи ГДЕ Продажи.Регистратор ССЫЛКА Документ.РасходнаяНакладная Не использовать запросы, результатом которых могут быть очень большие выборки Использование запросов к базе данных, результат кото- рых может неограниченно расти с ростом самой инфор- мационной базы, может привести к снижению произ- водительности и повышению вероятности аварийного завершения работы. Для обработки данных потенциально неограниченного объема следует организовывать «курсорный» механизм получения результата запроса: устанавливать уникаль- ный порядок сортировки получаемых данных и получать выборки по частям с помощью оператора ПЕРВЫЕ, исполь- зуя данные последней полученной записи предыдущей выборки в качестве начального условия при получении очередной выборки. Также в этом случае можно рассмотреть возможность использования метода Выбрать О различных прикладных объектов и выполнение дополнительной фильтрации по- лученных записей в процессе обхода выборки. Исключить вывод ссылочных полей в отчет Вывод в отчет непосредственно ссылок может существен- но замедлить выполнение отчета, так как при этом будет выполняться многократное получение представлений для этих ссылочных значений. В результате вывод отчета мо- жет быть замедлен в несколько раз. Поэтому для вывода в отчет в запросе необходимо полу- чать представления ссылочных полей. При использовании построителя отчета для вывода отче- тов также необходимо обеспечить получение представ- лений в запросе, поскольку построитель не добавляет представления для полей, изначально присутствующих в выборке. Например, после выполнения следующего запроса в от- чет следует выводить поля НоменклатураПредставление и КонтрагентПредставление: (листинг 18.14). Листинг 18.14. Пример запроса ВЫБРАТЬ ПродажиКомпанииОбороты.Номенклатура КАК Номенклатура. ПродажиКомпанииОбороты.Номенклатура.Представление КАК НоменклатураПредставление, ПродажиКомпанииОбороты.ДокументПродажи.Контрагент КАК ДокументПродажиКонтрагент, ПродажиКомпанииОбороты.ДокументПродажи.Контрагент. Представление КАК КонтрагентПредставление, ПродажиКомпанииОбороты.КоличествоОборот КАК КоличествоОборот, ПродажиКомпанииОбороты.СуммаПродажиОборот КАК СуммаПродажиОборот ИЗ РегистрНакопления.ПродажиКомпании.Обороты КАК ПродажиКомпанииОбороты ИТОГИ СУММА(КоличествоОборот), СУММА(СуммаПродажиОборот) ПО ОБЩИЕ, Номенклатура. ДокументПродажиКонтрагент Исключить хранение вспомогательной информации большого объема в реквизитах документов Вспомогательную информацию не следует хранить в рек- визите самого объекта с типом Строка неограниченной длины или ХранилищеЗначения. При работе в объектной тех- нике данные объекта считываются целиком, поэтому большой объем вспомогательной информации, хранимой в реквизитах объекта, может замедлить получение объек- та из базы данных.
Для хранения подобных данных следует использовать другие объекты: подчиненные справочники или регистры сведений. Оптимизировать работу с таблицей значений В алгоритмах, в которых многократно выполняется поиск в таблице значений с большим количеством строк, реко- мендуется использовать объект ПостроительЗапроса, источ- ником данных для которого является данная таблица значений. Объекты ПостроительЗапроса и ПостроительОтчета имеют одинаковую функциональность в плане работы с внешним источником данных. Об этом можно более подробно прочитать в разделе «Использование произ- вольного источника данных», с. 464. Также следует избегать сортировки строк таблицы значе- ний по колонкам ссылочного типа — для каждого такого значения выполняется получение представления. Оптимизировать работу форм Минимизировать обращения к базе данных Основное направление оптимизации форм — минимиза- ция обращений к базе данных. Прежде всего следует об- ратить внимание на обработчики следующих событий: ♦ ОбновлениеОтображения формы; ♦ ПриВыводеСтроки табличного поля; ♦ ПриАктивизацииСтроки табличного поля. Если отказаться от выполнения неоптимальных действий невозможно, следует перенести их в обработчики других событий. Использовать кэширование данных Значения, которые изменяются относительно редко и по- лучение которых требует обращения к базе данных, мож- но хранить в переменных модуля формы. Это могут быть, например, значения, получаемые «через точку», или зна- чения констант. Например, если значение константы используется много- кратно, то не следует каждый раз получать его из базы данных (листинг 18.15). Листинг 18.15. Пример неоптимального использования Если ВалютаДокунента <> Константы.ВалютаРегламентированногоУчета.Получить() Тогда В этом случае можно считать значение константы в пере- менную модуля формы мВалютаРегламентированногоУче- та и в дальнейшем обращаться именно к ней (лис- тинг 18.16). Листинг 18.16. Пример оптимального использования Если ВалютаДокунента <> мВалютаРегламентированногоУчета Тогда Правильно использовать свойства ТекущаяСтрока и ТекущиеДанные При работе с табличным полем следует аккуратно ис- пользовать свойство ТекущаяСтрока табличного поля. Тип значения этого свойства приведен в описаниях расшире- ний табличного поля у соответствующих объектов. Для списков объектных данных это свойство содержит обыч- но ссылку на объект. Поэтому для обращения к полям, необходимым для функционирования динамических спи- сков и расширений табличного поля (таких как ЭтоГруппа, ПометкаУдаления, Проведен и т. д.), всегда следует исполь- зовать свойство ТекущиеДанные. Обращение к этим же по- лям через свойство ТекущаяСтрока будет приводить к лиш- нему чтению данных всего объекта из базы данных или из кэша. Если есть необходимость обращения к реквизитам объек- та, которые не отображаются в списке, то вместо обраще- ния к этим полям «через точку» от свойства ТекущаяСтрока лучше включить колонки со значениями данных рекви- зитов в источник данных табличного поля, отключить ав- тоудаление у нужных колонок источника данных и затем отключить видимость у соответствующих колонок таб- личного поля. В результате эти реквизиты не будут ото- бражаться в табличном поле, но к ним можно будет обра- щаться через свойство ТекущиеДанные. Не отображать ссылки в табличном поле Порой в качестве источника данных табличного поля используется таблица значений, содержащая ссылочные значения, например колонку Номенклатура. Такие колон- ки не следует напрямую отображать в табличном поле, так как система будет выполнять многократные запросы к базе данных для получения представлений отображае- мых ссылочных значений. В этом случае следует создать в таблице значений — ис- точнике данных, дополнительную колонку Представле- ниеНоменклатуры, заполнить ее в процессе заполнения са- мой таблицы значений, и в таблице значений отображать уже не ссылочное поле Номенклатура, а поле Представле- ниеНоменклатуры. Использовать событие ПриПолученииДанных Для повышения быстродействия форм следует стремить- ся использовать событие ПриПолученииДанных табличного поля, вместо события ПриВыводеСтроки. Событие ПриВыводе- Строки вызывается многократно и предоставляет данные только одной строки табличного поля, в то время как со- бытие ПриПолученииДанных вызывается один или несколько раз и предоставляет доступ к данным всех строк, отобра- жаемых табличным полем. Поэтому, например, гораздо эффективнее выполнить один запрос к базе данных для получения остатков товара по складам в обработчике ПриПолученииДанных, чем много- кратно выполнять запросы для каждой строки таблично- го поля в обработчике ПриВыводеСтроки (листинг 18.17). Листинг 18.17. Пример использования события ПриПолученииДанных Процедура СписокНоменклатураПриПолученииДанныхОлемент, ОфорнленияСтрок) Запрос = Новый Запрос("ВЫБРАТЬ ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток, ТоварыНаСкладахОстатки.Номенклатура КАК Товар |ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки( , Номенклатура В (&МассивТоваров)) | КАК ТоварыНаСкладахОстатки”); МассивНоменклатуры = Новый Массив: И для передачи в // параметр запроса Соответствие = Новый Соответствие; // для заполнения // остатков в строках // табличного поля
Для Каждого Строка из ОфорнленияСтрок Цикл МассивНоненклатуры.Добавить(Строка.ДанныеСтроки.Ссылка); Соответствие.Вставить(Строка.ДанныеСтроки.Ссылка, Строка); КонецЦикла; Запрос.УстановитьПаранетр("МассивТоваров”, МассивНоненклатуры); Выборка = Запрос.ВыполнитьО.ВыбратьО; // Вывести остаток в строку, найденную в соответствии // по ноненклатуре из запроса. Пока Выборка.СледующийО Цикл Соответствие.Получить(Выборка.Товар).Ячейки.Остаток. Значение = Выборка.Остаток; КонецЦикла: КонецПроцедуры Оптимизация производительности на уровне СУБД Локализация проблем производительности на уровне 4 (СУБД) может быть выполнена только для клиент-сер- верного варианта работы (когда используется SQL Server). В файловом варианте работы используется соб- ственный движок базы данных 1 С: Предприятия, управ- ление которым недоступно для разработчика прикладно- го решения. Оптимизацию производительности на уровне СУБД (уро- вень 4) можно условно разделить на два вида: это стан- дартная оптимизация и тонкая оптимизация. Стандартная оптимизация заключается в основном в ор- ганизации выполнения регламентных процедур SQL Server и оптимизации прикладного кода и должна про- водиться всегда (по крайней мере в части выполнения регламентных процедур). «Тонкая» оптимизация явля- ется гораздо более сложной и кропотливой задачей, ко- торая требует специальных знаний. Она должна выпол- няться в редких случаях, когда это действительно оправдано поставленными задачами. Основные принци- пы «тонкой» оптимизации описаны в разделе «Основы «тонкой» оптимизации производительности на уровне СУБД», с. 745. Стандартная оптимизация SQL Server, под управлением которого работает инфор- мационная база в клиент-серверной версии, имеет свои особенности, которые могут существенно повлиять на производительность прикладного решения. Для оптими- зации работы клиент-серверной базы необходимо про- изводить регулярные регламентные работы: обновление статистики, очистку процедурного кэша и реиндексиро- вание. Здесь следует заметить, что в ходе реиндексирова- ния будут обновляться статистики, но только частично, по тем полям, по которым построены индексы. В общем случае SQL Server может рассчитывать статистики не только по индексированным полям, поэтому обновление статистики рекомендуется выполнять дополнительно от- дельным действием. Обновление статистики и очистка процедурного кэша При массированном вводе новых данных следует забо- титься о том, чтобы сервер как можно чаще обновлял ста- тистику. Для этого необходимо выполнить следующий запрос: exec sp msforeachtable N'UPDATE STATISTICS ?' Например, можно создать работу (JOB), которая выпол- няла бы этот запрос каждые два часа. Выполнение данно- го запроса не блокирует таблицы базы данных и не при- ведет к заметному падению производительности работы пользователей системы. Одновременно с этим рекомен- дуется очищать процедурный кэш сервера. Для этого сле- дует выполнить запрос: DBCC FREEPROCCACHE Реиндексирование Одно из ключевых условий эффективности использова- ния SQL Server состоит в создании такого набора индек- сов для таблиц, чтобы любые запросы к таблицам могли бы выполняться эффективно. С увеличением объема дан- ных эффективность использования индексов может сни- жаться, приводя к увеличению времени выполнения опе- раций по чтению и модификации данных. Microsoft SQL Server имеет свойство автоматического обновления ста- тистики индексов, но сами индексы Microsoft SQL Server не перестраивает автоматически. Можно заметить, что после выполнения интенсивных операций по модификации данных в таблицах базы дан- ных увеличивается время выполнения запросов и опера- ций по модификации данных. Это обусловлено тем, что при таких операциях происхо- дит модификация индексов, что приводит к их фрагмен- тации и увеличению количества операций ввода-вывода при использовании индексов в процессе выполнения опе- раций чтения и записи данных. Для того чтобы поддерживать статистику распределения данных в индексах SQL Server в актуальном состоянии можно использовать два способа: переиндексацию таб- лиц и дефрагментацию индексов. Переиндексация таблиц базы данных выполняется с по- мощью команды DBCC DBREINDEX (table name), а дефрагмен- тация индексов базы данных — с помощью команды DBCC INDEXDEFRAG(database_name, table name, index name). Выбор того или иного способа зависит от интенсивности операций по модификации таблиц базы данных. Регулярная переиндексация таблиц базы данных являет- ся более эффективной процедурой, однако время выпол- нения у нее существенно больше. Кроме того, ее выполне- ние может замедлить работу пользователей и привести к возникновению большого количества конфликтов блоки- ровок, поскольку на время перестроения индекса блоки- руется доступ к таблице базы данных, индекс которой в данный момент перестраивается. В отличие от переиндексации дефрагментация индексов является обычной операцией и не приводит к блокиров- кам таблиц, поэтому она может выполняться без преры- вания работы пользователей. Эта операция использует стандартный механизм транзакций для перемещения
страниц индекса. Кроме того, это работает быстрее, чем построение нового индекса. С помощью ее можно повы- сить эффективность доступа к данным, поскольку умень- шается количество операций ввода-вывода при просмот- ре индекса. При высокой интенсивности операций модификации данных возможно использование комбинации этих мето- дов: выполнение в течение рабочего дня дефрагментации индексов и выполнение переиндексации таблиц базы данных после окончания рабочего дня. Сочетание этих двух методов позволит поддерживать ин- дексы в актуальном состоянии, независимо от интенсив- ности операций с базой данных. Эту процедуру можно автоматизировать, написав скрипт на Transact-SQL, который будет исполняться с требуемой периодичностью с помощью SQL Server Agent. Вот пример подобного скрипта, оформленный в виде хра- нимой процедуры (листинг 18.18). Листинг 18.18. Переиндексация и дефрагментация CREATE PROCEDURE DBReindex AS SET NOCOUNT ON DECLARE PTableName char(32) DECLARE SysCur CURSOR FOR SELECT name FROM sysobjects WHERE type='U’ OPEN SysCur FETCH NEXT FROM SysCur INTO OTableName WHILE №FETCH_STATUS=O BEGIN DBCC DBREINDEX(OTableName) FETCH NEXT FROM SysCur INTO OTableName END CLOSE SysCur DEALLOCATE SysCur Аналогичный результат можно получит с помощью Data- base Maintenance Plan Wizard из SQL Server Enterprise Manager. Диагностика блокировок и взаимных блокировок Также во время стандартной оптимизации производи- тельности на уровне СУБД может быть проведена диаг- ностика и оптимизация блокировок SQL Server. Блоки- ровки и взаимные блокировки SQL Server являются одним из основных факторов снижения производитель- ности в многопользовательском режиме работы. В большинстве случаев основной причиной их возникно- вения являются ошибки в прикладном решении. Особенностью блокировок является то, что они влияют на скорость выполнения операций с базой данных только во многопользовательском режиме. В однопользователь- ском режиме они никак не проявляются. Блокировки Для диагностики блокировок SQL Server используется System Monitor (подробнее этот инструмент описан в разделе «System Monitor», с. 740). Основными счетчика- ми, которые позволяют диагностировать проблемы с бло- кировками, являются счетчики SQL Server: Locks\\Lock Wait Time (ms) и SQL Server: Locks\\Average Wait Time (ms). SQL Server: Locks\\Lock Wait Time (ms) — показывает общее время ожидания (в миллисекундах) выполнения запро- сов на блокировку за последнюю секунду (рис. 18.39). Рис. 18.39. Lock Wait Time (ms) SQL Server: Locks\\A verage Wait Time (ms) — показывает сред- нее время ожидания (в миллисекундах) выполнения каж- дого запроса на блокировку (рис. 18.40). Рис. 18.40. Average Wait Time (ms) Если среднее значение общего времени ожидания (SQL Server: Locks\\Lock Wait Time (ms)) больше, чем заданное время отклика системы (реакции системы на некоторое действие пользователя), умноженное на количество ак- тивных пользователей, — это говорит о наличии пробле- мы с блокировками SQL Server. Взаимные блокировки Взаимная блокировка (deadlock) — это ситуация, когда транзакции блокируют друг друга таким образом, что дальнейшее выполнение их становится невозможно. Ни одна из участвующих во взаимной блокировке транзак- ций не может освободить уже захваченные ей ресурсы до того, как наложит блокировки на все ресурсы, которые ей необходимы для завершения. Получить все необходимые ресурсы мешают уже наложенные другой транзакцией блокировки. Для диагностики взаимных блокировок SQL Server ис- пользуется System Monitor (подробнее этот инструмент описан в разделе «System Monitor», с. 740). Основным счетчиком, который позволяет диагностировать пробле- му со взаимными блокировками, является счетчик SQL Server: Locks\\N umber of Deadlocks/sec (рис. 18.41).
Рис. 18.41. Number of Deadlocks/sec SQL Server: Locks\\Number of Deadlocks/sec — показывает количество запросов на блокировку в секунду, которые закончились взаимной блокировкой. При нормальной работе значение этого счетчика должно быть близко к нулю. Если значение отличается от нуля, это свидетель- ствует о наличии проблемы со взаимными блокировками. Способы оптимизации Существует ряд общих рекомендаций, которые позволя- ют снизить влияние блокировок SQL Server на произво- дительность системы. Прежде всего, это сокращение времени выполнения тран- закции, поскольку блокировка существует то время, пока активна транзакция. Чем дольше выполняется транзак- ция, тем больше вероятность того, что блокировки, на- кладываемые данной транзакцией, вступят в конфликт с блокировками другой транзакции. Добиться сокращения времени выполнения транзакции можно путем оптимизации прикладного кода и, в част- ности, путем оптимизации запросов, используемых в прикладном решении. Есть несколько рекомендаций, ка- сающихся выполнения сложных запросов SQL Server, о которых будет сказано ниже. Сокращения времени выполнения транзакции можно до- биться, разбивая большую транзакцию на несколько бо- лее мелких. Также существенно сократить диапазон блокировок по- зволяет грамотное индексирование, в результате которо- го уменьшается количество блокировок, накладываемых SQL Server на всю таблицу, а не на диапазон записей. Другими словами, повышается «гранулярность блокиро- вок», блокируется меньшее количество записей. На ряде следующих рекомендаций остановимся более подробно. Единый порядок доступа к ресурсам. Обеспечение еди- ного порядка доступа к ресурсам позволяет сократить ко- личество конфликтов взаимных блокировок SQL Server. Рассмотрим ситуацию записи движений документов дву- мя различными сессиями (например, два пользователя одновременно проводят документы). Как правило, доку- мент выполняет движения сразу по нескольким регист- рам. Предположим, что среди движений как одного, так и другого документа есть движения по регистрам остатков Регистр 1 и Регистр 2. В этом случае возможна следующая ситуация: допустим, первый пользователь начал проведе- ние документа и транзакция Транзакция 1 записывает движения документа, и обновляет записи в таблице ос- татков регистра Регистр 1, устанавливая на эти записи экс- клюзивную блокировку (Exclusive Lock) (рис. 18.42). Транзакция 2 Рис. 18.42. Транзакция 1 блокирует записи регистра 1 В то же время второй пользователь проводит другой до- кумент, и транзакция Транзакция 2 записывает движение документа и обновляет записи в таблице остатков регист- ра Регистр 2, устанавливая на эти записи эксклюзивную блокировку (Exclusive Lock) (рис. 18.43). Рис. 18.43. Транзакция 2 блокирует записи регистра 2 Пока что эти две транзакции работают независимо и ни- каких конфликтов не возникает. Но вот транзакция 1 за- кончила запись движений регистра 1 и теперь ей необ- ходимо записать движения в регистр 2. Она пытается выполнить запись движений и обновить записи в таблице остатков регистра 2. Для этого ей нужно установить экс- клюзивную блокировку (Exclusive Lock) также и на запи- си регистра 2. Однако она не может этого сделать, так как на эти записи ранее уже установлена эксклюзивная бло- кировка транзакцией 2 (рис. 18.44). Видя такую «несправедливость», транзакция 1 переходит в состояние ожидания до тех пор, пока транзакция 2 не ос- вободит требуемые ей ресурсы. В это время транзакция 2, в свою очередь, закончила за- пись движений в регистр 2 и теперь ей требуется записать движения в регистр 1. Она пытается выполнить запись
движений и обновить записи в таблице остатков регистра 1. Для этого ей нужно установить эксклюзивную блокиров- ку (Exclusive Lock) также и на записи регистра 1. Однако она не может этого сделать, так как на эти записи ранее уже установлена эксклюзивная блокировка транзакцией 1 (рис. 18.45). Рис. 18.44. Транзакция 1 не может заблокировать записи регистра 2 Рис. 18.45. Транзакция 2 не может заблокировать записи регистра 1 В результате возникает ситуация, называемая взаимной блокировкой (deadlock): транзакция 1 ожидает заверше- ния транзакции 2, а транзакция 2, в свою очередь, ожидает завершения транзакции 1. Обнаружив такую ситуацию, SQL Server принудительно отменяет одну из транзакций. Другая транзакция завер- шается нормально. Избежать подобной ситуации можно, обеспечив единую последовательность работы с ресурсами во всех транзак- циях, то есть сначала запись регистра 1, затем регистра 2. В этом случае транзакция 2 не сможет заблокировать ре- сурсы, необходимые транзакции 1 для завершения, и вза- имной блокировки не возникнет. Транзакция 2 будет ожи- дать завершения транзакции 1 (рис. 18.46). Обеспечить единую последовательность работы с ресур- сами можно, используя автоматический режим записи движений документа в модуле проведения. Поясним, что это значит. Рис. 18.46. Единая последовательность работы с ресурсами У документа существует свойство Движения, в котором со- держатся наборы записей регистров, по которым доку- мент может делать движения. Каждый из этих наборов записей может быть изменен и записан разработчиком по-отдельности либо в некоторой последовательности в алгоритме проведения документа. Это ручной режим за- писи движений. Но кроме этого существует и автоматический режим. За- ключается он в том, что при записи самого документа (а проведение документа это частный случай записи) платформа контролирует модифицированность наборов записей, находящихся в свойстве Движения, и, если они были изменены, — записывает их. Полезным свойством автоматической записи движений является то, что запись наборов происходит строго в одинаковом порядке, следо- вательно, порядок таблиц, записи которых блокируются, будет одним и тем же во всех транзакциях. Более подробно о совместимости блокировок SQL Server можно прочитать в разделе «Совместимость блокиро- вок», с. 757. Использование в запросах оператора ДЛЯ ИЗМЕНЕ- НИЯ. Использование в запросах оператора ДЛЯ ИЗМЕНЕНИЯ также позволяет сократить количество конфликтов вза- имных блокировок SQL Server. Однако это достигается за счет уменьшения параллельности работы, так как в этом случае будет использоваться более «серьезный» уровень блокировок. Рассмотрим ситуацию, когда два запроса, выполняемые в различных сессиях, читают и записывают данные одно- го и того же регистра (например, при проведении доку- мента). Например, запрос в транзакции 1 выполняет чте- ние данных из регистра остатков Регистр 1, при этом он устанавливает разделяемую блокировку (Shared Lock) на прочитанные записи (рис. 18.47). Рис. 18.47. Транзакция 1 блокирует записи регистра 1
В это же время другой запрос в транзакции 2 также выпол- няет чтение данных из регистра остатков Регистр 1 и так- же устанавливает разделяемую блокировку (Shared Lock) на прочитанные записи. Разделяемые блокировки со- вместимы, поэтому никакого конфликта не возникает (рис. 18.48). Рис. 18.48. Транзакция 2 блокирует записи регистра 1 После этого в транзакции 1 выполняется обработка дан- ных, полученных запросом, и выполняется запись движе- ний документа и попытка обновления записей в таблице остатков регистра 1. Для этого требуется установить на эти записи эксклюзивную блокировку (Exclusive Lock). Однако выполнить это не удается, потому что эксклюзив- ная блокировка не совместима с разделяемой блокиров- кой, наложенной другой транзакцией (транзакцией 2). По- этому транзакция 1 вынуждена ждать, когда транзакция 2 закончится и снимет разделяемую блокировку (рис. 18.49). Рис. 18.49. Транзакция 1 пытается установить эксклюзивную блокировку на записи регистра 1 В свою очередь, в транзакции 2 также выполняется обра- ботка данных, полученных запросом, и выполняется запись движений документа и попытка обновления записей в таблице остатков регистра 1. Для этого требуется установить на эти записи эксклюзивную блокировку (Excl usi ve Lock). Однако выполнить это не удается, потому что эксклюзив- ная блокировка не совместима с разделяемой блокиров- кой, наложенной другой транзакцией (транзакцией 1). По- этому транзакция 2 вынуждена ждать, когда транзакция 1 закончится и снимет разделяемую блокировку (рис. 18.50). В результате возникает ситуация, называемая взаимной блокировкой (deadlock): транзакция 1 ожидает заверше- ния транзакции 2, а транзакция 2 в свою очередь ожидает завершения транзакции 1. Обнаружив такую ситуацию, SQL Server принудительно отменяет одну из транзакций. Другая транзакция завер- шается нормально. Избежать подобной ситуации можно, используя при вы- полнении запросов к таблице остатков регистра 1 опера- тор ДЛЯ ИЗМЕНЕНИЯ. В этом случае на прочитанные записи будет установлена блокировка более высокого уровня — блокировка обновления (Update Lock). Такая блокировка совместима с разделяемой (Shared Lock), что позволит транзакциям, осуществляющим обычное чтение данных, на которые установлена блокировка обновления, обра- щаться к этим данным беспрепятственно. Зато если дру- гая транзакция обратится к этим данным также с блоки- ровкой обновления (то есть попытается прочитать их для последующего изменения), то конфликта не возникнет, так как блокировки обновления несовместимы между со- бой. Другая транзакция будет ждать, пока эти данные не поменяются, и только после этого сможет прочитать их для последующего изменения (рис. 18.51). Рис. 18.50. Транзакция 2 пытается установить эксклюзивную блокировку на записи регистра 1 Рис. 18.51. Использование оператора ДЛЯ ИЗМЕНЕНИЯ Переформулировка сложных запросов Еще одно действие, которое может быть выполнено при стандартной оптимизации производительности на уровне СУБД, является переформулировка сложных запросов. Почему это может потребоваться? Дело в том, что язык запросов ЮПредприятия 8.0 является SQL-подобным языком и устроен аналогичным образом. При трансляции запросы, написанные на встроенном языке запросов, практически без изменения транслируются в запросы на языке Transact SQL. Один и тот же запрос может быть выполнен SQL Server по-разному. Выбор того или иного способа выполнения операции находится полностью в ведении оптимизатора SQL Server, и повлиять на него «извне» довольно сложно. На низком уровне работы с данными SQL Server опери- рует планом запроса (Query Execution Plan). SQL Server имеет специальный механизм — оптимизатор запроса, — который преобразует запрос на языке Transact SQL в план запроса. План запроса однозначно описывает после- довательность действий, которые необходимо выполнить для получения результата. Важно понимать, что для од- ного и того же запроса в различных ситуациях SQL Server может выбрать различные планы запроса, которые будут давать одинаковый результат за разное время. То есть в зависимости от выбора плана запрос может рабо- тать быстрее или медленнее.
Именно потому, что оптимизатор SQL Server составляет план запроса исходя из своих собственных представле- ний о том, как это лучше сделать, его выбор не всегда сов- падает с тем, что имел в виду разработчик, когда писал за- прос на языке запросов 1С:Предприятия. Но в некоторых конкретных ситуациях он не в состоянии принять пра- вильное решение. Рассмотрим пример. Часто в прикладном решении используются в качестве источников данных подзапросы (листинг 18.19). Листинг 18.19. Пример использования подзапроса ВЫБРАТЬ ... ИЗ (ВЫБРАТЬ ... ИЗ ... ГДЕ ... СГРУППИРОВАТЬ ПО ... ) СГРУППИРОВАТЬ ПО... Особенностью приведенного примера является то, что в подзапросе разработчик решил «оптимизировать» работу запроса и использовал группировку только лишь с той целью, чтобы выбрать меньшее количество записей, то есть аналогичная группировка вполне могла бы быть вы- полнена (и выполняется) на верхнем уровне. При одном уровне вложенности SQL Server в состоянии адекватно оценить подобную конструкцию. Однако при большом количестве уровней вложенности такой подход может иметь отрицательный результат: скорость выполнения запроса может уменьшиться. Дело в том, что такие конструкции транслируются серве- ром 1 С:Предприятия в Transact-SQL практически без из- менений (листинг 18.20). Листинг 18.20. Запрос, транслированный в язык Transact-SQL SELECT ... FROM (SELECT ... FROM ... WHERE ... GROUP BY ... ) GROUP BY... С точки зрения логики работы запроса такая конструк- ция является оптимальной. Действительно, мы сначала выбираем нужное количество записей из внутренней таб- лицы, а затем передаем их «наверх» — в основной запрос. По идее, сервер должен создать временную таблицу, по- местить в нее результаты внутреннего запроса, а затем об- ратиться к ней из основного запроса. Теперь усложним конструкцию (листинг 18.21). Листинг 18.21. Более сложное использование подзапроса ВЫБРАТЬ ... ИЗ (ВЫБРАТЬ ... ИЗ ... ГДЕ ... СГРУППИРОВАТЬ ПО ... ) СГРУППИРОВАТЬ ПО... ЛЕВОЕ СОЕДИНЕНИЕ ВЫБРАТЬ ... ИЗ (ВЫБРАТЬ ... ИЗ ... ГДЕ ... СГРУППИРОВАТЬ ПО ... ) СГРУППИРОВАТЬ ПО... ПО... В такой ситуации SQL Server не всегда может правильно оценить количество записей, возвращаемых каждым из подзапросов. Особенно часто это случается, если вложен- ность подзапросов повышается до 3-х и более уровней, то есть встречаются конструкции вида ВЫБРАТЬ ИЗ (ВЬБРАТЬ ИЗ (ВЫБРАТЬ ИЗ... Иногда это приводит к тому, что оптимизатор принимает решение выбрать самый простой способ объединения двух запросов — так называемый LOOP JOIN. Это означает, что один из запросов будет выполняться столько раз, сколько записей вернет второй запрос. А если запросов три, то мы получим N * М исполнений, где N — количест- во записей в запросе 1, а М — количество записей в запро- се 2. И так далее. Сам по себе подзапрос может быть сколь угодно опти- мальным и работать практически мгновенно, но при мно- гократном его повторении происходит катастрофическое падение производительности. Поэтому если прикладное решение содержит запрос, ко- торый: ♦ состоит из подзапросов с большим уровнем вложен- ности; ♦ содержит операции соединения подзапросов; ♦ демонстрирует нелинейное увеличение времени вы- полнения при увеличении количества возвращаемых записей, то с большой вероятностью мы можем столкнуться с дан- ной ошибкой оптимизатора. В этом случае следует попытаться переписать запрос в прикладном решении, уменьшив степень вложенности подзапросов. Для нашего примера запрос должен при- нять следующий вид (листинг 18.22). Листинг 18.22. Уменьшение степени вложенности подзапросов ВЫБРАТЬ... ИЗ... ЛЕВОЕ СОЕДИНЕНИЕ ВЫБРАТЬ... ИЗ... ГДЕ... СГРУППИРОВАТЬ ПО... При этом на начальном этапе запроса будет выбрано большее количество записей, поскольку мы исключили группировку на уровне подзапроса. Теоретически это должно привести к падению производительности. Одна- ко эксперименты показывают, что такое падение на ма- лом количестве записей практически незаметно, а на большом с лихвой компенсируется тем, что SQL Server выбирает правильный план запроса, то есть объединяет таблицы при помощи HASH или MERGE JOIN. Это приводит к созданию временной таблицы для результатов одного из подзапросов, то есть каждый из них выполняется ровно один раз.
Оптимизация п роиз во дител ьности на уровне оборудования Для локализации проблем производительности на уровне 5 (операционная система и оборудование) используются сле- дующие инструменты: журнал событий Windows и System Monitor. Работа с журналом событий Windows описана в разделе «Журнал событий Windows», с. 739, а работа с System Monitor описана в разделе «System Monitor», с. 740. Существует несколько основных критериев, которые следует использовать при локализации проблем с оборудованием. Типичные проблемы оборудования Во-первых, это дисбаланс нагрузки на компьютеры, вхо- дящие в систему. Во всех режимах работы приложение должно обеспечить сбалансированную загрузку всех ком- пьютеров, входящих в систему. Например, не должно быть режимов работы, при которых простаивают клиент- ские рабочие станции и сервер базы данных, в то время как перегружен сервер 1С:Предприятия. Во-вторых, это дисбаланс нагрузки в рамках одного ком- пьютера. Например, не должно быть режимов работы, при которых перегружена дисковая подсистема сервера базы данных, в то время как простаивает его процессор. В-третьих, это дисбаланс нагрузки на совместно используе- мые ресурсы одного типа. Например, размещение журнала транзакций и файла данных базы данных на одном диске при наличии в системе нескольких дисковых устройств. В-четвертых, это нехватка ресурсов. Ресурсы требуется дополнить или модернизировать. Например, типичным примером недостаточности ресурсов является малый объем оперативной памяти, установленной на компьютере. В-пятых, это ресурсы, работающие со сбоями. Например, сбойные секторы на диске приводят к повторному чте- нию данных. В-шестых, это неправильно настроенные ресурсы. На- пример, неправильная конфигурация числа подключений пользователей может привести к медленной работе систе- мы или ограничению объёма памяти, доступного SQL Server (за счет исчерпания ресурсов памяти). Оптимизация использования оперативной памяти Недостаток объема оперативной памяти, установленной на компьютере, оказывает негативное влияние на произ- водительность всех компонентов системы: клиентской части 1С:Предприятия, сервера 1С:Предприятия 8.0 и Microsoft SQL Server (рис. 18.52). Особенно «требовательными» к памяти являются сервер 1С:Предприятия 8.0 и Microsoft SQL Server, причем на- стоятельно рекомендуется производить диагностику ис- пользования оперативной памяти в следующих случаях: ♦ при увеличении количества пользователей; ♦ при увеличении объема информационной базы в теку- щем периоде; ♦ при увеличении в параметрах нагрузки доли аналити- ческих отчетов, обрабатывающих большие объемы ин- формации. Рис. 18.52. Влияние объема оперативной памяти на компоненты системы Нехватка оперативной памяти приводит к увеличению интенсивности страничного обмена между файлом под- качки и физической памятью, что существенно снижает производительность системы. Для диагностики производительности оперативной па- мяти используется System Monitor. Основным счетчи- ком, который позволяет диагностировать проблемы с па- мятью, является счетчик Memory\\Pages/sec: (рис. 18.53). Рис. 18.53. Pages/sec Этот счетчик показывает скорость страничного обмена между файлом подкачки и физической памятью компью- тера. Операционная система в процессе своей работы вы- гружает неиспользуемые страницы памяти в файл под- качки на жесткий диск. В то же время, если происходит обращение к странице, которая в данный момент отсутст- вует в памяти, операционная система выполняет загрузку этой страницы из файла подкачки. Счетчик Memory\\ Pages/sec показывает суммарное значение выгружаемых в файл подкачки и загружаемых из файла подкачки стра-
ниц в секунду. Это значение должно быть близко к нулю, для нормально работающей системы. Если значение это- го счетчика превышает 20 страниц в секунду, то это гово- рит о том, что объем оперативной памяти недостаточен, в результате чего система выполняет интенсивный обмен с файлом подкачки. Если узкое место производительности заключается в опе- ративной памяти, то прежде всего рекомендуется увели- чить объем оперативной памяти, установленной на ком- пьютере. Если на компьютере помимо ЮПредприятия 8.0 работа- ют другие приложения, которые интенсивно используют оперативную память, рекомендуется перенести их на от- дельный компьютер. Кроме этого, если подобный эффект наблюдается на ком- пьютере, на котором установлены одновременно сервер ЮПредприятия и SQL Server, то рекомендуется разнес- ти эти приложения на разные компьютеры. Оптимизация использования процессоров Низкая производительность процессора оказывает не- гативное влияние на производительность всех компо- нентов системы: клиентской части ЮПредприятия, серве- ра ЮПредприятия 8.0 и Microsoft SQL Server (рис. 18.54). ется, когда ни один другой поток не готов к выполнению. Таким образом этот счетчик показывает процент «занято- сти» процессора. Для нормально работающей системы оптимальное значение этого счетчика должно соответст- вовать 50-70%. Рис. 18.55. % Processor Time Add Counters И*1 Рис. 18.54. Влияние производительности процессора на компоненты системы Недостаточная производительность процессоров или не- достаточное их количество может стать узким местом при увеличении количества пользователей, работающих с системой. Примечательным является тот факт, что в мно- гопользовательской системе более эффективным являет- ся увеличение числа процессоров, нежели увеличение быстродействия существующего количества процессоров. Для диагностики производительности процессоров ис- пользуется System Monitor. Основными счетчиками, которые позволяют диагностировать проблемы с процес- сорами, являются счетчики Processor\\%Processor Time и System\\Processor Queue Length. Processor\\%Processor Time (рис. 18.55) — показывает вре- мя, которое процессор затратил на выполнение несвобод- ного потока, в процентах от общего времени. Каждый процессор содержит свободный поток, который исполня- (•) Use local computer counters О Select counters from computer Performance object | System О ДЙ counters • Я1 instances () Select counters from list Select instances from fist File Write Operations/sec Floating Emulations/sec Processes Рис. 18.56. Processor Queue Length System Cails/sec System Up Time System\\Processor Queue Length (рис. 18.56) — показывает количество потоков в очереди процессора. Этот счетчик показывает только выполненные потоки, то есть все пото- ки кроме тех, которые еще выполняются. Существует одна очередь, даже если компьютер имеет несколько про- цессоров. Поэтому если процессоров несколько, нужно разделить это значение на количество процессоров. В об- щем случае считается нормальным, если постоянное зна- чение этого счетчика не превышает 10 потоков на процес- сор. Однако конкретные приложения могут иметь свои особенности. Наличие проблем с производительностью процессора можно определить как по значению одного, так и по зна- чению другого счетчика. Если процент использования процессора (Processor\\%Processor Time) превышает 85%,
или если длина очереди (System\\Processor Queue Length) к одному процессору превышает 2, это говорит о том, что производительности процессоров недостаточно. Прежде всего, рекомендуется увеличить количество про- цессоров, что является наиболее эффективным решением для многопользовательских систем. Также можно заме- нить процессоры на более быстродействующие. Если на компьютере помимо ЮПредприятия 8.0 работа- ют другие приложения, которые интенсивно используют процессоры, рекомендуется перенести эти приложения на отдельный компьютер. Кроме этого, если подобный эффект наблюдается на ком- пьютере, на котором установлены одновременно сервер ЮПредприятия и SQL Server, то рекомендуется разнес- ти эти приложения на разные компьютеры. Оптимизация дисковой подсистемы Производительность дисковой подсистемы является од- ним из решающих факторов, определяющих производи- тельность Microsoft SQL Server. На производительность клиентской части и сервера ЮПредприятия 8.0 произво- дительность дисковой подсистемы практически не влия- ет (рис. 18.57). Рис. 18.57. Влияние производительности дисков на компоненты системы Для диагностики производительности дисковой подсис- темы используется System Monitor. Основными счетчи- ками, которые позволяют диагностировать проблемы с дисками, являются счетчики Physical Disk\\%Disk Time и Physical Disk\\Avg. Disk Queue Length. Physical Disk\\%Disk Time (рис. 18.58) — показывает про- цент времени, в течение которого диск был занят обслу- живанием запросов чтения или записи. Physical Disk\\Avg. Disk Queue Length (рис. 18.59) — показы- вает среднее количество запросов (как записи, так и чте- ния), которые находятся в очереди. Позволяет оценивать эффективность работы дисковой подсистемы. Наличие проблем с производительностью дисковой под- системы можно определить по нескольким показате- лям. Возможна ситуация, когда при увеличении общей нагрузки на систему процент использования процессора (Processor\\%ProcessorTime) не изменяется (или уменьша- ется), в то время как процент использования дисков (Physical Disk\\%Disk Time) возрастает (или не изменяется). Это говорит о том, что дисковая подсистема не справ- ляется с возросшей нагрузкой и процессоры простаива- ют, ожидая завершения выполнения дисковых операций. Кроме этого, тревожным симптомом является увеличе- ние очереди запросов к дисковой подсистеме (например, если более чем два запроса постоянно находятся в очере- ди для однодисковой системы, то это свидетельствует о том, что диск является узким местом в системе). Рис. 18.58. %Disk Time Рис. 18.59. Avg. Disk Queue Length В случае недостаточной производительности дисковой подсистемы, прежде всего, рекомендуется установить бо- лее быстрые диски. Кроме этого, значительный выигрыш в производительности дает использование дисков с интерфейсом SCSI, а также использование аппаратного RAID-контроллера. Если же RAID-контроллер уже используется, то можно увеличить количество дисков в RAID-массиве.
Оптимизация сетевого интерфейса Производительность сетевого интерфейса оказывает влия- ние в основном на производительность сервера 1 С: Пред- приятия 8.0 (рис. 18.60). Рис. 18.60. Влияние производительности сетевого интерфейса на компоненты системы Для диагностики производительности дисковой подсис- темы используется System Monitor. Основным счетчиком, который позволяет диагностировать проблемы с сетевым интерфейсом, является счетчик Network Interface\\Bytes Total/sec (рис. 18.61). Рис. 18.61. Bytes Total/sec Network Interface\\Bytes Total/sec — показывает суммарную скорость отсылки и приема для каждого сетевого адапте- ра в байтах в секунду. Если значение этого счетчика превышает 65% от величи- ны пропускной способности сетевого адаптера, то это го- ворит о недостаточной производительности сетевого обо- рудования. В этом случае рекомендуется (если позволяют параметры сети) установить сетевой адаптер с более высокой пропу- скной способностью. Также можно установить дополни- тельный сетевой адаптер. Еще одним из возможных способов снижения сетевого трафика может стать перенос обработки информации в отдельных режимах с клиента на сервер 1С:Предприятия. Подробнее о передаче исполнения встроенного языка с клиента на сервер можно прочитать в разделе «Организа- ция выполнения кода на сервере или на клиенте», с. 86. Оптимизация устойчивости системы Неустойчивая работа системы проявляется в аварийном завершении программы и в какой-либо дополнительной диагностике не нуждается. Причина нестабильной рабо- ты может заключаться в различных компонентах систе- мы: это может быть как оборудование, так и прикладное решение или платформа. В большинстве случаев проблемы с устойчивостью рабо- ты можно решить самостоятельно. Кроме этого, можно обратиться за помощью в фирму «1С». Самым главным моментом здесь является грамотный анализ ситуации на месте и получение подробной инфор- мации о проблеме (диагностика проблемы). Диагностика и устранение проблем с защитой Не всегда аварийное завершение сеанса работы 1С:Пред- приятия 8.0 связано с наличием ошибок в приложении. Зачастую причиной подобного поведения системы явля- ется временная потеря связи между клиентским прило- жением и HASP License Manager. При работе 1С:Пред- приятия 8.0 происходит периодический опрос сетевого ключа защиты, и в случае неполучения за определенное время ответа от HASP License Manager, клиентская сес- сия прерывается и происходит аварийное завершение се- анса работы 1С:Предприятия 8.0. Косвенными признаками наличия проблем в работе сис- темы защиты могут служить следующие факторы: ♦ ошибки проявляются не систематически; ♦ проявление ошибки не зависит от выполняемых поль- зователем операций; ♦ записи в журнале событий Windows клиентского ком- пьютера содержат ссылки на различные модули ^Пред- приятия 8.0 и различные адреса; ♦ после установки ключа защиты NetHASP локально ошибки прекращаются. По характеру возникновения проблемы с защитой можно разделить на две группы: проблемы, связанные с конкрет- ным рабочим местом, и проблемы, связанные с тем ком- пьютером, на котором установлен ElASP License Manager. Проблема конкретного рабочего места В этом случае, как правило, ошибки проявляются только на отдельных рабочих местах. Наряду с этим существуют рабочие места, на которых ошибки не проявляются. Перенос ключа NetHASP и HASP License Manager на другой компьютер проблемы не решает, но после уста- новки ключа защиты локально в проблемные компьюте- ры ошибки прекращаются.
В этом случае причиной возникновения описанных про- блем могут быть некорректные настройки брандмауэра Windows: следует убедиться, что HASP License Manager включен в список исключений брандмауэра Windows. Кроме этого, причиной могут быть аппаратные проблемы используемого сетевого оборудования проблемных ком- пьютеров. Также следует проверить настройки и качество работы сетевых протоколов на проблемных компьютерах. Кроме этого, возможен конфликт с установленным про- граммным обеспечением. Проблема компьютера, на котором установлен HASP License Manager В этом случае ошибки проявляются на всех рабочих мес- тах, а после переноса ключа NetHASP и HASP License Manager на другой компьютер появление ошибок прекра- щается. В этом случае причиной возникновения описанных про- блем может быть высокая загрузка компьютера, на кото- ром установлен HASP License Manager. По этой причине его не рекомендуется устанавливать на компьютеры с ус- тановленными MS SQL Server и(или) сервером ЮПред- приятия 8.0. Также следует проверить соответствие вер- сий HASP License Manager и драйвера ключа NetHASP. В дополнение к перечисленному, причины возникнове- ния подобных проблем могут быть те же, что и для кон- кретного рабочего места: следует проверить корректность настроек брандмауэра Windows (HASP License Manager должен быть включен в список исключений брандмауэра Windows), проверить, нет ли на компьютере, на котором установлен HASP License Manager, проблем с аппарат- ным обеспечением (в частности, с сетевым оборудовани- ем и USB-портами), убедиться в правильности настроек и качестве работы сетевых протоколов этого компьютера, а также в отсутствии конфликтов с установленным про- граммным обеспечением. Диагностика нестабильной работы Нестабильная работа сервера ЮПредприятия Нестабильная работа сервера 1 С:Предприятия выражает- ся в том, что у большинства пользователей, работающих с сервером 1 С: Предприятия 8.0, появляется сообщение об ошибке: «Потеряна связь с сервером 1 С:Предприятия. Возможно, сервер был перезагружен». Кроме этого в жур- нале событий Windows компьютера, на котором установ- лен сервер ЮПредприятия 8.0, присутствуют записи об ошибках со следующими параметрами: Event Type: Error; Event Source: СОМ+; Server Application Name: 1CV8. Нестабильная работа клиентской части ЮПредприятия Нестабильная работа клиентской части 1 С: Предприятия выражается в том, что у некоторых пользователей, рабо- тающих с 1 С: Предприятием 8.0, происходит аварийное завершение ЮПредприятия 8.0 с выдачей сообщения об ошибке. Текст сообщения может быть различным, в зави- симости от ошибки, приведшей к аварийному заверше- нию ЮПредприятия 8.0. Кроме этого, в журнале событий Windows компьютера, на котором установлено ЮПред- приятие 8.0, присутствуют записи об ошибках со следую- щими параметрами (листинг 18.23). Листинг 18.23. Параметры записей об ошибках Event Type: Error Event Source: Application Hang Description: Hanging application lcv8.exe ... Повышение стабильности системы При самостоятельном решении проблемы следует ис- пользовать все доступные источники информации: ин- формационно-технологическое сопровождение. С боль- шой долей вероятности может оказаться, что решение вашей проблемы уже известно. Для диагностики проблемы в прикладном решении или платформе можно использовать для анализа журнал ре- гистрации ЮПредприятия 8.0 (работа с журналом реги- страции 1 С: Предприятия описана в разделе «Журнал ре- гистрации 1 С:Предприятия», с. 734): ♦ вставить запись информации о начале и завершении подозрительных операций или фрагментов кода в жур- нал регистрации; ♦ попытаться собрать статистику сбоев и проанализиро- вать, с чем она связана; ♦ найти по журналу регистрации операцию, после выпол- нения которой происходит аварийное завершение; ♦ переписать проблемный код с использованием других механизмов ЮПредприятия, изменить запрос или ал- горитм решения задачи. Если принято решение собрать и передать информацию о проблеме в фирму «1С», то следует помнить, что чем подробнее будет информация, тем быстрее будет предло- жен вариант решения проблемы. Наличие подробного описания условий воспроизведения ошибки существенно сокращает время решения проблемы. Перечень информации, предоставляемой при обращении в отдел технической поддержки Общая информация ♦ Используемая версия ЮПредприятия; ♦ используемая конфигурация и ее версия; ♦ используемый вариант 1С:Предприятия; ♦ используемая версия операционная системы; ♦ версия пакета обновления для операционной системы. Нестабильная работа сервера ЮПредприятия 8.0 ♦ Используемая версия SQL Server; ♦ параметры настройки СОМ+ и компоненты сервера 1 С:Предприятия; ♦ информация из журнала событий Windows, касающая- ся обстоятельств аварийного завершения работы серве- ра ЮПредприятия; ♦ подробное описание (по возможности) обстоятельств, при котором происходит аварийное завершение работы сервера 1 С: Предприятия: количество активных пользователей; операции, при выполнении которых происходит ава- рийное завершение работы сервера 1 С: Предприятия; как часто это происходит;
♦ тестовый пример, демонстрирующий эту ошибку: тестовая база данных; обработка и/или подробная инструкция для воспро- изведения проблемы; ♦ дополнительная информация, которая может быть ис- пользована при анализе проблем. Нестабильная работа клиентской части 1С:Предприятия 8.0 ♦ Подробное описание (по возможности) обстоятельств, при которых происходит аварийное завершение работы 1 С: Предприятия: количество активных пользователей; операции, при выполнении которых происходит ава- рийное завершение работы 1 С: Предприятия; как часто это происходит; ♦ информация из журнала событий Windows, касающаяся обстоятельств аварийного завершения работы 1 (^Пред- приятия; ♦ результаты предварительного анализа (если проводился); ♦ тестовый пример, демонстрирующий проблему: исходная база данных или конфигурация; необходимые для воспроизведения проблемы обра- ботки; подробное описание процесса воспроизведения про- блемы; ♦ дополнительная информация, которая может быть ис- пользована при анализе проблем. Проблемы с производительностью клиент- серверного варианта ^Предприятия 8.0 ♦ Подробное описание условий проявления проблемы. Для многопользовательского режима необходимо ука- зать параметры нагрузки на систему: среднее количество активных пользователей; среднее количество записываемых в час документов; среднее количество строк в документе; ♦ параметры используемого оборудования: клиентские компьютеры; сервер баз данных; сервер 1 С:Предприятия 8.0 (если установлен на от- дельном компьютере); ♦ результаты предварительного анализа (если проводил- ся); дополнительная информация, которая может быть использована при анализе проблем с производительно- стью: результаты замеров производительности проблемной операции: — замер производительности средствами 1С:Пред- приятия; — замер производительности средствами SQL Profiler; замер параметров загрузки клиентского и серверного оборудования средствами System Monitor: — загрузка процессора; — загрузка дисковой системы; — загрузка памяти; — тестовый пример, демонстрирующий проблему: — исходная база данных или конфигурация; — необходимые для воспроизведения проблемы обра- ботки; — подробное описание процесса воспроизведения проблемы. Инструментальные средства, используемые при оптимизации производительности Журнал регистрации 1С:Предприятия Использование журнала регистрации 1 С: Предприятия может понадобиться при локализации проблем произво- дительности прикладного решения на уровне конфигура- ции и технологической платформы. При локализации проблем производительности журнал регистрации используется для получения информации о тех действиях, которые выполнялись системой в неко- торый момент, например перед тем, как система начала с большими задержками реагировать на действия пользо- вателя. Журнал регистрации содержит информацию о том, какие события происходили в информационной базе в опреде- ленный момент времени или какие действия выполнял тот или иной пользователь. Журнал регистрации может быть открыт как в режиме конфигуратора (Администрирование ► Журнал регистрации), так и в режиме 1С:Предприятия (Сервис ► Журнал регист- рации) (рис. 18.62). По умолчанию для новой информационной базы регист- рация событий в журнале отключена. Установка требуе- мого уровня регистрации событий в журнале выполняется в режиме конфигуратора. Для этого следует выполнить команду Администрирование ► Настройка журнала регистра- ции... (рис. 18.63). Существует четыре уровня важности событий журнала регистрации (в порядке понижения важности): ошибки, предупреждения, информация и примечания. На уровне ошибок регистрируются значительные про- блемы, например, исключительные ситуации, возникаю- щие в результате ошибок выполнения модулей. На уров- не предупреждений регистрируются события, которые не обязательно являются значительными, но могут служить источником проблем в дальнейшем. На уровне информа- ции регистрируются события, сообщающие об успешном выполнении операций. Например, начало и завершение сеанса работы пользователя, добавление и изменение данных, изменение конфигурации и пр. Информацию, находящуюся в журнале регистрации, мож- но отбирать по большому количеству критериев. Например, можно отобрать только информацию о том, какие докумен- ты изменялись определенным пользователем в заданный промежуток времени (рис. 18.64).
ГГ' Журнал регистрации <2> _ П х Де Дата, время Пользователь Событие Метаданные я и Приложение Комментарий Данные Представление данных 1 27.04.2004 11-23.36 Иванов 1 С: Предприятие Данные. Проведение Документ РеализацияТоваров Реализациятоеаров ТК000028 от 16.06 2003 1 2:00:00 i 27 04 2004 11 23:37 Иванов 1 С. Предприятие Данные. И зменение Регистр накопления Партии! овзроеК i 27 04 2004 11 23.37 Иванов 1 С. Предприятие Данные Изменение Регистр накопления Партии! i 27.04 2004 1123.37 Иванов 1 С: Предприятие Данные. И зменение Регистр накопления П. i 27 04 2004 11 23:37 Иванов 1 С: Предприятие Данные. И зменение Регистр накопления Партии!оваровКомпании i 27 04 2004 11 23:37 Иванов 1 С. Предприятие Данные Изменение Регистр накопления ПродажиКомпании i 27.04 2004 11 23:37 Иванов 1С Предприятие Данные. И зменение Документ ПроведениеПоПартиям Проведение по партиям 00014 от 30.06.2003 1 6.33:53 i 2704.2004 11:23:37 Иванов 1 С. Предприятие Данные. П роведение Документ ПроведениеПоПартиям Проведение по партиям 00014 от 30 06.2003 1 6.33:53 i 27 04 2004 11 23:47 Иванов 1 С. Предприятие Сеанс. Завершение i 27.04.2004 19.56.25 Иванов Конфигуратор Сеанс. Завершение Отбор. Рис. 18.62. Журнал регистрации Рис. 18.63. Настройка журнала регистрации Рис 18.64. Отбор журнала регистрации Также можно отобрать только те события, которые отно- сятся, например, к действиям с определенным объектом базы данных (например, с конкретным элементом спра- вочника). Такие отборы выполняются на закладке «Прочие». В процессе длительной эксплуатации системы в журнале регистрации может накапливаться значительное число записей. Поэтому поддерживается возможность сокраще- ния журнала регистрации и удаления записей, ставших неактуальными. Сокращение журнала регистрации вы- полняется в режиме конфигуратора, по команде Адми- нистрирование ► Настройка журнала регистрации... ► кнопка Сократить. При сокращении журнала регистрации можно записать удаляемые события в файл, если предвидится необходимость их анализа в будущем (рис. 18.65). Рис. 18.65. Сокращение журнала регистрации Сокращение журнала регистрации может быть выполне- но также при запуске ЮПредприятия из командной строки. Для этого следует использовать режим пакетного запуска конфигуратора из командной строки с парамет- ром /ReduceEventLogSize. (листинг 18.24). После параметра /ReduceEventLogSize обязательно должна быть указана новая граница журнала регистрации, а ключ -saveAs позволяет указать файл, в который будут сохране- ны копии выгружаемых записей.
Консоль анализа журнала регистрации ОЛЖурнал регистрации*} xml _ □ X Рис. 18.66. Консоль анализа журнала регистрации Листинг 18.24. Сокращение журнала регистрации "C:\Prograni Files\lcv8\bin\lcv8.exe" CONFIG /F"C:\Documents and Settings\user\My Documents\lC\DemoTrd2" /М"Федоров (администратор)" /Р"“ /OutD:\my\log.txt /ReduceEventLogSize 2004-12-26 -saveAsCAOldLog.elf ВНИМАНИЕ В приведенном примере текст командной строки разбит на несколько строк исключительно в целях повышения «читабельности» примера. Для запуска ЮПредпрития текст командной строки должен представлять собой одну строку. Журнал регистрации может быть сохранен в файл, в фор- мате *.elf. Для этого следует использовать команду Файл ► Сохранить как... Также журнал регистрации можно сохранить в формате *.xml. Для этого следует использо- вать команду Файл ► Сохранить копию.... Журнал регистрации, сохраненный в формате *.xml, можно анализировать с помощью универсальной обра- ботки «Консоль анализа журнала регистрации». Эта обработка опубликована в информационно-технологи- ческом сопровождении (ИТС) в разделе «Универсаль- ные отчеты и обработки» — «Консоль анализа журнала регистрации». Консоль анализа журнала регистрации использует построитель отчета для обработки данных, содержащихся в журнале. Таким образом, имеется воз- можность управлять отбором, группировками, поряд- ком, оформлением и условным оформлением получае- мого отчета. Также имеется возможность выполнения анализа данных Общая статистика для получения стати- стических оценок информации, содержащейся в журна- ле регистрации (рис. 18.66). Режим замера производительности 1С:Предприятия Использование режима замера производительности 1 С: Предприятия может понадобиться при диагности- ке производительности прикладного решения на уровне конфигурации и технологической платформы. При локализации проблем производительности режим замера позволяет выявить, например, тот запрос, который выполняется наибольшее количество времени, по сравне- нию с остальными. Режим замера производительности позволяет разработ- чику оценивать скорость работы как всей конфигурации в целом, так и отдельной ее части. В этом режиме измеря- ется частота использования конкретных участков кода и скорость их выполнения. Следует учитывать, что замеряется время выполнения только прикладного кода, написанного в явном виде в мо- дуле. Время выполнения автоматических действий, кото- рые выполняются платформой, в замер не входит. Подобный анализ помогает выбирать наиболее оптималь- ный способ программной реализации алгоритмов работы системы, а также определять пути для повышения быст- родействия прикладного решения. Запуск и остановка замера производительности выпол- няется в режиме конфигуратора, а непосредственно замер производительности выполняется в режиме ЮПредпри- ятие. Поэтому для выполнения замера производительно- сти необходимо открыть прикладное решение в режиме конфигуратора и затем начать отладку или подключиться к уже работающему в режиме ЮПредприятие приложе- нию.
Возможны несколько сценариев замера производитель- ности. Если требуется измерить производительность участка кода, включая участок, выполняемый при старте системы, не- обходимо сначала в режиме конфигуратора начать замер производительности (Отладка ► Замер производительности), затем начать отладку (Отладка ► Начать отладку). После того как требуемый участок кода будет выполнен, нужно в конфигураторе завершить замер производительности (Отладка ► Замер производительности). После этого будет автоматически открыто окно с результатом замера произ- водительности (рис. 18.67). Рис. 18.67. Выполнение замера производительности Если требуется измерить производительность некоторого участка кода, без учета участков, выполняемых при нача- ле и завершении работы (например, производительность процедуры проведения документа), необходимо сначала в режиме конфигуратора начать отладку (Отладка ► Начать отладку) или подключиться к уже запущенному в режиме ЮПредприятие приложению (Отладка ► Подключиться...). После этого в режиме 1 С: Предприятие подготовить при- ложение к выполнению требуемого участка кода. Затем нужно перейти в режим конфигуратора, начать замер производительности (Отладка ► Замер производительности), перейти в режим ЮПредприятие и начать выполнение требуемого участка кода. После того, как выполнение кода будет завершено, нужно в режиме конфигуратора за- вершить замер производительности (Отладка ► Замер про- изводительности). После этого будет автоматически от- крыто окно с результатом замера производительности (рис. 18.68). Если требуется измерить производительность участка кода, включая участок, выполняемый при завершении работы системы, необходимо сначала в режиме конфигуратора начать отладку (Отладка ► Начать отладку) или подклю- читься к уже запущенному в режиме ЮПредприятие приложению (Отладка ► Подключиться...). После этого в режиме 1 С: Предприятие подготовить приложение к вы- полнению требуемого участка кода. Затем нужно перейти в режим конфигуратора, начать замер производительно- сти (Отладка ► Замер производительности), перейти в режим 1 С: Предприятие, начать выполнение требуемого участка кода и после этого завершить работу системы. В этом слу- чае не требуется прекращать замер производительности вручную - окно с результатом замера производительно- сти будет открыто автоматически после завершения рабо- ты системы в режиме 1 С:Предприятие (рис. 18.69). Рис. 18.68. Выполнение замера производительности 1С Предприятие Конфигуратор Запуск в режиме 1 СПредприятое Подготовка к выполнению замеряемого участка кода Замер т • - - Выполнение замеряемого участка кода Завершение работы в режиме ЮПредприятие Результат замера производительности Рис. 18.69. Выполнение замера производительности Результат замера производительности представляет собой список ссылок на конкретные строки модуля, с указанием частоты их выполнения и длительности (абсолютного вре- мени выполнения и относительного, в процентах от обще- го времени выполнения замеряемого участка) (рис. 18.70). Результаты замера можно видеть также непосредственно в окне с исходным текстом модуля. Щелчком мыши на выбранной строке списка можно прейти к тексту модуля, для которого на отдельном поле будет отображено коли- чество вызовов и относительное время выполнения каж- дой строки (рис. 18.71).
П х Новый! - “"“ЙО? - - - у . - Кол Врем. * %(Врем) Документ Поступление!оваров 3121 Возврат Запрос Выполнить^), 1 0,013211 12.87 Документ Поступление!оваров 3 478 Возврат Запрос. Выполнить!), 1 0.010629 1036 Документ. Поступление! оваров 4 363 СуммаДокуменга = рцСумма. 1 0.001067 1,04 Документ Поступление!оваров 3 650 Движение = Движения!ИмяР 1 0.000881 0.86 Документ ПоступлениеТоваров 4 397 Заголовок « “Проведение док 1 0.00087S 0.85 ОбщийМодуль обПроцедурыОбщ 105 !ипЗначения = !ип3нч(3наче. 52 0.000624 0,61 0 бщийМодуль. обПроцедурыОбщ. 130 Если Значение = Новый!!ипЗ. 30 0 000551 0,54 Документ Поступление!оваров 3 721 Движение = Движени^ИмяР 4 0,000466 0,45 Документ Поступление!оваров 3 881 Движение. Стоимость 4 0.000447 0,44 Документ ПоступлениеТоваров 3 899 Движение = Движения[ИмяР 4 0,000419 0,41 Документ Поступление!оваров 3 848 Движение = Движени^ИмяР 4 0.000380 0.37 ОбщийМодуль. обПроцедурыОбщ 108 Если Значение = Неопределе 52 0.000376 0,37 ОбщийМодуль. обПроцедурыОбщ. 110 ИначеЕсли Значение = NULL 46 0.000334 0,33 Документ. Поступление! оваров 4 400 РезультатЗапросаПоШапке =. 1 0,000309 0,30 Документ Поступление!оваров 3975 Движение = Движениями мяР 4 0,000299 0,29 ОбщийМодуль обПроцедурыОбщ. 112 ИначеЕсли ! ипЗначения = Ти 46 0,000292 0.28 Документ. Поступление! оваров 4 434 РезультатЗапросаПо! оварам. 1 0,000277 0,27 ОбщийМодуль.обПроцедурыОбщ . 116 ИначеЕсли ! ипЗначения = !и. 46 0,000235 023 Документ Поступление!оваров 4 503 РезультатЗапросаПоВозврат . 1 0.000194 0,19 П ГМУ 1 ЛШ ГГ ГТ 1 m ,.“-1 •" Т 1~> С '~ Г~ 1 0,058926 57.42 V Кол. | ij Врем. | 0,0583261 Х(Врем.) | 57.421 □ Для вызова процедур и функций включать время выполнения Рис. 18.70. Результат замера производительности 3 Документ ПоступлениеТоваров: Модуль объекта [Только для чтения) _ □ X 1 : 0.00 1 : 57.42 1 : 0.01 | Ко нс танта. Обновлять Це ныПо с тавщико вПр иПо с ту п л е нииТо варов К АК ™ | КурсыВалютСрезПоследних.Курс КАК 1 КурсыВалютСрезПоследник.Краткость КАК |ИЗ | Документ.ПоступлениеТоваров КАК Док, | Константы | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследн | ПО Константы.ВалютаУправленческогоУчетаКомпании = Курсы | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.УчетнаяПолитикаКомпани | ПО Истина (ГДЕ Док.Ссылка = «ДокументСсылка"; КонецЕсли; | Возврат Запрос.Выполнить() ; -КонецФункции // СформироватьЗапросПоШапке0 Е // Формирует запрос по товарам документа, при оперативном проведении до Е Функция СформироватьЗапросПоТоварам(Режим, ВыборкаПоШапкеДокумента) [”] Рис. 18.71. Отображение результата замера производительности в модуле Результаты замера могут быть отсортированы по любой из колонок, например по количеству вызовов строки. Кроме этого, режим замера производительности позволя- ет производить выборочное суммирование строк замера, для получения суммарных характеристик выполнения некоторых строк (рис. 18.72). Рис. 18.72. Суммирование строк результата замера производительности Дополнительной возможностью является включение в за- мер или исключение из замера времени выполнения вы- зываемых процедур и функций (для этого используется соответствующий флаг в окне результата замера произво- дительности). Использование этой возможности позво- ляет получать картину замера, максимально приближен- ную к реальной, в случае когда из замеряемого модуля вызываются внешние по отношению к нему, процедуры. Разработчик может сохранить результаты замера в файл *.pff для последующего анализа и сравнения с результатами других замеров. Для этого используется команда Файл ► Сохранить. Журнал SQL Server Использование журнала SQL Server может понадобиться при диагностике нестабильной работы системы. Сообщения журнала SQL Server могут понадобиться, на- пример, в том случае, когда принимается решение ото- слать информацию о проблеме в фирму «1С». Просмотреть журнал SQL Server можно с помощью SQL Server Enterprise Manager. Для его запуска нужно выпол- нить команду Start ► All Programs ► Microsoft SQL Server ► Enterprise Manager: (рис. 18.73). В результате выполнения этой команды будет открыто окно Enterprise Manager. Если нужный сервер еще не за- регистрирован, нужно установить курсор на ветку SQL Server Group и выполнить команду Action ► New SQL Server
Registration.... Будет запущен мастер регистрации, кото- рый поможет выполнить регистрацию нового сервера. После этого можно просмотреть журналы этого сервера, которые находятся в ветке Management ► SQL Server Logs (рис. 18.74). E . Databases ЕЙ Data Transformation Services ВЙ Management SQL Server Agent Backup Current Activity Database Maintenance Plans SQL Server Logs____________ Books Online .S. Client Network Utility Conf igure SQL XML Support in IIS m Enterprise Manager Archive #1 - 09/20/2004 19.46 (2 Archive #2 - 09/20/2004 19:42(2 Archive #3 - 09/20/2004 18:59 (2 £ Archive 144 - 09/20/2004 18:57 (i . Z Archive #5 - 09/20/2004 18:48 (I । J Archive #6 - 09/20/2004 18:47(7 Replication E ' . Security В В Support Services E Bl Meta Data Services View New Window from Here Refresh 9 Import and Export Data I Profiler Query Analyzer Help Рис. 18.73. Enterprise Manager Рис. 18.75. Сохранение журнала регистрации в файл Рис. 18.74. Журналы SQL Server Сообщения журнала событий Windows могут понадо- биться, например, в том случае, когда принимается реше- ние отослать информацию о проблеме в фирму «1С». Журнал событий Windows позволяет собирать информа- цию об аппаратных, программных и системных пробле- мах. Кроме этого он позволяет отслеживать события по- литики безопасности Windows. Для просмотра журнала событий Windows нужно выпол- нить команду Start ► All Programs ► Administrative Tools ► Event Viewer (рис. 18.76). » Component Services s Computer Management 9 Data Sources (ODBC) Event Viewer Internet Information Services Ц Local Security Pokey % Microsoft .NET Framework 1.1 Configuration Microsoft .NET Framework 1.1 Wizards № erformance Services Рис. 18.76. Команда Event Viewer Рядом с каждым журналом указаны дата и время послед- ней записи, содержащейся в этом журнале. Установив курсор на нужный журнал, можно просмотреть его содер- жимое. Также содержимое журнала SQL Server можно просмотреть с помощью любого текстового редактора. По умолчанию журналы находятся в папке Program Files\Microsoft SQL Server\Mssql\Log\Errorlog на том компьютере, на котором установлен SQL Server. Обычно новый журнал создается каждый раз при запуске новой копии SQL Server. Как правило, SQL Server сохра- няет копии шести предыдущих журналов, отмечая их по- следовательно номерами от 1 до 6. Журнал SQL Server может быть выгружен в файл форма- та *.txt или *.csv. Для этого необходимо установить кур- сор на нужный журнал и выполнить команду Action ► Export List... или выполнить аналогичную команду кон- текстного меню (рис. 18.75). Журнал событий Windows Использование журнала событий Windows может пона- добиться при диагностике производительности оборудо- вания, а также при диагностике нестабильной работы системы. В результате будет открыто окно журнала событий Win- dows (рис. 18.77). Рис. 18.77. Event Viewer Как правило, в системе ведутся три вида журналов: Журнал приложений (Application) — содержит события, генерируемые приложениями или программами. Напри- мер, база данных может записывать в него ошибки рабо- ты с файлами. Журнал безопасности (Security) — содержит, например, такие события, как успешные или неуспешные попытки входа в систему, события, относящиеся к использованию различных ресурсов (чтение, открытие или удаление
файлов или объектов). Администратор может настраи- вать состав событий, которые будут регистрироваться в журнале безопасности. Системный журнал (System) — содержит события, гене- рируемые различными компонентами Windows. Например, сбой при загрузке драйвера или системной компоненты при запуске системы. Типы событий, записываемые в этот журнал, определены на уровне Windows. Если компьютер является контроллером домена или DNS- сервером, то в дополнение к перечисленным, ведется еще несколько видов журналов. Как правило, для диагностики производительности обору- дования и для диагностики нестабильной работы системы достаточно журнала приложений и системного журнала. Журнал событий Windows может быть выгружен в файл формата *.evt, *.txt или *.csv. Для этого необходимо уста- новить курсор на нужный журнал и выполнить команду Action ► Save Log File As... или выполнить аналогичную ко- манду контекстного меню (рис. 18.78). Рис. 18.78. Сохранение журнала событий Журнал, выгруженный в формате *.evt, в дальнейшем может быть просмотрен в Event Viewer (Action ► Open Log File...). Журналы, сохраненные в форматах *.txt или *.csv, могут быть просмотрены с помощью текстового редактора или других приложений. System Monitor Использование System Monitor может понадобиться при диагностике производительности оборудования. System Monitor используется для измерения производи- тельности локального компьютера или другого компью- тера в сети. В частности, System Monitor может использо- ваться для выполнения следующих действий: ♦ сбора и просмотра в реальном времени параметров про- изводительности локального компьютера или других удаленных компьютеров; ♦ просмотра данных, собранных в настоящее время или ранее в журнале; ♦ представления данных в виде графика, гистограммы или отчета; ♦ создания конфигураций мониторинга, которые могут быть установлены и использованы на других компью- терах, при помощи Microsoft Management Console. Для запуска System Monitor нужно выполнить команду Start ► All Programs ► Administrative Tools ► Performance (рис. 18.79). » Cornponent Services s Computer Management I Data Sources (ODBC) 0 Event Viewer v j Internet Information Services i local Security Policy Microsoft .NET Framework 1.1 Configuration % Microsoft .NET Framework 1.1 Wizards К Services Рис. 18.79. Выбор команды Performance После выполнения этой команды будет открыто окно консоли производительности, содержащее два инстру- Рис. 18.80. Окно консоли производительности
мента: System Monitor и Performance Logs and Alerts: (рис. 18.80). По умолчанию открывается представление System Mo- nitor в виде графика, который отображает значения неко- торого набора счетчиков (этот набор счетчиков указан в Performance Logs and Alerts ► Counter Logs ► System Overview). Для того чтобы добавить новый счетчик, необходимо вы- полнить команду Add в командной панели (рис. 18.81). о □ Зо цаца й(+У * Ча е (S о ав Рис. 18.81. Добавление нового счетчика После выполнения этой команды будет открыто окно, по- зволяющее выбрать и настроить необходимый счетчик (рис. 18.82). Рис. 18.82. Настройка счетчика Прежде всего, в этом окне указывается, производитель- ность какого компьютера будет анализироваться. Это мо- жет быть локальный компьютер (Use local computer counters) или другой компьютер в сети (Select counters from computer). Затем следует выбрать объект производительности (Perfor- mance object). Объект производительности — это логиче- ская коллекция счетчиков, связанных с ресурсом или службой, производительность которых должна быть изме- рена. Например, процессор, память, сетевой интерфейс ит. д. Для каждого объекта производительности существует воз- можность выбрать один или несколько счетчиков (Counters). Счетчик это элемент данных, соответствующий некото- рому объекту производительности. Для каждого счетчика System Monitor отображает значение, характеризующее определенный аспект производительности объекта про- изводительности. Например, загруженность процессора, длина очереди процессора и пр. Кроме этого, может потребоваться указать все или неко- торые экземпляры объектов производительности, для ко- торых необходимо производить замер (Instances). Напри- мер, если на компьютере установлено два процессора, то можно замерять значение выбранного счетчика для одно- го, для другого или для обоих вместе. Кнопка Explain позволяет получить подробное описание выбранного счетчика, а кнопка Add — добавить выбран- ный счетчик в System Monitor. Когда добавляется новый счетчик, то после некоторой за- держки (в зависимости от интервала обновления) System Monitor начинает отрисовывать диаграмму значений, со- ответствующих выбранному счетчику. Названия выбранных счетчиков и информация, связан- ная с ними, отображается в таблице (легенде), располо- женной в нижней части окна. Легенда содержит следую- щие информацию: компьютер, на котором запущен System Monitor, объект производительности, счетчик, экземпляр объекта производительности, а также графические свой- ства счетчика (цвет, ширина, вид линии и коэффициент, применяемый к значению счетчика). Для того чтобы выделить жирным график выбранного в легенде счетчика, следует выполнить команду Highlight в командной панели (рис. 18.83). р □ Во [оиэ о»it Рис. 18.83. Подсвечивание текущего счетчика Над легендой расположена панель значений, которая ото- бражает замеряемые значения выбранного счетчика. Она содержит: последнее измеренное значение (Last), среднее значение за период (Average), минимальное (Minimum), максимальное значение (Maximum), а также продолжи- тельность интервала, отображенного на графике (Duration). Все перечисленные значения рассчитываются относи- тельно интервала, отображенного на графике, а не от об- щего времени, прошедшего с запуска System Monitor. System Monitor позволяет выполнить фиксированное количество (100 шт.) дискретных замеров, которые ото- бражаются в виде графика. Существует возможность управлять частотой замеров и, таким образом, изменять продолжительность интервала, отображенного на графике. Для того чтобы задать частоту замера необходимо выпол- нить команду Properties в командной панели (рис. 18.84). □ □ Вэ Важ + х[ж| а Рис. 18.84. Свойства Затем на закладке General задать нужную продолжитель- ность интервала между замерами (Sample automatically every ... seconds) (рис. 18.85). Таким образом, если задать интервал между замерами равным 1 секунде, то на графике будет отображено изме- нение значений счетчиков в течение 1 минуты 40 секунд. Если задать интервал равным 3 секундам, то на графике будет отображено 5 минут. В этом же окне, на закладке Data существует возможность задать оформление и коэффициент для каждого измеряе- мого счетчика (рис. 18.86). Поля Color, Width и Style позволяют задать соответственно цвет, ширину и вид линии на графике, а поле Scale — уменьшающий или увеличивающий коэффициент. Ис- пользование увеличивающего или уменьшающего коэф- фициента необходимо в тех случаях, когда значения счет- чиков отличаются друг от друга более чем на порядок.
Тогда применение этого коэффициента позволяет «уме- стить» значения в отображаемый в графике интервал (по умолчанию от 0 до 100, но можно задать собственный в свойствах монитора на закладке Graph). Рис. 18.85. Свойства ~ общие Рис. 18.86. Свойства — данные Windows Error Reporting Использование Error Reporting может понадобиться при диагностике нестабильной работы системы. Дампы Error Reporting могут понадобиться, например, в том случае, когда принимается решение отослать ин- формацию о проблеме в фирму «1С». Опишем, вкратце, суть работы Error Reporting. Когда происходит системная ошибка, на дисплее отображается синий экран, содержащий коды ошибки, и все операции прекращаются. Когда выполняется недопустимая операция или возникает другая ошибка в программе (например, Microsoft Word), это является программной ошибкой и программа прекращает работу. Error Reporting служит для оповещения о таких систем- ных и программных ошибках. Можно настроить Error Reporting на сбор только определенной информации. На- пример, если нужно собирать только системные ошибки, можно указать, что подобный отчет будет генерироваться только для операционной системы. То же самое относит- ся и к компонентам Windows (таким как as Windows Explorer, Paint или Internet Explorer), и к программам, ус- тановленным на компьютере. Когда происходит ошибка, отображается диалоговое окно, предлагающее отослать или не отсылать отчет о проблеме. Наряду с этим сформированный отчет может быть сохра- нен в файле и использован для самостоятельного анализа. Для того чтобы разрешить оповещение об ошибках, следует: 1. Выполнить команду Start ► Control Panel ► System. 2. На закладке Advanced нажать кнопку Error Reporting. 3. Нажать Enable error reporting (рис. 18.87). Рис. 18.87. Error Reporting Для дополнительной настройки следует запустить редак- тор групповой политики (Start ► Run ► gpedit.msc) и в ветке Local Computer Policy ► Computer Configuration ► Administra- tive Templates ► System ► Error Reporting выполнить настрой- ку Report Errors: (рис. 18.88). Следует нажать Enabled и в поле Corporateupload file path ввести путь к каталогу, в котором будут сохраняться от- четы об ошибках. Для нормальной работы оповещения об ошибках также должен быть запущен сервис Error Reporting Service (Start ► Settings ► Control Panel ► Administrative Tools ► Services ► Error Reporting Service) (рис. 18.89). В результате работы Error Reporting в указанном катало- ге будет формироваться структура каталогов, состоящая на верхнем уровне из двух каталогов: cabs и counters. В папке cabs будет находиться структура папок, соответ- ствующая именам и версиям каждого приложения, вы- звавшего ошибку, внутри которых будут содержаться файлы *.cab. Дамп для клиентского приложения будет содержаться в каталоге lcv8.exe, а для сервера ЮПред- приятия — в каталоге dllhost.exe.
Рис. 18.88. Дополнительная настройка Error Reporting Рис. 18.89. Error Reporting Service Dr. Watson Использование утилиты Dr. Watson может понадобиться при диагностике нестабильной работы системы. Dr. Watson представляет собой отладчик программных ошибок, входящий в состав Windows. Информация, собираемая и сохраняемая Dr. Watson, не- обходима, как правило, службе технической поддержки для диагностики программной ошибки на компьютере, работающем под управлением Windows. Каждый раз, ко- гда обнаруживается ошибка, создается текстовый файл, имеющий по умолчанию имя Drwtsn32.log. Этот файл мо- жет быть впоследствии передан в службу технической поддержки. Также существует возможность создания аварийного дампа (по умолчанию файл User.dmp). Ава- рийный дамп представляет собой бинарный файл, кото- рый можно загрузить в отладчик. Если возникает программная ошибка, Dr. Watson запус- кается автоматически и сохраняет файл журнала и, если указано, файл аварийного дампа. Прежде всего, следует убедиться в правильности настроек Dr. Watson. Для этого можно запустить его вручную, вы- полнив команду Start ► Run ► drwtsn32. Для диагностики ошибок достаточно настроек по умолчанию (рис. 18.90). Рис. 18.90. Окно настроек утилиты Dr. Watson Для удобства сбора файлов, которые формирует Dr. Wat- son, можно изменить стандартные пути к этим файлам. В поле Log File Path задается путь, куда будет сохранен файл журнала. В поле Crash Dump задается путь, куда бу- дет сохранен файл аварийного дампа. Обратите внимание, что должна быть установлена опция Create Crash Dump File для того, чтобы Dr. Watson создавал файл аварийного дампа. После этого следует назначить Dr. Watson отладчиком по умолчанию, так как в системе, в общем случае, может ис- пользоваться другой отладчик, который будет запускать- ся при обнаружении ошибки. Для этого нужно запустить Dr. Watson с ключом -1 (Start ► Run ► drwtsn32 -i). Сценарии оптимизации производительности Рассмотрим несколько типичных сценариев, по которым следует действовать в случае необходимости оптимиза- ции производительности прикладного решения. Для луч- шего понимания каждый из сценариев будет сформули- рован в виде краткой фразы, выражающей желаемый результат. Прикладное решение работает медленно. Что нужно поменять или переделать? Прежде всего, следует сделать оговорку о том, что опи- санная последовательность действий предполагает, что конфигурация не содержит явных ошибок в прикладном коде. В случае если стоит вопрос об анализе производи- тельности незнакомого прикладного решения, которое могло быть модифицировано без надлежащего контроля качества, прежде всего нужно проверить, не является ли
причиной низкой производительности прикладной код, который был изменен. Для этого используется оптимиза- ция производительности на уровне конфигурации (уро- вень 2). После этого можно приступать к выполнению описанного алгоритма (рис. 18.91). Рис. 18.91. Сценарий оптимизации производительности Шаг 1. Для того чтобы понять причину недостаточной производительности, прежде всего необходимо провести оптимизацию производительности на уровне оборудова- ния (уровень 5). Если производительность оборудования достаточна, то нужно переходить к оптимизации на уров- не СУБД. Если производительность оборудования недос- таточна, необходимо выполнить его модернизацию и посмотреть, достигнут ли желаемый уровень производи- тельности. Если желаемый уровень достигнут, процесс завершен. Если же нет — нужно переходить к оптимиза- ции на уровне СУБД. Шаг 2. Следует проверить оптимизацию на уровне СУБД. Если оптимизация выполнена правильно и со- блюдены все рекомендации, то нужно переходить к опти- мизации на уровнях 0 и 1. Если же требуется оптимизация на уровне СУБД, ее необходимо выполнить и посмот- реть, достигнут ли желаемый уровень производительно- сти. Если желаемый уровень достигнут, процесс завер- шен. Если же нет — нужно переходить к оптимизации на уровнях 0 и 1. Шаг 3. Необходимо выполнить нагрузочное тестирование и оптимизацию на уровнях 0 и 1. Может так случиться, что требуемый результат так и не будет достигнут. В этом случае следует обратиться за помощью в фирму «1С» с подроб- ным описанием проблемы и причин, по которым не уда- лось достигнуть требуемого уровня производительности. Отдельно следует сказать о ситуации, когда на первом шаге выявлена недостаточная производительность аппа- ратных средств, однако заказчик сомневается в целесооб- разности модернизации. Такая ситуация встречается до- вольно часто и вполне объяснима: прежде чем вкладывать средства в модернизацию оборудования, заказчик хочет знать в понятных ему терминах, какой результат он от это- го получит. В этом случае необходимо смоделировать бу- дущую конфигурацию аппаратных средств и выполнить нагрузочное тестирование, соответствующее текущей кон- фигурации заказчика. После этого можно будет предста- вить ему количественные показатели изменения произво- дительности. Например, после модернизации заработная плата будет рассчитываться столько-то времени, а прове- дение документов будет занимать столько-то времени. Если эти результаты не устроят заказчика, необходимо выполнить шаги 2 и 3, проводя после каждого из них на- грузочное тестирование на созданном макете и определяя новый уровень производительности. Какие компьютеры необходимо использовать, чтобы данное прикладное решение работало нормально? Вопрос выбора соответствующих аппаратных средств при покупке нового прикладного решения является одним из главных для заказчика. От того, насколько правильно бу- дут выбраны компьютеры, зависит успешность его вне- дрения, использования и эксплуатации. Если предполага- ется использовать типовую конфигурацию фирмы «1С», то можно воспользоваться результатами тестирования, которое проводится фирмой «1С». Если для данного ти- пового решения таких результатов нет или внедрение имеет специфические особенности, тогда следует смоде- лировать конфигурацию оборудования, в которой будет работать прикладное решение у заказчика, и провести ис- следование масштабируемости. Вот основные вопросы, на которые должно давать ответ это исследование. ♦ какие компьютеры нужны, если будет такое количество пользователей, такой объем данных и такая нагрузка на систему; ♦ в каких пределах можно увеличивать количество поль- зователей, объем данных и нагрузку на систему без мо- дернизации компьютеров; ♦ как нужно будет модернизировать компьютеры, если количество пользователей станет таким, объем данных станет таким, а нагрузка станет такой. Разработчику требуется получить параметры оборудования и возможности масштабирования для созданного им прикладного решения Третьим сценарием оптимизации производительности, который мы рассмотрим, будет ситуация, когда для ори- гинального тиражного прикладного решения требуется получить показатели производительности и рекоменда- ции по используемому оборудованию.
Этот сценарий, по сути, представляет собой нагрузочное тестирование «в полный рост». Суть выполняемых действий та же, что и в предыдущем сценарии, однако есть ряд особенностей, которые значи- тельно усложняют процесс. Во-первых, в отличие от предыдущего случая, где совер- шенно точно известна конфигурация аппаратных средств заказчика, здесь приходится ориентироваться на некото- рый усредненный вариант использования прикладного решения. Важно выбрать его так, чтобы он соответство- вал тому варианту, который будет использоваться наибо- лее часто. Для этого нужно обладать некими статис- тическими данными о том, как в настоящий момент автоматизирована данная область, отрасль и т. д. Возмож- но придется моделировать несколько различных вариан- тов типичного использования. Во-вторых, неизвестна точная нагрузка, которая будет создаваться на систему. Поэтому также нужно ориенти- роваться на некую усредненную нагрузку и, возможно, моделировать несколько различных вариантов. В-третьих, одно и то же прикладное решение может быть использовано с различными акцентами в распределении нагрузки. Наиболее наглядным примером могут служить многофункциональные системы, в которых используют- ся не все подсистемы, а лишь какая-то их часть или когда нагрузка по-разному распределена по подсистемам в пре- делах прикладного решения. Здесь также стоит задача правильного выбора и моделирования различных вари- антов. И, наконец, наиболее важная особенность — это большой объем тестирования, обусловленный первыми тремя осо- бенностями. Проведение подобного тестирования тре- бует значительных материальных (оборудование для моделирования) и временных (человеко-часы) затрат. Поэтому важным фактором в проведении такого тестиро- вания является правильный и обоснованный выбор пара- метров тестирования, проще говоря, «стоит ли овчинка выделки?» Здесь требуется делать непростой выбор ме- жду желанием исследовать тот или иной показатель, и трудозатратами, необходимыми для его исследования. Кроме этого, следует также помнить о том, что подобное тестирование должно проводиться регулярно, после каж- дого обновления прикладного решения (выпуска новой версии), поэтому сценарий тестирования и его продолжи- тельность должны укладываться в разумные функцио- нальные и временные рамки. В частности, процесс тести- рования в этом случае должен быть автоматизирован, что подразумевает также определенные затраты (как матери- альные, так и временные) на автоматизацию. Основы «тонкой» оптимизации производительности на уровне СУБД При работе в клиент-серверном варианте четвертый уро- вень (уровень СУБД) имеет четко выраженное деление еще на два уровня: высокий уровень работы с данными (запросы на языке Transact SQL), и низкий уровень работы с данными (планы запросов). Для проведения «тонкой» оптимизации производительности прикладного решения 1 С: Предприятия на уровне SQL Server понадобится ис- пользование таких инструментов, как SQL Profiler, SQL Query Analyzer и Index Tuning Wizard. Все эти инстру- менты входят в состав SQL Server. Симптомы проблем с производительностью на уровне СУБД следующие: запрос выполняется неоправданно дли- тельное время, и план запроса содержит операции Table Scan или Nested Loops. Оптимизация запросов Локализация и оптимизация проблем производительно- сти на уровне SQL Server — это отдельная тема, требую- щая специальных знаний. Ключевым моментом в понимании методов оптимизации на уровне СУБД является то, что почти всегда есть боль- шая разница между самим запросом на языке Transact SQL и той операцией, которую будет выполнять SQL Server. Это связано с тем, что язык Transact SQL предназначен для формулирования запроса в терминах ожидаемого ре- зультата, но не в терминах действий, которые необходимо для этого выполнить. То есть на языке Transact SQL мож- но сформулировать, какой результат необходимо полу- чить, но трудно (а зачастую и невозможно) описать, ка- ким образом должен быть получен этот результат. Обратите внимание на то, что язык запросов ЮПред- приятия 8.0 является SQL-подобным языком и устроен аналогичным образом. При трансляции запросы, напи- санные на встроенном языке запросов, практически без изменения транслируются в запросы на языке Transact SQL. Один и тот же запрос может быть выполнен SQL Server по-разному. Например, таблицы могут обрабатываться в разном порядке, выражения в условиях могут проверять- ся в разной последовательности, могут использоваться или не использоваться те или иные индексы, объедине- ние таблиц может осуществляться несколькими разными способами. Например, если в запросе присутствует левое соединение, то это соединение может быть осуществлено как минимум тремя разными способами (а если учесть, что таблицы могут обрабатываться в различном поряд- ке — то способов будет уже шесть): как соединение с вло- женными циклами (Nested loops join), как соединение со слиянием (Merge join) или как соединение с хеширова- нием (Hash join). Подробнее об этом можно прочитать в SQL Server Books Online — Optimizing Database Performance — Query Tuning — Advanced Query Tuning Concepts. Выбор того или иного способа выполнения операции на- ходится полностью в ведении оптимизатора SQL Server и повлиять на него «извне» довольно сложно. На низком уровне работы с данными SQL Server оперирует планом запроса (Query Execution Plan). SQL Server имеет специ- альный механизм — оптимизатор запроса, — который преобразует запрос на языке Transact SQL в план запро- са. План запроса однозначно описывает последователь- ность действий, которые необходимо выполнить для по- лучения результата. Важно понимать, что для одного и того же запроса в различных ситуациях SQL Server мо- жет выбрать различные планы запроса, которые будут да-
вать одинаковый результат за разное время. То есть в за- висимости от выбора плана запрос может работать быстрее или медленнее. Оптимизатор запросов SQL Server принимает решение о выборе того или иного плана на основании различных критериев: текущего наполнения базы данных, статисти- ки распределения значений в таблицах базы данных, сложности выполнения различных операций, предполо- жений относительно количества записей, которые будут извлечены тем или иным запросом, стремления на самых ранних стадиях выполнения запроса выбрать как можно меньшее количество записей и т. д. Кроме этого, на выбор плана запроса может повлиять, например, конфигурация компьютера, на котором работает SQL Server (количество процессоров и объем оперативной памяти). Воздействовать на оптимизатор SQL Server можно толь- ко косвенным образом. То есть в 1 С:Предприятии 8.0 не существует штатных средств, при помощи которых мож- но было бы «заставить» оптимизатор выбирать нужный план запроса. Однако можно попытаться «уговорить» его путем изменения условий, которые он учитывает, при вы- боре плана. Алгоритмы работы оптимизатора MS SQL Server доста- точно сложны и плохо документированы. Иногда бывает трудно или практически невозможно понять, почему оп- тимизатор выбрал именно этот план выполнения запроса. Примерный сценарий диагностики и оптимизации запросов Рассмотрим примерный сценарий диагностики и опти- мизации запросов на основе анализа операции расчета, выполняемой в документе НачислениеЗарплатыСотрудни- камОрганизаций конфигурации Зарплата и Управление Пер- соналом. Прежде всего нужно закрыть все приложения ЮПред- приятия, работающие с данным сервером ЮПредпри- ятия. Затем нужно выгрузить из памяти сервер ЮПредпри- ятия. Это необходимо для того, чтобы сервер 1С:Пред- приятия удалил все временные таблицы, которые он соз- дает в процессе своей работы. Для этого на компьютере, где запущен сервер предприятия, нужно выполнить ко- манду Start ► Control Panel ► Administrative Tools и запустить Component Services (рис. 18.92). Рис. 18.92. Component Services В ветке Console Root ► Component Services ► Computers ► My Computer открыть папку COM+ Applications (рис. 18.93). Нажать правую кнопку мыши на приложении 1CV8 и вы- брать из выпадающего меню команду Shutdown (рис. 18.94). Component Services Fte Action View Window Help X| ийихОйВ*! > rc 1И ж a - Console Root 0 ф Component Services aa Computers В Я My Computer E В DCOM Conf ч a Distrbuted Transaction Coordinator E a Running Processes Ё ЗЭ Event Viewer (Local) ffi Services (Local) П@'х1 COM4 Appfications 21 ob)ect(s) 1CV8 COM4 Explorer COM4 QC Dead Letter Queue... COM4 Utilities IIS In-Process IIS Applications Out-Of-Proc... Рис. 18.93. COM4 Applications Рис. 18.94. Shut down После этого следует запустить тестируемое приложение Ю: Предприятия и подготовить его к выполнению первой операции. Для нашего примера необходимо найти нуж- ный документ НачислениеЗарплатыРаботникамОрганизаций и открыть его. Следует учитывать, что подготовительные действия не должны включать в себя какие-либо расчеты и модификацию базы данных. В противном случае трас- сировку выполняемых операций SQL Profiler нужно на- чинать ДО запуска ЮПредприятия. Затем следует запустить SQL Query Analyzer и подклю- читься к тестируемой информационной базе. Теперь нужно узнать идентификатор (поле dbid) тести- руемой информационной базы. Для этого в окне SQL Query Analyzer необходимо выполнить следующий за- прос: select dbid, name from master.dbo.sysdatabases order by name В полученном результате надо найти имя тестовой базы данных и запомнить ее DBID. В нашем случае это база 19000 и ее ID — 23 (рис. 18.95). dbidjnarae 2 J16 Test 3 9 2000 J____21 1000 С |22 Н2000 7 Ю 500 6 25 6000 Рис. 18.95. Определение идентификатора базы Теперь надо запустить SQL Profiler и подготовить его к трассировке SQL-запросов, поступающих на сервер баз данных от приложения Ю. Для этого: ♦ выбрать пункт меню File ► New ► Trace; ♦ указать параметры для подключения к серверу БД;
♦ в появившемся окне Trace Properties открыть закладку Filters; ♦ установить значение фильтра DatabaselD ► Equals в то значение идентификатора DBID, который мы запомнили; ♦ запустить трассировку, нажав клавишу Run (рис. 18.96). Рис. 18.96. Trace Properties Теперь надо перейти в окно тестируемого приложения и запустить тестируемую операцию. В нашем случае для этого необходимо нажать кнопку Расчитать ► Расчитать (полный расчет). После того как выполнение операции будет завершено, следует перейти в SQL Profiler и остановить трассировку, нажав кнопку Stop selected trace. Теперь нужно сохранить полученную трассировку. Сна- чала следует сохранить ее в файл (File ► Save As ► Trace File), а затем в SQL-скрипт (File ► Save As ► SQL Script). После этого можно закрыть окно трассировки в SQL Profiler и открыть сохраненный файл трассировки. Со- храненный SQL-скрипт также следует открыть в SQL Query Analyzer. Подготовка скрипта к тестированию SQL-запросы, генерируемые 1 С: Предприятием, содержат обращение к временным таблицам, которые создаются непосредственно перед тем, как в них будут записаны данные. При повторном выполнении такого скрипта воз- никнут проблемы, поскольку во время предыдущего вы- полнения таблица уже была создана, и попытка создать ее второй раз приведет к ошибке. При этом будет отменена текущая транзакция и сброшены все блокировки, уста- новленные во время транзакции. Поскольку данная методика предусматривает неодно- кратное выполнение скрипта, то следует подготовить его к работе без ошибок. Для этого необходимо вынести все объявления временных таблиц в начало скрипта. Следует перейти в SQL Query Analyzer и произвести по- иск всех таких запросов в открытом скрипте. Все объявления временных таблиц в скрипте начинаются строкой SELECT ТОР 0, за которой идут описания полей вре- менной таблицы и команда до (рис. 18.97). Рис. 18.97. Объявление временной таблицы Найденные запросы (включая команду до) следует пере- носить в самое начало скрипта (перед первым оператором BEGIN TRANSACTION). Каждый запрос создания временной таблицы перед до со- держит оператор INTO <имя_таблицы>. Имя таблицы всегда имеет вид #ttN, где N — порядковый номер таблицы. В на- чале скрипта (перед самой первой таблицей) следует уда- лить все временные таблицы, которые создаются этим скриптом. Для этого надо написать последовательность запросов вида (листинг 18.25). Листинг 18.25. Пример последовательности запросов drop table #ttl drop table #tt2 go В результате скрипт должен приобрести следующую структуру: ♦ Удаление временных таблиц " drop table #tt 1 drop table #tt2 Go ♦ Создание временных таблиц * select top 0 ... into #ttl select top 0 ... into #tt2 • go ♦ Первая транзакция скрипта * begin transaction commit transaction ♦ Вторая транзакция скрипта ♦ ... После этого скрипт будет готов к многократному выпол- нению. Отметим, что на самом деле 1С:Предприятие имеет более сложный алгоритм работы с временными таблицами.
Дело в том, сервер 1 С: Предприятия «помнит» структуру всех уже созданных временных таблиц и в случае необхо- димости сначала ищет таблицу среди уже созданных. Если подходящая таблица найдена, то она очищается от старых данных и используется для текущего запроса. И только если такой таблицы не существует, она создает- ся заново. Поскольку SQL-скрипт, выполняемый из SQL Query Analyzer не сможет воспользоваться таблицами, создан- ными другим приложением (временная таблица сущест- вует в контексте текущего подключения и не доступна для других подключений), то следует сделать скрипт пол- ностью самодостаточным. В нашем случае это означает, что все необходимые для его работы таблицы должны быть созданы в нем же самом. Поэтому в качестве необхо- димого требования к записи скрипта выступает предва- рительная выгрузка сервера 1С:Предприятия. При этом сервер удаляет и «забывает» все созданные временные таблицы и затем создает их заново, то есть запросы созда- ния попадут в записываемую трассировку, а затем в текст скрипта. Выбор подозрительных запросов К подозрительным можно отнести запросы, время выпол- нения которых превышает некоторый предел. Значение этого предела может быть различным для разных тести- руемых операций и зависит от общего времени выполне- ния операции. Например, если общее время выполнения операции составляет 10 минут, а в трассировке присутст- вует запрос, выполняющийся, например, 6 минут, то на- верняка следует обратить на него пристальное внимание. В нашем примере будем анализировать запросы, время выполнения которых составляет более 10 секунд. Для того чтобы отобрать такие запросы нужно, перейти в SQL Profiler (где у нас уже открыта сохраненная трас- сировка операции) и установить фильтр по продолжи- тельности выполнения запроса. Для этого нужно выпол- нить команду File ► Properties перейти на закладку Filters и в ветке Duration установить значение фильтра Greater than or equal в значение 10000 (так как Duration измеряется в миллисекундах) и нажать 0К (рис. 18.98). В окно будут выведены результаты выполнения, от- фильтрованные по значению поля Duration (рис. 18.99). Рис. 18.98. Фильтр по продолжительности выполнения запроса В нашем случае таких подозрительных запросов всего два. Возьмем первый из них и попробуем его проанализи- ровать. Анализировать его удобнее всего в SQL Query Analyzer, и для того, чтобы найти этот запрос в скрипте, который открыт в SQL Query Analyzer, найдем характер- ную часть запроса и скопируем ее в буфер обмена. На- пример, пусть это будет часть текста, расположенная по- сле предложения LEFT OUTER JOIN (рис. 18.100). Перейдем в SQL Query Analyzer, откроем окно поиска (Edit ► Find) и найдем текст, который сохранен в буфере обмена. После того как текст найден, выполним поиск еще раз и убедимся, что вхождение этого текста единст- венное. Если обнаружены и другие вхождения, нужно вы- брать другой, более характерный фрагмент подозритель- ного запроса. Рис. 18.99. Результат фильтрации
THEN _CalcReg3305 MAIN. BPDateFrom л ELSE #ТМР9м Bd2O18cf05f49bcd265807050f5_SLAVE._D AT EFRON END DATEFROM, CASE ^HEN_CalcReg3305_MAIN. BPDateTifl< «ТМРЗьм ’ I1 8cf05F49bcd285807050f5 SLAVE. DATETILL THEN CalcRefl3305 MAIN BPDateTiU ELSE #TMP3ea2dB<£ i8cffl5h • C 5i f SLAVE .DATETILL END DATETILL FROM Я CalcReg3305 _CakReg3305 MAIN WITH(SERIALIZABLE) LEFT OUTER JOIN #»9ttTMF fe . j 8cft35f49bcd285807050f5 SLAVE WITH [NOLOCK] ЩИ ЗПИШ ПЗ ! INNER JOIN CalcKind263 BaseCK_CalcKind263_BaseCK_BASE CALCKIND WlTH(R EPEATABLE READ] ON CalcKind263 BaseCK BASECALCKIND. BaseCKBaseCK.TYPE » QxO8AND _CalcKtnd263 ВaseCK.BASECALCKIND BaseCKBast INNER JOIN ( SELECT ttTM^’ г • - 705015 SLAVE ..RecorderTRef „Recorder!Ref, UTM#-*->: .v 8cf05f49bcd285807050f5 SLAVE .RecotdaRRef.RecorderRRef ЙТМ- - 1 8cf05f49bcd2B5807050f5_SLAVE._LineNo LineNo, 5UM(#TMP9ea2d8d2018cf05f4 R . ;??5337^:«SLAVE..CALEND) .CALEND FROM ЙНЧ ii-rMP9pA?XfWX11 Й<ЧП^Л<^Я7ЯЯЯЛ7ПЦЛ^ At tW UrtTHfWHt Г1ГК1 25. < I > Рис. 18.100. Выбор характерного фрагмента запроса Анализ плана запроса После того как подозрительный запрос найден в SQL скрипте, нужно построить план выполнения этого запроса. Для того чтобы не «потерять» случайно найденный нами запрос в SQL-скрипте, найдем начало запроса и поставим метку (Edit ► Bookmarks ► Toggle bookmark). В дальнейшем можно будет быстро перейти к нашему запросу, выполнив команду Edit ► Bookmarks ► Next bookmark (рис. 18.101). #V3TmpTab le 1_S L AVE. _F ld3 353 RRef , #VBTmpTable1_SLAVE. _Fld33 54RRef, #V3TmpTable1_SLAVE._DATEFROM, #V8TmpTable1_SLAVE._DATETILL SELECT 00TRANCOUNT', N'OPl varbinary(16),0P2 varbinary^ go sp_executesql N'SELECT _CalcReg3 305_Q_000_T_001._RecorderTRef f_l, _CaIcReg3305_Q_0ОO_T_O01._RecorderRRef f_2 , _CalcReg3305_Q_000_T_001 ._LineNo CASE WHEN _CalcKind263._Fld3211RRef = OxOOOOOOOOOOOOOOOOOOOOC THEN CASE £ I A' Рис. 18.101. Метка Теперь, прежде чем перейти собственно к выполнению этого скрипта, создадим «идеальные» условия для SQL Server: выполним обновление статистики, реиндексацию и очистку процедурного кэша. Если в этом случае будут обнаружены проблемные планы запросов, значит, навер- няка им будет «еще хуже» при неправильной статистике и индексах. Обратите внимание, что выполнение этих ко- манд может занять продолжительное время. В новом окне о SQL Query Analyzer следует выполнить следующий запрос (листинг 18.26). Листинг 18.26. Реиндексация, обновление статистики и очистка процедурного кэша spmsforeachtabl е N' DBCC DBREINDEX ("Т'У exec spmsforeachtable N' UPDATE STATISTICS ?' DBCC FREEPROCCACHE После того как закончится обновление статистики, реин- дексация и очистка процедурного кэша, можно перехо- дить к выполнению нашего скрипта и построению плана запроса. План выполнения запроса, который мы собираемся ис- следовать, зависит от данных которые, в том числе, созда- ются в нашем скрипте до выполнения самого запроса. По- этому чтобы построить план только одного нужного нам запроса, выполним весь скрипт до нужного нам запроса, а затем выполним запрос с формированием плана запро- са. Для этого выделим весь текст, расположенный от начала запроса до начала скрипта (Shift — Control — Home), и запустим выполнение командой Query ► Execute (будет выполнен только выделенный текст). При первом выпол- нении скрипта будут выданы сообщения об ошибках сле- дующего вида: Cannot drop the table '#ttl', because it does not exist in the system catalog. Это нормальный результат первого выполнения скрипта, поскольку временных таблиц, создаваемых нами в начале скрипта, действительно еще не существует перед первым его выполнением. Для того чтобы увидеть план запроса, создаваемый SQL Server, следует выполнить команду Query ► Show Execution Plan, а затем выделить наш запрос и выполнить его. После выполнения запроса в панели результатов на закладке Execution Plan будет представлен план запроса, построен- ный SQL Server (рис. 18.102). План запроса представляет собой графическое изображе- ние последовательности операций, выполняемых SQL Server с указанием дополнительной информации об этих операциях. Дополнительная информация доступна для просмотра при наведении курсора мыши на изображение операции или на соединительную стрелку (рис. 18.103). При анализе плана запроса нас будут интересовать две операции: Table Scan и Nested Loops. Нужно понимать, что ни Table Scan, ни Nested Loops сами по себе не являются проблемой и очень часто встречают- ся в планах запроса. Для того чтобы оценить данные опе- рации как неоптимальные, следует учитывать сразу не- сколько факторов. Table Scan Table Scan представляет собой операцию выборки из таб- лицы путем полного перебора всех записей (рис. 18.104). Операция Table Scan свидетельствует о неоптимальной работе запроса в следующих случаях. Во-первых, если ее выполнение (Cost) занимает значи- тельную часть от общего времени выполнения запроса (рис. 18.105). Cost показывает удельное время выполнения этого действия в процентах от общего времени выполнения. Например, зна- чение 20% может считаться уже довольно большим и,
Рис. 18.102. План запроса Compute Scalar Cost: 0% — tsl s—’fa) s—'4» — Nested Loot®/Le.. Nested Loops/In... Bookmark Lookup Cost: Nested Loops/Left Outer Join For each row in the top (outer) input, scan the bottom (inner) input, and output matching rows. t: 0% Physical operation: Logical operation: Row count: Estimated row size: I/O cost CPU cost: Number of executes: Subtree cost: Estimated row count: Nested Loops Left Outer Join 20128 465 0,000000 4,00 1 0,000000 9 12 64.PK. . . t: 0% uh/Left... t: 0% Argument: OUTER REFERENCES :([_CalcReg3342_Q_000 T_0 01].[ RecorderTRef], LCakReg3342_Q_000_T_00 l].[_RecorderRRef], LCakReg3342_Q_000_T_00 l].[JJneNo]) Рис. 18.103. Дополнительная информация скорее всего, на него нужно обратить пристальное вни- мание. Table Scan Cost: 0% Рис. 18.104. Table Scan Table Scan Scan rows from a table. пользуется операция Table Scan, то это ситуация, близкая к «катастрофе», и на нее нужно обратить пристальное внимание. В то же время если из десяти записей выбира- ется две, то это не так интересно (при условии, что исход- ная таблица не будет постоянно расти). Также следует за- метить, что если Table Scan выбирает много записей из большой таблицы, то это вполне нормальная ситуация, которую не стоит пытаться оптимизировать. Чтобы понять, какое количество записей содержится в исходной таблице, нужно сначала узнать имя таблицы, из которой Table Scan осуществляет выборку данных, на- пример из значения Argument этой операции (рис. 18.106). Physical operation: Logical operation: Row count: Estimated row size: I/O cost: CPU cost: Number of executes: Cost: Subtree cost: Estimated row count: Table Scan Scan rows from a table Table Scan Table Scan 30 905 880 163 4,00 0,000000 290 Argument: OBJECT :([tempdb].[dbo].[#tt9 Physical operation: Logical operation: Row count: Estimated row size: I/O cost: CPU cost: Number of executes: Cost: Subtree cost: Estimated row count: Table Scan 4,00 0,000000 106572 4,000000(0%) _______________О>00000005»] AS [#TMP9ea2d8 d2018cf05f4 -»-.-SLAVED Argument: O6XCT:([teffpdb].[db(g#tt9 Рис. 18.105. Время выполнения операции ________________» CjOOCOOCF^»] as [#TMP9ea2d8 d2018cf05f4-<___»Ж>7ПЯ< .SLAVED Во-вторых, о неоптимальной работе запроса может гово- рить тот факт, что количество записей, возвращаемых в результате сканирования, составляет незначительную часть от общего количества записей. Например, если из миллиона записей возвращается десять и при этом ис- Рис. 18.106. Исходная таблица операции Затем с помощью запроса можно посмотреть количество строк в этой таблице: Select count (*) from _AccumReg2879
В приведенном примере _AccumReg2879 — это имя таблицы базы данных. Опасность операции Table Scan заключается в том, что время ее выполнения напрямую зависит от количества записей в таблице. На небольших базах время выполне- ния запроса с Table Scan будет незначительным, но во вре- мя реальной эксплуатации системы при увеличении количества записей произойдет резкое падение произво- дительности и будут заблокированы все записи в табли- це. В результате при параллельном выполнении запроса несколькими пользователями он может быть выполнен только последовательно. Это приведет к тому, что общее время выполнения запроса может быть выше, чем в си- туации, когда запрос выполняется медленнее, но парал- лельно (когда блокируются только нужные записи). ПРИМЕЧАНИЕ Следует заметить, что если Table Scan выполняет выборку из временной таблицы, то эту ситуацию можно даже не анализировать, потому что проиндексировать такую вре- менную таблицу мы не сможем, и в этом случае Table Scan — это совершенно нормальная операция, независимо от количества выбираемых данных. Сканирование всей таблицы в поисках необходимых за- писей выполняется SQL Server в следующих случаях. Во-первых, если не существует индекса, подходящего для данных условий выборки. Следует учитывать, что для эффективного отбора по значению некоторого поля дол- жен существовать индекс, в котором это поле расположе- но на первой позиции. Во-вторых, если индекс существует, но не обеспечивает нужной селективности, то есть отбор по данному полю вернет большую часть записей таблицы и дальше их при- дется перебирать непосредственно по таблице, отрабаты- вая условия по другим полям. В-третьих, если в запросе участвует большое количество полей, которые не содержатся в данном индексе. В этом случае оптимизатор может решить, что искать сначала по индексу, а затем выбирать значения полей из таблицы бу- дет дольше, чем сразу перебрать все записи таблицы. В-четвертых, операция Table Scan может быть выбрана просто в результате ошибки оптимизатора SQL Server. Учитывая все перечисленное выше можно сказать, что идеальный индекс для запроса должен в первой позиции иметь поле, отбор по которому значительно сократит ко- личество перебираемых записей таблицы, а в остальных позициях индекса содержать большую часть (желатель- но — все) поля, которые используются в запросе. Естественно, создать такой индекс не всегда возможно, но при прочих равных условиях надо к этому стремиться. При этом нужно учитывать, что добавление индекса мо- жет замедлить операции изменения данных, и этот мо- мент надо обязательно тестировать. Nested Loops Nested Loops представляет собой операцию объединения таблиц наиболее простым способом, при котором запрос к одной из таблиц выполняется столько раз, сколько вер- нул записей запрос ко второй таблице (рис. 18.107). Операция Nested Loops свидетельствует о неоптимальной работе запроса в том случае, если одна из операций, уча- ствующих в объединении, выполнялась многократно, то есть имеет значение Number of executes больше 1 (рис. 18.108). Nested Loops/Le... Cost: 0% I Рис. 18.107. Nested Loops Table Scan Warning: Statistics missing for this table. Choose 'Create Missing Statistics from the context (right click) menu. Table Scan Cost: 0% Scan rows from a table. Physical operation: Logical operation: Row count: Estimated row яге: I/O cost: CPU cost: Number of executes: Subtree cost: Estimated row count: Argument: OBJECT :([HRM].[dbo],[tt6] AS [#TMP85367ea26ea63dlMborfo>eti01dd 64JR]) Рис. 18.108. Number of executes На приведенной иллюстрации мы как раз видим такой пример: операция Table Scan, участвующая в Nested Loops, была выполнена 10 064 раза, причем общий размер вы- бранных данных составил 40 256 строк (то есть каждый раз из таблицы tt6 выбиралось 4 записи). Причем если посмотреть количество строк, возвращенных первой опе- рацией, участвующей в объединении (Nested Loops), то мы увидим, что она вернула 10 064 строки, то есть Row count для первой операции будет равно Number of executes для второй. Опасность этого действия заключается в том, что время его выполнения напрямую зависит от количества запи- сей, которые вернет первый из объединяемых запросов. То есть поведение Nested Loops во многом аналогично по- ведению Table Scan. При небольшом количестве записей, возвращаемых первых запросом, объединение отрабаты- вает быстро, но при увеличении этого количества проис- ходит резкое падение производительности. Такой алгоритм объединения таблиц хорошо работает только в том случае, если один из запросов возвращает мало записей, удовлетворяющих условию объединения. Желательно — одну запись. В том случае, если это не так, Nested Loops может стать причиной серьезных проблем
с производительностью, поскольку второй запрос будет выполняться столько раз, сколько записей вернет первый. Nested Loops — самый простой способ объединения двух таблиц, то есть накладные расходы при его выполнении минимальны. Поэтому когда оптимизатор «сомневается» в том, сколько записей вернет подзапрос, он предпочита- ет использовать Nested Loops, который будет иметь то яв- ное преимущество, что сам по себе выполняется быстро. SQL Server может выбрать план с операцией Nested Loops в следующих случаях. Во-первых, если нет актуальной статистики по распреде- лению значений в таблицах базы данных. Во-вторых, если в запросе использованы объединения сложных подзапросов, которые содержат вложенные под- запросы и так далее (листинг 18.27). Листинг 18.27. Пример объединения подзапросов ВЫБРАТЬ ... ИЗ (ВЫБРАТЬ ... ИЗ ... ГДЕ ... СГРУППИРОВАТЬ ПО ... ) СГРУППИРОВАТЬ ПО ... ЛЕВОЕ СОЕДИНЕНИЕ ВЫБРАТЬ ... ИЗ (ВЫБРАТЬ ... ИЗ ... ГДЕ ... СГРУППИРОВАТЬ ПО ... ) СГРУППИРОВАТЬ ПО ... ПО... В-третьих, операция Nested Loops может быть выбрана просто в результате ошибки оптимизатора SQL Server. Подбор индексов При обнаружении неэффективного плана запроса пер- вым делом следует узнать, какие рекомендации дает SQL Server для оптимизации индексов таблиц, участвующих в этом запросе. Для этого следует подготовить исследуемый запрос к ав- тономному выполнению и анализу с помощью Index Tuning Wizard. Для этого, прежде всего, следует просмотреть текст за- проса и определить, какие временные таблицы использу- ются в этом запросе (временные таблицы имеют имена вида #tt<HOMep таблицы>, например #tt6 или #tt8). После этого следует зафиксировать открытые транзак- ции и перенести данные временных таблиц в постоянные таблицы. Для этого в открытом окне нашего скрипта сле- дует выполнить команду commit tran а затем команды переноса данных (в данном случае дан- ные временных таблиц #tt6 и #tt8 переносятся соответст- венно в таблицы tt6 или tt8): select * into tt6 from #tt6 select * into tt8 from #tt8 Теперь нужно скопировать текст исследуемого запроса и перенести его в отдельное новое окно SQL Query Ana- lyzer. Особенность работы Index Tuning Wizard заключается в том, что он обрабатывает только «чистые» запросы, по- этому запрос, содержащийся в процедуре sp executesql нужно «вытащить» из этой процедуры. Для этого удалим текст в самом начале до слова SELECT (рис. 18.109). _CalcReg3342_q_000_T_001.-RecorderTRef f_l, _CalcReg3342_Q_000_T_001._RecorderRRef ±2, _CalcReg33420_000_T_OO1._LineNo _CalcReg3342_Q_000_T_001._AFDeteFrora f_3, _CalcReg3 3 42_0_000 T OO1. APDateTi11 t_4, _CalcKind264._Fld3222 IS, CalcKind264. Fld3223 t 6, Рис. 18.109. Выделение «чистого» запроса Теперь перейдем в конец текста. В конце текста мы видим присвоение значений трем переменным запроса: @р1, @р2 и @рЗ (рис. 110). Необходимо в тексте запроса заменить имена этих пере- менных соответствующими им значениями, например @р1 заменить на 0xB9B3AF28E5E196ED463006496A0BC66C и т. д. ON _CalcReg3342_0_000_T_001._CalcKindRRef = _CalcKind264._IDRRef WHERE _CalcKind264._Fld3230RRef - 0F1 AND _CalcReg3342_Q_000_T_001.RecorderTRef - 0F2 AND Calc' ORDER BY _CalcRegS 3 42_Q_000_T_001. _L IneNo SELECT 00TRANCOUNT' , N'0P1 varbinary (16) , 0P2 varbinary (4) , 0P3 varbinary (16) ' , OXB9B3AF28E5 go Рис. 18.110. Присвоение значений переменным запроса WHERE _CalcKind264._Fld3230RRef = 0Р1 AND _CalcReg3342_Q_000_T_001._RecorderTRef = 0P2 AND Calc ORDER BY CalcReg3342 Q ООО T 001. LineNo Рис. 18.111. Выделение «чистого» запроса
После этого последние две строки текста также можно удалить (рис. 18.111). И в заключение осталось только в тексте запроса везде заменить имена виртуальных таблиц на имена таблиц ре- альных (в нашем случае #tt6 на tt6 и #tt8 на tt8). После этого следует запустить выполнение полученного запроса и убедиться, что все изменения внесены правиль- но и план запроса не изменился. Теперь можно собственно заняться подбором индексов для таблиц, используемых в запросе. Для этого следует выполнить команду Query ► Index Tuning Wizard. Будет от- крыто окно мастера (рис. 18.112). Рис. 18.112. Index Tuning Wizard На следующих двух шагах мастер предложит выбрать базу данных и указать нагрузку. Ничего не изменяя, при- мем значения по умолчанию. На третьем шаге будет пред- ложено выбрать таблицу для настройки — выберем все таблицы (Select All Tables). После нажатия на кнопку Next мастер произведет анализ таблиц и предложит варианты использования индексов (рис. 18.113). Рис. 18.113. Index Tuning Wizard В открывшемся списке перечислены индексы, сущест- вующие в используемых таблицах. Может так случиться, что мастер не предложит ничего нового (новый ин- декс имеет специальную пиктограмму, отмеченную на рис. 18.113). С этим мнением стоит согласиться, потому что, как показывает практика, даже если, несмотря на это, проанализировать план выполнения запроса и составить индекс, которого не хватает, скорость работы запроса в лучшем случае не изменится, а в худшем может увели- читься. Если же Index Tuning Wizard предложит создать новый индекс, необходимо проанализировать возможность соз- дания такого индекса средствами ЮПредприятия. Далеко не во всех случаях система ЮПредприятие пре- доставит возможность создать требуемый индекс. Напри- мер, создать составной индекс по двум различным рекви- зитам не удастся; также не удастся проиндексировать таблицу регистра бухгалтерии по какому-либо субконто. Подробнее особенности индексирования полей базы дан- ных 1С:Предприятия описаны в разделе «Порядок», с. 61. Если создать такой индекс можно, следует найти объект конфигурации, которому принадлежит указанная таблица и проиндексировать требуемый реквизит. Index Tuning Wizard может предложить индекс, состоящий из несколь- ких полей, — в этом случае нас интересует только первое поле (поскольку разработчик, используя «принудитель- ное» индексирование в 1 (/Предприятии, может задать только первое поле составного индекса), поэтому мы так- же индексируем соответствующий реквизит. Для того чтобы сопоставить таблицу и ее поля с объектом метаданных и его реквизитами, нужно выполнить поиск соответствующего запроса ЮПредприятия (см. раздел «Поиск запроса ЮПредприятия», с. 754) и посмотреть, какие объекты метаданных задействованы в этом запросе. После этого выполнить тестовый запрос (можно в консо- ли запросов) ко всем полям этих объектов, одновременно выполнив трассировку выполняемого запроса в SQL Pro- filer. Затем сопоставить имена полей, выбираемых в за- просе ЮПредприятия, с именами таблиц и полей в трас- сировке SQL Profiler. Однако не всегда рекомендуемый индекс может быть соз- дан. Например, в случае, приведенном на рис. 18.113, Index Tuning Wizard предлагает проиндексировать вре- менную таблицу tt8. В этом случае остается последнее действие, которое мо- жет привести к успеху, — попытаться переформулиро- вать запрос ЮПредприятия так, чтобы оптимизатор SQL Server начал строить эффективный план выполне- ния запроса. Но перед этим полезно будет узнать, а возможна ли вооб- ще оптимизация выбранного нами запроса. Для этого после текста запроса, можно вставить команду, которая «заставит» SQL Server использовать вместо опе- рации Nested Loops операцию Merge Join (option (merge join)) (рис. 18.114). Запустив выполнение запроса можно оценить, насколько изменится время выполнения и каков будет план запроса в этом случае. Для примера, рассматриваемый запрос вы- полняется 43 секунды, а с опцией Merge Join время его вы- полнения составило всего 1 секунду. Это говорит о том, что план запроса, изначально выбираемый SQL Server,
действительно является неоптимальным и наш запрос в принципе может быть выполнен на порядок быстрее. вии с рекомендациями в главе «Переформулировка сложных запросов», с. 727. LEFT OUTER JOIN CalcKlndZEI UITHfREFEATABLEREA* ON _CaicReg3342_Q_000_T_001-_CalcKindRRef = _Ca UHERE _CalcKind264._Fld3230RRef - 0XB9B3AF26E5E196ED4 ORDER BY _CalcReg3 3 42_Q_000_T_001._LineNo option [merge join)| V Рис. 18.114. Использование операции Merge Join Аналогичным образом можно посмотреть, как изменится время выполнения запроса, если его заставить использо- вать третий вариант соединения Hash Join (option (hash join)). ПРИМЕЧАНИЕ Следует заметить, что в некоторых редких случаях для очень сложных запросов SQL Server может не откомпили- ровать запрос с такими опциями и просто откажется его выполнять. Поиск запроса ЮПредприятия После того как мы убедились, что запрос действительно может быть выполнен быстрее, необходимо собственно в прикладном коде ЮПредприятия найти тот самый за- прос, который мы изучаем на уровне SQL Server. Последовательность действий довольно проста: нужно запустить трассировку в SQL Profiler с фильтром, содер- жащим характерную (одинаковую для каждого выполне- ния) часть используемого нами запроса. После этого за- пустить 1 С: Предприятие и в режиме пошаговой отладки пройти всю последовательность действий, которая вы- полнялась нами при первоначальном замере. Момент, когда в SQL Profiler появится строка с текстом исследуемого нами запроса, будет говорить о том, что в ЮПредпри- ятии только что выполнился нужный нам запрос. Запустим ЮПредприятие в режиме отладки и подклю- чимся к работающему сеансу. Установим точку останова в процедуре РассчитатьВсе() модуля объекта документа НачислениеЗарплатыРаботникамОрганизаций. Эта процедура как раз и вызывается при нажатии на кнопку Рассчитать в форме документа. Теперь перейдем в SQL Profiler, выделим характерный фрагмент нашего запроса и скопируем его в буфер обмена. Запустим новую трассировку и на закладке Filters устано- вим фильтр по номеру нашей базы (DatabaselD), а в ветке TextData установим значение фильтра Like равным скопи- рованному нами фрагменту, обрамленному символами % (рис. 18.115). Запустим трассировку, в ЮПредприятии запустим про- цедуру расчета и в отладчике начнем пошаговую отладку, периодически контролируя данные, отображаемые в SQL Profiler. В результате, после того как запрос ЮПредприятия най- ден, в отладчике можно получить текст исполняемого за- проса и попытаться упростить запрос, уменьшая количе- ство уровней вложенности и сокращая количество левых соединений в нижних уровнях вложенности в соответст- Рис. 18.115. Установка фильтра Диагностика блокировок Изложенный далее сценарий предназначен для полной проверки параллельного выполнения двух произвольных операций в клиент-серверном варианте работы ЮПред- приятия. Этот сценарий позволяет гарантировать обна- ружение всех блокировок, которые могут возникнуть при параллельном выполнении двух заданных операций, и определить оправданность (необходимость) этих бло- кировок. Сценарий содержит рекомендации по выбору операций для тестирования и по преодолению обнаруженных бло- кировок. Эти рекомендации не могут подходить для всех случаев жизни, поэтому их следует рассматривать только в качестве примеров. Общие сведения о параллельности операций Можно выделить три степени параллелизма выполнения операций (в порядке ухудшения): ♦ Полная параллельность. Операции идут одновременно и не блокируют друг друга. ♦ Частичная параллельность. Операции блокируют друг друга, но эти блокировки не приводят к возникновению ошибок, то есть каждая операция завершается успешно. ♦ Одна из операций завершается с ошибкой «lock timeout» или «deadlock». Говоря о проверке операций на параллельность, следует учитывать, что различные операции по-разному сочета- ются в плане одновременного выполнения. Поэтому мож- но выделить также и три степени сочетаемости операций, проверяемых на параллельность (в порядке ухудшения):
♦ Идеальная сочетаемость. Операции должны удовле- творять следующим условиям: Операции «разнесены» по данным таким образом, что не затрагивают одни и те же записи. То есть опе- рации не обращаются к одним и тем же записям ка- ких либо таблиц данных, хотя могут обращаться к од- ним и тем же таблицам. Каждая операция работает внутри области, заполнен- ной данными. То есть в системе уже существуют дан- ные такого типа, и тестируемая операция не попадает на крайние значения этих данных. ♦ Реальная сочетаемость. Ситуация, приближенная к ре- альной жизни. Операции частично пересекаются по данным или работают «на краю» области, заполненной данными, то есть затрагивают граничные значения, на- пример, по периоду регистрации. ♦ Плохая сочетаемость. Операции работают с общими данными в пустой области данных. Исходя из этих двух классификаций, можно дать понятие работоспособной системы. Работоспособной следует счи- тать систему, которая показывает следующие результаты: ♦ Полный параллелизм при идеальной сочетаемости опе- раций. Операции, не затрагивающие друг друга по дан- ным, должны идти полностью параллельно. Наличие блокировок в этом случае будет говорить о проблемах, которые необходимо решать, поскольку они обязатель- но проявятся в реальных ситуациях. ♦ Частичный параллелизм при реальной сочетаемости операций. Операции, пересекающиеся по данным, должны блокировать друг друга. То есть в этом случае блоки- ровка является необходимым условием правильности работы системы. Однако при этом могут возникать и неоправданные блокировки, которые не следуют из логики задачи. Например, запрос может блокировать таблицу целиком, хотя для его правильной работы достаточно заблокировать только одну запись этой таблицы. На начальном этапе тестирования рекомендуется прове- рять параллельность выбранных операций в условиях идеальной сочетаемости данных. Такая проверка позво- лит выявить и преодолеть большую часть проблем с па- раллельностью операций. После того как это будет сдела- но, необходимо проверить те же операции в условиях реальной сочетаемости данных. Система блокировок MS SQL Server Система блокировок MS SQL Server является одним из важнейших механизмов обеспечения целостности данных информационной базы в многопользовательской среде. Сервер автоматически обеспечивает возможность конку- рентной работы нескольких пользователей с одними и теми же данными, таким образом, чтобы каждый пользо- ватель получал корректные результаты в соответствии с уровнем изоляции транзакций, который установлен для его соединения. SQL Server устанавливает блокировку на ресурс, как при чтении, так и при записи данных. Тип этой блокировки зависит от выполняемой операции и от уровня изоляции текущей транзакции. Важно понимать, что срок жизни любой блокировки ограничен транзакцией, внутри кото- рой она была установлена. SQL Server поддерживает два типа транзакций: ♦ Неявная (скрытая) транзакция. Транзакция этого типа не задается в явном виде, а автоматически создается сервером при выполнении любой операции с данными. То есть даже если в тексте SQL-скрипта отсутствует операция BEGIN TRANSACTION, любой запрос чтения или изменения данных (например, INSERT) будет выпол- няться в транзакции. Эта транзакция будет автоматиче- ски открыта перед началом операции и автоматически закроется после успешного ее завершения, или отмене- на в случае ошибки. ♦ Явная транзакция. Такая транзакция создается в том случае, если выполнен запрос BEGIN TRANSACTION. Все сле- дующие SQL-операторы до запроса COMMIT (или ROLLBACK) TRANSACTION будут выполняться в контексте этой тран- закции и не будут создавать своих собственных скры- тых транзакций. Что более важно: изменения, внесенные в данные с самого начала и до самого конца транзакции, будут либо полностью приняты (в случае успешного за- вершения), либо полностью отменены (в случае ошибки). По окончании транзакции SQL Server автоматически сни- мает все блокировки, которые были установлены запро- сами, выполненными внутри транзакции. Поэтому изуче- ние блокировок, накладываемых приложением, невоз- можно (и не имеет смысла) в отрыве от транзакционного контекста приложения. Блокировки предназначены для того, чтобы конкурирую- щий процесс не смог нарушить целостность данных, ко- торая установлена уровнем изоляции транзакции. SQL Server хранит блокировки в системной таблице master, dbo.syslockinfo. Каждая запись таблицы содержит полную информацию об одной блокировке, установленной SQL Server. Конфликты блокировок Не следует путать слово «блокировка» с выражением «конфликт блокировок». Под блокировкой понимается ограничение доступа к некоторому ресурсу при работе в многопользовательском окружении. Конфликт блоки- ровок — это ситуация, которая приводит к тому, что один из двух конкурирующих процессов ставится в очередь, что вызывает замедление работы системы, а в некоторых случаях может привести к ошибке «lock timeout» или «deadlock». Следует отметить, что ошибки, которые мо- гут возникнуть в результате конфликта блокировок, не приводят к потерям или разрушению данных. Однако они замедляют работу системы и делают ее использова- ние менее удобным. Приведем простой пример возникновения конфликта бло- кировок. 1. Процесс 1 посылает запрос на редактирование некото- рого ресурса, например конкретной записи (запись 1) таб- лицы 1. 2. Перед редактированием записи SQL Server устанавли- вает блокировку на данный ресурс, то есть помещает в таблицу syslockinfo информацию о том, что данная запись таблицы 1 заблокирована процессом 1. 3. Процесс 1 приступает к редактированию записи. 4. Процесс 2 посылает другой запрос, который так или иначе будет изменять тот же самый ресурс. Например, процесс удаляет все записи таблицы 1.
5. Поскольку одна из записей таблицы 1 находится в со- стоянии редактирования, то она не может быть удалена. Если это случится, то процесс 1, который эту запись уже прочитал, не сможет ее записать и завершится с ошибкой. Для того чтобы этого не произошло, SQL Server перед вы- полнением команды удаления пытается заблокировать все удаляемые записи таблицы 1. 6. Одна из этих блокировок (а именно блокировка на за- пись 1) оказывается несовместимой с уже имеющейся блокировкой на ту же самую запись и получает статус WAIT, то есть ставится в очередь. Данная ситуация называется конфликтом блокировок. До тех пор пока процесс 1 не закончит редактирование ре- сурса, процесс 2 будет находиться в состоянии ожидания. Если операция, которую выполняет процесс 1, длится не- большое время, то этот конфликт практически не скажет- ся на общей работоспособности системы. Если же опера- ция длится достаточно долго (например, потому, что находится внутри большой транзакции), то эта задержка будет заметна и может даже привести к возникновению ошибки блокировок. Блокируемые ресурсы SQL Server «умеет» блокировать ресурсы базы данных с различной степенью детализации (гранулярностью) (табл. 18.12). Таблица 18.12. Гранулярность блокировок Блокировка Обозначение Описание Блокировка базы данных DB При установке блоки- ровки на базу данных блокируются все входя- щие в нее таблицы Блокировка таблицы TAB При установке блоки- ровки на таблицу бло- кируются все записи данной таблицы, а так- же все ее индексы Экстент — часть таблицы размером 8 страниц EXT При установке блоки- ровки на экстент блоки- руются все страницы, входящие в данный экс- тент Страница — часть экстента размером 8 КВ PAG При установке блоки- ровки на страницу бло- кируются все записи данной страницы Запись — одна запись таблицы RID Диапазон индекса KEY Блокируются данные, соответствующие диа- пазону индекса При выполнении одной, даже самой простой операции с данными SQL Server может установить множество раз- личных блокировок. Например, редактирование одной за- писи может привести к появлению следующих блокировок: ♦ исключительная блокировка на редактируемую запись; ♦ разделяемые блокировки намерения на страницу и таб- лицу, которые содержат редактируемую запись; ♦ исключительные блокировки на записи всех индексов таблицы, затронутые операцией редактирования. Типы блокировок При анализе проблем блокировок необходимо уметь оце- нивать оправданность той или иной блокировки. Для того чтобы правильно это сделать, нужно понимать, ка- кие типы блокировок накладываются SQL Server при вы- полнении определенных операций. Основные блокировки. Наиболее распространенные бло- кировки, накладываемые SQL Server: Shared Lock — разделяемая блокировка (обозначается S). Накладывается на ресурс при чтении данных. Блокиров- ка гарантирует, что данные, на которые она установлена, не будут изменены другой транзакцией. Exclusive Lock — монопольная блокировка (обозначается X). Устанавливается при изменении данных. Если на ресурс установлена монопольная блокировка, то другие транзак- ции не смогут ни изменять данные, ни даже читать их. Update Lock — блокировка обновления (обозначается U). Блокировка устанавливается в том случае, если запрос на чтение данных выполняется с опцией UPDLOCK. В этом слу- чае другим транзакциям разрешается устанавливать раз- деляемые блокировки, но не позволяется устанавливать монопольные. Блокировки намерения. Предположим, что процесс 1 со- бирается изменить некоторую запись в таблице. Для это- го он накладывает блокировку типа X на эту запись. В это время другой процесс (процесс 2) хочет заблокировать ту же самую таблицу целиком (например, чтобы удалить все записи). В нашем случае процесс 2 должен быть поставлен в очередь, поскольку редактируемая запись занята другой транзакцией и ее удаление невозможно. Но для того чтобы это определить, необходимо пробежать по всем блокиров- кам, отыскивая те, которые относятся к интересующей нас таблице. Для оптимизации этого процесса и предназначе- ны блокировки намерения. Одновременно с установкой исключительной блокиров- ки на редактируемую запись, процесс 1 накладывает бло- кировки намерения на страницу, где находится эта запись и на всю таблицу. Процесс 2, пытаясь определить, имеет ли он право блокировать таблицу целиком, видит блоки- ровку таблицы и становится в очередь. При этом у него нет необходимости сканировать всю таблицу syslockinfo, достаточно найти только одну ее запись. Блокировки намерений бывают следующих типов: IS — разделяемая блокировка намерений. Если транзак- ция пытается монопольно захватить ресурсы, на которые установлена разделяемая блокировка намерений, ее вы- полнение заблокируется до момента снятия блокировки IS. IX — монопольная блокировка намерений. Запрещает дос- туп на чтение и запись к заблокированным ресурсам. SIX — разделяемо-монопольная блокировка намерений. Подсказывает менеджеру блокировок, что транзакция в основном выполняет чтение данных и лишь частично, в очень небольшом объеме — их изменение. Блокировки диапазона индекса. Блокировка этого вида позволяет заблокировать не конкретные строки или за-
писи, а диапазон строк, что позволяет блокировать запи- си по некоторому логическому условию. Например, если мы читаем записи при помощи запроса select * from tablet where fieldl > 15 то должны запретить остальным транзакциям произво- дить любые манипуляции с записями tablet, где fieldl > 15. В противном случае мы не сможем гарантировать устой- чивость результата запроса. То есть, при его повторном выполнении в той же транзакции мы можем получить другой результат. С другой стороны, мы не должны бло- кировать, например, добавление записи fieldl = 5, по- скольку это ничему не противоречит. Для решения таких задач и предназначены блокировки диапазона значений индекса. Блокировка диапазона индекса может накладываться на: ♦ диапазон между двумя значениями ключевых полей; ♦ диапазон от начала ключа до первой записи индекса; ♦ диапазон от последней записи индекса до конца ключа. Существуют следующие типы блокировок диапазона ин- декса: Ranges-S — разделяемая блокировка диапазона. RangeS-U — блокировка обновления диапазона индекса. RangeX-X — монопольная блокировка диапазона индекса. Rangel - N — блокировка тестирования. Применяется перед вставкой нового значения в диапазон индекса. Прочие блокировки. Bui k Update — блокировка массиро- ванного обновления данных (обозначается BU). Schema Stability Lock — блокировка стабильности схемы (обозначается Sch-S). Устанавливается при компиляции тела запроса или хранимой процедуры. На это время за- прещается вносить изменения в схему данных. Schema Modification Lock — блокировка изменения схемы (обозначается Sch-M). Устанавливается после внесения изменений в схему данных и снимается после заверше- ния транзакции. Состояния блокировок Каждая блокировка может находиться в одном из трех состояний: GRANT, WAIT или CNVT. GRANT — означает, что блокировка была успешно установ- лена. WAIT — означает, что при попытке добавить блокировку была обнаружена ее несовместимость с уже установлен- ными блокировками. То есть блокировка не может быть установлена в настоящий момент, но будет установлена сразу же, как только будут сняты все несовместимые бло- кировки. Иначе говоря, блокировка, а вместе с ней и вся транзакция, которая ее устанавливала, находятся в со- стоянии ожидания. Наличие блокировки, находящейся в состоянии WAIT, является признаком конфликта блокиро- вок. CNVT — транзакция может изменять тип своих блокиро- вок, то есть конвертировать одни блокировки в другие. Например, в начале транзакции выполняется запрос, ко- торый устанавливает блокировку S на некоторый ресурс, а затем выполняется другой запрос, который требует мо- нопольной блокировки X. Вместо того чтобы создавать вторую блокировку на тот же самый ресурс, SQL Server конвертирует имеющуюся, меняя ее тип. На время изме- нения блокировка переводится в состояние CNVT. Затем SQL Server проверяет, может ли он произвести конверта- цию, то есть нет ли блокировок, несовместимых с откон- вертированной. Если такие блокировки обнаружены, то текущая блокировка так и остается в состоянии CNVT до тех пор, пока не будут сняты все несовместимые блоки- ровки. Важно понимать, что если вы видите блокировку, находящуюся в состоянии CNVT, то это точно такой же конфликт блокировок, как если бы она была в состоянии WAIT. То есть транзакция, которая пытается произвести конвертацию, в настоящий момент находится в состоя- нии ожидания по причине несовместимости блокировок. Совместимость блокировок Ключевым вопросом в обсуждении блокировок является совместимость блокировок друг с другом. Совместимо- стью блокировок А и Б называется возможность устано- вить блокировку Б при уже установленной блокировке А. Если блокировки А и Б не совместимы, то это сделать не- возможно, то есть процесс, которому необходимо нало- жить блокировку Б, будет поставлен в очередь и сможет это сделать только тогда, когда блокировка А (и все дру- гие блокировки, несовместимые с Б) будут сняты. Важно понимать, что процесс блокирует другие процес- сы, но не блокирует сам себя. Вопросы совместимости блокировок относятся только к блокировкам между про- цессами, выполняемыми в контексте разных подключе- ний (табл. 18.13). Таблица 18.13. Таблица совместимости блокировок Тип IS s и IX SIX X Sch-S Sch-M BU IS + + 4- 4- 4- - 4- - - S 4- + 4- - 4- - 4- - - и + + - - - - 4- - - IX + - - 4- - - 4- - - SIX + + - - - - 4- - - X - - - - - - 4- - - Sch-S + 4- 4- 4- 4- 4- 4- - 4- Sch-M - - - - - - - - - BU - - - - - - 4- - 4- Сценарий тестирования Идея заключается в том, чтобы сохранить трассировку обеих тестируемых операций в отдельные SQL-скрипты, а затем выполнять их пошагово в разных окнах SQL Query Analyzer, отслеживая и изучая возникающие кон- фликты блокировок. Для этого необходимо: ♦ подготовить тестовую информационную базу; ♦ выбрать две операции для тестирования на параллель- ность выполнения; ♦ получить их трассировку при помощи SQL Profiler и сохранить ее в виде SQL-скрипта; ♦ вернуть тестовую информационную базу в то состоя- ние, которое она имела к моменту начала записи трас- сировок;
♦ выделить в обоих скриптах отдельные транзакции и про- верять их попарно по принципу «каждый с каждым». Для проверки блокировок двух транзакций: ♦ выполнить одну из них, начиная с запроса BEGIN TRANSACTION и заканчивая последним запросом перед COMMIT TRANSACTION; ♦ выполнять вторую транзакцию пошагово, отслеживая возникающие конфликты блокировок и анализируя их причины. Подготовка информационной базы Для тестирования параллельности выполнения операций понадобится информационная база, которая содержит данные, соответствующие исследуемой ситуации. Обра- тите внимание на то, что содержимое информационной базы окажет самое непосредственное влияние на резуль- таты тестирования, то есть на то, какие конфликты бло- кировки будут обнаружены и исследованы. Проводя тестирование на неадекватной информационной базе, есть риск: ♦ потратить время на расследование конфликтов блоки- ровок, которые никогда не встретятся в реальной жизни; ♦ упустить из виду конфликты блокировок, которые мо- гут проявиться в реальности, но не проявились на тес- товой базе. Таким образом, главное требование к тестовой информа- ционной базе — адекватность реальным данным. Идеаль- ной является ситуация, когда необходимо протести- ровать на предмет конфликтов блокировок реальную рабочую информационную базу. В случае если тестиро- вание является синтетическим, то есть не предполагает наличия реальных данных, необходимо сгенерировать информационную базу таким образом, чтобы она была максимально достоверной. Для этого необходимо реализовать обработку для их ге- нерации. Что и как будет делать эта обработка — целиком и полностью зависит от текущей задачи. Однако можно дать несколько общих рекомендаций, следование кото- рым может существенно повысить качество полученных результатов. ♦ Данные должны быть максимально приближены к ре- альным. Например, если создается список физических лиц, то в качестве фамилий не подойдут данные Фамилия!, Фамилия? и так далее. Необходимо использовать реаль- но возможные фамилии, выбирая их случайным обра- зом из ограниченного, но не слишком маленького списка. ♦ Числовые данные должны иметь реалистичный раз- брос значений. Скажем, месячный оклад может вычис- ляться персонально для каждого работника, как слу- чайное число в диапазоне 3000 — 15 000 рублей, но не может быть равен 500 рублей для всех работников. ♦ Данные должны реалистичным образом распределять- ся по времени. Скажем, если требуется уволить опреде- ленное количество работников, то не следует увольнять всех работников одним документом. Правильнее будет задать период времени, в течение которого должны быть уволены работники, и вероятность того, что тот или иной работник будет уволен — например, 15%, а за- тем идти по списку работников, увольняя их с заданной вероятностью по нескольку человек в документе. Другие рекомендации можно прочитать в разделе «Фор- мирование исходных данных», с. 711. Выбор операций для тестирования Данный сценарий описывает тестирование параллельно- сти двух конкретных операций. Естественно, реальная система содержит большое количество операций, кото- рые могут образовывать множество различных пар. Не все эти сочетания одинаково важны для обеспечения па- раллельной работы системы. Некоторые из них могут ни- когда не встречаться в реальной жизни, другие будут встречаться крайне редко или не оказывать большого влияния на параллельность работы. Следовательно, от- дельной задачей является выбор пар операций, которые необходимо протестировать на предмет параллельного выполнения. Этот выбор может диктоваться различными соображе- ниями, которые не предполагается формализовать в рам- ках настоящего описания. Нижеследующие рекоменда- ции по выбору операций являются лишь примером подхода к осуществлению такого выбора. Каждая система имеет несколько типичных сценариев использования. Например, типовая конфигурация Зар- плата и Управление Персоналом может содержать следую- щие сценарии: обычный рабочий день, конец месяца, ко- нец квартала, конец года. Сценарий предполагает выполнение определенных опе- раций с определенного числа рабочих мест и с определен- ной частотой. Например, сценарий обычного рабочего дня будет включать создание документов кадрового уче- та, получение управленческих отчетов и т. д. Сценарий конца месяца будет включать интенсивное заполнение документов начисления зарплаты и расчета налогов с не- скольких рабочих мест. Для выбора тестируемых операций необходимо описать типичные сценарии использования и замерить время всех операций, входящих в каждый из них. Например, сценарий Конец месяца для прикладного решения Зарплата и Управление Персоналом может содержать следующие операции (табл. 18.14). В приведенном примере наибольший интерес с точки зре- ния тестирования параллельности будет представлять документ НачислениеЗарплатыРаботникамОрганизаций, по- скольку он имеет максимальное общее время выпол- нения, а следовательно, вероятность того, что некий кон- курирующий процесс «встретится» с этой операцией, является максимальной. Очевидно, что интересно будет протестировать следую- щие пары: ♦ 1—1. То есть параллельный расчет двух документов На- числениеЗарплатыРаботниковОрганизаций для разных ор- ганизаций или подразделений. ♦ 1—2. ♦ 1-3. Пара 2—3 вряд ли представляет большой интерес, по- скольку вероятность «столкновения» этих процессов крайне невысока. После того как выбраны пары операций, следует принять решение относительно конкретного содержания данных, которые будут порождаться каждой из операций в дан- ной паре.
Таблица 18.14. Сценарий «конец месяца» № Название операции Длительность операции, с Частота операции, раз в день Количество рабочих мест Общее время, часов в день 1 Заполнение, расчет и прове- дение документа «Начисле- ниеЗарплатыРаботникам- Организаций» 300 15 5 6:15 2 Заполнение, расчет и прове- дение документа «Расче- тЕСН» 150 5 3 0:38 3 Заполнение, расчет и прове- дение документа «Зарплата- КВыплатеОрганизаций» 20 50 1 0:17 Предположим, что решено тестировать два документа На- числениеЗарплатыРаботникамОрганизаций (пара 1—1) при идеальной сочетаемости данных. В этом случае следует выбрать две различные организации и два достаточно от- даленных периода начисления. Например, операция 1 бу- дет начислять зарплату для ООО Лада-Вариант за январь 2004 года, а операция 2 — зарплату для СтройТехКомплекса за июнь 2004 года. При этом необходимо проследить, что- бы период регистрации не попадал на крайние значения, то есть чтобы для обеих организаций существовали доку- менты «НачислениеЗарплатыРаботникамОрганизаций» как за более ранние периоды начисления, так и за более поздние. «Тяжелые» операции, занимающие продолжительное вре- мя целесообразно разбивать на более короткие отрезки, если такая возможность предусмотрена логикой прило- жения. Например, полный цикл работы с документом На- числениеЗарплатыРаботникамОрганизаций (в случае его ав- томатической обработки) включает в себя следующие операции: автозаполнение документа, расчет документа, проведение документа. Эти действия целесообразно тестировать по отдельности по принципу «каждый с каждым». Это значительно со- кратит размер SQL-скрипта, используемого при тестиро- вании, и сделает его более обозримым. Таким образом, для данного документа мы должны про- тестировать на параллельность выполнения следующие пары действий: ♦ Автозаполнение—Автозаполнение; ♦ Расчет—Расчет; ♦ Проведение—Проведение; ♦ Автозаполнение—Расчет; ♦ Автозаполнение—Проведение; ♦ Расчет—Проведение. В дальнейшем обсуждении в качестве примера будем ис- пользовать пару Автозаполнение—Расчет. Подготовка к тестированию Подготовка скриптов к тестированию выполняется ана- логично тому, как это описано в разделе «Подготовка скрипта к тестированию», с. 747. Отличие заключается в том, что после того, как в SQL-скрипте объявления вре- менных таблиц вынесены в начало скрипта и снабжены соответствующими операторами drop table, необходимо определить границы транзакций. Одна тестируемая операция может содержать несколько транзакций, а также запросы, выполняемые вне явных транзакций, то есть при помощи транзакций скрытых. Как уже было сказано, срок жизни блокировки совпадает с границами транзакций, поэтому поиск блокирующихся запросов возможен только на уровне изучения взаимо- действия двух отдельных транзакций. Соответственно, если операция состоит из нескольких транзакций, следу- ет изучать конфликты блокировок каждой из них по от- дельности и независимо от остальных. В нашем примере исследуются конфликты блокировки операций Автозаполнение и Расчет. Предположим, что они состоят из следующих транзакций: ♦ Процесс 1. Автозаполнение: Транзакция 1А. Последовательность запросов, выполняемых вне яв- ной транзакции. " Транзакция 1Б. ♦ Процесс 2. Расчет: Транзакция 2А. Каждая транзакция начинается запросом BEGIN TRANSACTION и заканчивается запросом COMMIT TRANSACTION. Последователь- ность запросов, выполняемых вне явной транзакции, начи- нается после запроса COMMIT TRANSACTION первой транзакции и заканчивается перед запросом BEGIN TRANSACTION второй транзакции. Каждый запрос этой последовательности вы- полняется в своей собственной скрытой транзакции. Все скрытые транзакции, содержащиеся в обоих скрип- тах, следует преобразовать в явные. Для этого необхо- димо обрамить запросами BEGIN TRANSACTION и ROLLBACK TRANSACTION каждый такой запрос по отдельности. Предпо- ложим, что последовательность запросов, выполняемых вне явной транзакции в процессе 1, состояла из 10 запро- сов. В таком случае получим два скрипта: ♦ Скрипт Автозаполнение: 12 транзакций. ♦ Скрипт Расчет: 1 транзакция. Тестирование Тестирование следует проводить в условиях, когда никто не работает с тестовой информационной базой. В против-
ном случае будет невозможно отделить «свои» блокиров- ки от «чужих», и никакой анализ конфликтов блокиро- вок будет практически невозможен. Перед началом тестирования необходимо воспроизвести ситуацию, которая была на момент начала записи обеих трассировок. В нашем случае для этого необходимо: ♦ открыть первое приложение 1С:Предприятия, найти документ 1, очистить и записать его. Документ будет го- тов к автозаполнению; ♦ открыть второе приложение 1С:Предприятия, найти документ 2, выполнить операцию автозаполнения и за- писать его. Документ будет готов к расчету. Обратите внимание на то, что мы заполняем и рассчитыва- ем уже существующий документ, а не создаем его заново. Дело в том, что полученный в результате трассировки SQL- скрипт содержит в явном виде идентификатор документа, который участвовал в расчете. Если мы удалим документ и создадим его заново, то идентификатор будет уже другим и записанный нами SQL-скрипт не будет правильно работать. Для тестирования конфликтов блокировок, возникаю- щих при конкурентном исполнении двух скриптов, необ- ходимо решить, какой из скриптов будет выступать в роли блокирующего, а какой — в роли блокируемого. Вы- бор роли не окажет влияния на полученный результат. Однако удобнее использовать в качестве блокирующего тот скрипт, который содержит меньшее количество тран- закций. Для нашего примера получим следующее распределение ролей: ♦ Процесс 1 (Автозаполнение) — блокируемый скрипт. ♦ Процесс 2 (Расчет) — блокирующий скрипт. Последовательность тестирования. 1. Открыть блокирующий скрипт в отдельном окне SQL Query Analyzer. 2. Выполнить все запросы удаления и создания времен- ных таблиц. 3. Выполнить первую транзакцию, начиная с запроса BEGIN TRANSACTION и заканчивая последним запросом пе- ред COMMIT TRANSACTION. В этом случае транзакция оста- нется незавершенной, и все ее блокировки будут ак- тивны до тех пор, пока не будет выполнен запрос COMMIT TRANSACTION или не отмена транзакция при помощи кнопки Cancel Query Execution. 4. Открыть блокируемый скрипт во втором окне SQL Query Analyzer и запустить его на выполнение цели- ком, 5. Если блокируемый скрипт выполнится до конца, то те- кущая транзакция блокирующего скрипта не создает конфликтов блокировок. Завершаем ее и переходим к следующей транзакции блокирующего скрипта. То есть выполняем запрос COMMIT TRANSACTION текущей транзакции и повторяем те же самые действия, начи- ная с шага 3 для всех последующих транзакций блоки- рующего скрипта. 6. Если блокируемый скрипт «завис», то имеется кон- фликт блокировок. Переходим к анализу конфликта блокировки. 7. Если нет уверенности в том, что блокируемый скрипт «завис», но это можно предположить судя по времени его выполнения, то следует перейти к анализу кон- фликта блокировок. На первых шагах анализа ситуация будет диагностирована более точно. Сбор информации о конфликте блокировок Работа с процедурой splock. Для анализа конфликта блокировок нам понадобится еще одно окно SQL Query Analyzer. В нем мы будем изучать текущие блокировки, установленные SQL Server, и определять причины кон- фликтов блокировок. Основным инструментом анализа блокировок является системная хранимая процедура sp_l ock. Она выдает теку- щий список блокировок SQL Server в следующем фор- мате: SPID — идентификатор процесса SQL Server. DBID — идентификатор базы данных. Objld — идентификатор объекта, на который установлена блокировка. Indld — идентификатор индекса. Туре — тип объекта. Может принимать значения: DB, EXT, TAB, PAG, RID, KEY. Resource — заблокированный ресурс. Mode — тип блокировки. Status — статус процесса SQL Server. Может принимать значения: GRANT — блокировка установлена. WAIT — блокировка поставлена в очередь и ожидает, когда будут сняты все несовместимые блокировки. CNV — попытка конвертировать блокировку, то есть изме- нить ее тип. Процедура sp lock имеет один параметр — идентификатор (или список идентификаторов через запятую) процесса SQL Server. Идентификатор процесса текущего окна SQL Query Analyzer указан в правом нижнем углу формы ря- дом с именем пользователя. Нас будут интересовать бло- кировки процессов в тех окнах SQL Query Analyzer, где открыты тестируемые скрипты. Следует запомнить или записать эти идентификаторы. В каждом случае эти иден- тификаторы будут разными. Для нашего примера предпо- ложим, что идентификатор процесса 1 (Автозаполнение) — 51, а идентификатор процесса 2 (Расчет) — 52. Поиск конфликта блокировок 1. Перевести SQL Query Analyzer в текстовый режим ото- бражения результата (Ctrl-T). 2. Получить список блокировок блокируемого скрипта. Для нашего примера: sp_lock 51. 3. Перейти в окно результата и найти (при помощи ком- бинации клавиш Ctrl-F) блокировку, находящуюся в со- стоянии ожидания. Такая блокировка будет иметь статус WAIT. Если такая блокировка найдена, то скопировать ее в окно запроса для дальнейшего анализа. 4. Если блокировка со статусом WAIT не найдена, то искать блокировку со статусом CNV. Если такая блокировка най- дена, то скопировать ее в окно запроса для дальнейшего анализа. 5. Если блокировка со статусом CNV не найдена, то в дан- ном случае мы имеем дело не с конфликтом блокировок, а с большим временем выполнения запроса.
Поиск заблокированного ресурса Статус WAIT или CNV говорит о том, что данная блокировка находится в состоянии ожидания, то есть процесс, кото- рый пытается ее установить, «висит». Строка описания блокировки содержит полные сведения об общем ресур- се, который стал причиной конфликта блокировок. То есть именно он понадобился обоим процессам. Эта ин- формация будет нужна нам для поиска конкретных за- просов, которые захватывают этот ресурс. Пример такой строки: SpiddbidObjldlndldTypeResourceModeStatus 532731033513KEY(c30097d7dal7)XWAIT Из этой строки можно понять, каков тип захваченного ре- сурса, и узнать имя таблицы SQL Server, к которой при- надлежит данный ресурс. Для этого выполним запрос: select name from sysobjects where id = 73103351 В нашем примере получим следующий результат: name _CalcReg3252 Таким образом, заблокированный объект относится к таблице _CalcReg3252. В разделе «Подбор индексов», с. 752, описана процедура, которая позволяет установить соответствие таблицы базы данных определенному объ- екту конфигурации ЮПредприятия. Поскольку в данном случае заблокирована запись индек- са (Туре = KEY), мы должны знать, какой именно индекс со- держит заблокированную запись. Для этого выполним за- прос: select name from sysindexes where id = 73103351 and indid = 3 В нашем примере получим результат: name _CalcReg3252_ByRecorder_RN Более подробную информацию о составе полей таблицы и индекса можно получить при помощи запроса: sp help _CalcReg3252 Поиск конфликтующих запросов После того как мы выяснили, что данная транзакция бло- кирующего скрипта вызывает конфликт блокировок, и узнали, за какой общий ресурс «поспорили» два конкури- рующих процесса, необходимо понять, какие именно за- просы в обоих скриптах блокируют этот ресурс. Каждый из процессов, будучи выполнен совершенно самостоя- тельно, будет устанавливать ровно ту же самую блокиров- ку. По этому признаку мы можем обнаружить запрос, ко- торый это делает. Мы можем быть уверены в следующем: ♦ оба процесса захватывают один и тот же ресурс. Иначе говоря, создают записи в таблице syslockinfo, для кото- рых поля dbid, Objld, Indid, Type, Resource — будут одина- ковыми. Поля Spid, Mode и Status могут быть разными; ♦ в тексте искомого запроса упоминается имя таблицы, к которой принадлежит заблокированный ресурс. Перед началом поиска запросов необходимо прервать ра- боту обоих скриптов. Для этого нужно: ♦ перейти в окно SQL Query Analyzer с блокируемым скриптом и нажать кнопку Cancel Query Execution; ♦ перейти в окно SQL Query Analyzer с блокируемым скриптом и выполнить команду ROLLBACK TRANSACTION. Действия по поиску блокирующего запроса одинаковы как для блокируемого, так и для блокирующего скрипта. Последовательность тестирования скриптов в данном случае не важна. Алгоритм поиска конфликтующих запросов в скрипте: 1. Перейти в окно скрипта и найти первое упоминание таблицы, к которой относится заблокированный ре- сурс. В нашем случае это будет таблица _CalcReg3252. Предположим, что именно этот запрос является при- чиной конфликта, то есть блокирует общий ресурс. 2. Выполнить скрипт с начала до найденного запроса включительно. 3. Перейти в третье (тестовое) окно SQL Query Analyzer и выполнить запрос splock, указав идентификатор тестируемого процесса. Например: sp lock 52. 4. Открыть окно результатов запроса (Ctrl-R) и выпол- нить поиск нужной блокировки. Параметры заблоки- рованного ресурса были нами сохранены на одном из предыдущих шагов. Теперь достаточно скопировать их в окно поиска, начиная с Objld до Resource включитель- но. В нашем случае это будет следующий фрагмент: Spi ddbidObjIdIndIdTypeResourceModeStatus 532731033513KEY(c30097d7dal7)XWAIT 5. Запустить поиск по этому фрагменту. Если поиск ока- зался успешным, то есть блокировка такого ресурса найдена, то текущий запрос (тот, на котором мы закон- чили выполнение скрипта) является искомым. 6. Если блокировка с таким ресурсом не найдена, то сле- дует повторить действия, начиная с шага 2, для сле- дующего запроса, в котором упоминается нужная таб- лица. Поиск конфликтующих запросов на прикладном уровне Итак, теперь мы знаем, какие SQL-запросы привели к возникновению конфликта блокировок. Но этого не- достаточно для понимания общей картины. Почти всегда бывает необходимо выяснить, какие действия прикладно- го уровня (уровня приложения ЮПредприятия) приве- ли к генерации конфликтующих запросов на уровне SQL. Этот анализ можно производить независимо для блоки- руемого и для блокирующего процессов. Алгоритм поис- ка в обоих случаях будет одинаковым. Нам необходимо найти команду языка ЮПредприятия, которая привела к генерации конфликтующего запроса. Порядок выпол- нения этого действия описан в главе «Поиск запроса 1С:Предприятия», с. 754. Анализ полученной информации Итак, мы располагаем полной информацией о данной блокировке (как на уровне прикладного решения, так и на уровне SQL Server) и о том, какой именно ресурс за- блокирован. Перейдем к анализу этой информации. Необходимо проанализировать оба конкурирующих про- цесса. Главными результатами анализа должны быть от- веты на следующие вопросы: ♦ Является ли данный конфликт блокировок оправ- данным, то есть вытекающим из прикладной логики задачи? ♦ Если конфликт блокировок является неоправданным (ошибочным), то на каком уровне была выполнена ко-
манда, которая привела к установке неправильной бло- кировки: На уровне прикладного решения. Прикладное решение содержит команду, обращающуюся к данным, без ко- торых можно обойтись исходя из логики задачи. На урювне 1 (^Предприятия. Команды прикладного уровня верны, но при их трансляции в запросы SQL Server, 1 С: Предприятие ошибочно обращается к дан- ным, без которых можно обойтись, исходя из логики задачи. На уровне SQL Server. 1 С: Предприятие посылает пра- вильные SQL-запросы, но SQL Server накладывает неоправданные (неадекватные) блокировки, которые приводят к конфликтам с блокировками других про- цессов. Возможны различные подходы к анализу полученной ин- формации. Наиболее оправданной представляется сле- дующая последовательность действий: ♦ На уровне SQL Server определить соответствие SQL- запроса и устанавливаемых им блокировок. Если бло- кировки не адекватны запросу, то есть блокируют из- быточные ресурсы информационной базы, то источни- ком проблемы является уровень SQL Server. Как показывает практика, этот случай является наиболее распространенным. ♦ Если блокировки адекватны SQL-запросу, то следует определить их адекватность по отношению к приклад- ному запросу. Для этого требуется анализ на уровне прикладного решения. Если такая адекватность обна- ружена, то есть блокируются ровно те ресурсы, которые задействованы в запросе, то источником проблемы яв- ляется прикладное решение. ♦ Если блокировки неадекватны прикладному запросу, то есть блокируют избыточные ресурсы, то проблема заключена в некорректной трансляции прикладного за- проса в запрос SQL. Таким образом, источником про- блемы является уровень ЮПредприятия. Дальнейшие действия зависят от результатов анализа и от постановки задачи. Если мы выяснили неадекват- ность блокировок для одного из конкурирующих процес- сов и хотим получить полную параллельности процессов, то мы должны добиться адекватности блокировок, решая проблему на том уровне, где она локализована — на уров- не прикладного решения, 1 С:Предприятия или SQL Server. Способы решения проблемы целиком и полно- стью зависят конкретной ситуации и не могут быть пол- ностью формализованы в рамках настоящей методики. Соответствие SQL запроса и блокировки Первый вопрос, на который необходимо получить ответ: является ли данная блокировка оправданной с точки зре- ния запроса? Иначе говоря: не заблокировал ли SQL Server больше, чем нужно для выполнения данного SQL-запроса? Здесь следует понимать, что блокировки устанавливают- ся исходя из плана запроса, а не из запроса в его пользо- вательском представлении. Например, для выполнения запроса select * from tablel with(serializable) where id = 1 вполне может быть выбран план, включающий полный перебор всех записей таблицы tablel (операция Table Scan). В результате блокировка будет установлена не на одну-единственную запись, которая реально участвует в запросе, а на все записи таблицы или — что то же самое — на таблицу целиком. Естественно, что все конкурирую- щие запросы, обращающиеся к данной таблице, столкнут- ся с конфликтом блокировок, даже в том случае, если они затрагивают записи отличные от id = 1. Признаком такой ситуации является несоответствие ме- жду тем, что написано в запросе и тем, какие блокировки этот запрос устанавливает. В приведенном примере несо- ответствие будет заключаться в том, что операция, реаль- но затрагивающая одну единственную запись (в чем мож- но убедиться, исходя из результатов ее выполнения) устанавливает блокировку следующего вида: Spi ddbidObjIdIndIdTypeResourceModeStatus 53273103351TABSGRANT Очевидно, что в этом случае план содержит совсем не то же самое, что написано в запросе. Включим режим отображения плана (CtrL-K), выполним запрос и откроем закладку Execution Plan в окне результа- та запроса. Одна из операций плана в нашем случае будет выглядеть таким образом (рис. 18.116). Рис. 18.116. Table Scan То есть, как и предполагалось, вместо получения одной записи сканируется (а значит, блокируется) вся таблица. При наведении указателя мыши на этот рисунок в окне SQL Query Analyzer, будет показана более подробная ин- формация о том, какая таблица сканируется в данном случае. Такая ситуация довольно часто встречается на практике, но, конечно, не является единственно возможным случа- ем, когда блокировка неадекватна выполняемому запро- су. Не представляется возможным дать исчерпывающее описание всех таких случаев в рамках данной методики. Возможно лишь указать общее направление: необходимо определить оправданность установленных блокировок путем сопоставления: ♦ исходного текста запроса; ♦ результатов выполнения запроса; ♦ плана выполнения запроса; ♦ блокировок, устанавливаемых запросом. Итак, мы определили, что SQL Server устанавливает бло- кировки, несоответствующие исполняемому запросу. В этом случае следует попытаться «воздействовать» на компилятор SQL Server с целью получения другого, бо- лее выгодного с точки зрения блокировок плана запроса. Подробнее см. «Рекомендации по преодолению конфлик- тов блокировок на уровне SQL Server», с. 763. В том случае, если изучаемая блокировка соответствует запросу, то есть блокирует ровно те ресурсы, которые нужны, переходим к решению следующего вопроса: явля- ется ли данная блокировка оправданной с точки зрения прикладной логики задачи. Иначе говоря, не заблокировал ли SQL Server больше, чем нужно для выполнения дан- ной прикладной команды?
Соответствие блокировки прикладной логике задачи Обратимся к уровню прикладного решения. Необходимо проанализировать логику работы данной команды для того, чтобы понять, какие прикладные ресурсы потребу- ются для ее выполнения. Кроме того, необходимо сопос- тавить эти прикладные ресурсы с ресурсами уровня SQL Server. При этом следует учитывать что: ♦ один прикладной объект уровня приложения может храниться в виде нескольких записей в нескольких раз- ных таблицах SQL Server; ♦ одна команда прикладного уровня может транслиро- ваться в несколько запросов SQL (один из которых и является причиной конфликта блокировок). Скорее всего, потребуется снять трассировку отдельно для данной прикладной команды. Затем, сопоставляя прикладной запрос и SQL-запрос (или несколько SQL- запросов), поступивший на выполнение на SQL Server, нужно определить, являются ли установленные блоки- ровки адекватными с точки зрения прикладной логики. Если соответствие установлено, то источником проблемы является прикладной уровень, и решать проблему следу- ет на уровне приложения исходя из его функциональных требований. В противном случае имеет место несоответствие между прикладной командой и генерируемыми в результате SQL-запросами, которые блокируют больше данных, чем необходимо. То есть источником проблемы является 1С:Предприятие. Такая проблема может быть решена только на уровне платформы. Рекомендации по преодолению конфликтов блокировок на уровне SQL Server Компилятор запросов SQL Server является «черным ящиком», который работает по сложным и плохо доку- ментированным алгоритмам. Не всегда можно понять, почему он выбрал именно такой план исполнения запро- са. Но в том случае, если понять это удалось, возникает возможность косвенным образом воздействовать на ком- пилятор с целью получения более оптимального (с точки зрения блокировок) запроса. Регламентные работы Следует учитывать, что выбор того или иного плана опре- деляется большим количеством факторов, не все из кото- рых доступны для изучения. По этой причине один и тот же запрос может компилироваться в разные планы вы- полнения при условиях, которые кажутся пользователю идентичными. Одним из факторов, сильно влияющих на выбор плана, является статистика — информация о плотности рас- пределения значений в индексах таблиц. SQL Server не обновляет статистику в реальном режиме времени, поэто- му, например, план запроса может вдруг «испортиться» после массированного обновления данных. Ситуация с блокировками, как правило, ухудшается по мере того, как статистика делается неактуальной. Сервер начинает чаще ошибаться в выборе правильного плана, чаще пред- почитает заблокировать таблицу целиком, чем искать по индексу и так далее. Для обновления статистики по всем таблицам базы дан- ных необходимо открыть отдельное окно SQL Query Analyzer и выполнить там следующий запрос: sp msforeachtable N'DBCC DBREINDEX ('•?')• Эта операция требует монопольного доступа к каждой таблице базы данных, поэтому во время работы запроса не должно быть незакрытых транзакций. Если незакры- тые транзакции имеются, то запрос «зависнет» и будет ждать, пока нужная ему таблица не станет доступна. Кроме того, рекомендуется время от времени выполнять следующий запрос: DBCC FREEPROCCACHE Эта команда сбрасывает ранее откомпилированные за- просы, и SQL Server вынужден заново создавать план вы- полнения. Рассмотрим несколько типичных случаев установки из- быточных (с точки зрения запроса) блокировок. Блокировка всей таблицы в результате выбора плана Table scan Как правило, SQL Server выбирает план Table Scan для за- проса к таблице по причине отсутствия подходящего ин- декса. В самом простом случае запрос содержит условие по полю, которого нет ни в одном из индексов таблицы. В этом случае следует рассмотреть возможность создания индекса по этому полю либо включения его в один из су- ществующих индексов. Обратите внимание на то, что по- рядок полей в индексе является ключевым моментом при выборе индекса, подходящего для того или иного условия выборки. Если условие выборки содержит условие по од- ному полю, то недостаточно, чтобы это поле просто при- сутствовало в одном из индексов. Необходимо, чтобы оно было первым полем индекса или чтобы отбор (условие) включал и предыдущие поля индекса. В противном слу- чае поиск по индексу ничего не даст, поскольку SQL Server придется перебирать все записи индекса, что, как правило, менее выгодно с точки зрения производительно- сти, чем прямой перебор всех записей таблицы. Запрос выбирает множество полей, не содержащихся ни в одном индексе, и результатом этого запроса является большое количество записей. В этом случае сервер так же может решить сканировать таблицу, поскольку для полу- чения результата ему необходимо не только найти нуж- ные записи по индексу, но и обратиться к таблице за зна- чениями полей, которые указаны в выборке. Блокировка всей таблицы в результате эскалации блокировок Эскалация блокировок является средством оптимизации SQL Server его собственной работы. При активной работе нескольких пользователей либо при наличии «тяжелых» транзакций, содержащих большое количество действий, в таблице syslockinfo накапливается большое количество блокировок, что сказывается на производительности ра- боты с ними, то есть увеличивает время, потраченное SQL Server на «непроизводительные расходы». Сущест- вует некоторое пороговое значение количества блокировок, начиная с которого SQL Server может принять решение об эскалации блокировок, то есть об их укрупнении. На- пример, он может удалить несколько тысяч блокировок
на отдельные записи таблицы и вместо них создать одну блокировку на всю таблицу. Пороговое значение количе- ства блокировок определяется SQL Server исходя из про- изводительности компьютера, на котором он исполняется. Ключевое значение для определения порогового числа имеет объем оперативной памяти, доступной SQL Server. Это связано с тем, что таблица syslockinfo целиком хра- нится в оперативной памяти сервера. Следовательно, ко- личество блокировок напрямую влияет на объем памяти, доступный для решения других задач. Если блокировки занимают более 40% оперативной памяти, то сервер будет пытаться уменьшить количество блокировок путем эска- лации. Определить, что произошла эскалация блокировок, мож- но при помощи SQL Profiler: 1. Открыть окно свойств фильтра и перейти на закладку Events. 2. Добавить в группу Selected event classes событие Lock: Escalation из группы Locks. 3. Выполнить запрос. 4. Если трассировка профайлера показывает строки со значением поля Eventclass = Lock:Escalation, то мы имеем ситуацию эскалации блокировок. В качестве средства борьбы с эскалациями блокировками можно рекомендовать: ♦ разбиение «тяжелых» транзакций на несколько более мелких. Это приведет к уменьшению числа одновремен- но установленных блокировок и может помочь спра- виться с эскалациями блокировок; ♦ увеличение количества памяти сервера баз данных. Ко- личество памяти является одним из факторов, которые оценивает SQL при принятии решения об эскалации блокировок. Ее увеличение приведет к увеличению максимально допустимого числа блокировок, при кото- ром эскалация не наступает. Блокировка диапазона индекса в результате отсутствия записей, удовлетворяющих запросу Блокировка на весь диапазон значений индекса может воз- никнуть в том, случае, если запрос осуществляет выборку по условию, но сама таблица при этом является пустой. Такая ситуация практически равносильна блокировке всей таблицы, поскольку почти любой конкурирующий запрос к этой таблице приведет к конфликту блокировок. В этом случае таблица блокировок будет сдержать за- пись, с полем Resource = (ffffffffffff). Например, такую: SpiddbidObjldKIndldTypeResourceModeStatus 532731033513KEY(ffffffffffff)RangeS_SGRANT Решения, которые можно предложить в данном случае: из- менить логику работы приложения таким образом, чтобы таблица всегда содержала некоторый набор записей или исключить обращения к таблице, поскольку она пустая. В том случае, если таблица содержит записи, но они не удовлетворяют условию запроса, SQL Server будет бло- кировать диапазон между двумя соседними значениями ключа. Предположим, что некая таблица содержит сле- дующие записи: Id = 1 Id = 2 Id = 3 Id = 10 Если выполнить запрос по условию id = 5, то (при нали- чии ключа по полю id) будет заблокирован диапазон это- го ключа от id = 3 до id = 10 включительно. Это делается для того, чтобы гарантировать, что ни одна конкурирую- щая транзакция не сможет добавить запись id = 5 либо поменять граничные значения (3 и 10) на 5. Если же выполнить запрос по условию id = 20, то SQL Server должен будет заблокировать диапазон от id = 10 до предельного возможно значения поля id. Блокировка та- кого большого диапазона значений так же с высокой ве- роятностью приводит к конфликту блокировок. Многоязычныеприкладныерешения Система 1С:Предприятие позволяет использовать раз- личные языки как при разработке прикладного решения, так и при работе пользователей прикладного решения. Благодаря механизмам интернационализации становится возможным создание прикладных решений на языках, от- личных от русского, а также многоязычных прикладных решений. Многоязычные прикладные решения позволя- ют каждому пользователю работать с интерфейсом на привычном ему языке. Можно сказать, что благодаря механизмам интернацио- нализации одно и то же прикладное решение способно различным образом представлять одни и те же строки ин- терфейса, одни и те же логические элементы прикладного решения. Например, значение даты — 10:56:35 20 августа 2004, — может быть представлено как 2004 20 08, ЗабаЬзззо 10:56:35 для грузинского пользователя, и как ларсюкьу'Т], 20 avyovcrov 2004 10:56:35 пр для пользова- теля из Греции. Одна и та же надпись пункта меню Найти может быть представлена как Табу для пользователя из Казахстана и как Suchen для пользователя, разговариваю- щего на немецком языке. Система 1С:Предприятие, работающая на компьютере пользователя, имеет четыре «источника», которые мо- гут вызывать «проявление» определенных региональных особенностей в процессе работы пользователя: ♦ операционная система; ♦ информационная база ЮПредприятия; ♦ платформа ЮПредприятия; ♦ конфигурация. Каждый из перечисленных источников (за исключением операционной системы) имеет свои собственные средст- ва, благодаря которым становится возможным отобра- жение в прикладном решении различных региональных особенностей и языков. Операционная система. Влияние операционной систе- мы сказывается при установке системы ЮПредприятие
и при установке дистрибутивов прикладных решений, созданных в системе ЮПредприятие. Система ЮПред- приятие использует региональные настройки операцион- ной системы для выбора наиболее подходящего языка программы установки. Региональные настройки операци- онной системы не оказывают влияния на работу пользо- вателей с прикладным решением 1 С: Предприятия. Информационная база. Информационная база ЮПред- приятия имеет региональные установки, похожие на на- стройки операционной системы. Их просмотр и измене- ние могут быть выполнены командой Администрирование ► Региональные установки ИБ... (рис. 18.117). Рис. 18.117. Региональные установки информационной базы Важным моментом здесь является то, что все эти свойст- ва можно не указывать, за исключением свойства Язык (Страна). Список доступных языков/стран достаточно велик, однако он включает в себя не все языки/страны, которые доступны в региональных настройках операци- онной системы. Например, в этом списке отсутствуют языки с написанием справа налево. Если другие регио- нальные установки информационной базы не указаны в явном виде, они будут определяться установками, приня- тыми в ЮПредприятии для указанного языка/страны по умолчанию. Из этого следует важный вывод: региональные установки информационной базы одинаковым образом влияют на представление данных для всех пользователей данной информационной базы. Платформа 1С:Предприятия. Платформа ЮПредпри- ятия влияет на прикладное решение благодаря тому, что позволяет использовать различные языки интерфейса плат- формы. При запуске клиентского приложения пользо- ватель может указать язык, который будет использовать- ся для вывода системных меню, диалогов, сообщений, справки и т. д. Таким образом, та часть интерфейса при- кладного решения, которая обеспечивается непосредст- венно платформой, будет отображаться на выбранном языке. Поскольку каждый пользователь запускает свой экземпляр клиентского приложения, платформа ЮПред- приятия будет оказывать влияние уже на каждого пользо- вателя в отдельности. Конфигурация. На уровне конфигурации основным средст- вом, позволяющим интернационализировать прикладное решение, являются объекты конфигурации Язык. Благодаря тому, что в прикладном решении может быть определено необходимое количество языков, каждый пользователь мо- жет использовать интерфейс прикладного решения на сво- ем родном языке (ту его часть, которая обеспечивается кон- фигурацией). Кроме этого встроенный язык, а также и некоторые другие механизмы системы, могут использовать языки конфигурации для управления отображением дан- ных. На уровне конфигурации региональные особенности могут проявляться уже не только для каждого конкретного пользователя, но и для одного и того же пользователя в за- висимости от логики прикладного решения. Например, печатная форма отчета может быть получена пользователем на его родном языке, а также на языке, ко- торый он выберет при формировании отчета. Рассмотрим более подробно, какое влияние на приклад- ное решение оказывает каждое из перечисленных средств интернационализации, и какие существуют особенности на каждом из уровней. Информационная база Региональные установки информационной базы опреде- ляют представление данных примитивных типов — Число, Дата, Булево. Формат представления чисел, дат и логиче- ского типа используется в пользовательском интерфейсе, а также при преобразовании соответствующих значений в строку. Кроме этого, региональные настройки информационной базы влияют на представление встроенного календаря и на порядок сортировки строк. Встроенный календарь Встроенный календарь может быть вызван по команде Сервис ► Календарь. Также встроенный календарь ис- пользуется системой при редактировании значений полей ввода, имеющих тип Дата. Кроме этого, ка- лендарь доступен в формах как элемент управления ПолеКалендаря. При отображении календаря система всегда будет ис- пользовать региональные установки информационной базы. Например, при указании региональной установки Английский (Великобритания) для всех пользователей ин- формационной базы календарь будет отображаться сле- дующим образом (рис. 18.118). Рис. 18.118. Календарь при региональной установке Английский (Великобритания)
Если будет выбрана, например, региональная установка Гру- зинский (Грузия), календарь примет такой вид (рис. 18.119). Рис. 18.119. Календарь при региональной установке Грузинский (Грузия) Порядок сортировки строк Порядок сортировки строк определяет правила сравнения строк для того или иного языка и, соответственно, порядок сортировки строк в базе данных. Забегая вперед скажем, что внутри платформы ЮПредприятие все строки хранятся в формате UNICODE. Строковые данные в базах данных также сохраняются в UNICODE. Соответственно и все индексы в ба- зах данных строятся на основе UNICODE-представлений. Стандартом определен некоторый генеральный порядок сортировки для UNICODE. Но он подходит не для всех язы- ков. Поэтому для некоторых языков в упомянутый гене- ральный порядок внесены минимальные изменения для обеспечения соответствия конкретному языку. Например, отличается порядок сортировки для русского и украин- ского языков. Порядок сортировки для русского соответ- ствует генеральному, а в украинском алфавите, напри- мер, буква Ь (мягкий знак) является последней. Также, например, не соответствует генеральному порядок сортировки для латышского языка. Если отсортировать строки: аса, acb, аса и acb при региональных установках для русского и латышского языков, то будет наблюдаться средующая разница (табл. 18.15). Таблица 18.15. Сортировка строк при различных региональных настройках Русский язык Латышский язык аса аса аса acb acb аса acb acb Таким образом, все пользователи информационной базы имеют одинаковый порядок данных при просмотре спи- сков и при формировании отчетов. Платформа 1С:Предприятия Основным средством, реализующим возможность интер- национализации на уровне платформы, являются языки интерфейса технологической платформы. Существует определенный набор языков, из которых пользователь может выбрать один, для запуска системы в режиме ЮПредприятие или Конфигуратор. Стандартная поставка ЮПредприятия содержит все доступные языки интерфейсов платформы (рис. 18.120). При установке системы 1 С: Предприятие предоставляет- ся возможность выбрать один или несколько дополни- тельных языков интерфейсов платформы, которые будут установлены на компьютере пользователя. После завер- шения установки в каталоге программных файлов (по умолчанию C:\Program Files\lcv8\bin) будут созданы соот- ветствующие каталоги с ресурсными файлами (рис. 18.121). Рис. 18.120. Языки интерфейса платформы X н а Program Files ЕПЗЭ 1С Archive Client S ) 1cv8 H&Pft Side | en g|kk g|Fv ro @1ru И tmpits gbg g|de Sizej Type fj^ru 108 KB 72 KB 146 KB 556 KB 1 KB ICMaiVe.dl lCML32.dll 1CV8 Server s.msc lcv8,exa lCV85erver.dat File Folder File Folder Fite Folder File Folder File Folder File Folder File Folder File Folder File Folder File Folder Application Extension Application Extension Microsoft Common.. Application DAT File Рис. 18.121. Каталоги ресурсных файлов На момент написания данной книги поставка 1 С: Пред- приятия содержит десять языков интерфейса (табл. 18.16). Таблица 18.16. Языки интерфейса платформы Язык Код Английский Еп Болгарский Bg Грузинский Ка Казахский Кк Латышский Lv Литовский Lt Немецкий De Румынский Ro Русский Ru Украинский Uk
Точный список используемых кодов языков интерфейса находится в файле в Lodlnfo.txt По умолчанию файл рас- положен в каталоге C:\Program Files\lcv8. Язык интерфейса платформы определяет, на каком языке будут отображаться системные меню, системные диалоги, системные сообщения, справка и т. д. Для каждого поль- зователя информационной базы это может быть свой язык. Более того, на одном и том же клиентском компью- тере может быть запущено несколько клиентских прило- жений, работающих с одной и той же информационной базой и имеющих разные языки интерфейсов платформы. Для запуска системы с тем или иным языком интерфейса можно использовать несколько способов. Во-первых, запуск с нужным интерфейсом может быть выполнен из командной строки. Для этого используется параметр командной строки L, после которого указывает- ся код нужного языка. Например, строка запуска системы с казахским языком интерфейса может выглядеть сле- дующим образом: "C:\Program Files\lcv8\bin\lcvB.exe" Enterprise /LKk Во-вторых, для того чтобы система по умолчанию при за- пуске использовала один из языков интерфейсов, в ката- логе программных файлов находится файл, имеющий расширение res. Имя этого файла соответствует коду од- ного из языков интерфейсов платформы. Этот язык будет использоваться системой, если в командной строке не со- держится явного указания. Первоначально файл *.res соз- дается при установке системы 1 С: Предприятие и его имя соответствует коду языка, выбранного как язык интер- фейса по умолчанию (рис. 18.122). Рис. 18.122. Язык интерфейса платформы по умолчанию В дальнейшем можно просто переименовать этот файл, выбрав другой код языка. Содержимое файла значения не имеет, файл может быть пустым. Помимо того, что языки интерфейса платформы отобра- жают системную часть интерфейса прикладного решения на нужном языке, они используются в других частях сис- темы и прикладного решения. Программа установки шаблонов конфигураций Языки интерфейса платформы используются программой установки шаблонов конфигураций системы 1 С: Пред- приятие для того, чтобы выводить сообщения на языке, наиболее подходящем пользователю. При запуске программы установки определяются регио- нальные настройки операционной системы компьютера, на котором она запущена. Если есть язык интерфейса платформы, который соответствует этим региональным настройкам, — вывод сообщений осуществляется на этом языке. Если такого языка нет, по умолчанию использует- ся английский язык. Все вышесказанное относится не только к текстам самой программы установки, но и к той информации, которая отличается для различных комплектов поставки: наиме- нование прикладного решения, наименование фирмы. Например, при формировании комплекта поставки мож- но указать наименование прикладного решения на каж- дом из языков интерфейсов технологической платформы. Аналогичным образом можно включить в комплект по- ставки сопроводительный файл также на каждом из язы- ков интерфейсов платформы. При окончании установки пользователь сможет просмотреть справочный файл на том языке, который наиболее подходит для региональных установок операционной системы на его компьютере. Подробнее о формировании комплектов поставки можно прочитать в разделе «Механизм создания комплектов по- ставки», с. 668. Каталог шаблонов Отображение названий шаблонов прикладных решений в каталогах шаблонов выполняется также в соответствии с выбранным языком интерфейса платформы. После запуска системы пользователь может создать но- вую информационную базу. При этом ему предостав- ляется возможность создать ее на основе одного из суще- ствующих шаблонов, которые отображаются в списке шаблонов (рис. 18.123). Рис. 18.123. Список шаблонов Кроме этого, любой из каталогов шаблонов может быть открыт по команде Конфигурация ► Поддержка ► Шаблоны конфигураций и обновлений.... Также наименования шаб- лонов используются при выборе обновления прикладно- го решения. Структура манифеста (файла, описывающего шаблон при- кладного решения) позволяет задать наименование при- кладного решения на каждом из возможных языков интер- фейса платформы. Таким образом, пользователь может просматривать списки шаблонов на привычном ему языке.
Подробнее о шаблонах конфигураций можно прочитать в разделе «Шаблоны конфигураций», с. 672. Журнал регистрации Сообщения журнала регистрации отображаются на языке интерфейса платформы. Если к одной и той же инфор- мационной базе подключены, например, пользователи с русским и казахским языком интерфейса, то просматри- вая журнал регистрации, один будет видеть его на рус- ском языке (рис. 18.124) В то время как другой — на казахском (рис. 18.125). Рис. 18.124. Журнал регистрации на русском языке С* Пркеу журналы <1> П X ерекеггер - [§ Ц [«•) Тх g S Mepsiw уаи^т Ко л дану шы Ок)*а ® Косыми® Тусиктвме i 24.3 200512:03 40 Федоров (администратор) 1С KecinopwH Сеанс Басы i 24 3.20051248:28 Федоров (администратор) 1С KecinopbiH Деректер Озгерт/ i 24.3.200512 48.28 Федоров (администратор) 1 С. КеФпорын Деректер епчзудАлып тастау О i 24.3.2005 12 48.29 Федоров (администратор) 1С Кэсторын Деректер ©згерту i 24 3.2005 12 49-13 Федоров (администратор) 1С KecinopbiH Деректер ©згерту i 24 3.200512 49-13 Федоров (администратор) 1С KecinopbiH Деректер бтпзудДлып тастау i 24 3 200517 4426 Федоров (администратор) 1С KecinopbiH Сеанс .Аягггау S ... - Ipkrey Рис. 18.125. Журнал регистрации на казахском языке Встроенный язык Некоторые функции встроенного языка формируют пред- ставление своих данных в соответствии с языком интер- фейса платформы. Например, такие функции сеанса работы, как Представле- ниеПриложения() и ПредставлениеСобытияЖурналаРегистрации(). Функция ПредставлениеПриложенияО позволяет получить название приложения на языке, который соответствует языку интерфейса платформы. Это может понадобиться, например, при анализе подключений к текущей инфор- мационной базе. В качестве примера следующий код позволяет вывести в окно сообщений имя пользователя, подключенного к информационной базе, и название приложения, которое он использует (листинг 18.28). Листинг 18.28. Получение списка активных пользователей Соединения = ПолучитьСоединенияйнфорнационнойБазыО; Для Каждого Соединение из Соединения Цикл Пользователь = Соединение.Пользователь.Имя; Приложение = ПредставлениеПриложения(Соединение.ИмяПриложения): Сообщить(Пользователь + " - ” + Приложение); КонецЦикла; При использовании русского языка интерфейса плат- формы будут введены, например, следующие сообщения (рис. 18.126). Рис. 18.126. Список активных пользователей по-русски Если для этой же информационной базы запустить ЮПред- приятие с литовским языком интерфейса платформы, то вид сообщения изменится (рис. 18.127). Рис. 18.127. Список активных пользователей по-литовски Функция ПредставлениеСобытияЖурналаРегистрацииО позво- ляет получить название события на языке, который со- ответствует языку интерфейса платформы. Это может понадобиться, например, при программном анализе вы- груженного журнала регистрации. Язык интерфейса платформы также определяет пред- ставление значений системных перечислений и систем- ных наборов значений. Например, значение системного перечисления ГоризонтальноеПоложение.Лево будет иметь различные представления для разных языков интерфейса платформы (табл. 18.17). Аналогичным образом, например, значение системного набора значений МтпбсмзЦвета.ГраницаАктивногоОкна также будет иметь различные представления для разных языков интерфейса платформы (табл. 18.18).
Таблица 18.17. Представление значения системного перечисления ГоризонтальноеПоложение.Лево для разных языков платформы Язык Значение Английский Left Болгарский Ляво Русский Прижать влево Таблица 18.18. Представление значения системного набора значений \Мпс1ом/5Цвета.ГраницаАктивногоОкна для разных языков интерфейса платформы Язык Значение Английский Active window border Болгарский Граница на активния прозорец Русский Граница активного окна UNICODE Помимо набора языков интерфейса, платформа 1 С:Пред- приятия обладает еще одним важным, в плане интерна- ционализации, свойством. Она обеспечивает хранение всех строк и текстов в формате Unicode. Этот формат по- зволяет включать в любую текстовую информацию одно- временно символы различных языков. Таким образом, пользователь может вводить данные на разных языках, например, если описание товара или текст договора нужно включить на языке страны-произ- водителя. Аналогичным образом, разработчик может, при создании интерфейса системы, использовать тексты на разных языках для наименования пунктов интерфейса, надписей формы или подсказок. Конфигурация Основным средством, реализующим возможность интер- национализации на уровне конфигурации, являются при- кладные объекты конфигурации Язык. Они используются для идентификации строк интерфейса, которые должны быть использованы в том или ином случае. Общая идеология работы с языками конфигурации за- ключается в следующем. В любом прикладном решении существует один объект конфигурации Язык. Этот объект создается при создании новой информационной базы и соответствует языку интерфейса платформы, с которым она была запущена. Например, если платформа запуска- лась с русским языком интерфейса, то будет создан язык Русский с кодом ru, если с литовским, то Lietuviijc кодом It. При сохранении конфигурации каждому непустому свойству конфигурации, которое может быть представле- но строками на разных языках, ставится в соответствие код этого языка и собственно значение строки. В дальнейшем разработчик может добавить необходимое количество языков в конфигурацию и задать значения свойств конфигурации на нужных языках. Таким обра- зом, в общем случае, любое «многоязычное» свойство конфигурации связано с массивом элементов, каждый из которых хранит код языка и значение свойства конфигу- рации на этом языке. ВНИМАНИЕ Код языка сохраняется вместе со значением строки, кото- рое указано для этого языка. Если затем код языка в конфи- гурации будет изменен, автоматическая «перепривязка» существующих строк к новому коду языка не производится. Таким образом, все строки, привязанные к старому коду, будут недоступны. С другой стороны, для каждого пользователя информа- ционной базы можно задать язык (один из объектов кон- фигурации). Если для пользователя язык не задан, то при его работе с системой будет использован основной язык конфигурации. Таким образом, при формировании меню, форм, диалогов и других элементов прикладного интер- фейса будут использованы те значения «многоязычных» свойств конфигурации, код которых совпадает с кодом языка, заданного для пользователя. В результате пользо- ватель будет работать с интерфейсом прикладного реше- ния на том языке, который для него установлен. На следующем рисунке представлен пример формирова- ния надписи на кнопке (рис. 18.128). Рис. 18.128. Пример формирования надписи В информационной базе существует пользователь Ива- нов, для которого в свойстве язык указан язык Русский, имеющий код ru. После того как пользователь будет аутентифицирован в информационной базе, система при- ступит к формированию командного интерфейса, и при выводе, например, элемента управления кнопка будет ис- пользовать то значение ее свойства Заголовок, которое со- ответствует коду ru, то есть Выполнить. Использование языков в режиме конфигуратора При конфигурировании прикладного решения система 1С:Предприятие с помощью различных инструментов (в окне редактирования объекта конфигурации, в палитре свойств, в форме и т. д.) отображает значения свойств кон-
фигурации — для каждого свойства указывается его значе- ние. Очевидно, что для строк на разных языках не имеет смысла отображать одновременно все возможные значе- ния на каждом языке. Во-первых, в этом нет практической необходимости, так как в один момент времени выполня- ется редактирование интерфейса только на одном языке, а во-вторых, это значительно ухудшило бы эргономику и «читабельность» разрабатываемых форм. Поэтому в каж- дый момент времени при работе в конфигураторе система отображает значения строк только на одном языке. Теку- щий язык, используемый для отображения многоязычных строк, устанавливается командой Конфигурация ► Язык ре- дактирования конфигурации (рис. 18.129). Рис. 18.129. Выбор языка редактирования конфигурации Кроме этого, текущий язык редактирования конфигура- ции отображается в панели состояния и там же может быть оперативно переключен (рис. 18.130). Рис. 18.130. Оперативное переключение языка редактирования конфигурации В дополнение к этому, каждая строка на разных языках имеет (в случае, если в конфигурации определено более одного языка) кнопку открытия (рис. 18.131). Эта кнопка позволяет просмотреть и изменить все значе- ния этого свойства для языков, определенных в данной конфигурации (рис. 18.132). Рис. 18.131. Кнопка открытия Рис. 18.132. Ввод строк на разных языках Элементы системного интерфейса, использующие языки конфигурации Некоторые элементы системного интерфейса используют значения строк на разных языках. Например, в списках объектов конфигурации, которые открываются через сис- темное меню Операции для отображения объектов исполь- зуются их синонимы, которые представляются строками на разных языках. Таким образом, например, для пользо- вателя с английским языком будут выведены английские синонимы справочников конфигурации, а для пользова- теля с русским языком — русские. Если значение на ука- занном языке отсутствует, будет выведено имя объекта конфигурации. Также синонимы объектов конфигурации на языке поль- зователя применяются, например, в диалоге поиска и уда- ления помеченных объектов, в меню Перейти и других местах. Интернационализация во встроенном языке Два варианта встроенного языка Все операторы встроенного языка имеют как русское, так и англоязычное написание, которое можно использовать одновременно в одном исходном тексте. Для этого не тре- буется изменения каких-либо настроек конфигуратора — система будет правильно воспринимать операторы, напи- санные на обоих языках. Документация и синтакс-по- мощник содержат русскоязычный и англоязычный син- таксис и синонимы для всех конструкций встроенного языка. Использование языков конфигурации Функция НСтр() Функция НСтр() позволяет получить строку на указанном языке или языке, определенном для текущего пользова- теля прикладного решения (листинг 18.29). Листинг 18.29. Пример использования функции НСтрО Текст = "ru = '"’Добрый вечер!"" en = ""Good Evening!.; Сообщить(НСтрСТекст. "еп")); В результате выполнения приведенного примера в орю сообщений будет выведена следующая строка: Good Evening! Если второй параметр метода опущен, будет возвращена строка на языке текущего пользователя. Если код языка текущего пользователя отсутствует в первом параметре, будет возвращена пустая строка.
Получение макетов на указанном языке Текстовый документ. Текстовый документ содержит свойство КодЯзыкаМакета. В этом свойстве указывается код языка, кото- рый будет искаться в названиях областей текстового макета при работе с ними. В случае, когда это свойство содержит значение Неопределено, язык макета будет определяться язы- ком, установленным для текущего пользователя. Если теку- щему пользователю язык не назначен, тогда язык макета будет определяться свойством Основной язык конфигурации. Например, текстовый документ может содержать области на разных языках для того, чтобы формировать выходную форму на каждом из языков. Для каждой области текстово- го макета можно указать язык, к которому «относится» эта область. После этого, используя один и тот же алгоритм вы- вода документа, можно просто менять значение КодЯзыкаМа- кета и получать области макета на нужном языке. Пример работы с макетом текстового документа можно посмотреть в разделе «Процедура формирования тексто- вого документа», с. 470. Табличный документ. Табличный документ содержит свойство КодЯзыкаМакета. В этом свойстве указывается код языка, строки на котором будут использоваться для вы- вода данного табличного документа в другой табличный документ. В случае, когда это свойство содержит значе- ние Неопределено, язык макета будет определяться языком, установленным для текущего пользователя. Если теку- щему пользователю язык не назначен, тогда язык макета будет определяться свойством Основной язык конфигурации. Табличный документ предполагает более «тонкое» ис- пользование интернационализации, по сравнению с тек- стовым документом. Шаблон табличного документа может содержать стро- ки на разных языках. Это могут быть текст ячейки или шаблона, а также форматная строка. Указывая значение свойства КодЯзыкаМакета, можно одним и тем же алгорит- мом получать выходную форму на разных языках. Использование региональных установок ПредставлениеПериодаО Эта функция позволяет формировать внешнее представле- ние периода, заданного датами начала и окончания на од- ном из языков, для которых поддерживается локализация. Формирование представления периода поддерживается для следующих языков (табл. 18.19). Точный список доступных региональных настроек, ис- пользуемых в этой функции, находится в файле в Lodlnfo.txt. По умолчанию файл расположен в каталоге C:\Program Files\lcv8. Пример использования функции ПредставлениеПериодаО показан в листинге 18.30. Листинг 18.30. Пример использования функции ПредставлениеПериода() Начало = '20041101000000'; Конец = КонецМесяца( '20041101000000'): Результат = ПредставлениеПериода(Начало, Конец. "L = bg_BG"); Сообщить(Результат): В результате выполнения этого кода будет получено пред- ставление периода ноябрь 2004 года по-болгарски: Ноенври 2004 г. Таблица 18.19. Региональные установки, используемые в функции ПредставлениеПериодаО Код Язык(страна) en_US Английский (США) be_BY Белорусский (Белоруссия) bg_BG Болгарский (Болгария) ka_GE Грузинский (Грузия) kk_KZ Казахский (Казахстан) lv_LV Латышский (Латвия) lt_LT Литовский (Литва) de_DE Немецкий (Германия) ro_RO Румынский (Румыния) ru_RU Русский (Россия) uk_UA Украинский (Украина) fi_FI Финский (Финляндия) et_EE Эстонский (Эстония) Приведем другой пример использования этой функции (листинг 18.31). Листинг 18.31. Пример использования функции ПредставлениеПериодаО Начало = '20040401000000'; Конец = КонецМесяца( '20040601000000'); Результат = ПредставлениеПериода(Начало. Конец, "L = fi_FI"): Сообщить(Результат); В результате выполнения этого кода будет получено представление второго квартала 2004 года по-фински: 2 vuosineljannes 2004 v. Третий пример показывает возможность вывода так на- зываемых финансовых периодов — первого полугодия и первых девяти месяцев года (листинг 18.32). Листинг 18.32. Пример использования функции ПредставлениеПериодаО Начало = НачалоМесяца('20040101000000'); Конец = КонецМесяца('20040901000000'); Результат = ПредставлениеПериодаСНачало. Конец. "L = ka_GE; ФП = Истина"); Сообщить(Результат); В результате выполнения этого кода будет получено представление периода девять месяцев 2004 года по-гру- зински: 9 созд 2004 ЧислоПрописью() Эта функция позволяет формировать представление чис- ла прописью в соответствии с форматной строкой и на одном из языков, для которых поддерживается локали- зация. Формирование представления числа прописью под- держивается для следующих региональных установок (табл. 18.20).
Таблица 18.20. Региональные установки, используемые в функции ЧислоПрописьюО Код Язык(страна) en_US Английский (США) be_BY Белорусский (Белоруссия) bg_BG Болгарский (Болгария) ka_GE Грузинский (Грузия) kk_KZ Казахский (Казахстан) lv_LV Латышский (Латвия) lt_LT Литовский (Литва) de_DE Немецкий (Германия) ro RO Румынский (Румыния) ru_RU Русский (Россия) ukUA Украинский (Украина) fi_FI Финский (Финляндия) et_EE Эстонский (Эстония) Точный список доступных региональных настроек, ис- пользуемых в этой функции, находится в файле в Locllnfo.txt. По умолчанию файл расположен в каталоге C:\Program Files\lcv8. Пример использования функции ЧислоПрописьюО показан в листинге 18.33. Листинг 18.33. Пример использования функции ЧислоПрописьюО Сообщить(ЧислоПрописью(1457.25, ”L = de_DE; FS = Истина". "EURO, EURO. М. Cent. Cent. М. 2")): В результате выполнения этого кода будет получено пред- ставление суммы 1457 евро 25 центов по-немецки: Ei ntausendvi erhundertsi ebenundfunfzi g EURO und fiinfundzwanzig Cent ФорматО Эта функция формирует удобное для чтения представле- ние значений. Представление может формироваться с учетом стандартного форматирования выбранного языка или страны. С помощью функции формат представления значений может быть получен для одной из более чем 80 регио- нальных установок, которые перечислены в документа- ции. Приведем некоторые примеры использования этой функции. Истина по-гречески: Сообщить(Формат(Истина, "L = el_GR”)); Результат: аА.т]6е^ Ложь по-чешски: Сообщить(Форнат(Ложь, "L = cs_CZ”)): Результат: Nepravda 20 августа 2004 г. 10:56:35 по-латышски: ФорматС20040820105635’. "L = lv_LV; ДЛФ=’ДД+В’"): Результат: piektdiena, 2004. gada 20. augusta 10:56:35 Редактирование текстов интерфейса Платформа 1С:Предприятия содержит инструмент, по- зволяющий автоматизировать процесс редактирования строк на разных языках, содержащихся в конфигурации. Окно редактирования текстов интерфейса позволяет на- ходить в конфигурации все строки на разных языках, группировать их по совпадающим значениям на каком- либо языке, копировать значения из одного языка в дру- гой, а также выгружать значения строк из одной конфи- гурации и загружать их в другие. По команде Правка ► Редактирование текстов интерфейса... открывается окно настройки поиска (рис. 18.133). Рис. 18.133. Настройка редактирования текстов интерфейсов Поиск возможен в основной конфигурации, в конфигура- ции базы данных, в файлах на диске, в открытых доку- ментах и в модулях в функциях НСтрО. После того, как область поиска задана, открывается окно, содержащее результаты поиска (рис. 18.134). Все найденные строки располагаются в таблице. Первая колонка показывает объект конфигурации, содержащий данную строку. Следующие колонки соответствуют всем кодам языков, которые заданы в конфигурации, плюс всем кодам, найденным при поиске. На пересечении на- ходятся значения строк. Таблица может быть сгруппирована по значениям, совпа- дающим на всех языках или только на языке, по которому выполнена сортировка. Это облегчает чтение и редакти- рование таблицы. Значения строк на разных языках можно редактировать прямо в этой таблице. Значение, введенное для группы строк, автоматически дублируется в каждую строку, вхо- дящую в группировку. Копирование строк из одного языка в другой Копирование строк из одного языка в другой может пона- добиться, например, при использовании внешних обрабо- ток, созданных в других информационных базах, или при частичном переводе интерфейса, когда непереведенные строки нужно заполнить из другого языка. Дело в том, что в различных информационных базах код языка, ис- пользуемого по умолчанию, может быть разным. Напри- мер, в одной базе для русского языка был задан код ru_RU, а в другой базе — ru. Тогда внешняя обработка, созданная в первой базе, будет содержать код ru_RU для всех строк
Редактирование текстов интерфейса 9 X Действия * Сворачивать'j Совпадающие на всех языках Русский (ru) Английский (ей) ИЙ Е- «Вхождений 11> г О Основная конфигурация Обработка ОтправкаЭле Вложения О Основная конфигурация Обработка ОтправкаЭле . Закрыть ! Й-сВхоядений’ 3> Заполнить текст Заполнить текст О Основная конфигурация Обработка Отправка.. Заполнить текст Заполнить текст | т О Основная конфигурация Обработка Отправка.. Заполнить текст Заполнить текст О Основная конфигурация Обработка Отправка Заполнить текст Заполнить текст □ Настройка параметров Настройка параметров | О Основная конфигурация Обработка Отправка Настройка параметров Настройка параметров | Т □ Основная конфигурация Обработка Отправка Настройка параметров Настройка параметров ! О Основная конфигурация Обработка Отправка Настройка параметров Настройка параметров ГО Основная конфигурация Обработка. Отправка Эле Отправить 0 «Вхождений: 2> Отправить сообщение 0-« Вхождений. 2> Отправка электронного сообщения в отд 0-< Вхождений 3> Отправлять слепую копию себе Ё-< Вхождений. 2> Путь к файлу О Основная конфигурация Обработка ОтправкаЭле Справка Справка Рис. 18.134. Редактирование текстов интерфейса Рис. 18.135. Отсутствие строк интерфейса на нужном языке Редактирование текстов интерфейса 9 X ' на всех ярыгах ' Ищположвние Русский (ru) * Английский (еп) ru.RU = wf ОАВазезЮтправкаЭл Вложения м* ОАВазезЮтправкаЭл Закрыть s • -щ* ОАВазезЮтправкаЭл . Отправить Ё«Вхождений. 2> Отправить сообщение Ё - «Вхождений 2> Отправка электронного сооб . Е "< Вхождений 3> Отправлять слепую копию себе Ё «Вхождений’ 2> Путь к файлу j М* ОАВазезЮтправкаЭл Страница! ; -щ* 0АВазез\0тлравкаЭл Текст сообщения i 0 - «Вхождений. 2> Тема сообщения Г-щ* О \ВазезЮтправкаЭл . Тема i "Й* D ^ВазезЮтправкаЭл . Файлы вложения г-щ* ОАВазезЮтправкаЭл Форма 0 < Вхождений 3> Заполнить текст 0 «Вхождений. 3> Настройка параметров !--щ* ОАВазезЮтправкаЭл . Справка V Рис. 18.136. Редактирование текстов интерфейсов Редактиро-ан» текс то» интерфейса * X Действия * Сворачивать. | Совпадающие на всех языках • *7 ’VjPyCCKMH (ru) ” Английский (еп) ru RU 0' ЦП г ’И* Г \ВазезЮтправкаЭл Вложения Вложения i: "Ей* D \ВазезЮтправкаЭл Закрыть Закрыть Ё- «Вхождений: 3> Заполнить текст Заполнить текст Ё «Вхождений' 3> Настройка параметров Настройка параметров г--Ш* ОАВазезЮтправкаЭл Отправить Отправить 0-« Вхождений. 2> Отправить сообщение Отправить сообщение Ё-«Вхождений 2> Отправка электронного сооб . Отправка электронного сооб... ©••«Вхождений. 3> Отправлять слепую копию се Отправлять слепую копию себе Ё-«Вхождений 2> Путь к файлу Путь к файлу г "a* D \ВазезЮтправкаЭл Справка Справка Н-ва* ОАВазезЮтправкаЭл. Страница! Страница! | “И* D кВазезЮтправкаЭл Текст сообщения Текст сообщения Ё «Вхождений’ 2> Тема сообщения Тема сообщения ГВ* ОАВазезЮтправкаЭл... Тема. Тема ; И* О АВазезЮтправкаЭл Файлы вложения Файлы вложения = м* ОАВазезЮтправкаЭл . Форма Форма * Рис. 18.137. Копирование текстов интерфейса для другого языка
обработки. Если такую обработку открыть во второй ин- формационной базе, то ни одна строка интерфейса ото- бражена не будет (рис. 18.135). В этом случае можно запустить редактирование текстов интерфейса для открытой обработки (рис. 18.136). Командой Действия ► Копировать тексты... выполнить ко- пирование текстов языка с кодом ru_RU в язык с кодом ru (код языка Русский в текущей базе) (рис. 18.137). В результате этих действий надписи интерфейса будут корректно отображены при текущем коде языка Русский: (рис. 18.138). Рис. 18.138. Тексты интерфейса скопированы для нового языка Удаление строк на выбранном языке По разным причинам конфигурация может содержать строки, соответствующие языку, который отсутствует в конфигурации. Это может происходить как в результате изменения кода существующего языка, так и в результате копирования объектов из других конфигураций. Для того чтобы удалить из конфигурации такие строки, можно использовать команду Действия ► Очистить тексты... окна редактирования текстов интерфейсов. В результате строки, соответствующие выбранному языку, будут уда- лены из конфигурации. Перенос текстов интерфейса из одной базы в другую Необходимость в переносе текстов интерфейса из одной информационной базы в другую может понадобиться в том случае, когда выполняется локализация интерфейсов функционально пересекающихся между собой приклад- ных решений. Например, если интерфейс Бухгалтерии предприятия переведен на английский язык, то с большой вероятностью аналогичные строки интерфейса будут встречаться и в прикладном решении Управление произ- водственным предприятием. Поэтому можно просто выгрузить строки интерфейса из прикладного решения Бухгалтерия предприятия и загру- зить их в Управление производственным предприятием. При выполнении такой выгрузки-загрузки следует учи- тывать неоднозначность перевода. Одна и та же строка на русском языке может иметь различный перевод на анг- лийском. Например, русское слово Счет может быть пере- ведено на английский как Invoice, если речь идет о торгов- ле, и как Account, если речь идет о бухгалтерии. Поэтому, чтобы обеспечить однозначность переноса строк из одной конфигурации в другую, следует в исходной конфигурации создать новый объект конфигурации Язык, и назвать его, например, Служебный. Этот язык нужно ис- пользовать для уточнения толкования терминов. Тогда, например, для русских названий Счет в служебном языке необходимо указать различные толкования, например, Счет бухгалтерия и Счет торговля (рис. 18.139). Рис. 18.139. Использование служебного языка в базе-источнике Во второй информационной базе следует также создать язык Служебный и придерживаться тех же правил указания различных толкований одного и того же слова (рис. 18.140). Рис. 18.140. Использование служебного языка в базе-приемнике Для того чтобы выгрузить из первой конфигурации тексты на разных языках в файл, необходимо выполнить команду Действия ► Экспорт в табличный документ... (рис. 18.141). Рис. 18.141. Экспорт в табличный документ Флаг Включать расположение позволяет вывести в файл также и название объекта конфигурации, которому соот- ветствуют строки. Для выполнения переноса в другую базу это не нужно, поэтому этот флаг следует сбросить. Флаг Не включать пустые строки имеет смысл установить, хотя это не является обязательным требованием. В результате будет сформирован табличный документ, имеющий следующую структуру (рис. 18.142). Рис. 18.142. Выгруженный табличный документ Для того чтобы этот табличный документ можно было использовать в качестве файла соответствий для загрузки в другую информационную базу, его следует немного от- редактировать. Дело в том, что формат файла соответст- вий практически совпадает с форматом этого табличного документа за исключением того, что в первой строке фай-
ла соответствии должны содержаться только коды язы- ков. Поэтому доработка должна заключаться в удалении из первой строки этого документа названий языков и ско- бок. После этого в другой информационной базе необходимо добавить язык Английский с кодом еп и открыть окно ре- дактирования текстов интерфейсов (рис. 18.143). Рис. 18.143. Тексты интерфейса в базе-приемнике Затем следует выполнить команду Действия ► Заполнить тексты ... (рис. 18.144). Рис. 18.144. Заполнить тексты В окне настройки необходимо указать исходный язык, по которому будет осуществляться установка соответствия загружаемых текстов существующим в этой информаци- онной базе. В нашем случае это будет язык Русский. Так- же следует отметить язык, в который будет осуществ- ляться загрузка текстов из файла соответствий. В нашем случае это будет язык Английский. Для языка Служебный отметку надо снять. Дело в том, что при поиске необходимого соответствия учитывают- ся не только исходный язык, но и все языки, присутст- вующие и в конфигурации и в файле, и не помеченные на заполнение. Таким образом, в установке соответствий (кроме значений на русском языке) будут принимать участие и наши уточняющие толкования неоднозначных русских слов. После загрузки тексты на разных языках во второй конфигурации будут иметь следующий вид (рис. 18.145). Рис. 18.145. Результат загрузки Редактирование строк, используемых в функции НСтр() Строки на разных языках могут формироваться про- граммно, с помощью функции НСтрО (подробнее см. раз- дел «Функция НСтр()», с. 770). При этом нужно строго соблюдать синтаксис при написании строк на разных языках. Особенность реализации функции НСтрО состоит в том, что ни при синтаксической проверке модулей, ни при исполнении, никакой ошибки выдано не будет, если есть ошибка в синтаксисе. Функция просто вернет пус- тую строку. Поэтому для редактирования сложных строк, используе- мых в функции НСтрО, надежнее использовать механизм редактирования текстов интерфейса. По умолчанию поиск в вызовах функции НСтрО не произ- водится; для его включения требуется включить соответ- ствующий флаг в диалоге настройки редактирования тек- стов интерфейса (рис. 18.146). Рис. 18.146. Флаг поиска в функциях НСтрО При этом нужно соблюдать одно правило. Если необхо- димо сформировать сложную строку как результат не- скольких вызовов функции НСтрО, то рекомендуется рас- полагать эти вызовы в разных строках модуля. Например, вместо строки (листинг 18.34) рекомендуется использо- вать вариант, представленный в листинге 18.35. Листинг 18.34. Неправильное использование вызовов функции НСтрО НСтр("ги='Документ"') + " " + НСтр(”ги='Накладная"’): Листинг 18.35. Правильное использование вызовов функции НСтрО НСтр(”ги='Документ"') + " " + НСтр("ги='Накладная "'): Если несколько вызовов функции НСтрО расположены в одной строке, это может привести к ошибкам в работе механизма редактирования текстов интерфейса. При первичном редактировании строк с помощью этого механизма все вызовы НСтрО будут обработаны правиль- но. Однако при последующем редактировании тексты, со- ответствующие функциям НСтрО, расположенным не пер- выми в строке, будут недоступны. Для решения этой проблемы достаточно заново произве- сти поиск интерфейсных текстов, но лучше не допускать возникновения подобной ситуации и располагать вызовы функции НСтрО на разных строках.
Приложение. Хранение данных Размещение данных системы ЮПредприятие Разработка прикладных решений в системе 1С:Предпри- ятие ведется в терминах объектов метаданных. Благодаря этому разработчик избавлен от необходимости вникать в то, каким образом данные того или иного объекта будут храниться в той или иной базе данных. Система само- стоятельно создает необходимые структуры данных и ра- ботает с ними. Кроме удобства разработки, такой подход гарантирует единообразную работу с создаваемыми структурами дан- ных, так как за все операции с данными на уровне СУБД отвечает сама система. В частности, это позволяет в зна- чительной мере гарантировать целостность и непротиво- речивость данных, хранимых в базе данных. Однако в редких ситуациях разработчику или админист- ратору информационных баз ЮПредприятия все же мо- жет потребоваться информация о расположении данных, используемых системой. При этом нужно отдавать себе отчет в том, что такая информация может быть использо- вана только для понимания расположения и состава дан- ных, используемых системой. Непосредственная работа с данными должна выполняться исключительно средства- ми 1С:Предприятия. Все данные, которые использует система 1С:Предпри- ятие, можно условно разделить на 5 групп, в соответст- вии с их назначением и значимостью. Данные информационной базы. Это наиболее ответствен- ная информация, включающая: конфигурацию, все данные о хозяйственной деятельности предприятия, а также адми- нистративную информацию. Все данные, относящиеся к информационной базе, объединяются в базу данных. По- теря или искажение каких-то данных информационной базы может привести к потере работоспособности систе- мы, построенной на базе ЮПредприятия. Данные хранилища конфигурации. Хранилище конфигу- рации содержит текущую конфигурацию и историю ее разработки при использовании в Конфигураторе средств групповой разработки. При разработке конфигурации эта информация также является «жизненно важной». Данные журнала регистрации. Журнал регистрации со- держит список операций, совершенных над данной ин- формационной базой. Эта информация не является необ- ходимой для работы системы на базе ЮПредприятия, но может быть важной с организационной точки зрения. Вспомогательные данные. К вспомогательным данным относятся такие данные, которые служат для удобства пользователя и не влияют на логику работы системы на базе ЮПредприятия. Основная часть вспомогательных данных хранится в про- файлах. Профайлы содержат информацию о располо- жении окон, текущих позициях, состоянии диалогов и других настройках, позволяющих пользователю работать наиболее комфортно. Различные конфигурации могут хранить в профайлах и другую информацию, которая мо- жет быть полезной, но не является необходимой. Также используются и другие вспомогательные данные. К ним относятся списки информационных баз, зарегист- рированных на клиенте или на сервере, и некоторые дру- гие данные. Временные данные. Эти данные использует приложение 1С:Предприятия для служебных целей. Они актуальны только в пределах одного сеанса работы и после его за- вершения уничтожаются. Информационные базы Данные, которые определяют логику функционирования системы на базе 1 С:Предприятия, относятся к информа- ционной базе. Хранение информационной базы осущест- вляется в базе данных в виде набора таблиц, для чего 1 С: Предприятие может использовать одну из двух систем управления базами данных (СУБД): файловую или кли- ент-серверную. В случае файлового варианта работы все данные инфор- мационной базы хранятся в файле с именем 1Cv8.1CD. Этот файл имеет двоичный формат и, по сути, является базой данных, встроенной в ЮПредприятие. В случае клиент-серверного варианта работы все данные информационной базы хранятся в базе данных Microsoft SQL Server. На уровне объектов базы данных (таблиц, полей, индек- сов и т. п.) как файловый, так и клиент-серверный вари- ант информационной базы имеют сходный формат (отли- чающийся несущественными деталями). Обязательные таблицы информационной базы Существует ряд таблиц, которые обязательно присутст- вуют в любой информационной базе 1 С: Предприятия. Наличие этих таблиц проверяется при старте системы. Если какая-либо из таблиц отсутствует, выдается сооб- щение об ошибке. Если отсутствуют все обязательные таблицы, то считает- ся, что такая база данных не является информационной базой (в терминах ЮПредприятия). В этом случае пере- численные ниже таблицы будут созданы в указанной базе данных. Описанная ситуация может возникнуть в случае, когда база данных SQL Server создается не средствами ЮПред-
приятия, а средствами SQL Server. Например, если тре- буются специфические настройки базы данных, не свя- занные с работой 1С:Предприятия и по этой причине доступные только средствами SQL Server. В этом случае после подключения и запуска такой базы данных система 1 С:Предприятие создаст в ней все обязательные таблицы. Перечислим обязательные таблицы информационной базы: Config. В этой таблице хранится конфигурация базы дан- ных. Конфигурация базы данных соответствует реальной структуре данных и используется системой 1 (^Предпри- ятие в режиме работы ЮПредприятие. ConfigSave. В этой таблице хранится основная конфигу- рация. Основная конфигурация предназначена для непо- средственного редактирования в режиме Конфигуратор. Files. Эта таблица содержит служебную информацию, на- пример, о работе с хранилищем конфигурации. Params. Эта таблица содержит параметры информацион- ной базы. Параметры информационной базы включают в себя список пользователей информационной базы, регио- нальные установки информационной базы, таблицу соот- ветствия объектов метаданных и объектов базы данных (таблицы, поля, индексы), а также некоторую другую ин- формацию. _YearOffset. Эта таблица создается только в клиент-сер- верном варианте работы системы и содержит смещение дат в базе данных. DBSchema. Эта таблица содержит информацию о струк- туре базы данных 1С:Предприятия и определяет другие объекты базы данных, используемые данной информаци- онной базой. Таблицы информационной базы, определяемые структурой метаданных Помимо обязательных таблиц информационная база, как правило, содержит ряд таблиц, которые предназначены для хранения данных объектов, описанных в конфигура- ции. Каждому объекту конфигурации соответствует одна или несколько таблиц информационной базы, в зависи- мости от вида объекта и его структуры (наличия таблич- ных частей и пр.). Количество этих таблиц напрямую зависит от количества и «сложности» объектов конфигу- рации и может быть достаточно большим. В штатном режиме 1 С:Предприятие не выполняет про- верку наличия этих таблиц. Также не проверяется цело- стность и непротиворечивость данных, которые содер- жатся в этих таблицах. Поэтому важно, чтобы база данных, в которой размещена информационная база ЮПредприятия, была защищена от несанкционированного доступа и ее модификация вы- полнялась только средствами ЮПредприятия. Выполнить проверку информационной базы можно в ре- жиме конфигуратора, командой Администрирование ► Тес- тирование и исправление. Также важным моментом является то, что резервное ко- пирование и восстановление базы данных, хранящей ин- формационную базу, должно выполняться только цели- ком. В зависимости от варианта работы ЮПредприятия (файловый или клиент-серверный) можно рекомендо- вать следующие способы создания резервной копии ин- формационной базы. В файловом варианте работы достаточно скопировать файл 1CV8.1CD в отдельный каталог. Это можно выпол- нить как ручным копированием, так и с использованием программного обеспечения для резервного копирования и восстановления данных. При этом нужно учесть, что на время копирования работа пользователей с информаци- онной базой должна быть запрещена. Это необходимо для обеспечения целостности и согласованности данных во время создания резервной копии В клиент-серверном варианте работы следует создавать резервные копии информационной базы средствами SQL Server. SQL Server позволяет выполнять резервное копи- рование данных в то время, когда база данных находится в многопользовательском режиме и доступна для всех пользователей. Использование этих способов дает максимально точную копию состояния информационной базы, что не всегда может быть получено при использовании, например, ре- жима загрузки/выгрузки информационной базы. Если в базе данных есть нарушения, то при выгрузке некоторая информация может быть не выгружена, в то время как при копировании будет сохранена вся информация, и по- сле восстановления можно будет выполнить исправление базы данных. Также существенно уменьшается время нахождения ин- формационной базы в однопользовательском режиме в случае файлового варианта работы ЮПредприятия 8.0, а в случае клиент-серверного варианта однопользова- тельский режим вообще не используется. Кроме этого, положительным моментом является то, что при использовании перечисленных способов, можно при- менять различные специализированные программные средства для создания резервных копий. Таблицы информационной базы, определяемые структу- рой метаданных, имеют имена, создаваемые по одному и тому же правилу. Имя таблицы начинается с буквенного префикса, который обозначает принадлежность таблицы определенному виду объектов конфигурации и может уточнять функциональное назначение таблицы «внутри» этого вида. Например, префикс _AccumReg означает, что это таблица некоторого регистра накопления, а префикс _AccumRegTotals означает, что это таблица итогов некото- рого регистра накопления. После префикса следует номер (далее обозначается <п>), который позволяет различать таблицы объектов одинако- вого вида. Например, если в конфигурации определены два регистра накопления, то в информационной базе могут содержаться таблицы с именами _AccumReg4012 и _AccumReg4018. Таблицы, в которых хранятся записи табличных частей, также обозначаются одинаковым образом. После префик- са и номера, определяющих принадлежность к некоторому объекту конфигурации, идет префикс _VT, указывающий, что это таблица табличной части, и номер (далее обознача- ется <к>), позволяющий различить несколько табличных частей одного и того же объекта конфигурации. Например, для документа, имеющего две табличные части, могут быть созданы таблицы с именами _Documentl04_VT2061 и _Documentl04_VT2076.
Если в конфигурации определен хотя бы один план обме- на с установленным флагом Распределенная информацион- ная база, то будут созданы следующие таблицы: Эти таблицы имеют сквозную нумерацию, поэтому для одной последовательности могут быть созданы, напри- мер, таблицы с именами: _ConfigChangeRec — таблица регистрации изменений объ- ектов конфигурации. _ConfigChangeRec_ExtProps — таблица имен файлов изме- ненных внешних свойств объектов конфигурации. Перечислим, какие таблицы создаются для каждого из прикладных объектов конфигурации: _Sequence4504 _SequenceBoundary4505 _SequenceChangeRec<n> — таблица регистрации изменений последовательности. Создается для каждой последовательности, которая уча- ствует хотя бы в одном плане обмена. Константа _Consts — таблица констант. Все значения констант, определенных в конфигурации, хранятся в одной таблице. _ConstsChangeRec — таблица регистрации изменений кон- стант. Создается, если хотя бы одна константа участвует хотя бы в одном плане обмена. Журнал документов _DocumentJournal<n> — таблица журнала документов. Бизнес-процесс _BusinessProcess<n> — основная таблица бизнес-процесса. _BusinessProcess<n>_VT<k> — табличная часть бизнес-про- цесса. _BPRoutePoint<n> — таблица точек маршрута бизнес-про- цесса. Перечисление _Enum<n> — таблица перечисления. Таблицы, содержащие табличные части бизнес-процесса, имеют тот же номер <п>, что и основная таблица бизнес- процесса, однако для таблицы точек маршрута бизнес- Справочник _Reference<n> — основная таблица справочника. _Reference<n>_VT<k> — табличная часть справочника. Таблицы, содержащие табличные части справочника, имеют тот же номер <п>, что и основная таблица справоч- ника. процесса используется сквозная нумерация. Поэтому для одного бизнес-процесса могут быть созданы, например, следующие таблицы: BusinessProcess75 _Busi nessProcess75_VT76 _BPRoutePoint78 _BusinessProcessChangeRec<n> — таблица регистрации из- менений бизнес-процесса. Например: _Reference54 _Reference54_VT600 _Reference54_VT605 _ReferenceChangeRec<n> — таблица регистрации измене- ний справочника. Создается, если справочник участвует хотя бы в одном плане обмена. Создается для каждого бизнес-процесса, участвующего хотя бы в одном плане обмена. Задача _Task<n> — основная таблица задачи. _Task<n>_VT<k> — табличная часть задачи. Таблицы, содержащие табличные части задачи, имеют тот же номер <п>, что и основная таблица задачи. Документы _Document<n> — основная таблица документа. _Document<n>_VT<k> — табличная часть документа. Таблицы, содержащие табличные части документа, име- ют тот же номер <п>, что и основная таблица документа. Например: Task77 Task77_VT80 _TaskChangeRec<n> — таблица регистрации изменений в задачах. Создается для каждого объекта метаданных Задача, кото- Например: _Documentl44 _Documentl44_VT3409 _Documentl44_VT3416 _Documentl44_VT3420 _DocumentChangeRec<n> — таблица регистрации измене- ний документа. Создается для каждого объекта метаданных Докунент, ко- торый участвует хотя бы в одном плане обмена. рый участвует хотя бы в одном плане обмена. Регистр сведений _InfoReg<n> — таблица движений регистра сведений. _InfoRegChangeRec<n> — таблица регистрации изменений регистра сведений. Создается, если регистр сведений участвует хотя бы в од- ном плане обмена. Последовательность _Sequence<n> — таблица регистрации документов в после- довательности. _SequenceBoundary<n> — таблица границ последовательно- сти. Регистр накопления _AccumReg<n> — таблица движений регистра накопления. _AccumRegTotals<n> — таблица итогов регистра накопле- ния. Эта таблица создается в случае, если регистр накоп- ления поддерживает остатки.
_AccumRegTurnovers<n> — таблица оборотов регистра на- копления. Эта таблица создается в случае, если регистр поддерживает обороты. _AccumRegOptions — таблица настроек хранения итогов регистров накопления. Эта таблица создается одна на все регистры накопления. Эти таблицы имеют сквозную нумерацию, поэтому для одного регистра накопления могут быть созданы, напри- мер, следующие таблицы: Регистр накопления остатков: _AccumReg4012 AccumRegTotals4017 Оборотный регистр накопления: _AccumReg4047 AccumRegT urnovers4064 _AccumRegChangeRec<n> — таблица регистрации измене- ний регистра накопления. Создается, если регистр накопления участвует хотя бы в одном плане обмена. План видов характеристик _Chrc<n> — основная таблица плана видов характеристик. _Chrc<n>_VT<k> — табличная часть плана видов характери- стик. Таблицы, содержащие табличные части плана видов ха- рактеристик, имеют тот же номер <п>, что и основная таб- лица плана видов характеристик. Например: Chrc262 _Chrc262_VT4513 _ChrcChangeRec<n> — таблица регистрации изменений плана видов характеристик. Создается, если план видов характеристик участвует хотя бы в одном плане обмена. План счетов _Асс<п> — основная таблица плана счетов. _Acc<n>_ExtDim<k> — таблица видов субконто плана сче- тов. Эта таблица создается в том случае, если максималь- ное количество субконто больше нуля. _Acc<n>_VT<k> — табличная часть плана счетов. Таблицы, содержащие табличные части плана счетов, и таб- лица видов субконто имеют тот же номер <п>, что и ос- новная таблица плана счетов. Например: _Асс65 _Acc65_ExtDim70 _Acc65_VT66 _AccChangeRec<n> — таблица регистрации изменений пла- на счетов. Создается, если план счетов участвует хотя бы в одном плане обмена. Регистр бухгалтерии _AccntReg<n> — таблица движений регистра бухгалтерии. _AccntRegED<n> — таблица значений субконто регистра бухгалтерии. Эта таблица создается в том случае, если ре- гистр бухгалтерии ссылается на план счетов, у которого максимальное количество субконто больше нуля. _AccTtLO<n> — таблица остатков и оборотов по счетам и субсчетам. _AccTtl<i><n> — таблица остатков и оборотов по счетам, субсчетам и субконто. Эти таблицы создаются в том слу- чае, если регистр бухгалтерии ссылается на план счетов, у которого максимальное количество субконто больше нуля. Номер i изменяется от 1 до максимального количе- ства субконто. _AccTtLC<n> — таблица итогов оборотов между счетами. Эта таблица создается только для регистра бухгалтерии, поддерживающего корреспонденцию. _AccntRegOptions — таблица настроек хранения итогов. Эта таблица создается одна на все регистры бухгалте- рии. Все таблицы регистра бухгалтерии имеют сквозную ну- мерацию, поэтому для регистра бухгалтерии, поддержи- вающего корреспонденцию и связанного с планом счетов, у которого максимальное количество субконто равно 3, могут быть созданы, например, следующие таблицы: _AccntReg83 _AccntRegED98 _AccTtlO85 _AccTtll95 _AccTtl296 _AccTtl397 AccTtlC92 _AccntRegChangeRec<n> — таблица регистрации изменений регистра бухгалтерии. Создается, если регистр бухгалтерии участвует хотя бы в одном плане обмена. План видов расчета _CalcKind<n> — основная таблица плана видов расчета. _CalcKind<n>_BaseCK — таблица базовых видов расчета. Эта таблица создается в случае, если у плана видов расче- та свойство Зависимость от базы имеет значение, отличное от Не зависит. _CaLcKind<n>_DispLacedCK — таблица вытесняемых видов расчета. Эта таблица создается в случае, если для плана видов расчета установлен флаг Использует период действия. _CalcKind<n>_LeadingCK — таблица ведущих видов расчета. _CalcKindDN<n> — вспомогательная таблица для порядка вытеснения. Эта таблица создается в случае, если у плана видов расчета установлен флаг Использует период действия. _CalcKind<n>_VT<k> — табличная часть плана видов рас- чета. Все таблицы плана видов расчета имеют один и тот же номер <п>, за исключением вспомогательной таблицы для порядка вытеснения. Для нее используется сквозная ну- мерация. Например: _CalcKind71 CalсКтnd71_BaseCK CalcKind71_D1splacedCK CalcKi nd71_Leadi ngCK _CalcKind71_VT72 _CalcKindDN74 _CalcKindChangeRec<n> — таблица регистрации изменений плана видов расчета. Создается, если план видов расчета участвует хотя бы в одном плане обмена.
Регистр расчета _CaLcReg<n> — таблица движений регистра расчета. _CaLcRegActPer<n> — таблица фактического периода дейст- вия. Эта таблица создается в том случае, если у регистра расчета установлен флаг Период действия. _CalcRegRecalc<n> — таблица перерасчета регистра расчета. Все таблицы регистра расчета имеют сквозную нумера- цию. Например, для одного регистра расчета могут быть созданы следующие таблицы: CalcReglOO _CalcRegActPerlO6 _CalcRegRecalс104 _CalcRegChangeRec<n> — таблица регистрации изменений регистра расчета. Создается для каждого регистра расчета, участвующего хотя бы в одном плане обмена. _CalcRegRecaLcChangeRec<n> — таблица регистрации изме- нений перерасчета. Создается, если перерасчет участвует хотя бы в одном плане обмена. План обмена _Node<n> — основная таблица плана обмена. _Node<n>_VT<k> — табличная часть плана обмена. Таблицы, содержащие табличные части плана обмена, имеют тот же номер <п>, что и основная таблица плана обмена. Например: _Node62 _Node62_VT63 Хранилище конфигурации Хранилище конфигурации используется при групповой разработке конфигураций и служит для хранения исто- рии версий конфигурации, включая последнюю (теку- щую) версию. Все хранилище содержится в одном фай- ле — lCv8ddb.lcd. Каталог, в котором располагается этот файл, может быть произвольным и задается при создании хранилища кон- фигурации. Если разработка конфигурации ведется с использованием хранилища конфигурации, то данные, хранимые в этом файле, являются жизненно важными. Поэтому рекоменду- ется выполнять резервное копирование файла lCv8ddb.lcd. Журнал регистрации Журнал регистрации относится к информационной базе, но не является ее частью. Он служит для сохранения ин- формации о событиях, возникающих в процессе работы пользователей с данной информационной базой. Эта ин- формация может быть важной с организационной точки зрения, но не является необходимой для функционирова- ния прикладного решения ЮПредприятия. Журнал регистрации хранится в файле lCv8.log. Располо- жение этого файла различное в файловом и клиент-сер- верном вариантах работы. В файловом варианте работы журнал регистрации распо- лагается в том же каталоге, что и сама информационная база. Например, если информационная база хранится в файле C:/EnterpriseInfoBase/lCv8.1CD, то журнал регистрации будет находиться в файле C:/EnterpriseInfoBase/lCv8.log. В клиент-серверном варианте работы журнал регистра- ции располагается в каталоге данных приложения, не за- висящем от пользователя, а именно: <0бщие данные приложений>/1С/1Су8/<Идентификатор инфор- мационной базы>/1Су8.1од, например: C:/Documents and Settings/All Users/Application Data/lC/lCv8/ 4129dbdb-b495-41cb-99ea-ef315060a03e/lCv8.log. Профайлы Профайлы содержат информацию, не оказывающую влия- ния на логику функционирования системы на базе ЮПредприятия. Такая информация не является необходи- мой, но ее сохранение может, например, повысить комфорт- ность работы пользователя. В профайлах обычно хранятся формат и расположение окон и диалогов, настройки шриф- тов, цветов, отборов и т. и. Потеря такой информации не может привести к нарушению работоспособности системы. Данные из профайлов читаются при старте ЮПредпри- ятия 8.0 и записываются при его штатном завершении. По этой причине в случае нештатного завершения неко- торые пользовательские настройки могут не сохраниться. Профайлы различаются по принадлежности хранимой в них информации. Этим же свойством определяется то, что хранятся они в различных каталогах различных ком- пьютеров. Например, параметры, связанные с экранными характеристиками компьютера, хранятся так, чтобы дей- ствовать только в пределах данного компьютера, а пара- метры, связанные только с данными и не имеющими от- ношение к компьютеру, хранятся таким образом, чтобы быть доступными при запуске пользователем системы с любого компьютера. Параметры, связанные с конфигури- рованием, сохраняются независимо от информационной базы, так как считается, что разработчик может работать с несколькими информационными базами и несколькими конфигурациями. Параметры работы пользователя в ре- жиме 1 С: Предприятия сохраняются для конкретной ин- формационной базы и конкретного пользователя. Далее перечислены профайлы, используемые системой Ю:Предприятие с привязкой к их расположению. Компьютер пользователя Каталог клиентских данных приложения 1С Этот каталог расположен на клиентском компьютере: <Данные приложений пользователя>\1С\1Су8\ Например: C:\Documents and Settings\User\AppLication Data\lC\lCv8\ Профайлы этого каталога хранят следующие данные: lCv8.pfl — параметры для клиентского компьютера, на- пример: ♦ открыто ли табло; ♦ настройки текстового редактора.
lCv8cmn.pfl — общие параметры для клиентского компью- тера, используемые в Конфигураторе, например: ♦ расположение окон конфигуратора; ♦ цвета редактора модулей в конфигураторе. lCv8strt.pfl — параметры диалога выбора информацион- ной базы, например: ♦ размеры и расположение диалога запуска; ♦ настройки диалогов установки параметров информаци- онных баз. Каталоги информационных баз Эти каталоги расположены на клиентском компьютере: «Данные приложений пользователя>\1С\1Сл/8\ «Идентификатор ИБ>\ Например: C:\Documents and Settings\User\Application Data\lC\ lCv8\4129dbdb-b495-41cb-99ea-ef315060a03e\ Профайлы этих каталогов хранят следующие данные: lCv8.pfl — параметры для клиентского компьютера и ин- формационной базы, например: ♦ настройки сравнения файлов конфигураций; ♦ настройки глобального поиска по текстам конфигу- рации. Каталоги пользователей информационных баз Эти каталоги расположены на клиентском компьютере: «Данные приложений пользователя>\1С\1Сл/8\ «Идентификатор ИБ>\«Идентификатор пользователя^ Например: C:\Documents and Settings\User\Application Data\lC\ lCv8\4129dbdb-b495-41cb-99ea-ef315060a03e\ E8D87DA4-A087-4145-95E7-D613E0F7CB64\ Профайлы этих каталогов хранят следующие данные: lCv8.pfl — параметры для компьютера, информационной базы, пользователя, например: ♦ расположение окна синтакс-помощника; ♦ список переменных для быстрого просмотра в отладчике. lCv8cmn.pfl — общие параметры для компьютера, исполь- зуемые в 1С:Предприятии, например: ♦ расположение системных окон; ♦ цвета редактора модулей; ♦ параметры калькулятора. Компьютер пользователя или компьютер сервера ЮПредприятия Каталоги информационных баз В клиент-серверном варианте работы эти каталоги распо- ложены на компьютере, где установлен сервер ЮПред- приятия: «Общие данные приложений>\1С\1Сл/8\ «Идентификатор информационной базы>\ Например: C:\Documents and Setti ngs\All Users\Application Data\lC\lCv8\ 4129dbdb-b495-41cb-99ea-ef315060a03e\ В файловом варианте работы используется каталог, в ко- тором расположен файл информационной базы, напри- мер: C:\EnterpriseInfoBase\ Имя профайла — lCv8.pfl (в клиент-серверном вариан- те — ib.pfl). Этот профайл хранит параметры для инфор- мационной базы, не зависящие от компьютера пользова- теля, например: ♦ режим аутентификации при старте ЮПредприятия из отладчика; ♦ каталог последнего сохранения хранилища конфигура- ции в файл. Имя профайла — lCv8.pfL В клиент-серверном варианте: «Идентификатор пользователяэ-.pfl, например, E8D87DA4- A087-4145-95E7-D613E0F7CB64.pfl. Этот профайл хранит параметры для информационной базы, пользователя, не зависящие от компьютера пользователя, например: ♦ настройки динамических списков; ♦ настройки отборов по журналу регистрации. Другие вспомогательные данные Кроме профайлов, система 1С:Предприятие использует целый ряд других вспомогательных файлов. В них содер- жится информация, которая помогает сделать работу пользователей системы более удобной. def.usr — содержит имя пользователя, который последним открывал данную информационную базу. Этот файл хранится в каталоге: «Данные приложений пользователя>\1С\1Сл/8\ «Идентификатор ИБ> Например: C:\Documents and Settings\User\Application Data\lC\lCv8\ lCv8\4129dbdb-b495-41cb-99ea-ef315060a03e\def.usr v8ib.lst — содержит список информационных баз, заре- гистрированных на данном клиентском компьютере. Этот список отображается в диалоге Запуск ЮПредпри- ятия. Файл создается ЮПредприятием версии 8.0.7 и более поздними. Для 1 С:Предприятия версии 8.0.6 и более ранних для аналогичных целей используется файл ib.lst. Этот файл хранится в каталоге: «Данные приложений пользователя>\1С\1Сл/8 Например: C:\Documents and Settings\User\Application Data\lC\ lCv8\ib.lst v8cscadr.lst — содержит адрес каталога шаблонов конфи- гураций. Этот файл хранится в каталоге: «Данные приложений пользователя>\1С\1Сл/8
Например: C:\Documents and Settings\User\Application Data\lC\lCv8\ v8cscadr.lst GenTempLst — стандартный файл шаблонов текста. Этот файл хранится в каталоге загрузочных модулей 1 С:Предприятия. Например: C:\Program Files\lCV8\bin appsrvrs.lst — содержит список серверов 1 С:Предприятия, зарегистрированных в утилите администрирования ин- формационных баз в варианте клиент-сервер. Этот файл хранится в каталоге: «Данные приложений пользователя>\1С\1Сл/8 Например: C:\Documents and Settings\User\Application Data\lC\lCv8\ appsrvrs.lst srvrib.lst — содержит список параметров информацион- ных баз, зарегистрированных на данном сервере ЮПред- приятия. Содержащиеся в нем данные необходимы для нормальной работы приложений, использующих данный сервер ЮПредприятия. Этот файл хранится в каталоге: «Общие данные приложений>\1С\1Сл/8 Например: C:\Documents and Settings\All Users\Application Data\lC\ lCv8\srvrib.lst Группа файлов CACHE\ddb«n>.snp хранится в каталоге хра- нилища конфигурации и служит для кэширования запро- шенных версий конфигурации из этого хранилища. Наличие этих файлов не является обязательным и позво- ляет ускорить получение версий конфигурации. Временные данные Временные данные нужны только в течение нескольких пересекающихся во времени или одного сеанса 1С:Пред- приятия. К нескольким пересекающимся во времени сеансам отно- сятся данные совместного использования, которые относят- ся к файловой информационной базе в целом. Например, это данные, которые нужны для реализации блокировок данных информационной базы. Такие данные хранятся в том же каталоге, что и файл информационной базы: ICvS.ld — является носителем блокировок объектов базы данных, расположенной в файле lCv8.1cd. lCv8Tmp.lcd — хранит служебную сеансовую информа- цию, в частности список активных пользователей. lCv8Tmp.lcl — является носителем блокировок данных, расположенных в файле lCv8Tmp.lcd. Для хранилища конфигурации 1С:Предприятие 8.0 в ре- жиме Конфигуратора создает временные файлы аналогич- ного назначения, расположенные в каталоге хранилища конфигурации: ICvSddb.ld — является носителем блокировок данных из хранилища конфигурации. lCv8dtmp.lcd — хранит служебную сеансовую информа- цию, в частности список активных пользователей храни- лища конфигурации. lCv8dtmp.ld — является носителем блокировок данных, расположенных в файле lCv8ddb.lcd. Данные, используемые только в течение одного сеанса ЮПредприятия, размещаются во временных файлах, создаваемых в каталоге, определенном в системе Micro- soft Windows как каталог временных файлов. При этом для клиентского приложения используется каталог вре- менных файлов текущего пользователя Windows, напри- мер C:\Documents and Settings\User\LocalSettings\Temp. Для сервера 1 С: Предприятия используется системный ката- лог временных файлов, например C:\WINNT\Temp. Поля таблиц базы данных Как упоминалось в предыдущем разделе, многие объекты конфигурации описывают определенные структуры хране- ния информации в базе данных. При этом для хранения данных одних объектов конфигурации создаются одна или несколько связанных таблиц базы данных, а другие объек- ты конфигурации определяют наличие тех или иных полей в этих таблицах. Как правило, это подчиненные объекты конфигурации. Исключение составляют константы, кото- рые хранятся в одной таблице базы данных, поэтому для ка- ждой константы создается поле в этой таблице. В обобщенном виде информация о соответствии тех или иных объектов конфигурации таблицам или полям базы данных представлена в табл. П.1. Таблицы базы данных, создаваемые для объектов конфи- гурации, были перечислены в разделе «Таблицы инфор- мационной базы, определяемые структурой метаданных», с. 777. Здесь мы подробнее остановимся на полях базы данных, создаваемых для хранения данных тех или иных объектов конфигурации. Для всех перечисленных объектов конфигурации должен быть указан тип значений хранимых данных. В общем случае это может быть один из примитивных типов, ссы- лочный тип или составной тип. Хранение значений полей примитивных и ссылочных типов Если назначен один из примитивных типов или ссылоч- ный тип, то в базе данных создается одно поле, тип которо- го соответствует указанному типу. В табл. П.2 приведен список примитивных типов с указанием соответствующе- го типа поля базы данных в терминах SQL Server.
Таблица П.1. Соответствие объектов конфигурации полям и таблицам базы данных Элемент базы данных Объект конфигурации Таблица Бизнес-процесс Все константы Документ Журнал документов Задача Перерасчет Перечисление План видов расчета План видов характеристик План обмена План счетов Последовательность Регистр бухгалтерии Регистр накопления Регистр расчета Регистр сведений Справочник Табличная часть Поле Измерение Константа Признак учета Признак учета субконто Реквизит Реквизит адресации Ресурс Таблица П.2. Типы полей, хранящих значения примитивных и ссылочных типов Тип данных Тип поля базы данных Пример Число длины п, точность к NUMERIC(n, к) _Fld390 Строка фиксированной длины п NCHAR(n) _Fld390 Строка переменной длины п NVARCHAR(n) _Fld390 Строка неограниченной длины NTEXT _Fld390 Дата DATETIME _Fld390 Булево BINARY(l) _Fld390 Хранилище значения IMAGE _Fld390 Ссылка BINARY(16) _Fld242 RRef Для примитивных типов и хранилища значения имя фор- мируется из префикса _Fld и некоторого номера, позво- ляющего однозначно идентифицировать данное поле. Для ссылочных типов к имени поля добавляется суф- фикс _RRef. Схема базы данных содержит информацию о типах тех или иных полей. Таким образом, известно, что, например, в поле _Fld39O содержится тип значения Булево, а в поле _Fld242_Rref — значение типа СправочникСсылка.Номенклатура. Хранение значений полей составного типа Если указано, что объект конфигурации имеет составной тип данных или набора типов, то для хранения значений такого типа будет использовано несколько полей базы данных. Количество используемых полей будет зависеть от набора типов, входящих в составной тип. Все поля базы данных содержащие значение такого объекта кон- фигурации, имеют одинаковые имена, различающиеся суффиксами (несколькими последними символами). Суффикс имени поля базы данных определяет тип и на- значение хранимых в нем данных. В табл. П.З перечисле- ны все возможные суффиксы имен полей базы данных с указанием их типа (в терминах Microsoft SQL Server), на- значения полей с этими суффиксами и условия, при ко- торых они добавляются к представлению объектов базы данных данного типа. В общем случае состав полей для хранения значения та- кого объекта может включать в себя до семи полей. Зна- чение поля с суффиксом _TYPE указывает, каков фактиче- ский тип значения, хранящегося в этих полях: Число, Строка, Дата, Булево или ссылка. Если хранится значение одного из примитивных типов, то это значение получает- ся из поля с соответствующим суффиксом: _N, _S, _Т или _L (рис. П.1). Рис. П.1. Хранение значений составного типа Если хранится значение некоторого ссылочного типа из нескольких возможных, то поле с суффиксом _RTRef со- держит указание на конкретный тип ссылки (фактиче- ски — содержит номер таблицы), а поле с суффиксом _RRRef — собственно ссылку (идентификатор записи, на которую ссылается значение). Если хранится значение единственно возможного ссы- лочного типа, то поле с суффиксом _RTRef отсутству- ет (так как тип ссылки известен из схемы базы данных), а в поле с суффиксом _RRRef также хранится идентифика- тор записи, на которую ссылается значение. Такой механизм хранения значений данных позволяет наиболее адекватным способом выполнять средствами СУБД сравнение, сортировки, группировки и другие one-
Таблица П.З. Типы полей, хранящие значения составного типа Суффикс Тип поля базы данных Когда присутствует Назначение Пример TYPE BINARY(l) Всегда Содержит идентификатор фактического типа: Булево, Число, Строка, Дата или ссылка _Fld631_TYPE L BINARY(l) Если в составе типов есть тип Булево Содержит значение типа Булево. Если тип не Булево — содержит 0x00 _Fld533_L _N NUMERIC(n, k) Если в составе типов есть тип Число длины п, точность к Содержит значение типа Число. Если тип не Число — содержит 0 _Fld211N _т DATETIME Если в составе типов есть тип Дата Содержит значение типа Дата. Если тип не Дата — содержит дату ‘00000101000000’ _Fld538_T _s NCHAR(n) Если в составе типов есть тип Строка длиной п символов. Содержит значение типа Строка. Если тип не Строка — содержит строку из п пробелов _Fld421_S _s NVARCHAR(n) Если в составе типов есть тип Строка, пере- менная с максималь- ной длиной п символов Содержит значение типа Строка. Если тип не Строка — содержит пустую строку _Fld421S RTRef BINARY(4) Если в составе типов есть несколько ссылочных типов или набор типов Содержит номер таблицы, на которую ссылается значение, если его тип ссылки, или 0x00000000 в противном случае _Fld354 RTRef Таблица П.4. Варианты представления полей объектов Вариант Состав типов Пример Один тип, в том числе ссылка на объекты базы данных одного типа Строка __Fld513 СправочникТовары.Ссылка _Fld469_RRef Набор типов или ссылка на объекты базы данных двух и более типов СправочникСсылка _Fld572_TYPE _Fld572_TRef Fld572 RRef СправочникСсылка. Организации, СправочникСсылка.Контрагенты Fld572_TYPE Fld572_TRef Fld572 RRRef ЛюбаяСсылка Fld572 TYPE _Fld572_TRef Fld572_RRRef Несколько примитивных типов или ссылки с хотя бы одним типом, отличным от ссылок Число, строка _Fld436_TYPE Fld436_N Fld436_S Булево, СправочникСсылка.Контрагенты Fld677 TYPE _Fld677_L _Fld677_RRRef Число, СправочникСсылка _Fld638_TYPE _Fld638_N Fld638_RTRef Fld638_RRRcf
рации над данными, предусмотренные во встроенных объектах 1 СгПредприятия и в языке запросов. В процессе конфигурирования 1 СгПредприятия следует учитывать увеличение объема хранимых данных в СУБД при ис- пользовании составных типов данных и использовать со- ставные типы, только если это оправдано с точки зрения функционирования конфигурации. Обобщая все сказанное выше, можно выделить следую- щие варианты представления полями таблиц СУБД по- лей объектов базы данных 1 С:Предприятия (табл. П.4). Все варианты перечислены в порядке уменьшения эф- фективности: первый вариант является наиболее эффек- тивным, последний — наименее эффективным, что явля- ется определенной «платой» за его универсальность. Поэтому при использовании последнего варианта необ- ходимо учитывать возможное снижение эффективности и быть уверенным в том, что это не скажется существенно на функционировании прикладного решения. Кроме собственно ресурсоемкости, дополнительные про- блемы могут возникнуть в тех случаях, когда поле, пред- ставляемое в соответствии с последним вариантом, участ- вует в индексах. Индексирование полей составного типа Создание индексов по полям составных типов имеет важ- ную особенность, которая при неосторожном использова- нии может отрицательно сказаться на производительно- сти информационной базы. Если в индекс входит поле составного типа, для которого задано несколько различных типов (отличных от ссылок, или ссылки с хотя бы одним типом, отличным от ссылок), то вместо каждого дополнительного индекса, включающе- го это поле, будет создано столько дополнительных индек- сов, сколько различных типов содержится в описании типа этого поля. Такой подход позволяет уменьшить дли- ну ключа в индексе и использовать построенные индексы в операциях сравнения полей составных типов. Рассмотрим несколько примеров. Пусть индексируемое поле составного типа включает следующие типы: ♦ Число; ♦ Дата; ♦ ДокунентСсылка.ПриходнаяНакладная. В этом случае будет создано три индекса, которые будут включать в себя следующие наборы полей (табл. П.5). Таблица П.5. Индексирование полей, хранящих данные составного типа Типы составного типа Индексы Число Fld647 TYPE + _Fld647_N Дата _Fld647_TYPE + _Fld647_D ДокументСсылка. ПриходнаяНакладная _Fld647_TYPE + _Fld647_RRRef Рассмотрим другой пример, когда составной тип содер- жит несколько ссылочных типов (табл. П.6). Таблица П.6. Индексирование полей, хранящих данные составного типа Типы составного типа Индексы Булево _Fld325_TYPE + _Fld325_L Число _Fld325_TYPE + _Fld325_N СправочникСсылка. ФизическиеЛица СправочникСсылка. ЮридическиеЛица _Fld325_TYPE + _Fld325_RTRef + _Fld325_RRRef Теперь рассмотрим ситуацию, когда в составной индекс входят сразу оба приведенных здесь поля составного типа. В этом случае, поскольку первое поле имеет состав- ной тип, для него будет создано три индекса, а поскольку второе поле также имеет составной тип, то для каждого созданного индекса будет создано еще три (табл. П.7). Из приведенных примеров видно, что в общем случае ко- личество фактически созданных индексов будет равно произведению количеств различных типов (ссылки счи- таются одним типом), составляющих тип каждого из по- лей. Подобная нелинейная зависимость количества соз- даваемых индексов может отрицательно сказаться на производительности системы в тех местах, где индексы таблиц базы данных, создаваемые системой автоматиче- ски, включают относительно большое количество полей: ♦ ресурсы регистров и реквизиты, для которых индекси- рование задается в явном виде в конфигураторе; ♦ измерения регистров. Более подробно об индексировании основных таблиц базы данных можно прочитать в разделе «Индексы таб- лиц базы данных», с. 788. Сравнение полей составного типа В процессе функционирования информационных баз од- ним из важнейших действий над данными является их сравнение. Способ представления в СУБД данных различ- ных типов, реализованный в 1С:Предприятии, вносит не- которые особенности в выполнение операций сравнения. Очевидно, что способ представления данных СУБД ска- зывается на тех сравнениях, которые выполняются сред- ствами СУБД. Сравнение значений во встроенном языке ЮПредприятия не вызывает обращений к СУБД и не зави- сит от представления в СУБД участвующих в них данных. Сравнение средствами СУБД выполняется, в основном при использовании запросов. Например, в операциях сравнения, группировки и упоря- дочивания (листинг П.1). Листинг П.1. Использование сравнения в запросе ВЫБРАТЬ ЗарплатаКВыплате.Представление ИЗ Документ.ЗарплатаКВыплате КАК ЗарплатаКВыплате ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Пользователи КАК Пользователи ПО ЗарплатаКВыплате.Ответственный = Пользователи.Ссылка
Таблица П.7. Построение индекса по двум реквизитам составного типа Типы первого поля Типы второго поля Индексы Число Булево _Fld647_TYPE + _Fld647_N + _Fld325_TYPE + _Fld325_L Число Число _Fld647_TYPE + _Fld647_N + _Fld325_TYPE + _Fld325_N Число СправочникСсылка. ФизическиеЛица СправочникСсылка. ЮридическиеЛица _Fld647_TYPE + _Fld647_N + _Fld325_TYPE + _Fld325_RTRef + _Fld325_RRRef Дата Булево _Fld647_TYPE + _Fld647_D + _Fld325_TYPE + _Fld325_L Дата Число _Fld647_TYPE + _Fld647_D + _Fld325_TYPE + _Fld325_N Дата СправочникСсылка. ФизическиеЛица СправочникСсылка. ЮридическиеЛица _Fld647_TYPE + _Fld647_D + _Fld325_TYPE + _Fld325 RTRef + _Fld325_RRRef ДокументСсылка. Приходная Накладная Булево _Fld647_TYPE + _Fld647_RRRef + _Fld325_TYPE + _Fld325_L ДокументСсылка. Приходная Накладная Число _Fld647_TYPE + _Fld647_RRRef + _Fld325_TYPE + _Fld325_N ДокументСсылка. ПриходнаяНакладная СправочникСсылка. ФизическиеЛица СправочникСсылка.ЮридическиеЛица _Fld647_TYPE + _Fld647_RRRef + _Fld325_TYPE + _Fld325_RTRef + _Fld325_RRRef В приведенном примере раздел ПО содержит сравнение двух полей на равенство. Другой случай — преобразование типов и обращение по ссылкам (листинг П.2). В этом примере значение реквизита Документ.ЗарплатаКВыпла- те.Ответственный преобразуется к типу СправочникСсылка.Поль- зователи, после чего выбирается представление объекта. Листинг П.2. Использование преобразования типов в запросе ВЫБРАТЬ ВЫРАЗИТЬСЗарплатаКВыплате.Ответственный КАК Справочник.Пользователи).Представление ИЗ Документ.ЗарплатаКВыплате КАК ЗарплатаКВыплате
И в том и в другом случае результат выполнения опера- ции будет зависеть от типа реквизита Ответственный доку- мента ЗарплатаКВыплате. Также операции сравнения могут содержаться в SQL-за- просах, которые порождаются различными программны- ми объектами ЮПредприятия. Например, исполнение метода ВыбратьО (листинг П.З) приведет к построению и исполнению SQL-запроса к базе данных, содержащего операции сравнения. Листинг П.З. Использование метода ВыбратьО Выборка = Справочники.ФильтрыДляЭлектронныхПисен. Выбрать(. УчетнаяЗапись, Новый Структура("Использование". Истина), "Порядок ВОЗР"); Выбранный в 1С:Предприятии 8.0 механизм представле- ния данных составных типов позволяет естественным об- разом исполнять сортировки, группировки и вычисление агрегатных функций в терминах SQL без потери эффек- тивности. В то же время операции сравнения данных, в представ- лении которых участвуют несколько полей, для СУБД не являются элементарными и приводят к формирова- нию сложных условий, включающих все поля, которые участвуют в представлении сравниваемых данных. ЮПредприятие обеспечивает адекватность исполне- ния любых сравнений данных. Однако игнорирование особенностей сравнения полей составного типа может привести к снижению эффективности разрабатывае- мых конфигураций. Рассмотрим общий случай, когда выполняется сравнение двух полей составного типа, содержащих полный набор возможных различных типов данных 1 С: Предприятия. Допустим, что в базе данных им сопоставлены имена по- лей _Fldlll и _Fld222. Тогда некоторые варианты сравне- ний этих полей на уровне базы данных будут выглядеть следующим образом (табл. П.8). Из приведенных примеров видно, что сравнение полей составных типов использует условие, содержащее опера- цию 0R. Наличие этой операции существенно ограничивает Таблица П.8. Варианты выполнения сравнения на уровне базы данных Операция сравнения Реализация средствами SQL Реквизит! = Реквизит2 _Fldlll_TYPE = _Fld222_TYPE AND (FldlllTYPE = 0x01 OR Fldlll TYPE = 0x02 AND FldlllL = _Fld222_L OR _Fldlll_TYPE = 0x03 AND _Fldlll_N = _Fld222_N OR Fldlll TYPE = 0x04 AND _Fldlll_T = _Fld222_T OR Fldlll TYPE = 0x05 AND FldlllS = _Fld222_S OR Fldlll TYPE = 0x06 AND FldlllB = _Fld222_B OR Fldlll TYPE = 0x07 AND FldlllRTRef = _Fld222_RTRef AND Fldlll RRRef = Fld222_RRRef ) Реквизит! <> Реквизит2 _Fldlll_TYPE <> _Fld222_TYPE OR ( _Fldlll_TYPE = 0x02 AND Fldlll L <> _Fld222_L OR Fldlll TYPE = 0x03 AND _Fldlll_N <> _Fld222_N OR Fldlll TYPE = 0x04 AND _Fldlll_T <> _Fld222_T OR Fldlll TYPE = 0x05 AND _Fldlll_S <> _Fld222_S OR Fldlll TYPE = 0x06 AND _Fldlll_B <> _Fld222_B OR_Fldlll_TYPE = 0x07 AND ( Fldlll RTRef <> _Fld222_RTRef OR Fldlll RRRef <> _Fld222_RRRef ) ) Реквизит! > Реквизит2 Fldlll TYPE > _Fld222_TYPE OR _Fldlll_TYPE = _Fld222_TYPE AND ( Fldlll TYPE = 0x02 AND _Fldlll_L > _Fld222 L OR_Fldlll_TYPE = 0x03 AND Fldlll N > _Fld222_N OR _Fldlll_TYPE = 0x04 AND FldlllT > _Fld222_T OR _Fldlll_TYPE = 0x05 AND _Fldlll_S > _Fld222_S OR Fldlll TYPE = 0x06 AND _Fldlll_B > _Fld222_B OR Fldlll—TYPE = 0x07 AND (_Fldlll_RTRef > _Fld222_RTRef OR FldlllRTRef = _Fld222_RTRef AND Fldl 1 IRRRef = _Fld222_RRRef )
возможности СУБД по оптимизации плана такого запро- са, и в том числе по использованию индексов. Это может привести к существенному замедлению исполнения тако- го запроса. Особым случаем сравнения полей составных типов явля- ются те сравнения, в реализации которых средствами SQL операция OR не используется. Исполнение таких сравнений не может привести к существенному сниже- нию производительности. Среди них: ♦ сравнение с литералом; ♦ сравнение со значением поля примитивного типа; ♦ сравнение на равенство со значением поля составного типа, включающего только ссылочные типы; ♦ сравнение на равенство значений полей составного типа с одинаковым набором типов (набор ссылочных типов может быть произвольным). Реализация следующих сравнений хотя и может содер- жать операции OR, но, как правило, хорошо оптимизирует- ся СУБД. Их исполнение обычно также не приводит к су- щественному снижению производительности: ♦ сравнение >, <, >=, <= со значением поля составного типа, включающего только ссылочные типы; ♦ сравнение >, <, >=, <= значений полей составного типа с одинаковым набором типов (набор ссылочных типов может быть произвольным). Приведенные выше соображения позволяют сформули- ровать следующие рекомендации по использованию по- лей составных типов: ♦ использовать поля составных типов следует только то- гда, когда это является оправданным с точки зрения ло- гики функционирования конфигурации; ♦ не следует использовать составные типы (кроме ссы- лочных) для полей, по которым связываются таблицы. Например, если в документах ПриходнаяНакладная и РасходнаяНакладная есть реквизит Контракт составного типа, то исполнение следующего запроса (листинг П.4) может быть неэффективным; ♦ желательно избегать выполнения операций поиска и отбора по значениям полей составных типов (кроме ссылочных); ♦ не следует определять поля составного типа (кроме ссылочных) в таблицах с потенциально очень большим количеством записей; ♦ желательно избегать использования субконто и изме- рений регистров составных типов (кроме ссылочных); ♦ индексирование по полям составных типов следует ис- пользовать только после тщательного анализа этого ре- шения с точки зрения его необходимости и с точки зре- ния возможных потерь производительности. Листинг П.4. Связь таблиц по полю составного типа ВЫБРАТЬ ПриходнаяНакладная.Контракт ИЗ Документ.ПриходнаяНакладная КАК ПриходнаяНакладная ЛЕВОЕ СОЕДИНЕНИЕ Документ.РасходнаяНакладная КАК РасходнаяНакладная ПО ПриходнаяНакладная.Контракт = РасходнаяНакладная.Контракт Индексы таблиц базы данных При создании таблиц, соответствующих тем или иным объектам конфигурации, система автоматически создает набор индексов, обеспечивающих эффективную работу с этими таблицами. В то же время разработчик может до- полнительно, если существует такая необходимость, ука- зать те или иные поля, которые также должны участво- вать в построении индекса. Информация об индексах, создаваемых системой авто- матически, может быть полезна при написании текстов запросов с целью оптимизации времени их выполне- ния. С другой стороны, возможность создания дополнитель- ных индексов таблиц базы данных может быть использо- вана при выполнении оптимизации конкретных алгорит- мов, сложных запросов. Реквизиты различных объектов конфигурации имеют свойство Индексировать. Это свойст- во может быть установлено в значения Индексировать и в некоторых случаях Индексировать с доп. упорядочиванием. При этом система при реструктуризации информацион- ной базы будет создавать дополнительные индексы с уче- том заданных свойств. Кроме этого, при работе с динамическими списками не- обходимо представлять правила, по которым система соз- дает индексы таблиц базы данных, так как механизм динамического просмотра напрямую «завязан» с ин- дексами, существующими в базе данных. Настройка динамических списков предоставляет широкие возмож- ности упорядочивания и отбора списков, однако далеко не все возможные варианты упорядочивания, например, могут быть реализованы одинаково эффективно. Вполне реальна ситуация, когда механизм динамического про- смотра просто будет отключен, потому что в базе данных не найдется подходящего индекса для выполнения уста- новленного упорядочивания. В этом случае работа спи- ска может значительно замедлиться, так как данные из базы данных будут выбираться не порциями, а целиком из всей таблицы. Более подробно о работе динамических списков можно прочитать в разделе «Список», с. 59. В приведенном ниже описании указаны имена полей, ис- пользуемые в таблицах запросов. Для измерений, реквизитов и т. д. применяются услов- ные имена Измерение!, Реквизит! и т. д. Те индексные поля, которые не являются обязательными, приведены в квадратных скобках. Если в индексе присутствует набор однотипных полей, это описывается многоточием, на- пример: Реквизит + Измерение! + [Измерение2 +...]
Справочник Основная таблица Основные индексы Ссылка Этот индекс создается всегда для любого справочника. Код + Ссылка Этот индекс создается в случае, если длина кода не рав- на 0. Наименование + Ссылка Этот индекс создается в случае, если длина наименова- ния не равна 0. Реквизит + Ссылка Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Реквизит + Код + Ссылка Этот индекс создается в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина кода не равна 0; ♦ основное представление справочника в виде кода. Реквизит + Наименование + Ссылка Этот индекс создается в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина наименования не равна 0; ♦ основное представление справочника в виде наимено- вания. Реквизит Этот индекс создается в случае, если справочник вклю- чен в критерий отбора через реквизит Реквизит. Дополнительные индексы Дополнительные индексы для подчиненного справочника (вне зависимости от иерархичности справочника) Владелец + Код + Ссылка Этот индекс создается в случае, если длина кода не рав- на 0. Владелец + Наименование + Ссылка Этот индекс создается в случае, если длина наименова- ния не равна 0. Владелец + Реквизит + Ссылка Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Владелец + Реквизит + Код + Ссылка Этот индекс создается в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина кода не равна 0; ♦ основное представление справочника в виде кода. Владелец + Реквизит + Наименование + Ссылка Этот индекс создается в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина наименования не равна 0; ♦ основное представление справочника в виде наимено- вания. Дополнительные индексы для иерархического неподчиненного справочника Родитель + ЭтоГруппа + Код + Ссылка Этот индекс создается в случае, если длина кода не рав- на 0. Родитель + ЭтоГруппа + Наименование + Ссылка Этот индекс создается в случае, если длина наименова- ния не равна 0. Родитель + ЭтоГруппа + Реквизит + Ссылка Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Родитель + ЭтоГруппа + Реквизит + Код + Ссылка Этот индекс создается в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина кода не равна 0; ♦ основное представление справочника в виде кода. Родитель + ЭтоГруппа + Реквизит + Наименование + Ссылка Этот индекс создается в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина наименования не равна 0; ♦ основное представление справочника в виде наимено- вания. Если для справочника не задано свойство Размещение групп сверху, то состав индексов соответствует приведенной выше таблице, но в индексы при этом не включено поле ЭтоГруппа. Дополнительные индексы для иерархического подчиненного справочника Владелец + Родитель + ЭтоГруппа + Код + Ссылка Этот индекс создается в случае, если длина кода не рав- на 0. Владелец + Родитель + ЭтоГруппа + Наименование + Ссылка Этот индекс создается в случае, если длина наименова- ния не равна 0. Владелец + Родитель + ЭтоГруппа + Реквизит + Ссылка Этот индекс создается в случае, если для реквизита уста- новлено индексирование.
Владелец + Родитель + ЭтоГруппа + Реквизит + Код + Ссылка Этот индекс создается в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина кода не равна 0; ♦ основное представление справочника в виде кода. Владелец + Родитель + ЭтоГ руппа + Реквизит + Наименование + Ссылка Этот индекс создается в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина наименования не равна 0; ♦ основное представление справочника в виде наимено- вания. Если для справочника не задано свойство Размещение групп сверху, то состав индексов соответствует приведенной выше таблице, но в индексы при этом не включено поле ЭтоГруппа. Таблица табличной части Все таблицы, предоставляющие доступ к табличным час- тям объектов, индексируются одинаково. Подробнее об индексировании таблицы табличной части написано в разделе «Табличная часть», с. 791. Документ Основная таблица Ссылка Дата + Ссылка Эти индексы создается всегда для любого документа. Номер + Ссылка Этот индекс создается в случае, если длина номера не равна 0. Реквизит + Ссылка Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Реквизит + Дата + Ссылка Этот индекс создается в случае, если для реквизита уста- новлено индексирование с дополнительным упорядочи- ванием. Реквизит Этот индекс создается в случае, если документ включен в критерий отбора через реквизит Реквизит. Таблица табличной части Все таблицы, предоставляющие доступ к табличным час- тям объектов, индексируются одинаково. Подробнее об индексировании таблицы табличной части написано в разделе «Табличная часть», с. 791. Журнал документов Дата + Ссылка Этот индекс создается всегда для любого журнала доку- ментов. Графа + Ссылка Этот индекс создается в случае, если для графы установ- лено индексирование. Графа + Дата + Ссылка Этот индекс создается в случае, если для графы установ- лено индексирование с дополнительным упорядочива- нием. План видов характеристик Индексы, создаваемые для таблиц плана видов характе- ристик, аналогичны индексам, создаваемым для справоч- ника. Разница заключается только в условиях создания индексов: у плана видов характеристик длина кода и на- именования не может быть равна нулю, и план видов ха- рактеристик не может быть подчиненным. Основные индексы таблиц справочника подробно описа- ны в разделе «Справочник», с. 789. План счетов Основная таблица Ссылка Код + Ссылка Родитель + Код + Ссылка Наименование + Ссылка Родитель + Наименование + Ссылка Эти индексы создается всегда для любого плана счетов. Порядок + Ссылка Родитель + Порядок + Ссылка Эти индексы создаются в случае, если длина порядка не равна 0. Реквизит + Ссылка Родитель + Реквизит + Ссылка Эти индексы создаются в случае, если для реквизита ус- тановлено индексирование. Реквизит + Порядок + Ссылка Родитель + Реквизит + Порядок + Ссылка Эти индексы создаются в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина порядка не равна 0.
Реквизит + Код + Ссылка Родитель + Реквизит + Код + Ссылка Эти индексы создаются в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина порядка равна 0; ♦ основное представление в виде кода. Реквизит + Наименование + Ссылка Родитель + Реквизит + Наименование + Ссылка Эти индексы создаются в случае, если: ♦ для реквизита установлено индексирование с дополни- тельным упорядочиванием; ♦ длина порядка равна 0; ♦ основное представление в виде наименования. Реквизит Этот индекс создается в случае, если план счетов вклю- чен в критерий отбора через реквизит Реквизит. Таблица табличной части Все таблицы, предоставляющие доступ к табличным час- тям объектов, индексируются одинаково. Подробнее об индексировании таблицы табличной части написано в разделе «Табличная часть», с. 791. План видов расчета Индексы, создаваемые для таблиц плана видов расчета, аналогичны основным индексам, создаваемым для спра- вочника. Основные индексы таблиц справочника подроб- но описаны в разделе «Справочник», с. 789. План обмена Индексы, создаваемые для таблиц плана обмена, анало- гичны основным индексам, создаваемым для справочни- ка. Разница заключается только в условиях создания ин- дексов: у плана обмена длина кода и длина наименования не могут быть равны нулю. Основные индексы таблиц справочника подробно описа- ны в разделе «Справочник», с. 789. Табличная часть Ссылка Этот индекс создается всегда для любой табличной части любого объекта конфигурации. Реквизит Этот индекс создается в случае если: ♦ объект конфигурации включен в критерий отбора через реквизит Реквизит табличной части или ♦ для реквизита табличной части установлено индекси- рование. Регистр сведений Непериодический регистр сведений Измерение! + [Измерение? +...] Индекс, включающий все измерения в том порядке, в ко- тором они заданы при конфигурировании. Этот индекс создается в случае, если есть хоть одно изме- рение регистра. Измерением + Измерение! + [Измерение? +...] Индекс, включающий все измерения. Первое поле — Измерением, затем все остальные измерения в том поряд- ке, в котором они заданы при конфигурировании. Этот индекс создается в случае, если: ♦ для реквизита измерением установлено индексирование или свойство Ведущее; ♦ измерением — не первое измерение; ♦ измерением — не единственное измерение. Реквизит + Измерение! + [Измерение? +...] Индекс, в котором первое поле — Реквизит, затем все из- мерения в том порядке, в котором они заданы при конфи- гурировании. Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Ресурс + Измерение! + [Измерение? +...] Индекс, в котором первое поле — Ресурс, затем все изме- рения в том порядке, в котором они заданы при конфигу- рировании. Этот индекс создается в случае, если для ресурса установ- лено индексирование. Периодический регистр сведений Период + [Измерение! +...] Этот индекс создается всегда для любого периодического регистра сведений. Измерение! + [Измерение? +...] + Период Индекс, включающий все измерения в том порядке, в ко- тором они заданы при конфигурировании, и поле Период. Этот индекс создается в случае, если есть хоть одно изме- рение регистра. Измерением + Период + Измерение! + [Измерение? +...] Индекс, включающий поле Период и все измерения. Пер- вое поле — Измерением, затем поле Период, затем все ос- тальные измерения в том порядке, в котором они заданы при конфигурировании. Этот индекс создается в случае, если: ♦ для измеренияИ установлено индексирование; ♦ измерениеИ — не единственное измерение. Реквизит + Период + [Измерение! +...] Индекс в котором первое поле — Реквизит, затем поле Пе- риод, затем все измерения в том порядке, в котором они заданы при конфигурировании.
Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Ресурс + Период + [Измерение! +...] Индекс в котором первое поле — Ресурс, затем поле Пери- од, затем все измерения в том порядке, в котором они за- даны при конфигурировании. Этот индекс создается в случае, если для ресурса установ- лено индексирование. Дополнительный индекс для регистра сведений, подчиненного регистратору Регистратор + НомерСтроки Этот индекс создается всегда для любого регистра сведе- ний, подчиненного регистратору. Регистр сведений с периодичностью По позиции регистратора Период + Регистратор + НомерСтроки Регистратор + НомерСтроки Эти индексы создаются всегда для любого регистра све- дений с периодичностью По позиции регистратора. Измерение! + [Измерение2 + ...] + Период + Регистратор Индекс, включающий все измерения в том порядке, в ко- тором они заданы при конфигурировании, поле Период и поле Регистратор. Этот индекс создается в случае, если есть хоть одно изме- рение регистра. Измерение + Период + Регистратор + НомерСтроки Этот индекс создается в случае, если для измерения уста- новлено индексирование. Реквизит + Период + Регистратор + НомерСтроки Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Ресурс + Период + Регистратор + НомерСтроки Этот индекс создается в случае, если для ресурса установ- лено индексирование. Регистр накопления Основная таблица Период + Регистратор + НомерСтроки Регистратор + НомерСтроки Этот индекс создается всегда для любого регистра накоп- ления. Измерение + Период + Регистратор + НомерСтроки Этот индекс создается в случае, если для измерения уста- новлено индексирование. Реквизит + Период + Регистратор + НомерСтроки Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Регистр бухгалтерии Основная таблица Основная таблица регистра без корреспонденции Период + Регистратор + НомерСтроки Регистратор + НомерСтроки Эти индексы создаются всегда для любого регистра бух- галтерии без корреспонденции. Счет + Период + Регистратор Этот индекс создается в случае, если регистру назначен план счетов. Измерение + Период + Регистратор + НомерСтроки Этот индекс создается в случае, если для измерения уста- новлено индексирование. Реквизит + Период + Регистратор + НомерСтроки Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Основная таблица регистра с корреспонденцией Для основной таблицы регистра бухгалтерии с коррес- понденцией создаются те же индексы, что и для регистра без корреспонденции, за исключением того, что вместо индекса по счету создаются два индекса по счету дебета и счету кредита: СчетДт + Период + Регистратор СчетКт + Период + Регистратор Эти индексы создаются всегда для любого регистра с кор- респонденцией. Таблица значений субконто Регистратор + НомерСтроки ВидСубконто + Значение + Период + Регистратор + НомерСтроки Эти индексы создаются в случае, если регистр бухгалте- рии ссылается на план счетов, у которого максимальное количество субконто больше нуля. Регистр расчета Основная таблица ПериодРегистрации + Регистратор + НомерСтроки Регистратор + НомерСтроки Эти индексы создаются всегда для любого регистра расчета.
ПериодРегистрации + [БазовоеИзмерение! +...] Индекс по полю ПериодРегистрации и всем базовым изме- рениям, то есть по тем измерениям, у которых установле- но свойство Базовое. Базовые измерения следуют в том порядке, в котором они заданы при конфигурировании. Если базовые измерения отсутствуют, то этот индекс бу- дет строиться только по полю ПериодРегистрации. [БазовоеИзмерение! +...] + ПериодРегистрации Индекс по всем базовым измерениям, то есть по тем из- мерениям, у которых установлено свойство Базовое, и по- лю ПериодРегистрации. Этот индекс создается в случае, если есть хоть одно базо- вое измерение. ПериодДействия + [БазовоеИзмерение! +...] Индекс по полю ПериодДействия и всем базовым измере- ниям, то есть по тем измерениям, у которых установлено свойство Базовое. Базовые измерения следуют в том по- рядке, в котором они заданы при конфигурировании. Этот индекс создается в случае, если установлено свойст- во регистра расчета Периоддействия. [БазовоеИзмерение1 +...] + ПериодДействия Индекс по всем базовым измерениям, то есть по тем изме- рениям, у которых установлено свойство Базовое, и полю ПериодРегистрации. Этот индекс создается в случае, если: ♦ установлено свойство регистра расчета Периоддействия; ♦ есть хоть одно базовое измерение. Измерение + ПериодРегистрации + Регистратор + НомерСтроки Этот индекс создается в случае, если для измерения уста- новлено индексирование. Реквизит + ПериодРегистрации + Регистратор + НомерСтроки Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Таблица перерасчета Регистратор + ВидРасчета + [Измерение! +...] Индекс по полю Регистратор, полю ВидРасчета и всем по- лям измерений перерасчета в той последовательности, в которой они сконфигурированы. Этот индекс создается всегда для таблицы перерасчета. Последовательность Таблица регистрации документов в последовательности Регистратор [Измерение! +...] + Период + РегистраторВсегда. Индекс по всем полям измерений, полю Период и полю Регистратор. Поля измерений следуют в том порядке, в ко- тором они заданы при конфигурировании. Эти индексы создаются всегда для любой последователь- ности. Таблица границ последовательности [Измерение! +...] + Период + Регистратор Индекс по всем полям измерений, полю Период и полю Регистратор. Поля измерений следуют в том порядке, в ко- тором они заданы при конфигурировании. Этот индекс создается всегда для любой последователь- ности. Перечисление Порядок + Ссылка Поле Порядок таблиц перечислений соответствует по- рядку в котором значения перечисления расположены в дереве конфигурации. Этот индекс создается всегда для любого перечисления. Бизнес-процесс Основная таблица Ссылка Дата + Ссылка Завершен + Дата + Ссылка Стартован + Дата + Ссылка ВедущаяЗадача + Ссылка Эти индексы создаются всегда для любого бизнес-про- цесса. Номер + Ссылка Этот индекс создается в случае, если длина номера не равна 0. Реквизит + Ссылка Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Реквизит + Дата + Ссылка Этот индекс создается в случае, если для реквизита уста- новлено индексирование с дополнительным упорядочи- ванием. Реквизит Этот индекс создается в случае, если бизнес-процесс включен в критерий отбора через реквизит Реквизит. Таблица табличной части Все таблицы, предоставляющие доступ к табличным час- тям объектов, индексируются одинаково. Подробнее об индексировании таблицы табличной части написано в раз- деле «Табличная часть», с. 791. Таблица точек маршрута Порядок + Ссылка Поле Порядок таблиц точек соответствует порядку, в ко- тором точки маршрута были введены в графическую схе- му бизнес-процесса. Этот индекс создается всегда для любого бизнес-процесса.
Задача Основная таблица Ссылка Дата + Ссылка Наименование + Ссылка Выполнена + Наименование + Ссылка Выполнена + Дата + Ссылка БизнесПроцесс + ТочкаМаршрута + Ссылка Выполнена + БизнесПроцесс + ТочкаМаршрута + Ссылка БизнесПроцесс + Дата + Ссылка Эти индексы создаются всегда для любой задачи. Номер + Ссылка Этот индекс создается в случае, если длина номера не равна 0. Реквизит + Ссылка Этот индекс создается в случае, если для реквизита уста- новлено индексирование. Реквизит + Дата + Ссылка Этот индекс создается в случае, если для реквизита установ- лено индексирование с дополнительным упорядочиванием. Реквизит Этот индекс создается в случае, если задача включена в критерий отбора через реквизит Реквизит. Таблица табличной части Все таблицы, предоставляющие доступ к табличным час- тям объектов, индексируются одинаково. Подробнее об индексировании таблицы табличной части написано в разделе «Табличная часть», с. 791.
Содержание Введение Об авторах.........................................3 Благодарности......................................4 От редактора.......................................4 Особенности книги..................................5 Как читать книгу...................................5 Структура книги....................................5 Что находится на компакт-диске.....................7 Скажите нам, что вы думаете .......................7 От издателей.......................................7 Глава 1. Архитектура ЮПредприятия Платформа и прикладные решения.............8 Средства разработки в составе платформы .... 8 Метаданные — способ описания прикладного решения....................................9 Метаданные и встроенный язык...............9 Подсистемы.................................9 Создание прикладных решений на основе модели . 9 Объектные и необъектные данные............10 Три способа представления данных..........10 Сквозная типизация........................10 Поддержка составных типов данных..........11 Смешанный подход к манипулированию данными...................................11 Встроенный язык...........................11 Язык запросов .......................... 12 Прикладные решения, независимые от используемого хранилища данных...........12 Файловый и клиент-серверный варианты работы.............................12 Сервер ЮПредприятия.........................13 Выполнение встроенного языка на клиенте и сервере . 13 Высокоуровневая модель интерфейса...........13 Использование информации из метаданных......13 Расширения форм и элементов управления......13 Автоматическое формирование командного интерфейса . 14 Генерация форм по умолчанию.................14 Собственная модель оконной системы..........14 Поддержка различных хранилищ данных .... 14 Обновление прикладных решений...............14 Интернационализация.........................15 Глава 2. Функциональность ЮПредприятия Обзор функциональности прикладных решений . 16 Справочники.....................................16 Документы.......................................16 Механизм характеристик..........................16 Механизм сведений...............................17 Механизм учета движения средств.................17 Механизм бухгалтерского учета...................17 Механизм сложных периодических расчетов ........17 Механизм бизнес-процессов.......................17 Механизм анализа данных и прогнозирования......18 Интеллектуальные механизмы подготовки отчетов . . 18 Табличный документ, географическая схема, диаграммы, диаграмма Ганта................................18 Средства интеграции и механизмы обмена данными . . 19 Web-расширение..................................19 Обзор функциональности средств разработки . . 20 Метаданные и инструменты для их редактирования . . 20 Конструкторы и редакторы........................20 Синтакс-помощник................................21 Отладчик и режим замера производительности .... 21 Проверка конфигурации ..........................21 Сравнение/объединение конфигураций..............21 Редактирование текстов интерфейса...............21 Групповая разработка прикладных решений.........21 Поставка и поддержка прикладных решений.........22 Создание дистрибутивов..........................22 Обзор функциональности средств администрирования...............................22 Список пользователей ...........................22 Система прав доступа............................22 Ограничение прав на уровне записей и полей......22 Журнал регистрации..............................23 Загрузка/выгрузка информационной базы...........23 Консоль сервера 1С: Предприятия.................23
Глава 3. Использование встроенного языка Введение....................................24 Модули конфигурации.........................25 Общий модуль................................26 Модуль приложения...........................26 Модуль внешнего соединения..................27 Модуль объекта..............................28 Модуль формы................................29 Компиляция модулей..........................30 Компиляция модулей и режимы исполнения встроенного языка............................30 Компиляция общих модулей......................31 Компиляция модуля приложения и модуля внешнего соединения.................32 Компиляция модуля объекта.....................32 Компиляция модуля формы.......................33 Использование инструкций препроцессору........33 Работа с метаданными..........................33 Глава 4. Работа с данными Объектные и необъектные данные................36 Объектные данные..............................36 Модель хранения данных.....................36 Ссылка.....................................37 Представление ссылочных значений.........38 Контроль ссылочной целостности...........39 Особенности использования пометки удаления . 39 Объект.....................................39 Кэширование представлений и объектов ... 41 Оптимизированная запись объектов.........42 Создание новых объектов..................42 Блокировки...............................43 Необъектные данные............................44 Модель хранения данных.....................44 Подчинение регистратору..................44 Уникальность записей.....................45 Набор записей..............................45 Интерактивное редактирование наборов записей.........................47 Система типов.................................47 Типы значений и типы данных...................47 Типы значений.................................48 Примитивные типы...........................48 Число ...................................48 Строка...................................50 Дата.....................................52 Булево...................................54 Неопределено ........................... 55 Null ....................................56 Тип......................................56 Типы, образуемые в прикладном решении.....57 Менеджер объектов........................58 Менеджер.................................59 Объект...................................59 Ссылка...................................59 Набор записей............................59 Список...................................59 Выборка..................................63 Типы данных...................................66 Числовые типы данных.......................66 Строковые типы данных......................66 Типы данных, описывающие значения типа Дата..................................67 Составной тип данных.......................68 Описание значений составного типа........68 Значение реквизита составного типа по умолчанию.............................69 Преобразование значений, хранящихся в реквизитах составного типа.............69 Наборы типов...............................69 Транзакции....................................70 Использование явного вызова транзакций........71 Обработка ошибок базы данных в транзакции.....71 Вложенный вызов транзакций....................72 Влияние транзакций на работу программных объектов . 74 Восстановление признака проведенности документа..................................75 Очистка ссылки.............................75 Очистка кода/номера объекта................76 Уровни изоляции транзакций....................76 Файловый вариант...........................76 Нетранзакционное чтение..................76 Чтение в транзакции......................77 Модификация..............................77 Клиент-серверный вариант...................77 Нетранзакционное чтение..................77 Чтение в транзакции, модификация.........77 Получение согласованных данных при чтении.....78 Глава 5. Клиент-серверный вариант работы Общие сведения о клиент-серверном варианте работы..............................79 Выполнение общих функций .....................80 Управление сервером 1С: Предприятия...........80 Работа встроенного языка на сервере...........81 Безопасная зона ..............................81 Контроль прав в привилегированных модулях . . 82 Администрирование клиент-серверного варианта работы............................82 Компьютер сервера баз данных.............83
Компьютер сервера ЮПредприятия...........83 Взаимодействие компьютеров...............83 Администрирование ЮПредприятия...........83 Варианты использования ...................... 83 Особенности использования ....................84 Запуск и остановка сервера.................84 Соединения с сервером......................85 Выполнение кода на сервере.................85 Отладка кода на сервере....................85 Использование аппаратных ресурсов сервером...................................85 Совместная работа с сервером...............85 Использование виртуальной памяти...........86 Размещение сервера ....................86 Длительная работа сервера ........... 86 Организация выполнения кода на сервере или на клиенте............................86 Изменение поведения объектов в зависимости от контекста выполнения...................88 Особенности использования экспортируемых переменных, функций и процедур модуля приложения (модуля внешнего соединения)...89 Передача параметров на сервер и возврат значений........................89 Выполнение кода на сервере без проверки прав ... 89 Глава 6. Хранение информации Задачи хранения информации....................91 Варианты подходов к решению задач хранения информации...........................93 Хранение информации, общей для информационной базы.......................93 Использование общих картинок...............93 Использование макетов......................93 Хранения единичных значений условно-постоянной информации ...................................94 Использование констант.....................94 Использование регистров сведений...........95 Использование перечислений....................95 Использование предопределенных элементов......96 Хранение информации объектных и необъектных сущностей ....................................97 Хранение информации в самих объектах или в других объектах ........................98 Хранение иерархической информации..............100 Хранение иерархии данных одной сущности . . 101 Хранение подчиненных данных в составе объекта.........................103 Хранение иерархии данных разных сущностей . . 105 Хранение подчиненных данных вне объекта ... 105 Хранение информации, имеющей привязку ко времени 106 Использование документов..................106 Использование периодических регистров сведений . 106 Использование объекта ХранилищеЗначения.......107 Хранение информации в регистрах сведений . 107 Уникальность записей регистра сведений.......108 Периодические регистры сведений..............109 Подчинение записей регистратору..............109 Структура регистра сведений .................111 Создание, изменение, удаление записей регистра сведений ....................................113 Дополнительная функциональность при создании и удалении записей регистра сведений . . . . 119 Получение данных из регистров сведений........120 Получение данных из непериодических регистров сведений..................................120 Получение данных из периодических регистров сведений..................................123 Особенности получения данных из регистров сведений с режимом записи Подчинение регистратору..............................127 Проектирование структуры регистров сведений . . . 128 Хранение дополнительных характеристик . . . 129 Хранение дополнительных характеристик определенного типа...........................130 Хранение дополнительных характеристик произвольного типа. Использование плана видов характеристик . . 131 Варианты хранения значений характеристик......134 Глава 7. Документы и последовательности Место документов в концепции системы 1С:Предприятие..............................136 Документы...................................137 Функциональность документов.................137 Заполнение документов....................137 Расположение на оси времени..............138 Запись документов........................139 Проведение документов....................139 Формирование движений по регистрам.......140 Пометка на удаление документа............142 Удаление документов......................143 Состав документов........................143 Структура таблиц базы данных..........144 Отдельные вопросы типового использования документов...............................145 Нумерация документов ............. 145 Автоматическая нумерация............146 Использование лидирующих нулей......147 Параллельное ведение нумераций документов одного вида..........................147 Организация сквозной нумерации при помощи нумераторов...............147
Запись документов.............................148 Действие Записать......................148 Действия Записать и закрыть, Провести . . . 149 Действие Отмена проведения.............149 Проведение документов....................150 Свойство Проведение объекта метаданных . . 150 Свойство Оперативное проведение объекта метаданных..............................151 Свойство Удаление движений объекта метаданных .....................151 Использование механизма оперативного проведения...............................152 Запрет проведения будущей датой.............152 Механизм оперативной отметки времени ... 152 Передача значения Оперативный в параметр Режим обработчика события ОбработкаПроведения........................154 Особенности работы формы документа .... 157 Установка даты документа при открытии формы......................157 Установка даты нового документа при записи нового документа в форме ... 157 Запрет интерактивной записи проведенного документа без проведения (перепроведения) . 157 Установка режима проведения.............158 Прочие функции..........................159 Ввод на основании.........................160 Интерактивный ввод на основании.........160 Программный ввод на основании...........161 Получение документов, введенных на основании............................161 Специальные случаи использования документов. Ручная операция..............................162 Журналы документов...........................164 Состав журналов..............................165 Заполнение журналов ........................ 166 Последовательности документов................166 Устройство последовательностей ..............168 Работа с последовательностями................169 Управление регистрацией документов в последовательности......................170 Перемещение границы последовательности назад.....................................173 Восстановление последовательности.........Y74 Параллельный ввод документов, участвующих в последовательности ....................... 176 Глава 8. Реализация задач учета движения средств Оперативный учет. Описание задач, решаемых регистрами накопления.............177 Структура регистра накопления..............179 Механизмы заполнения таблиц регистров накопления в базе данных...................182 Запись данных в таблицу движений регистра накопления.................................183 Свойство Движения объекта документа........184 Формирование наборов записей посредством свойства Движения объекта документа ... 184 Формирование движений при проведении документа ..............................186 Формирование движений в объекте документа, но без проведения документа.............187 Модификация существующих движений документа ..............................188 Интерактивное формирование наборов записей с помощью свойства Движения объекта документа ..............................190 Запись набора записей регистра без использования свойства Движения..........................191 Интерактивное формирование движений с помощью формы набора записей..........192 Механизмы заполнения таблицы итогов регистра накопления.................................193 Механизм заполнения таблицы итогов регистра остатков.......................193 Механизм заполнения таблицы итогов оборотного регистра.....................196 Получение данных из регистров накопления.................................198 Получение движений регистров накопления.....198 Вопросы быстродействия системы при получении движений ...................199 Получение остатков...........................202 Виртуальная таблица остатков..............203 Использование метода ОстаткиО менеджера регистра накопления.............206 Особенности использования периодов и моментов времени при получении остатков . . 207 Получение оборотов...........................209 Виртуальная таблица оборотов..............209 Алгоритм, применяемый системой для получения оборотов регистра остатков . . 212 Алгоритм, применяемый системой для получения оборотов оборотного регистра..............212 Метод Обороты() ..........................214 Особенности использования периодов и моментов времени при получении оборотов . . 216 Получение остатков и оборотов в одной таблице . . . 218 Виртуальная таблица остатков и оборотов . . 219 Особенности использования периодов и моментов времени при получении остатков и оборотов . 223 Расчет итогов по полям остатков при использовании виртуальной таблицы остатков и оборотов...............223 Получение итогов по одному полю остатков . 226 Получение итогов по регистратору или номеру строки.......................228 Получение итогов остатков в комбинации с другими полями........................228 Использование соединений с таблицей остатков и оборотов .........230 Применение отборов в запросах, использующих виртуальные таблицы регистров накопления .... 230
Когда следует использовать запрос вместо объектной модели обращения при получении данных регистров накопления.......................231 Отдельные вопросы использования регистров накопления..................................233 Работа с регистрами при отображении динамических данных.........................233 Объект РегистрНакопленияСписок.<имя> . . . 233 Работа с итогами при отображении динамических данных......................234 Получение остатков при проведении документов . . . 236 Блокировка записей регистров .............237 Чтение данных регистра остатков при неоперативном проведении.............239 Глава 9. Реализация задач бухгалтерского учета Введение.....................................240 Диаграмма взаимодействия объектов............240 План счетов и его основные свойства..........241 Коды счетов..................................244 Упорядочивание счетов в плане счетов.........245 Иерархичность плана счетов...................247 Ввод проводок и формирование отчетов по счетам, содержащим подчиненные.........248 Свойства счета-родителя и подчиненных ему счетов..................249 Предопределенные и пользовательские счета .... 250 Свойства счета............................250 Особенности написания запросов............250 Основы организации аналитического учета......251 План видов характеристик для создания списка видов субконто ....................253 Детализация счета плана счетов по видам субконто.........................255 Ввод в диалоге и хранение в базе данных объектов аналитического учета.............256 Признаки учета субконто...................258 Принятие решений при организации аналитического учета.........................259 Предназначение регистра бухгалтерии..........261 Объект Регистр бухгалтерии...................264 Основные свойства регистра бухгалтерии.......264 Данные регистра бухгалтерии..................265 Ресурсы регистра бухгалтерии..............266 Свойство ресурса Балансовый.............266 Свойство ресурса Признак учета..........267 Свойство ресурса Признак учета субконто . . 268 Измерения регистра бухгалтерии............269 Свойство измерения Балансовый...........270 Свойство измерения Признак учета........271 Запись движений в регистр бухгалтерии .... 273 Интерактивно: ручная операция................274 Активность ..................................275 Программно, при проведении документа.........276 Конструктор движений документа............277 Оперативное и неоперативное проведение . . . 278 Автоматическое удаление движений..........279 Программно без проведения документа..........279 Чтение данных регистра бухгалтерии...........280 Таблицы регистра бухгалтерии.................280 Реальные таблицы .........................280 Виртуальные таблицы.......................282 Таблица остатков........................282 Таблица оборотов........................283 Таблица остатков и оборотов.............286 Таблица движений с субконто.............288 Таблица оборотов Дт Кт..................289 Общие приемы работы с виртуальными таблицами..................291 Параметр Субконто: отбор и упорядочивание по виду субконто........................292 Параметры Период, НачалоПериода и КонецПериода..........................295 Периодичность «оборотных» таблиц........297 Развернутые остатки.....................299 Методы менеджера регистра бухгалтерии . . 301 Вопросы производительности регистра бухгалтерии..................................303 Физические таблицы регистра бухгалтерии .....303 Остатки и обороты по счетам...............303 Таблицы остатков и оборотов по счетам и субконто................................304 Обороты между счетами....................305 Управление итогами........................305 Индексы таблиц итогов регистра бухгалтерии .... 306 Тип значения субконто и его влияние на количество индексов....................306 Количество полей в индексе................307 Построение виртуальных таблиц регистра бухгалтерии..................................309 Механизм актуальных итогов................309 Таблица остатков..........................311 Таблица оборотов..........................312 Таблица остатков и оборотов ..............313 Таблица оборотов Дт Кт....................313 Таблица движений с субконто...............313 Зависимость производительности от настроек субконто счета...............................314 Глава 10. Реализация сложных периодических расчетов Введение....................................315 Основные понятия........................... Видрасчета.............................. Технология реализации расчетных задач . . . 315 Принципы регистрации записей................. 315 315 316
Пертюд регистрации..........................316 Период действия.............................316 Вытесняющие расчеты и фактический период действия..................................317 Зависимость по базовому периоду.............318 Ведущие расчеты и перерасчет................319 Сторнирование...............................320 Планы видов расчета..........................321 Назначение планов видов расчета................321 Свойства планов видов расчета..................321 Структура планов видов расчета.................322 Предопределенные табличные части............323 Проверки, выполняемые при записи вида расчета . . 323 Проверки в предопределенных видах расчета . . 323 Проверки предопределенных табличных частей . 323 Структура таблиц базы данных...................325 Регистры расчета ............................326 Назначение регистров расчета...................326 Свойства регистров расчета.....................326 Структура регистров расчета....................327 Предопределенные поля.......................328 Поля, добавляемые при разработке............329 Измерения регистров расчета ................329 Свойство Базовое измерения регистра расчета . 329 Ресурсы регистров расчета...................330 Реквизиты регистров расчета ................330 Структура таблиц базы данных...................330 Настройка протяженных во времени расчетов. . 332 Использование механизма вытеснения...........332 Настройка планов видов расчета и регистров расчета...................................332 Формирование фактического периода действия . 332 Получение фактического периода действия средствами встроенного языка..............333 Получение фактического периода действия при помощи запроса........................333 Использование графиков ......................334 Использование данных графика для расчета записей ......................334 Использование данных графика для вычисления части записи..............................335 Настройка использования нескольких графиков в одном регистре расчета..................335 Получение данных графика средствами встроенного языка ........................336 Получение данных графика при помощи запроса 337 Сторнирование ............................... 337 Конкуренция с записями более раннего периода регистрации.......................337 Формирование сторно-записей. Метод ПолучитъДополнение()......................338 Настройка зависимости по базовому периоду . 339 Настройка планов видов расчета и регистров расчета . 339 Настройка зависимости от базы..............339 Ввод записей, зависимых по базовому периоду . . 340 Получение базы средствами встроенного языка . 341 Получение базы при помощи запроса..........343 Технология формирования и расчета записей регистров расчета..........345 Формирование записей регистра расчета ........345 Настройка алгоритмов расчета..................346 Настройка способов расчета.................346 Настройка приоритета видов расчета.........347 Расчет записей регистра расчета...............348 Формирование набора записей по данным документа.......................349 Добавление в набор сторно-записей.........349 Расчет набора записей в общем модуле.......350 Запись набора с формированием фактического периода действия ............350 Классификация записей по приоритету видов расчета...................................352 Получение данных для расчета..............352 Расчет значений ресурсов записи............353 Перерасчет записей регистров расчета..........354 Объект конфигурации Перерасчет................354 Измерения перерасчета.........................355 Автоматическое формирование записей перерасчета при вводе вытесняющих расчетов...............356 Автоматическое формирование записей перерасчета при вводе прочих расчетов ...................356 Зависимость видов расчета..................356 Связь измерений и реквизитов через измерения перерасчета...............................356 Зависимость по базовому периоду............356 Особенности использования таблицы вытесняющих видов расчета.....................357 Формирование записей перерасчета средствами встроенного языка............................358 Автоматическое удаление записей перерасчета . . . 359 Анализ данных таблицы перерасчета ............359 Реализация перерасчета записей регистров расчета . 360 Глава 11. Механизм бизнес-процессов Первое знакомство .........................363 Карта маршрута.............................364 Точки маршрута.............................366 Точка старта, точка завершения.............366 Точка действия ............................367 Точка условия..............................368 Точка выбора варианта..........................369 Точка разделения, слияния .....................369 Точка обработки................................370 Точка вложенного бизнес-процесса...............370 Состояния бизнес-процесса......................370 Старт бизнес-процесса..........................372
Программный старт.............................372 Интерактивный старт бизнес-процесса...........374 Старт бизнес-процесса как вложенного .........374 Старт бизнес-процесса с несколькими точками старта ...............................375 Завершение бизнес-процесса....................376 Задачи........................................376 Формирование задач............................377 Выполнение задач..............................378 Проверка выполнения.............................379 Форма списка задач..............................380 Обратная связь..................................381 Примеры реализации бизнес-процессов .... 382 Единый объект Задача............................382 Бизнес-процесс Продажа товара...................386 Бизнес-процесс Продажа товара с предоплатой . . . 389 Бизнес-процесс Поручение........................389 Бизнес-процесс Обход............................392 Бизнес-процесс Согласование.....................394 Глава 12. Использование механизма анализа данных и прогнозирования Общие положения...........................398 Основные объекты механизма................399 Типы анализа данных.......................399 Общая статистика.......................399 Поиск ассоциаций.......................399 Поиск последовательностей..............400 Кластерный анализ......................400 Дерево решений ................. 400 Модели прогноза ..........................400 Тип анализа общая статистика..............400 Тип анализа поиск ассоциаций..............402 Типы отсечения правил.....................403 Отсечение покрытых правил..............404 Отсечение избыточных правил............404 Поиск последовательностей.................404 Тип анализа дерево решений................. 406 Тип анализа кластеризация ...................408 Используемые метрики ........................409 Евклидова метрика.........................409 Евклидова метрика в квадрате ......... 409 Метрика города............................410 Метрика доминирования.....................410 Методы кластеризации.........................410 Ближняя связь ............................410 Дальняя связь.............................410 Центр тяжести ............................410 «k средних»...............................411 Вывод данных в дендрограмму ..............411 Проведение прогнозов.........................411 Модель прогноза..............................412 Глава 13. Средства построения отчетов Общее описание средств для построения отчетов....................413 Построитель отчета........................415 Автоматическое заполнение настроек построителя отчета........................419 Заполнение настроек построителя отчета с использованием языка запросов построителя отчета........................420 Ключевые слова языка запросов построителя отчета.....................420 Ключевое слово ВЫБРАТЬ ..............420 Ключевое слово ГДЕ...................421 Ключевое слово УПОРЯДОЧИТЬ ПО .... 421 Ключевое слово ИТОГИ ПО..............421 Предложения языка запросов построителя отчета без ключевых слов . . .421 Условное включение таблиц в результирующий запрос................421 Использование повторяющихся псевдонимов в языке запросов построителя отчета ..............422 Заполнение настроек построителя отчета на основе сохраненных ранее настроек................423 Настройка построителя отчета интерактивными средствами .................................424 Изменение настроек при помощи полей ввода . . 425 Настройка построителя отчета средствами встроенного языка...........................426 Доступные поля...........................426 Порядок..................................428 Отбор....................................428 Измерения строки, измерения колонки......429 Выбранные поля...........................429 Выполнение запроса и вывод отчета...........430 Макет построителя отчета....................431 Механизм генерации и оформления макета построителя отчета.......................431 Макет линейного отчета...................432 Неоформленный макет....................432 Оформленный макет......................432 Кросс-отчет..............................433 Задание фиксированных макетов для вывода результата запроса...............433 Макет оформления и оформление...............434 Макет оформления.........................434
Оформление макета ........................434 Оформление макета линейного отчета........435 Оформление макета кросс-отчета............435 Условное оформление..........................437 Интерактивная настройка условного оформления......................437 Программная настройка условного оформления . 438 Область оформления......................438 Отбор оформления........................441 Настройка оформления....................441 Совместное использование оформления и условного оформления отчетов............442 Вывод в табличный документ...................443 Размещение измерений......................443 Размещение итогов.........................444 Размещение реквизитов измерений...........445 Примеры и особенности использования построителя отчета...........................447 Установка отбора .........................447 Вывод дополнительной информации в отчет . . 447 Изменение ширины колонок, выводимых в отчет и настройка формата...............448 Передача значений параметров в запрос построителя отчета........................450 Особенности оформления при разной иерархии . 451 Изменение полей для некоторых группировок . . 452 Особенности использования построителя отчета для отбора по значению субконто ..........453 Вывод представлений ссылочных значений ......455 Вывод в диаграмму ...........................456 Вывод в сводную таблицу......................457 Вывод в сводную диаграмму....................458 Работа с расшифровкой........................459 Автоматическое заполнение расшифровки при использовании макета по умолчанию . . . 459 Автоматическое заполнение расшифровки при использовании назначаемого макета . . . 460 Пример использования построителя отчета для получения уточненных данных по расшифровке............................460 Особенности заполнения расшифровок при выводе в диаграмму....................463 Использование произвольного источника данных . . 464 Установка источника данных................464 Текстовый документ...........................465 Чтение и запись текстовых файлов.............466 Работа с отдельными строками текстового документа 467 Использование макетов текстовых документов .... 468 Формат макета текстового документа .... 468 Служебная часть области.................469 Текстовая часть области.................469 Процедура формирования текстового документа 470 Сравнение текстовых документов...............471 Табличный документ...........................472 Общие свойства табличного документа .........472 Области табличного документа ................475 Обращение к области ячеек.................475 Обращение по номерам строк и колонок . . . 475 Обращение по адресу.....................476 Обращение по имени.....................476 Обращение к пересечению областей.......477 Общие свойства областей..................477 Оформление областей......................477 Скрытие областей ......................477 Защита областей........................477 Высота строк...........................478 Ширина колонок.........................478 Цвет фона и узор.......................478 Объединение ячеек......................479 Группировка............................479 Границы ...............................479 Примечание.............................480 Очистка................................480 Свойства области, относящиеся к тексту . . . 480 Текст и шрифт..........................480 Вертикальное и горизонтальное выравнивание . 480 Ориентация.............................481 Отступ.................................481 Размещение.............................481 Цвет ..................................481 Выделение отрицательных................481 Работа с областями табличного документа . . 481 Тип области............................481 Текущая область........................482 Выделенные области.....................482 Копирование области....................482 Удаление области.......................483 Очистка................................483 Поиск текста...........................484 Рисунки табличного документа................484 Общие свойства рисунков табличного документа . 484 Имя и тип .............................484 Размеры рисунка........................485 Ограничивающая линия...................486 Заполнение рисунка.....................486 Защита рисунка.........................486 Рисунки типа Текст ......................487 Рисунки типа Картинка....................488 Рисунки, содержащие объекты..............488 Рисунки типа Прямая......................489 Использование макетов табличных документов . . . 490 Формат макета табличного документа .... 490 Процедура формирования табличного документа ..............................491 Получение строк макета на разных языках . . 495 Использование расшифровки в табличном документе...................496 Печать табличного документа.................498 Свойства областей и рисунков табличного документа, управляющие печатью ...... 501 Сводная таблица.............................501 Поля сводной таблицы.....................502 Строки, колонки и данные сводной таблицы . . 504 Иерархия измерений ......................505 Оформление сводной таблицы .......... 507 Управление отображением реквизитов измерений ................... 509 Управление отображением ресурсов.........512 Оформление областей сводной таблицы .... 514 Использование табличного документа в форме .... 515
Использование события ПриАктивизацииОбласти . 516 Использование события Выбор...............516 Расшифровка в тле табличного документа ... 517 «Расшифровка» для сводной таблицы.........518 Значения в табличном документе.............519 Элементы управления в табличном документе . 521 Перетаскивание в табличном документе .... 523 Сравнение табличных документов................527 Глава 14. Интеграция с другими информационными системами Форматы файлов обмена.......................529 Работа с текстом............................529 Текстовый документ, поле текстового документа ...............................530 Отображение текстового документа.......531 Модель последовательного доступа.........531 Работа с DBF................................532 Работа с XML-документами....................533 Основные положения.......................533 Базовые средства 1С .Предприятие 8.0 для работы с XML.........................535 Запись данных в XML-документ...........535 Чтение данных из XML-документа.........536 XML-сериализация.........................537 Простые типы...........................538 Сложные типы...........................541 Пример реализации обмена при разной структуре объектов конфигурации.......................545 Работа с ZIP-архивами.......................548 Создание архива..........................548 Особенности упаковки файлов по маске . . . 549 Особенности работы метода ДобавитьО . . . 549 Чтение ZIP-apxueoe.......................550 Работа с файлами большого объема.........551 Использование Интернет-технологий...........551 Работа с HTML...............................552 Поле HTML-документа......................553 НИР-соединение...........................554 Использование FTP ...........................554 Процедура КопироватьФайл()................554 ТТРСоединение.............................555 Работа с электронной почтой .................556 Почта.....................................556 Интернет-почта............................556 Использование MSMQ...........................558 Использование WSMQ...........................559 Создание менеджера очередей..................560 Создание кластера............................560 Создание очередей ...........................560 Работа с IBM WebSphere MQ из встроенного языка........................561 Automation...................................562 Automation Server............................562 Automation Client............................563 СОМ-соединение...............................563 Использование COM для интеграции с Интернет- приложением.....................564 Средства Интернет-сервера.................565 Пример использования......................565 ActiveX .....................................569 ActiveDocument...............................570 Глава 15. Создание распределенных информационных систем Планы обмена................................572 Служба регистрации изменений................573 Управление регистрацией изменений........575 Автоматическая регистрация изменений . . . 576 «Ручная» регистрация изменений .............577 Принудительная регистрация изменений . . . 577 Инфраструктура сообщений....................579 Универсальный механизм обмена данными . . 580 Использование возможностей работы с XML-документами ...........................581 Пример реализации универсального обмена..........582 Полная регистрация изменений по узлу.............583 Удаление регистрации изменений по узлу...........584 Выполнение выгрузки данных в узел................584 Выполнение загрузки данных из узла ..............587 Регистрация в произвольные узлы..................590 Распределенные информационные базы .... 590 Общие принципы ..................................590 Главный и подчиненный узлы.......................592 Сообщение обмена данными в распределенной информационной базе...........................592 Создание узла распределенной информационной базы...........................593 Создание начального образа................593 Интерактивное создание начального образа . 593 Создание начального образа из встроенного языка.....................593 Создание узла из конфигурации.............594 Создание узла из копии информационной базы . 594 Запись и чтение сообщений обмена..............595 Подготовка конфигурации к работе в распределенной информационной базе .......596 Сценарии обмена данными в распределенной информационной базе...........................597 Поведение по умолчанию ...................597 Распределение данных по подчиненным узлам . . 597 Разрешение коллизий...........................598 Восстановление узла распределенной информационной базы из резервной копии .... 599
Процедура восстановления информационной базы корневого узла.......................599 Процедура восстановления информационной базы подчиненного узла....................599 Особенности использования последовательности документов в распределенной ИБ...............599 Использование транзакций при организации обмена ......................................600 Методика включения в сообщение обмена дополнительной информации .... 601 Организация одностороннего обмена..........602 Примеры реализации автоматического обмена данными.............................603 Использование командной строки.............603 Использование объекта СОМСоединение........604 Глава 16. Web-расширение Основные положения.........................607 ADO.NET....................................608 ASP.NET....................................609 Конструкторы Web-расширения для веб-приложений........................614 V8 List Form...............................616 Подробное знакомство ...................617 Форма объекта, вызываемая по умолчанию . . . 619 Связывание списков ............... 623 V8ItemForm.................................626 Обработка строки табличной части........628 V8ReportForm...............................629 Использование расшифровок ..............631 Простые расшифровки...................631 «Сложные» расшифровки ................632 Особенности реализации расшифровок .... 632 vechartForm................................633 Доступ к данным через ADO.NET..............634 Получение данных...........................634 Получение данных запросом...............635 Указание одной таблицы..................636 Добавление данных..........................637 Изменение данных...........................637 Удаление данных............................638 Веб-сервисы................................639 Обращение к веб-сервису из веб-формы...........641 Обращение к веб-сервису из ЮПредприятия 8.0 . . 641 Вызов процедур, функций Преобразование типов..........................641 Настройка прав доступа.........................643 Идентификация пользователя.....................643 Файл Web.config................................643 Файл global.asax...............................644 Форма, используемая для авторизации «на основе форм»..............................644 Работа с метаданными...........................645 Пул соединений.................................646 Полезные средства .NET Framework...............647 Объект Response................................647 Объект Request.................................647 Объект Session.................................648 Подготовка веб-приложения к работе............648 Состав файлов..................................649 Параметры автоформ.............................649 Форма списка (DefaultListForm).................649 Форма элемента объектной таблицы (DefaultObjectForm)...........................649 Форма записи регистра (DefaultRecordForm)......650 Форма строки табличной части (DefaultLineForm). . . 650 Глава 17. Поставка прикладных решений Механизм поставки и поддержки прикладных решений........................652 Изменение режима поддержки.................654 Начальный режим поддержки...............654 Полная поддержка — поддержка с возможностью изменения .... .........654 Поддержка с возможностью изменения — полная поддержка.......................654 Поддержка с возможностью изменения — снятие с поддержки.....................655 Конфигурация, не стоящая на поддержке — поддержка с возможностью изменения .... 655 Изменение правил поддержки.................655 Установка правил Объект поставщика редактируется с сохранением поддержки и Объект поставщика не редактируется . . . 656 Установка правила Объект поставщика не редактируется..........................656 Поддержка на разных языках...................657 Особенности работы с конфигурацией в хранилище, если конфигурация стоит на поддержке.........658 Редактирование объектов...................658 Настройка поддержки ......................658 Обновление конфигурации...................658 Настройка поставки...........................659 Обновление конфигурации, находящейся на поддержке.................................659 Обновление в автоматическом режиме........659 Обновление в режиме поддержки с возможностью изменения.................................659 Особенности обновления..................662 Рекомендации по модификации конфигурации поставщика...........................663 Общие технологические сведения о поддержке . . . 664 Сценарии поддержки ..........................666
Вертикальная поддержка.........................666 Последовательность установки вертикальной поддержки..................666 Горизонтальная поддержка..................667 Последовательность установки горизонтальной поддержки................667 Особенности горизонтальной поддержки . . . 667 Механизм создания комплектов поставки . . . 668 Файл поставки................................668 Создание файла поставки...................669 Файл обновления..............................670 Создание файла обновления.................670 Технологические особенности использования файлов поставки и обновления ........................671 Файл информационной базы..........................671 Файл выгрузки информационной базы.................671 Шаблоны конфигураций..............................672 Манифест..........................................673 Использование манифеста для автоматического поиска обновлений ............................675 Удаленный каталог шаблонов...................675 Файл списка шаблонов .....................676 Создание комплектов поставки ................676 Общие свойства описания комплекта поставки .......................677 Шаблоны конфигураций......................678 Свойства шаблона .........................678 Свойства файлов комплекта поставки.........678 Базовые каталоги..........................679 Варианты поставки.........................679 Языки.....................................680 Создание комплекта поставки...............680 Типичные сценарии создания комплектов поставки .........................680 Создание комплекта поставки версии прикладного решения.......................680 Создание комплекта поставки обновления для удаленного каталога шаблонов..........683 Создание файлов поставки и обновления из командной строки..........................685 Глава 18. Методология разработки «Жизненный цикл» прикладного решения . . . 686 Проектирование................................686 Разработка ...................................687 Функциональное тестирование...................687 Нагрузочное тестирование......................687 Внедрение.....................................687 Сопровождение.................................688 Выводы........................................688 Проектирование структуры метаданных .... 688 Выбор между объектными и необъектными данными . . 688 Анализ логики работы прикладных объектов сданными.....................................689 Анализ производительности.....................689 Анализ возможностей использования обмена данными . 689 Анализ параллельности работы..................690 Групповая разработка прикладных решений . . 690 Используемая терминология.....................690 Общие сведения о хранилище конфигурации.......690 Создание хранилища конфигурации...............692 Пользователи хранилища........................692 Права пользователей........................692 Подключение к хранилищу.......................692 Действия, выполняемые системой при подключении к хранилищу...............694 Действия, выполняемые системой при соединении с хранилищем...............694 Отображение состояния объектов конфигурации . . . 694 Просмотр состояния объектов...................695 Обновление информации о состоянии объектов конфигурации..............................695 Захват и помещение объектов в хранилище.......696 Захват в хранилище.........................696 Помещение в хранилище......................698 Версии конфигурации......................698 Отмена захвата.............................698 Получение объекта из хранилища.............698 Обновление конфигурации из хранилища .... 698 Администрирование хранилища...................698 Сравнение и сохранение текущей конфигурации хранилища....................................699 Работа с версиями хранилища конфигурации .... 699 Установка отбора в окне истории хранилища . . 700 Откат к предыдущей версии..................700 Сокращение до выбранной версии.............700 Объединение версий.........................700 Отчеты по истории хранилища...................700 Отчет по версиям хранилища.................701 Отчет по объектам разработки...............701 Отчет по комментариям к версиям хранилища . 701 Использование отчетов по истории хранилища . 701 Варианты использования хранилища конфигурации . 702 Локальная группа разработчиков.............702 Один разработчик ..........................702 Удаленные разработчики.....................702 Разработка на территории заказчика.........703 «Удаленный» заказчик.......................703 Работа с хранилищем конфигурации из командной строки...........................703 Производительность прикладного решения . . 704 Общее понятие производительности прикладного решения..........................704 Прикладное решение.........................704 Технологическая платформа .................704 Сервер баз данных .........................704 Оборудование...............................704 Взаимное влияние составляющих производительности .......................704 Последовательность решения задач оптимизации...............................705
Изменение производительности во времени . . . 705 Разработка..............................705 Внедрение ..................................705 Эксплуатация............................705 Уровни функционирования прикладного решения . . 707 Взаимодействие уровней....................707 Цикл оптимизации производительности..............707 Два вида проблем с производительностью...........709 Общие сведения об оптимизации производительности . 710 Следование рекомендациям......................710 Нагрузочное тестирование......................710 Оптимизация на уровне конфигурации........710 Оптимизация производительности на уровне СУБД..............................710 Оптимизация на уровне СУБД, требующая специальных знаний........................711 Оптимизация производительности на уровнях автоматизируемых процессов предприятия и автоматизированных рабочих мест.............711 Описание модели...........................711 Формирование исходных данных..............711 Учет особенностей тестируемых режимов . . 712 Регламентные операции с базой данных . . . 712 Сценарий тестирования ........................712 Выбор параметров нагрузки ....................713 Выбор условий тестирования................713 Выполнение тестов и сохранение результатов . 714 Оптимизация производительности на уровне конфигурации...............................714 Оптимизация параллельности работы пользователей с прикладным решением . ... 714 Выделить оперативные данные.................714 Убедиться, что бизнес-логика проведения документа содержит только оперативные операции................................714 Все внимание уделить оперативному режиму . 715 Выполнить анализ используемых регистров . 717 Оптимизировать действия, выполняемые в транзакции..............................719 Оптимизировать запросы......................719 Оптимизация различных режимов работы прикладного решения.......................719 Не использовать запросы в цикле ............719 Использовать параметры виртуальных таблиц . 720 Исключить получение поля Ссылка через точку...............................721 Использовать операцию ВЫРАЗИТЬ для ограничения количества таблиц .... 721 Не использовать запросы, результатом которых могут быть очень большие выборки .... 721 Исключить вывод ссылочных полей в отчет . 721 Исключить хранение вспомогательной информации большого объема в реквизитах документов...................721 Оптимизировать работу с таблицей значений 722 Оптимизировать работу форм..................722 Оптимизация производительности на уровне СУБД . . 723 Стандартная оптимизация.......................723 Обновление статистики и очистка процедурного кэша...........................723 Реиндексирование............................723 Диагностика блокировок и взаимных блокировок .................724 Переформулировка сложных запросов .... 727 Оптимизация производительности на уровне оборудования .............................. 729 Типичные проблемы оборудования...........729 Оптимизация использования оперативной памяти.......................729 Оптимизация использования процессоров .... 730 Оптимизация дисковой подсистемы.........731 Оптимизация сетевого интерфейса.........732 Оптимизация устойчивости системы .......732 Диагностика и устранение проблем с защитой . 732 Диагностика нестабильной работы........733 Перечень информации, предоставляемой при обращении в отдел технической поддержки 733 Инструментальные средства, используемые при оптимизации производительности..........734 Журнал регистрации 1С:Предприятия.........734 Режим замера производительности 1С:Предприятия.........................736 Журнал SQL Server........................738 Журнал событий Windows...................739 System Monitor...........................740 Windows Error Reporting ............. 742 Dr. Watson...............................743 Сценарии оптимизации производительности......743 Прикладное решение работает медленно. Что нужно поменять или переделать? .... 743 Какие компьютеры необходимо использовать, чтобы данное прикладное решение работало нормально?...............................744 Разработчику требуется получить параметры оборудования и возможности масштабирования для созданного им прикладного решения .... 744 Основы «тонкой» оптимизации производительности на уровне СУБД..............................745 Оптимизация запросов.....................745 Примерный сценарий диагностики и оптимизации запросов.................746 Выбор подозрительных запросов..........748 Анализ плана запроса...................749 Table Scan.............................749 Nested Loops...........................751 Подбор индексов........................752 Поиск запроса ЮПредприятия ............754 Диагностика блокировок...................754 Общие сведения о параллельности операций . 754 Система блокировок MS SQL Server........755 Конфликты блокировок ..................755 Сценарий тестирования..................757 Анализ полученной информации...........761 Рекомендации по преодолению конфликтов блокировок на уровне SQL Server...763 Многоязычные прикладные решения.............764 Информационная база.........................765 Встроенный календарь.....................765 Порядок сортировки строк.................766 Платформа ЮПредприятия......................766 Программа установки шаблонов конфигураций . 767
Каталог шаблонов.........................767 Журнал регистрации.......................768 Встроенный язык..........................768 UNICODE..................................769 Конфигурация................................769 Использование языков в режиме конфигуратора............................769 Элементы системного интерфейса, использующие языки конфигурации..........770 Интернационализация во встроенном языке . . 770 Два варианта встроенного языка..........770 Использование языков конфигурации .... 770 Использование региональных установок . . . 771 Редактирование текстов интерфейса............7TL Копирование строк из одного языка в другой . . 772 Удаление строк на выбранном языке.........774 Перенос текстов интерфейса из одной базы в другую..................................774 Редактирование строк, используемых в функции НСтр()..........................775 Приложение. Хранение данных Размещение данных системы 1С:Предприятие . 776 Информационные базы .........................776 Обязательные таблицы информационной базы . . 776 Таблицы информационной базы, определяемые структурой метаданных.....................777 Константа...............................778 Перечисление............................778 Справочник..............................778 Документы...............................778 Последовательность .....................778 Журнал документов ......................778 Бизнес-процесс..........................778 Задача .................................778 Регистр сведений........................778 Регистр накопления .....................778 План видов характеристик................779 План счетов.............................779 Регистр бухгалтерии.....................779 План видов расчета......................779 Регистр расчета.........................780 План обмена.............................780 Хранилище конфигурации.......................780 Журнал регистрации...........................780 Профайлы.....................................780 Компьютер пользователя....................780 Каталог клиентских данных приложения 1С . . 780 Каталоги информационных баз.............781 Каталоги пользователей информационных баз . 781 Компьютер пользователя или компьютер сервера ЮПредприятия......................781 Каталоги информационных баз.............781 Другие вспомогательные данные................781 Временные данные ............................782 Поля таблиц базы данных......................782 Хранение значений полей примитивных и ссылочных типов............................782 Хранение значений полей составного типа......783 Индексирование полей составного типа......785 Сравнение полей составного типа...........785 Индексы таблиц базы данных...................788 Справочник...................................789 Основная таблица .........................789 Основные индексы........................789 Дополнительные индексы ..................789 Таблица табличной части....................790 Документ......................................790 Основная таблица ..........................790 Таблица табличной части....................790 Журнал документов.............................790 План видов характеристик......................790 План счетов...................................790 Основная таблица ..........................790 Таблица табличной части....................791 План видов расчета............................791 План обмена...................................791 Табличная часть...............................791 Регистр сведений..............................791 Непериодический регистр сведений...........791 Периодический регистр сведений.............791 Дополнительный индекс для регистра сведений, подчиненного регистратору..................792 Регистр сведений с периодичностью По позиции регистратора....................792 Регистр накопления............................792 Основная таблица ..........................792 Регистр бухгалтерии...........................792 Основная таблица ..........................792 Основная таблица регистра без корреспонденции......................792 Основная таблица регистра с корреспонденцией.......................792 Таблица значений субконто..................792 Регистр расчета...............................792 Основная таблица ..........................792 Таблица перерасчета........................793 Последовательность............................793 Таблица регистрации документов в последовательности............793 Таблица границ последовательности.........793 Перечисление ................................ 793 Бизнес-процесс................................793 Основная таблица ..........................793 Таблица табличной части....................793 Таблица точек маршрута.....................793 Задача........................................794 Основная таблица ..........................794 Таблица табличной части....................794
Системы автоматизации управления и учета фирмы «1С» стали индустриальным стандартом е России и ближнам зарубежье. Создана уникальная технология распространения и внедрения, обеспечивающая доступность и эффективность автоматизации для сотен тысяч предприятий-потребителей и, одновременно, возможность развивать рентабельный бизнес для многих тысяч внедренческих предприятий. Фактически сформирована новая престижная профессия: под девизом «Есть такая профессия — Родину автоматизировать» работает целая отрасль — более ста тысяч квалифицированных специалистов. Система 1 ^Предприятие широко используется для автоматизации различных областей даятельности предприятий - управленческого учета, бухгалтерского учета, учета движения средств, расчета заработной платы и многих других. Эта книга посвящена версии 8 системы 1 ^Предприятие. По сравнению со своими предшественниками,! ^Предприятие 8 позволяет решать более сложные задачи, обеспечивает более высокую масштабируемость и предоставляет разработчику богатый набор инструментов для создания многофункциональных прикладных решений. Книга адресовена, а первую очередь, разработчикам, которые хотят повысить свой профессиональный уровень и более эффективно использовать возможности системы. В то же время, она будет интересна и для тех специалистов, которые только «присматриваются» к системе и еще не знают о том, насколько увлекательной может быть профессия, связанная с созданием прикладных решений для автоматизации управления бизнесом. Важнейшие темы книги: • архитектура 1 (^Предприятия; • структура прикладного решения; • методология использования клиент-серверного варианта работы; • особенности использования прикладных объектов; • возможности хранения информации в системе; • решение задач учета движения средств; • решение задач финансового и бухгалтерского учета; • решение задач расчета заработной платы; • использование механизма бизнвс-процессов; • использование механизма анализа данных и прогнозирования; • создание отчетов, в том числе управляемых пользователем; • интеграция с другими информационными системами; • создание распределенных информационных баз; • создание веб-приложений; • создание прикладных решений группой разработчиков; • оптимизация производительности прикладных решений; • создание многоязычных приложений; • создание дистрибутивов и обновление прикладных решений у пользователей; • особенности физического хранения данных. Заказ книг: 197198, Санкт-Петербург, а/я 619 Тел.: (812) 703-73-74, postbook@piter.com www.piter.com — вся информация о книгах и веб-магазин 123473, Москва, ул. Достоеаского, 1/21, строение 1 Тел.: (495) 681 -02-21, факс: (495) 681 -44-07 e-mail- publishing@1 c.ru — www.1c.ru,www.v8.1c.ru — подробная информация о программных продуктах «1С» и книгах ISBN 5-91180-076-4 11 /ЯГ