参加
最後オンライン
最近の投稿
プログラミング基礎に投稿されました 続きを読む

このトピックでは、SAP標準で用意された採番システムの使用方法を取り上げて説明します。

採番処理のために共通的な仕組みを提供します。 

  • NRIV
    番号範囲間隔
  • SNRO
    番号範囲オブジェクト


  • SM56
    番号範囲バッファの管理

下記の汎用モジュールを使用できます。

  • NUMBER_GET_NEXT 採番
  • NUMBER_GET_INFO 情報取得
  • NUMBER_CHECK チェック

プログラミング基礎に投稿されました 続きを読む

概要

バリアントとは

バリアントとは、同じ選択条件で実行することが多いプログラムに対して、入力値のセットを保存させておくものです。 レポートプログラムバリアント、画面バリアント、トランザクションバリアントなどがあります。

バリアント変数とは

バリアント変数とは、バリアントに格納される値を変数化したものです。 バリアント変数は二つのタイプがあります。

  • TYPE P
    単一値を定義することができます。
  • TYPE S
    選択テーブルとして条件を定義することができます。

バリアント変数の値定義はテーブルTVARVCに格納されます。

トランザクション利用

バリアント変数のメンテナンスは、トランザクションSTVARVとSTVARVCを使用します。

  • STVARV
    クライアント000用
  • STVARVC
    現在のクライアント用

プログラム利用

以下はバリアント変数をABAPプログラムで動的に変更して使用する方法です。

* バリアント変数テーブルを更新
UPDATE TVARVC
SET LOW = WK_FROM
  HIGH = WK_TO
WHERE NAME = 'VAL_NAME' 

AND TYPE = 'S'. "タイプ S:SELECT OPTIONS、P:パラメータ

プログラミング基礎に投稿されました 続きを読む

実行時データ型識別、略語は RTTI です。プログラム実行時にデータ型を識別して処理を行う仕組みです。。

DESCRIBE FIELD命令を使用して、変数のデータタイプを取得することができます。

構文

DESCRIBE FIELD obj TYPE typ.

  • obj
    データ型を取得したいデータオブジェクト。通常の変数やフィールドシンポルなどを使用することができます。
  • typ
    取得したデータ型が格納されるデータオブジェクト。

データ型

データ型は1 桁のIDで識別され、IDでは大文字と小文字が区別されます。

IDデータ型
b基本タイプB:1バイト整数(内部用)
C基本タイプC:固定長テキスト項目
D基本タイプD:日付項目
F基本タイプF:浮動小数点数
g基本タイプSTRING:可変長文字順序
h内部テーブル
i基本タイプI:整数
lデータ参照
N基本タイプN:数値テキスト項目
P基本タイプP:パック数値
rオブジェクト参照
s基本タイプS:2バイト整数(内部用)
T基本タイプT:時刻項目
uフラット構造
vディープ構造
X基本タイプX:16進数
y基本タイプXSTRING:可変長バイト順序

サンプルソース

FORM PARSE_STRING_TO_STRUC   USING    U_STR TYPE STRING
                        CHANGING C_STRUC.
  CONSTANTS:
    CONST_DT_DATE TYPE C VALUE 'D',
    CONST_TAB            TYPE STRING VALUE CL_ABAP_CHAR_UTILITIES=>HORIZONTAL_TAB.
  DATA:
   VL_STRINGS  TYPE STRING_TABLE, 
   VL_STR  TYPE STRING,
   VL_DATE TYPE D,
   VL_TYPE TYPE C.
  FIELD-SYMBOLS:
    <FS_WA>   TYPE ANY,
    <FS_COMP> TYPE ANY.
   SPLIT U_STR AT CONST_TAB INTO TABLE VL_STRINGS.
   ASSIGN C_STRUC TO <FS_WA>.
   TRY.
          LOOP AT TG_STRING INTO VG_STRING.
            ASSIGN COMPONENT SY-TABIX OF STRUCTURE <FS_WA> TO <FS_COMP>.
            DESCRIBE FIELD <FS_COMP> TYPE vl_type.
            IF vl_type = CONST_DT_DATE.    "日付型
               CALL FUNCTION 'CONVERT_DATE_TO_INTERNAL'
                 EXPORTING
                   date_external            = VL_STR
                   accept_initial_date      = 'X'
                 IMPORTING
                   date_internal            = vl_date
                 EXCEPTIONS
                   date_external_is_invalid = 1
                 OTHERS                   = 2.
               IF sy-subrc = 0.
                 VL_STR = vl_date.
               ENDIF.
                ENDIF.
             ENDIF.
            MOVE VL_STR TO <FS_COMP>.
          ENDLOOP.
        CATCH CX_SY_CONVERSION_ERROR.
          CLEAR: EX_AFDATA.
      ENDTRY.
