Р. Кречмер, В. Вейс - Разработка приложений SAP R3 на языке АВАР4. Р. Кречмер, В. Вейс - Разработка приложений SAP R3 на языке АВАР. Разработкаприложений sap r3Рюдигер Кречмерна языкеВольфганг Вейс
Скачать 28.36 Mb.
|
Глава 7. Работа с данными Глава 8. Запись данных Глава 9. События и управление выполнением программы Глава 10. Подпрограммы и функции Часть III Глава 7 Работа с данными • Копирование полей и составных объектов данных • Преобразование полей • Математические функции и формулы • Операции со строками 82 Глава 7 В предыдущих главах рассказывалось, как определять локальные данные программы, глобальные дан- ные в Dictionary и модели данных сущности связи приложения. Данная глава посвящена основам создания приложений на языке АВАР/4. При разработке программ и приложений пользователю необходимо мани- пулировать с данными, которые эти приложения содержат: передавать их, вычислять арифметические вы- ражения или работать со строками текста (например, при поиске какого-то шаблона в строке). При перемещении данных из одного поля в другое, имеющее иной тип, АВАР/4 всегда выполняет пре- образование содержимого. Обычно, если модель данных разработана правильно, такое преобразование не требуется. Однако в больших программных системах преобразование типов данных часто оказывается обходимым. АВАР/4 позволяет не беспокоиться об этом: язык предусматривает такую функцию. АВАР/4 обеспечивает также автоматическое копирование записей из одной структуры в другую — при условии, что их компоненты имеют одинаковые имена в обеих структурах. Копирование объектов данных одинакового типа с одной операции (in a single step) для структуры любой Работа с арифметическими выражениями осуществляется по правилам, принятым в большинстве дру- гих языков программирования. В АВАР/4 поддерживаются стандартные математические функции: cos и др. Кроме того, специальные команды обеспечивают выполнение таких распространенных операций со строками, как конкатенация, сдвиг строк или поиск в строке по шаблону. Копирование полей с помощью команд Move (переместить) и Compute (вычислить) Самый простой способ работы с данными в программе - их перемещение посредством команды move, которой иллюстрируется простой программой: data: counter type i. ' to to counter . После выполнения такой операции name содержит строку а счетчик поля — число 17. Команда move всегда копирует исходное поле в целевое: исходное to целевое Если пользователь предпочитает писать целевое поле с левой стороны оператора, можно восполь- зоваться командой compute: compute целевое исходное. Следующий оператор является сокращенным, так как в нем опущено ключевое слово compute: целевое = Все приведенные выше операторы выполняют одну и ту же функцию, поэтому выбор любого из них — дело программиста. Ключевое слово compute - единственное, которое разрешается опускать в операторах языка АВАР/4. Пропуск любого другого ключевого слова Syntax Check определит как ошибку. При необходимости заполнить несколько одинаковым содержимым можно объединить коман- ды compute, как показано в приведенном ниже примере. Допустим, вы формируете список адресов и некоторые клиенты из этого списка имеют совместно используемые номера рабочих телефонов. Тогда следует сделать этот номер исходным полем, а затем, используя вычислять каждый следующий номер телефона: = исходное. В данном разделе рассматривалось копирование полей одного типа данных. На практике же у ис- ходного и целевого поля типы обычно разные. Поэтому следующий раздел посвящен преобразованию содержимого полей при копировании в АВАР/4. Преобразование содержимого полей ЕСЛИ у исходного и целевого полей разный тип и размер данных, АВАР/4 всегда преобразует со- держимое исходного поля к формату целевого, что очень удобно. Вычислите, например, сумму двух чисел, записанных в поле типа character, размером три и четыре соответственно. Результат сохраните в поле типа integer. Эта будет иметь вид: Работа с данными 83 data: ( 4 ) , r e s u l t i . r e s u l t = + Если поле содержит строку 1771, a равно 005, тогда поле result будет содержать число 1776. Тот же результат получится, если содержит цифру 5 и впереди два пробела { 5), один пробел впереди и цифры 05 или цифры 05 и один пробел в конце Иногда допускается применять символьные поля разной длины. Если, допустим, необходимо исполь- зовать таблицу клиентов из старой базы данных, где поле имени клиента имело размер 10, чтобы за- писать их в новую таблицу, где размер этого поля 25, предлагается очень простое решение: data: (10) , (25) . move После выполнения операции поле будет содержать поле дополненное пробелами до 25 символов. Если значение переменной равно Edison, значение переменной — Edison (с 19 вательными пробелами в В другом примере необходимо вычислить число того же дня следующей недели, начиная с любого: data: = + 7. Так, числа 19991231 (31 декабря 1999 г.) это будет 20000107 (7 января 2000 г.). и т.д. Примеры демонстрируют очень важное качество АВАР/4, Если исходное и целевое поля имеют разные типы или содержимое исходного поля всегда преобразуется к формату целевого Ошибка выполнения возникает только в том когда преобразование приводит к потере инфор- мации. Например, переполнение числового поля при вычислениях вызывает прерывание выполнения и вывод на экран сообщения о переполнении. Так как АВАР/4 поддерживает различные типы и размеры данных, которые можно комбинировать, используя команды move и compute, существует множество комбинаций возможных преобразований: цифры внутри символьного поля могут рассматриваться как число, целевое поле — заполняться лами, исходное усекаться, числа — преобразовываться в дату и наоборот и т.д. В последующих раз- делах подробно рассматриваются некоторые типы преобразования. Если эта тема не вызывает у вас интереса, переходите сразу к разделу структурированных объектов". Преобразование символьных полей Символьные поля чаще всего содержат обычные текстовые строки разной длины — как а таблицах базы данных, так и в файлах (например, фамилии или адреса). Предположим, нужно сохранить назва- ние Washington в двух полях разного размера: d a t a : , move ' W a s h i n g t o n ' После выполнения операторов поле будет содержать строку а поле — Washington плюс шесть концевых пробелов. Очевидно, что в первом случае строка источника усекается до размера в во втором — дополняется пробелами в конце тоже до указанного размера поля. Таким образом, при использовании поля меньшего размера часть информации теряется, поэтом)' пред- почтение следует отдать более длинному полю: тогда сохранится название в базе данных. Кстати, иног- да достаточно восьми символов для идентификации объекта (фамилии человека или названия), в частности, системный пароль может содержать не более восьми символов. Существует и другая причина для усечения символьных строк — размер строки отчета, т.е. при ограниченной длине строки допуска- ется отображение только первых восьми символов. Приведенная ниже короткая программа иллюстрирует получение такого же, как и в первом примере, результата при заполнении Но при этом содержимое поля будет другим: = В данном случае строка вначале передается в поле short_name и усекается, а затем со- держимое (Washingt) передается в поле long_name, где дополняется пробелами до размера этого поля. В результате поле Tong_name будет содержать строку Washingt с восьмью пробелами в конце. Преобразование цифровых полей АВАР/4 позволяет достаточно просто обрабатывать числа различных типов и Например, состоящее из цифровых символов, может использоваться в арифметическом выражении вместе с целыми и упакованными числами: t y p e t y p e 84 Глава 7 p decimals = / В этом примере поле цифровых символов no_employees перед вычислением выражения преобразу- ется в упакованное число. Результат округляется в соответствии с форматом поля, стоящего слева от знака равенства, т.е. согласно формату В каждом конкретном случае необходимо тщательно анализировать, к каким результатам может при- вести округление. Проиллюстрируем это на следующих двух примерах: income type type p decimals type p decimals 2. income * ( 1 — ) . В данном примере содержимое поля есть 10,000, a tax — 20% (т.е. 0.20). Тогда результат net_income равен 8,000.00. В этом случае выражение (1 - tax) сначала преобразуется к 0.80 (или 80%), а затем умножается на 10,000. Результат (8,000) записывается в поле net_income (без преобразования, так как net_income того же типа, что и поле справа от равенства). В различных ситуациях числа могут использовать разное количество десятичных Предполо- жим, что было определено как целое поле и выполняется такой же фрагмент как и в предыдущем примере: data rounded rounded — income * ( 1 - t a x ) . В данном случае результат для значения income 10,000 будет таким получится 8,000 вместо 8,000.00, однако потери точности не произойдет. Однако может возникнуть существенная разница при округлении: если income равняется 10,002, то net_income будет a — 8,002. В общем случае при вычислении правой части арифметического выражения результат округляется до числа десятичных знаков, допустимых для поля-результата. Целые поля обрабатываются так же, как поля упакованных чисел без десятичных знаков. Если в арифметическом выражении встречается число с плавающей запятой или выполняется операция с плавающей запятой (например, cos или то все промежуточные результаты тоже будут числами с плавающей запятой. Преобразование полей типа даты Предположим, необходимо определить самую позднюю дату, когда можно отправить чек продавцу после получения счета к оплате. Допустим, что эта дата позже даты получения на 10 Для ления этой даты можно написать следующую программу: type type + Это простая и понятная программа. Что произойдет во время ее выполнения? содержи- мое (например, преобразуется к упакованному которое соответствует числу дней, прошедших с 01/01/0001. Во-вторых, добавляется число 10 и результат опять преобразуется к полю типа даты (в нашем примере 19980303), А если дата равняется 19960223 или 20000223? Встро- енный календарь АВАР/4 корректно обработает их, так что можете не беспокоиться о технических аспектах преобразования дат. АВАР/4 рассчитан на обработку дат, выходящих за пределы 2000 г. Следовательно, коммерческие приложения, написанные на АВАР/4, будут работать в следующем столетии и переход от 1999 к 2000 г. не вызовет сложностей. В главе рассматривается несколько типов преобразований, которые могут встретиться. Наиболее часто встречающиеся комбинации исходных и целевых полей приведены в разделе "Специальные пре- образования". Полный список этих комбинаций можно найти в справочном руководстве по АВАР/4, которое поставляется с программным обеспечением. Работа с данными 85 Специальные преобразования Здесь приведены комбинации различных типов исходных и целевых полей, наиболее часто встречающиеся в операторе move. Рассмотрим команды move указанного ниже типа: move s a to t2 . Здесь исходное поле s и целевые поля и имеют разные типы и длину. Преобразование типа с тип п. Рассматриваются только цифровые символы, которые записываются в t, сдвигаются вправо, а слева заполняются нулями (если это необходимо): data: s(4) value tl(2> n, t2<6) n. Результат выполнения команды move будет следующим: t1 = '24', a t2 - '000124'. Преобразование типа п в тип с. Исходное поле преобразуется в символьное поле и начальные нули остаются: data: value ' 0 1 2 4 ' , tl<2>, t2(6) . Результат будет следующим: t1 '01', a t2 = _' (два конечных пробела). Преобразование типа п • тип р. Исходное поле s является упакованным и записывается в целевое поле со знаком плюс (+). Если целевое поле слишком короткое, возникает ошибка переполнения: data: s(6) type n value '012345', tl(10) p, t2<6) type p. Результат выполнения будет следующим: t1 12345. Второй оператор move приведет к ошибке выполнения. Преобразование типа р в тип п. Исходное поле записывается со сдвигам вправо без знака и заполняется слева нулями: data: я (a) p value 124, tl<2) type n, t2<6) type n. Результат выполнения будет следующим; t1 = '24', a = '000124'. Копирование структурированных объектов Для копирования структурированных объектов данных (записей или внутренних таблиц) можно вос- пользоваться приемом явного пошагового копирования Для этого придется написать до- вольно длинную и сложную программу, в которой при последующих модификациях могут появиться ошибки. Оператор позволяет копировать из одной записи в другую компоненты с одинаковыми именами. Таким образом, при добавлении нового компонента к включающей его структу- ре все отслеживаются системой на уровне выполнения команды причем модифицировать исходный текст программы необязательно. Если в операторе move исходный и конечный объекты данных относятся к одному и тому же типу (например, к внутренней таблице), содержимое копируется за одну операцию. В этом случае отпадает необходимость разбивать структурированные объекты данных на компоненты для отдельного вания, как можно передать все объекты сразу. Предположим, записи содержат поля с одинаковыми именами (в нашем примере это id и city). Чтобы скопировать поля с одинаковыми именами, можно использовать команду begin of a, and of of city 86 Глава 7 id of move-corresponding to Команда копирует содержимое полей id и city, которые содержатся в записи в аналогичные поля записи Поле остается без изме- нений, так как исходная запись не имеет поля с таким именем. Приведенный пример демонстрирует, что поля с одинаковыми именами копируются независимо от их позиции внутри как ком- пилятор АВАР/4 принимает во внимание только имена полей. В примере поле city занимает третью позицию в записи и первую позицию в записи Если поля с одинаковыми именами относятся к разным типам, их содержимое преобразуется согласно правилам, принятым для полей. С помощью команды move можно также копировать структурированные объекты типа записей или внутренних таблиц. Предположим, имеются две записи с полями одинакового типа и длины: data: begin of i d e n t i f i e r like c i t y like end of to previous customer. Эта программа копирует все поля записи запись В отличие от команды move-corresponding имена полей (id и identifier) могут отличаться, однако эти поля должны иметь одинаковый элементарный тип и длину. Поддерживается также передача всех строк из одной таблицы в другую за одну операцию: types: begin of table_line, type i, end of source_table type table_line occurs type occurs move to target Изучив способы копирования полей и составных объектов данных, обратимся к математическим вычислениям. Арифметические выражения и математические функции Коммерческие приложения, как правило, ориентированы на доступ к таблицам базы данных и об- работку их содержимого. Практически в каждой прикладной программе встречаются такие элементар- ные арифметические операции, например, умножение. Некоторые приложения не требуют поддержки на уровне языка таких неэлементарных математических функций, как sin или cos. В язык АВАР/4 включен набор функций, которого вполне достаточно для большинства бизнес-приложений. Рассмотрим использование этих математических функций. Арифметические выражения уже в первых примерах, в частности при вычислении ко- нечной даты была использована формула last_admissible_dace + 10. Арифметические вы- ражения понятны и не требуют дополнительных пояснений: у а* х + = income * < 1 - tax ) . у * cos ( alpha ) . Например, можно использовать арифметическое выражение для вычисления процента черных сви- ней в популяции (в которой, как только черные и белые свиньи): black swans type swans type data percentage type p decimals = 100 / + ) . Используются и более сложные формулы для обычной математической обработки. Каждый, кто раз- бирается в математике, может написать набор подобных формул: Работа с данными 87 n5 = ( ( - n2 / пЗ ) * < n4 + > / ) . В некоторых случаях, порядок операций очевиден, скобки можно опустить. Например, следующего оператора будет таким же, что и в предыдущем поскольку деление имеет при- оритет над вычитанием: п5 ( n l - п2 / пЗ ) * ( n4 + n l ) Арифметические операции имеют следующую приоритетность: 1. Функции (например, cos или sin) 2. Возведение в степень (••) Умножение деление (/), целое деление вычисление остатка (mod) Сложение (+) и вычитание (-) Кроме этих элементарных операций, АВАР/4 поддерживает другие важные математические функ- ции, которые имеют высший приоритет по к приведенному списку: Абсолютная величина и знак: abs, sign • Тригонометрические функции: cos, sin, tan, atan, log • Квадратный корень: sqrt • Вычисление длины строки символьного поля: Полный список доступных математических функций приводится в справочном руководство по АВАР/4 (ключевое слово compute). Ниже приведены примеры записи формул, включающих математические функции на языке АВАР/4: у = • соэ( alpha ) ( Ь * l o g ( а ) ) - n q = n mod q Заметим, что круглые скобки для группировки подвыражений разделяются, как минимум, одним про- белом. Обработка арифметических выражений отличается от той, которая используется для операторов data, где размер поля указывается тоже в круглых скобках, но без промежуточных пробелов: data (25) . Если в арифметическом выражении встречается нечисловое поле, с помощью внутренней операции ОНО преобразуется к числу перед вычислением выражения. Преобразование подчиняется общим прави- лам для операции move: data: n4 (4) type n value ' 12A4' , n value ' 2 ' , p. X - n4 n l . Сначала содержимое n4 преобразуется к упакованному числу 124. Затем содержимое nl преобразу- ется к числу 2, и, наконец, осуществляется умножение на n l , которое дает результат 248 в поле х. АВАР/4 поддерживает все виды операций вычисления, необходимых для бизнес-приложе- ний, однако язык не предназначен для выполнения сложных технических и научных вычис- лений. Если требуется сложный статистический или числовой анализ, можно написать вычислительную функцию на другом языке программирования (например, С) и вызвать ее из граммы на языке АВАР/4, используя Remote Function Call (см. главу 27). Типичными арифметическими ошибками при выполнении программы являются переполнение поля деление на нуль. Некоторые ошибок, связанных с командой compute, обсуждаются в разделе Типичные ошибки, связанные с командой compute". Операции со строками текста АВАР/4 имеет набор элементарных операций для обработки строк текста. Благодаря этим командам можно сосредоточиться на обработке символьных строк и не заботиться о таких технических аспектах, как сдвиги и вычисление длины. 88 Глава 7 Типичные ошибки, связанные с командой compute Переполнение. Эта ошибка возникает, когда содержимое числового поля превышает размер самого поля: p. do 1000 tines. = + enddo. Эта короткая программа порождает ошибку выполнения, так как поле должно содержать три цифры и знак. Результат будет корректным, если определить счетчик как упакованное число стандартной длины (восемь): counter Другими словами, размер упакованных чисел должен указываться в явном виде, только если количество знаков содержимого превышает 15. Деление на нуль. В бизнес-приложениях чаще всего встречается ошибка деления на нуль, так как добиться, чтобы содержимое некоторых полей базы в системе всегда отличалось от нуля: p value у р, z p. Z / Если во время выполнения у станет равным нулю, возникнет ошибка и программа будет прервана. Чтобы избежать этого, следите за содержимым делителя: у = 0. * divisor do . . * divisor non-zero: divide I t Тем не менее, если оба операнда равны нулю, в языке АВАР/4 результат будет равным нулю. С математической точки зрения такая операция не определена. Однако на практике в языке АВАР/4 существует соглашение о том, что поля, получаемые из базы данных, всегда должны иметь некоторые начальные значения. Поэтому результат принимается равным этому начальному значению, т.е. нулю. Конкатенация и разделение символьных строк Символьные строки объединяются (конкатенируются) с помощью команды concatenate: data: first (25), last(25), first - middle . last = ' . concatenate middle last into После выполнения этой операции поле full будет содержать конкатенированную строку. Если строки должны иметь разделители (например, строки, содержащие каталоги и имя файла в пути доступа), такой разделитель задается следующим образом: data: (10) , , directory_l ' . directory_2 = 'usr' . . concatenate filename into path separated ' \ ' . Содержимое path в этом примере будет Система возвращает не равное нулю зна- чение переменной sy-subrc, если длина конкатенированной строки больше, чем длина поля, в которое она записывается. Работа с данными 89 Обратная операция разделения символьной строки осуществляется для произвольно выбранного раз- делителя: data; , , l i s t l i s t at ' , ' i n t o name_l name_2 В качестве разделителей строк можно использовать различные символы, например пробел, минус, или даже последовательность символов. Если одно из полей, в которые записывается результат, имеет недостаточную длину, все компоненты усекаются и переменная sy-subrc получает ненулевое значение. Кроме того, если число компонентов превышает число целевых полей, информация теряется, так как последнее поле содержит всю оставшуюся часть строки. Чтобы не допустить этого, в качестве целевого объекта используйте внутреннюю таблицу, которая может содержать любое число строк: data name 1 occurs l i s t split l i s t at ' , ' i n t o t a b l e Внутренняя таблица names будет содержать четыре строки: Young Edwards. Сдвиг числовых строк Сдвинуть символьную строку на один символ можно посредством команды shift, а на несколько сим- волов — путем добавления by n places: name_l = ' Edison' . name 2 = ' Smith' . name_3 = ' Young' . by 3 name_3 После этих операций поле name_l будет содержать символьную строку поле name_2 — th, a поле — Young (с начальными пробелами). Такие операции очень удобны, если к текста приступают не сначала, а с определенного слова. Если разработчик не хочет указывать число байтов, на которое осуществляется сдвиг (возможно, он и знает его), можно использовать другие варианты команды shift. Предположим, необходимо отыс- кать подстроку внутри строки и сдвинуть всю строку до начала этой подстроки; names 'Alexander B i l l Charles' . shift names up to ' B i l l ' . Так как подстрока найдена в поле names, после операции содержимое поля names будет Charles. Если подстрока не найдена, строка остается без изменения и система возвращает ненулевое значение переменной Аналогично, если должно быть сдвинуто вправо так, чтобы не в конце заданного символа, можно написать следующий программный фрагмент: ' ' . name r i g h t d e l e t i n g t r a i l i n g Эта команда shift удаляет все пробелы после последнего значащего символа в поле name и возвра- щает значение Значение space (пробел) является предварительно определенным полем, держащим пробелы. Замена и преобразование символов в строке ДЛЯ замены определенных символов в строке используется команда replace, которая позволяет за- мещать первый встретившийся символ (или подстроку) внутри строки; string = 'Variable: fi. The v a r i a b l e is s u b s t i t u t e d l a t e r . replace ' fi' with 'X' i n t o s t r i n g . Поле string будет равно X. The variable is substituted later.. Для замены всех символы на X вводится команда translate: t r a n s l a t e s t r i n g using Все символы & в поле символьной строки будут заменены на X, т.е. строка будет иметь вид Variable: X. The variable X is substituted later.. Команда translate позволяет заменить сразу несколько символов в строке. Правило замены записы- вается как последовательность пар, где первый символ всегда заменяется на второй. Например, можно заменить все переменные в математической формуле: 90 Глава 7 expression 'a 2 Ь ** 2 - с ** 2' . expression using . Результатом замены будет выражение х ** 2 + у ** 2 г •• 2. Поиск символьных строк в или внутренних таблицах Предположим, нужно отыскать строку California в символьном поле: text Mew Mexico search for ' California' . if 0. 'Not Поиск закончится успешно, и системный код возврата будет равен нулю. Кроме того, системное поле sy-fdpos содержит сдвиг найденной строки относительно начала (в этом примере sy-fdpos - 6). Команда search не различает символы верхнего и нижнего регистров, поэтому следующий оператор поиска завершится тоже успешно: search t e x t . Можно искать подстроки, содержащие пробелы: search M' . В результате выполнения этого оператора код возврата будет равен 0, а код sy-fdpos — 17. Чтобы определить, содержится ли подстрока с заключительными пробелами в символьной строке, за- ключите подстроку в символы "точка": data: value 'АВАР/4' . search string for ' ./4 .' . Заданный шаблон ./4_. не совпадает с содержимым поля, так как в поле string нет заключительного пробела, однако поиск /4_ закончится успешно. В АВАР/4 поддерживается поиск символьных строк во внутренних таблицах. Предположим, во ренней таблице letter содержится текст письма: types . data l e t t e r type occurs 100. Пусть первая строка письма letter равна а вторая — thank you for your letter of 12/31/1999. Оператор имеет вид search l e t t e r for 'you'. В этом случае оператор даст следующий результат: 0, - 2, sy-fdpos • 6. Системное поле возвращает индекс строки таблицы, содержащей искомую строку, a sy-fdpos — сдвиг отно- сительно начала этой строки. того, дополнения команды search позволяют ограничить диапазон поиска строк: l e t t e r for starting at 2 ending at search l e t t e r starting at Первый оператор ограничивает поиск строками от второй до сотой, для второго оператора поиск будет производиться по всем строкам, начиная с третьей. Работа с частями полей Если решить задачу с помощью специальных команд операций с символьными строками не удается, воспользуйтесь операциями с частями полей, заданными с помощью сдвига и размера. Сдвиг символа относительно начала поля всегда на единицу меньше номера его позиции (например, сдвиг первого символа равен нулю). Следующая программа копирует три символа, начиная с третьей позиции поля: - 2. 3. 4. 3. (lanl) to . Оператор move передает символы исходного поля (с позиции по позицию б) в часть целевого (с 5 7). Работа с данными 91 Резюме _ • С точки зрения выполнения следующие операторы эквивалентны: * compute = * target = move source to • АВАР/4 преобразует содержимое результат получается семантически значимым. • Структурированные объекты можно копировать с помощью оператора move, в частности, разре- шено копировать все строки внутренней таблицы. • Оператор все поля с одинаковыми именами копирует из начальной записи в целевую. • Арифметические выражения выполняются так же, как в большинстве языков программирования; поддерживаются математические функции. • Наиболее часто используемые операции с символьными строками могут быть заданы с помощью специальных ключевых слов: concatenate, shift, replace, translate, search. • Части полей могут определяться с помощью операции сдвига и задания размера. Основной темой следующей главы является вывод содержимого полей на экран. Будет дан анализ различных опций, управляющих представлением полей. |