суббота, 24 ноября 2007 г.

Форма: this is my first time, часть 1

[id:53]

Есть такие счастливчики, которые хотя бы раз в жизни слышали от девушки фразу «ЭТО у меня в первый раз». Хотя, кроме везения, там обязательно присутствует доля терпения и личные качества соблазнителя.

Создание формы 1 Давайте сделаем свою первую форму. Создайте проект Blog53 и группу типа Forms в нем. Щелкните правой кнопкой на ветке Forms, пункт "Создать", "Form".

Форму будут звать "VeryFirstForm".

Разделы формы В дереве проекта у формы отображается три ветки.
Ветвь "Methods" содержит в себе методы формы; изначально там только "ClassDeclaration" (смотри «Система: MorphX, среда разработки»). Вы можете создавать свои методы на форме, равно как и перегружать имеющиеся. В конце концов форма — это класс с некоторым готовым функционалом.
Следующая ветвь "Data Sources" содержит источники данных, то есть таблицы, из которых форма будет брать данные.
И последнее — "Designs" —, где навечно прописана ветвь Design. В Аксапте все свойства формы устанавливаются именно здесь.

Давайте сделаем заголовок формы: щелкните правой кнопкой на Design и выберите пункт «Свойства» (или нажмите Alt+Enter). Справа появится прикрепленное окно свойств. Установите свойство Caption равным «Самая первая форма». Установка свойств формы И сохраните форму: щелчок правой клавишей на форме VeryFirstForm, пункт «Сохранить».

Пока рано глядеть результат, нужно еще прикрепить источник данных. Форма работает с таблицами базы данных через них. Датасорсов (источников данных) может быть много, но здесь ограничимся одним — таблицей альтернативных адресов "Address". Откройте AOT нажатием Ctrl+D и найдите там таблицу "Address". Перетащите ее в ветку "Data Sources" нашей формы VeryFirstForm: Создание датасорса путем перетаскивания таблицы из дерева объектов Дитя дрэг-энд-дропа (drag-and-drop, перетащи и брось) обзавется так же, как и таблица, к которой он привязан. Но вовсе не обязательно, чтобы датасорс назывался также, как и представляемая им таблица.

Следующий шаг — накидывание контролов на форму (элементов пользовательского интерфейса). Типовая форма в Аксапте состоит из набора вкладок "Tab" и справа размещается группа кнопок "ButtonGroup". Делаем.

Джентельменский набор вкладок и набор кнопок на форме Щелкните на ветке "Design" правой клавишей, пункт «Создать Control», "Tab". Появится контрол Tab (набор вкладок) с именем "Tab". Таким же образом сделайте контрол типа ButtonGroup с именем "ButtonGroup".

Форма с набором вкладок Типовая форма Аксапты содержит две вкладки: «Обзор» и «Разное». На первой данные отображаются в табличном виде (на гриде, Grid), а вторая содержит поля только для текущей записи.
Щелкните на контроле "Tab", выберите пункт «Создать Control», "TabPage". Переименуйте созданную вкладку в "TabOverview", ее свойство "Caption" установите равным «Обзор». Точно также создайте вторую вкладку "TabGeneral" со свойством Caption=Разное.
На вкладку TabOverview добавьте контрол типа "Grid" с таким же именем.
В группе кнопок ButtonGroup создайте контрол типа "CommandButton" c именем "closeForm". Контролы CommandButton имеют специальное свойство "Command" (оно располагается в конце списка свойств), установите его в значение «Закрыть». Тем самым вы задаете команду, которая будет выполнена системой во время нажатия на кнопку.

Заключительный этап: отображение данных на форме.
В ветке Data Sources формы для единственного датасорса Address щелкните на разделе Fields правой клавишей, выберите «Открыть в новом окне». Откроется дополнительное окно со всеми полями таблицы Address. Оно нам сейчас пригодится. Окно со списком полей датасорса Как вы понимаете сам датасорс не имеет полей, их нельзя создать на нем. Все, что он имеет, взято из таблицы Address.

Чтобы создать поля на контроле Grid, которые будут показывать данные таблицы Address, снова воспользуемся приемом Drag-and-Drop: выделите поля "Name", "Address", "Phone" в дополнительном окне и перетащите их на контрол Grid. Будут созданы контролы Address_Name, Address_Address, Address_Phone, которые превраться в столбцы на таблице Grid. Добавление столбцов на грид

Наконец, добавим что-нибудь на закладку "Разное". Для этого в дополнительном окне с полями таблицы прокрутите список вниз до конца. Вы увидите элементы с ярлыками в виде желтых папочек; это группы полей (неважно что это конкретно, просто группы полей). Выделите Description и SalesTax, перетащите их на вкладку TabGeneral. Перенос групп полей

Все готово, чтобы увидеть свою собственную форму. Щелкните на форме VeryFirstForm правой клавишей, выберите "Открыть". Вот она: Самая первая форма, вкладка Обзор Самая первая форма, вкладка Обзор

Итог

Alt+Enter — открыть панель свойств объекта.

Слон и муха

или Трудности взаимопонимания

Комнатная муха в длину около пяти-девяти миллиметров. Метраж индийского слона составляет пять-шесть метров в длину и два метра в высоту. Вот такие отличия.

Разные люди смотрят на одни и те же вещи по разному: незакрытый тюбик зубной пасты, регулярные походы по магазинам, хамство в общественном транспорте; все эти вещи сравнимы с мухой для Феди, и превратятся в слоноподобную помеху для Димы или Маши. Все дело в отношении. И все бы ничего, если каждый жил сам по себе.