ENDFORM.

CL_ABAP_TYPEDESCR

|
|--CL_ABAP_DATADESCR
|     |
|     |--CL_ABAP_ELEMDESCR
|     |--CL_ABAP_REFDESCR
|     |--CL_ABAP_COMPLEXDESCR
|         |
|         |--CL_ABAP_STRUCTDESCR
|         |--CL_ABAP_TABLEDESCR
|
|--CL_ABAP_OBJECTDESCR
      |
      |--CL_ABAP_CLASSDESCR
       |--CL_ABAP_INTFDESCR

データ型を判定

型毎のメタ情報

属性名意味基本型参照型構造型テーブル型クラス型インタフェース型
absolute_name型名称
type_kind内部ABAPデータ型
length内部長
decimals小数桁数P×××××
OUTPUT_LENGTH出力長×××××
STRUCT_KIND構造タイプ×××××
COMPONENTSコンポーネント(name/type_kind/length/decimals)テーブル×××××
KEYテーブルキー×××××
INITIAL_SIZEテーブルの初期サイズ×××××
KEY_DEFKINDテーブルデータ型定義×××××
HAS_UNIQUE_KEY一意キー定義×××××
TABLE_KINDテーブルカテゴリ×××××
CLASS_KINDクラスタイプ×××××
CREATE_VISIBILITY可視性登録×××××
INTF_KINDインタフェースタイプ×××××

プログラミング基礎に投稿されました 続きを読む

背景

編集中

型の作成

編集中

基本型

数値や文字列などのABAP基本型を動的に作成するには、クラスCL_ABAP_ELEMDESCRのメソッドを利用します。 クラスCL_ABAP_ELEMDESCRからいかのようなStaticメソッドが用意されております。

メソッド名機能
GET_Cパラメータで指定された長さのC(テキスト)項目型を取得
GET_Nパラメータで指定された長さのN(数値テキスト)項目型を取得
GET_Xパラメータで指定された長さのX(16進数)項目型を取得
GET_Pパラメータで指定された長さのP(パック数値項目)型を取得

STRING(文字順序)、XSTRING(バイト順序)、I(整数)、F(浮動小数点数)、D(日付)、T(時間)などの型もメソッドが用意されておりますが、こちらの型は長さの指定がないので、型名を静的に指定すればよく、あえてメソッドを利用する必要がありません。

下記のサンプルソースでは、長さ10の固定長テキスト項目型を動的生成する方法を示しています。

DATA c10  TYPE REF TO cl_abap_datadescr. 

c10 = cl_abap_elemdescr=>get_c( 10 )."動的な型を取得

プログラミング基礎に投稿されました 続きを読む

このトピックは動的なデータオブジェクトを取り上げて、その特徴と使用方法を説明します。

動的なデータオブジェクトを説明する前にまず静的なデータオブジェクトを説明しておきます。

プログラムの宣言部分において DATAなどの命令を使用して定義するデータオブジェクトはすべて静的に登録され、プログラムの起動時にはすでに存在する「静的なデータオブジェクト」となります。

一方、動的なデータオブジェクトとは、プログラム実行時に、CREATE DATA命令を使用して作成されるデータオブジェクトです。

動的なデータオブジェクトは以下の特徴があります。

  • 現在の ABAPプログラムの内部セッションの中にデータオブジェクトが登録されます。
  • 動的なデータ型を利用することができます。
  • 登録されるデータオブジェクトは独自の名称を持ちません。データ参照変数を使用した場合にのみアドレス指定することができます。
  • 内容をアクセスするにはフィールドシンボルを利用しなければなりません。

静的なデータ型使用の場合

静的なデータ型を利用して動的なデータオブジェクトを作成するには、TYPEオプションを使用します。 TYPEオプションの使い方は基本DATA命令と同じですが、タイプ名を指定する際に動的な名称も使用可能です。 以下のような型を使用することができます。

  • ABAP基本タイプ
    CREATE DATA dref TYPE c LENGTH 3.
  • TYPESによって定義された任意のデータ型
    TYPES TYP_BKPF TYPE STANDARD TABLE OF BKDF
    CREATE DATA dref TYPE TYP_BKPF.
  • ABAP ディクショナリによる任意のデータ型
    CREATE DATA dref TYPE BKDF.
    CREATE DATA dref TYPE STANDARD TABLE OF BKDF

サンプルソース:

DATA typ  TYPE c.
DATA len  TYPE i.
DATA dref TYPE REF TO data.
FIELD-SYMBOLS <fs> TYPE ANY.
typ = 'c'.
len = 30.
CREATE DATA dref TYPE (typ) LENGTH len.
ASSIGN dref->* TO <fs>.
<fs> =  'ABCDEF'.
write <fs>.

動的なデータ型使用の場合

実行時データ型サービス (RTTS) データ型オブジェクトによって記述される動的なデータ型のデータオ ブジェクトを生成するには、TYPE HANDLEオプションを使います。

サンプルソース:

DATA:
      r_stru TYPE REF TO cl_abap_structdescr,
      it_comp TYPE cl_abap_structdescr=>component_table,
      r_comp TYPE abap_componentdescr,
      r_elem TYPE REF TO cl_abap_elemdescr,
      r_data TYPE REF TO DATA.
DATA: length_of_field
          TYPE I VALUE 10.
FIELD-SYMBOLS: <fs> TYPE ANY.
START-OF-SELECTION.
r_elem = cl_abap_elemdescr=>get_c( length_of_field ).
r_comp-name = 'FIELD1'.
r_comp-type  = r_elem.
APPEND r_comp TO it_comp.
r_stru = cl_abap_structdescr=>create( it_comp ).
 CREATE DATA r_data TYPE HANDLE r_stru.
 ASSIGN r_data->('FIELD1') TO <fs>.
<fs> = 'ABC'.
WRITE: / <fs>.

プログラミング基礎に投稿されました 続きを読む

このトピックでは、動的な名称の使用方法を取り上げて説明します。

ABAPプログラムでは、以下のように様々な名称が使用されます。

  • データ型を指定するための名称
  • データオブジェクトを参照するための名称
  • SQL文に記述されるテーブル名称

通常はプログラムを作成する際に明示的に記述しますが、より機能性が高いプログラムを作成する場合、その名前を可変にしなければならないケースがあります。この可変の名前は動的な名前と呼ばれます。

基本構文は以下のようになります (名称が格納された変数)

REPORT Y_TEST.
DATA:
      A TYPE C,
      V1 TYPE C.
FIELD-SYMBOLS <FS> TYPE ANY.
A  = 'T'.
V1 = 'A'.
ASSIGN (V1) TO <FS>.
WRITE:  <FS> . 

ツール型のプログラム作成

テーブル内容をエクスポートするツールを例とします、テーブル名はユーザから任意に指定可能です。

以下はその実装の抜粋です。

PARAMETERS: pn TYPE dd02l-tabname obligatory.
START-OF-SELECTION.
DATA:
   t_itab TYPE REF TO DATA.
FIELD-SYMBOLS:
   <itab>   TYPE STANDARD TABLE.
CREATE DATA t_itab TYPE STANDARD TABLE OF (pn).
ASSIGN t_itab->* TO <itab>.
SELECT *
FROM (pn)
INTO TABLE <itab>.
*後続は省略

コードの簡潔化

名前が番号違いだけである複数の変数に対してそれぞれ何かの処理を行う時に、動的に変数を割り当てループ処理化することにより、コーディング記述量を劇的に減らすことができます。

REPORT  Y_VARNAME_TEST.
DATA:V1(2) TYPE C,     
     V2(2) TYPE C,
     V3(2) TYPE C,
     V4(2) TYPE C,
     V5(2) TYPE C,
     V6(2) TYPE C,
     V7(2) TYPE C,
     V8(2) TYPE C,
     V9(2) TYPE C.