Только вот люди склоны к созданию семей. А любая мухослоновая несовместимость способна порушить желанный замок совместного счастья. Нужно подстраиваться, куда деваться. Придется тренировать память, чтобы всегда помнить о своевременном масштабировании собственных мух до приемлемых, пусть и не слоновьих, размеров. И не забыть политкорректно реагировать на встречи со слонами.

Но важнее всего вовремя заткнуться.

воскресенье, 11 ноября 2007 г.

Данные: перебор while select

[id:55]

Очень часто нужно перебирать данные, возвращаемые запросом select, запись за записью. Этой цели служит конструкция while select. Она отбирает набор записей и позволяет выполнить нужные действия над каждой из них.
Вот пример: static void BLG55_WhileSelect() { Currency currency; setprefix("Валюты"); while select currency where currency.CurrencyCode like "c*" || currency.CurrencyCode == "rur" { info(strfmt('%1 - %2', currency.CurrencyCode, currency.Txt)); } }

Результат перебора записей о валютах Здесь мы читаем список валют в соответствии с условиями. Отобраный запросом набор записей о валютах кэшируется в буфере, связанном с табличной переменной "currency". Затем данные, запись за записью, выдаются в цикле, пока не будет исчерпан буфер. Текущая запись доступна через табличную переменную (здесь, это "currency"). Удобно.

Если не считать ключевое слово "while", то синтаксис этой конструкции идентичен синтаксису "select".

Итог:

выражение "while select" предназначено для обработки записей в цикле.

понедельник, 5 ноября 2007 г.

X++: базисные типы данных

[id:54]

Как это не занудно, но я просто обязан об этом рассказать. Ведь это основательнейшая основа основ X++.
Итак, базисные типы данных или primitive data types:

Тип Ключевое слово Значение по умолчанию
Булев boolean false
Дата date null
Время timeOfDay 0
Перечисление <имя_перечисления> 0 или первый элемент в перечислении
Целое 32-бита int 0
Целое 64-бита int64 0
Вещественное real 0.00
Строка str "" (пустая строка)

Эти типы используются как для создания переменных в коде, так и в качестве типов при создании полей таблиц в базе данных. А все потому, что в Аксапте стерта граница между системой и базой данных.

В третьей колонке таблицы приведены значения по умолчанию для каждого типа, что наталкивает на несколько важных выводов.

Во-первых, после создания переменной базисного типа она будет автоматически проинициализирована значением по умолчанию. Правда, этим сейчас уже никого не удивишь.

Во-вторых, любой из указанных типов приводиться к булеву типу, а приведенные в таблице значения по умолчанию обозначают «Ложь»; все остальное это «Истина». По-простому говоря, вы можете переменную базисного типа вставлять в условный оператор, например вот так: if (my_integer_variable) или while (! my_date)

В-третьих, эти же типы данных используются при работе с базой данных. А как же эта проблема с NULL-значениями? Ведь известно, что в базах данных есть такое понятие, как «Отсутствие данных»/«Колбасы нет. Продавец ушла на склад»/«Извините, у нас учет». И это обозначается замечательным NULL-значением.
Создатели Аксапты отказались от концепции NULL. Каждое поле таблицы всегда содержит значение. А значения по умолчанию теперь интерпретируются системой как «Отсутствие данных».

Тип "Date" решил быть не как все; он всегда был какой-то не такой. Но о нем расскажу позже.

Итог:
  • для базисных типов данных есть значения по умолчанию;
  • для базисных типов данных нет понятия NULL;
  • для базисных типов данных значения по умолчанию играют роль NULL-значений.

суббота, 3 ноября 2007 г.

Система: InfoLog, часть 2. Иерархия c помощью setprefix()

[id:051]

Подсистема Infolog позволяет упорядочивать выводимые сообщения, создавая из них иерархии. Достигается это с помощью глобального метода "setprefix". Попробуем это на примере: static void BLG51_HierarchyOfMessages(Args _args) { Currency currency; ; info("Начало"); setprefix("Валюты"); while select currency { setprefix(currency.CurrencyCode); if (currency.CurrencyCode == "USD") { error("Да это же доллар!"); break; } else info(currency.Txt); } info("Конец"); } Здесь Currency — это таблица со списком валют.

И вот такой результат будет получен:

Дерево сообщений в инфологе Каждый вызов метода setprefix() увеличивает уровень вложенности на один. Каждая закрывающая фигурная скобка уменьшает этот уровень на единицу.

Посмотрите на приведенный рисунок снова. Самый первый вызов "setprefix(«Валюты»)" делает уровень вложенности сообщений равным единице. Затем мы вошли в цикл "while" и вызвали "setprefix(currency.CurrencyCode)". Это увеличило вложенность до двух. И вот уже на втором уровне и отобразилось сообщение «Канадские доллары». Затем интерпретатор упирается в окончание цикла "while", а это значит, что закончилось действие последнего "setprefix()" и уровень уменьшился до одного. Правда не надолго: очередной "setprefix()" для валюты «Китайский юань» снова возвращает нас на второй уровень.
Заметьте, что сообщение «Конец» находиться в ветке «Валюты».

Зачем вообще это нужно?
Нужно, но не жизненно необходимо. Например, недавно я писал модуль импорта данных из Excel. Каждая строка, естественно, предварительно проверяется, и в ней может быть несколько ошибок. Чтобы не писать в каждом сообщении об ошибке номер текущей строки, я использовал setprefix.

Итог:
  • setprefix() создает деревья сообщений.
  • если сообщений на текущем уровне вложенности не было, то не отобразится и текст, указанный в методе setprefix(). Проверьте это, закомментировав в приведенном джобе строку "else" и "info(currency.Txt)".