DATA: VNAME(5) TYPE c ,
VINDEX TYPE c.

FIELD-SYMBOLS <FS> TYPE ANY.
START-OF-SELECTION.
DO 9 TIMES.
VINDEX = SY-INDEX.
CONCATENATE 'V' VINDEX INTO VNAME.
ASSIGN (VNAME) TO <FS>.
CONCATENATE 'X' VINDEX INTO <FS>.
ENDDO.
DO 9 TIMES.
VINDEX = SY-INDEX.
CONCATENATE 'V' VINDEX INTO VNAME.
ASSIGN (VNAME) TO <FS>.

WRITE:/ VNAME,
: '=' ,
: <FS>.
ENDDO.

上記のサンプルの実行結果は以下の図で示します。

変数参照制限の回避

ABAPでは異なるプログラム(レポート、汎用グループetc)のグローバル変数を直接参照することができません。 但し、Exit実装のアドオンプログラムから、直接拡張された標準プログラムのグローバル変数を直接参照したいというニーズはたまたま発生します。 そこで裏技になりますが、動的な変数名を利用すれば、プログラムを跨ってグローバル変数を参照できないというABAP言語の制限を回避することができます。

以下はそのサンプルです。

*
DATA: I_OKCODE(17) TYPE C VALUE '(SAPLMR1M)OK-CODE'.
FIELD-SYMBOLS: <FS_OKCODE> TYPE ANY.
ASSIGN (I_OKCODE) TO <FS_OKCODE>.

プログラミング基礎に投稿されました 続きを読む

フィールドシンボルとは、物理的なメモリを占有せずに、任意の変数(単一変数、構造、内部テーブルなど)に 割り当てる(Assign)ことで、任意の変数を指し示すことができます。C言語でいうポインタのようなものです。

フィールドシンボルを宣言するには、以下のような構文を使用します。

FIELD-SYMBOLS <FS> [< データ型 >|STRUCTURE <s> DEFAULT <wa>]. <FS>にある角かっこも構文の一部です、タイプ指定しない場合は、TYPE ANYで宣言することができます。

FIELD-SYMBOLS <FS1> TYPE ANY. FIELD-SYMBOLS <FS2> TYPE ANY TABLE.

Assign命令を使います。

フィールドシンボルにやまかっこをつけて、フィールドシンボルがアドレスするデータを参照または書き込みすることができます。

FORM f_get_range_table  USING u_setclass u_subclass u_setname
                        CHANGING r_range TYPE TABLE.
DATA:
  lt_set LIKE setleaf OCCURS 0 WITH HEADER LINE,	 
  wl_range      TYPE REF TO DATA  
.
FIELD-SYMBOLS : <fs_rec>,<fs_itm>
.

SELECT * FROM setleaf
  INTO TABLE lt_set
  WHERE setclass = u_setclass
  AND subclass = u_subclass
  AND setname = u_setname.

LOOP AT lt_set.
CREATE DATA wl_range LIKE LINE OF r_range.
ASSIGN wl_range->* TO <fs_rec>.
ASSIGN COMPONENT 'SIGN' OF STRUCTURE <fs_rec> TO <fs_itm>.
<fs_itm> = lt_set-valsign.
ASSIGN COMPONENT 'OPTION' OF STRUCTURE <fs_rec> TO <fs_itm>.
<fs_itm> = lt_set-valoption.
ASSIGN COMPONENT 'LOW' OF STRUCTURE <fs_rec> TO <fs_itm>.
<fs_itm> = lt_set-valfrom.
ASSIGN COMPONENT 'HIGH' OF STRUCTURE <fs_rec> TO <fs_itm>.
<fs_itm> = lt_set-valto.
APPEND wl_range to r_range.
  ENDLOOP.
ENDFORM.

プログラミング基礎に投稿されました 続きを読む

このトピックはテーブルのデータ行に対して、読み込みや変更などの操作方法を取り上げて説明します。

内部テーブルから単一行を読み込みするには、以下の命令を使用します。

  • READ TABLE itab search-key search-result.

検索キーを指定

読み込む対象となるデータ行の検索キーを指定する方法を説明します。

(1)テーブルキー指定

検索キーとして itab のテーブルキーを使用するには、以下のように key を入力します。

  • READ TABLE itab FROM wa result.

または

  • READ TABLE itab WITH TABLE KEY k1 = f1 … kn = fn result.

全タイプの内部テーブルに対して、この方法を利用することができます。

(2)任意キー指定

テーブルキー以外の項目も検索キーとして指定することができます。

  • READ TABLE itab WITH KEY k1 = f1 … kn = fn result.

標準テーブルの場合、「BINARY SEARCH」をつけて検索の高速化を図ることができます。これは、標準テーブルが検索キー項目によってソートされていることを前提にしています、そうではない場合、エラーにならないが、意図しないデータ行が読み出されることになってしまいます。

(3)index指定

標準テーブルおよびソートテーブルに限りますが、読み込む行のテーブル索引を明示的にidxによって指定することができます。

  • READ TABLE 読出元の内部テーブル INTO 読み出し先構造 INDEX idx

idx は、i 型のデータオブジェクトである必要があります。

取得できたかをチェック

対象データが取得できた場合と取得できなかった場合、それぞれ以下のようにシステム項目に値が設定されます。

  • 取得できた場合
    • sy-subrc: 0
    • sy-tabix: 取得された行のインデックス
  • 取得できなかった場合
    • sy-subrc: エラーコード(0でない数字)

対象行のデータを照会

検索対象行のデータを照会するには、作業領域かフィールドシンボルかを使用することができます。

  • 作業領域を使用
    READ TABLE itab key INTO wa
  • フィールドシンボルを使用
    READ TABLE itab key ASSIGNING <fs>.

対象データ行の内容を関心せず、対象データが存在しているかどうかのみをチェックする場合があります。その際、「READ TABLE」命令に「NO FIELDS」オプションをつけることができます。

単一行挿入

単一行を内部テーブルの特定の箇所に挿入する場合は、「INSERT」を使用します。

  • INSERT wa INTO TABLE itab INDEX idx.

複数行挿入

複数行を内部テーブルの特定の箇所に挿入する場合は「INSERT LINES OF」を使用します。

  • INSERT LINES OF itab1 FROM idx1_1 TO idx1_2 INTO TABLE itab2 INDEX idx2.

単一行変更

単一行を変更するには、以下の命令を使用します。

  • MODIFY TABLE itab FROM wa [TRANSPORTING f1 f2 …].

複数行変更

条件を使用して 1 行または複数行を変更するには、以下の命令を使用します。 MODIFY itab FROM wa TRANSPORTING f1 f2 …WHERE cond.

単一行削除

内部テーブルの単一行を削除する場合は、DELETE 命令を使用します。

  • DELETE TABLE itab FROM wa.

または

  • DELETE TABLE itab WITH TABLE KEY k1 = f1 … kn = fn.

または

  • DELETE TABLE itab Index idx

複数行削除

内部テーブルの行を複数まとめて削除する場合には、「DELETE .. WHERE」文を使用します。

  • DELETE TABLE itable WHERE key = value.

内部テーブルを走査するには、命令LOOP~ENDLOOPを使用します。 FROM を指定できるのは、 標準テーブルおよび ソートテ ーブルの場合に限られます。 すべてのテーブルデータ型について WHERE を指定することができます。

  DATA : T_WITH_ITEM TYPE TABLE OF WITH_ITEM,
         W_WITH_ITEM TYPE WITH_ITEM.
* 処理         
  LOOP AT T_WITH_ITEM INTO W_WITH_ITEM WHERE
     BELNR = W_BELNR AND
     BUZEI = W_BUZEI.        
* 処理   

ENDLOOP.

プログラミング基礎に投稿されました 続きを読む

このトピックでは内部テーブル全体に対する操作を取り上げて説明します。

内部テーブルの割り当ては、MOVE命令を使用します。 MOVE itab1 TO itab2. なお、代入演算子も同様の働きを持ちます。 itab2 = itab1.

上記の命令が実行された結果、内部テーブルitab1の内容が内部テーブルitab2にコピーされることになります。

内部テーブルを初期化するには、clear、fresh、freeなどの命令を使用します。

  • clear
    • 構文1:clear itab[]
      内部テーブルの本体を初期化します。
      内部テーブルは初期メモリ所要量が予約され、その以外のメモリ領域がすべて解放されます。
    • 構文2:clear itab
      ヘッダ行を含まない内部テーブルの場合は、この命令はclear itab[]と同様に動作します。
      ヘッダ行を含る内部テーブルの場合は、ヘッダ行(作業領域)の名前が内部テーブルと同じであるため、このテーブルは単なるヘッダ行のクリアのみとなります。
  • fresh
    • 構文:fresh itab
      常に内部テーブルの本体を初期化します。この命令はclear itab[]と同様に動作します。
  • free
    • 構文:fresh itab
      常に内部テーブルの本体を初期化します。この命令はclear、fresh命令と異なり、内部テーブルに対して、初期メモリ所要量を含めた記憶域全体をすべて解放します。

ABAPでは、内部テーブルも論理式内のオペランドとして比較することができます。

内部テーブルのソートはSORT命令を使用します。

SORT itab [ASCENDING|DESCENDING] [AS text] [STABLE].

DESCRIBE TABLE命令を使用して、件数などの内部テーブルの各属性を取得することができます。

  • DESCRIBE TABLE
    構文:DESCRIBE TABLE itab [LINES lin] [OCCURS n] [KIND knd].
    • パラメータ:LINES
      内部テーブルのレコード件数を取得します。
    • パラメータ:OCCURS
      内部テーブルの初期サイズを取得します。
    • パラメータ:KIND
      内部テーブルの種類を取得します。

プログラミング基礎に投稿されました 続きを読む

テーブルデータ型は、ABAP における内部テーブルの構造と機能属性を示します。このトピックでは、テーブルデータ型を取り上げて、その構成や種類などを説明します。

テーブルデータ型は、行データ型、キー、およびアクセス方法によって完全指定されます。

(source:SAP Help Portal)

行データ型

通常、内部テーブルのデータ型は構造であり、その構造の各コンポーネントは、それぞれ内部テーブル内の1つの列になります。 ただし、内部テーブルのデータ型の仕様としては、構造以外の任意のデータ型を使用することも可能です。

キー

テーブル行データはキーによって識別されます。キーは、システムからデフォルトで生成されるは標準キーのほかに、ユーザから定義することもできます。ユーザ定義キーはUNIQUE または NON-UNIQUE として指定することができます。

アクセス方法

内部テーブルのアクセス方法は以下三つの種類から指定できます。

  • 標準テーブル
    標準テーブルは内部的な線型索引を持ちます。
    索引を使用して個別のテーブルエントリをアドレス指定する予定がある場合には、これが最適なデータ型です。
  • ソートテーブル
    ソートテーブルは常にキー別にソートされ、保存されます。ソートテーブルも内部索引を持ちます。
    バイナリ検索が求められる場合には、これが最適なデータ型です。
  • ハッシュテーブル
    ハッシュテーブルは線型索引を持ちません。キーを使用した場合にのみハッシュテーブルにアクセスすることができます。
    ハッシュ検索が求められる場合には、これが最適なデータ型です。

テーブルデータ型は以下の階層図で示されたように、内部テーブルのアクセス方法により分類することができます。

(source:SAP Help Portal)

完全指定のテーブルデータ型

内部テーブルのアクセス方法が明示されたテーブルデータ型です。

  • STANDARD TABLE または TABLE
    標準テーブルを登録します。
  • SORTED TABLE
    ソートテーブルを登録します。
  • HASHED TABLE
    ハッシュテーブルを登録します。

ジェネリックテーブルデータ型

内部テーブルのアクセス方法が明示されたテーブルデータ型です。

  • INDEX TABLE
    索引アクセスを使用するジェネリックテーブルデータ型を登録します。
  • ANY TABLE
    完全なジェネリックテーブルデータ型を登録します。

ジェネリックテーブルデータ型は動的なプログラミングでよく使用されます。

テーブルデータ型は、ローカルまたはグローバルに定義することができます。

ローカル定義

プログラムの中でTYPE命令を使用してテーブルデータ型をローカルに定義することができます。 構文:

TYPES type TYPE|LIKE tabkind OF linetype [WITH key]
 [INITIAL SIZE n].

グローバル定義

ABAP ディクショナリのデータ型としてテーブルデータ型をグローバルに定義することもできます。 例として、標準のMMPUR_REQUISITION_ITEMSを取り上げてそのイメージを示します。