概要
バリアントとは
バリアントとは、同じ選択条件で実行することが多いプログラムに対して、入力値のセットを保存させておくものです。 レポートプログラムバリアント、画面バリアント、トランザクションバリアントなどがあります。
バリアント変数とは
バリアント変数とは、バリアントに格納される値を変数化したものです。 バリアント変数は二つのタイプがあります。
- TYPE P
単一値を定義することができます。 - TYPE S
選択テーブルとして条件を定義することができます。
格納テーブル
メンテナンス
トランザクション利用
バリアント変数のメンテナンスは、トランザクション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命令を使用して、変数のデータタイプを取得することができます。
構文
DESCRIBE FIELD obj TYPE 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.
RTTS関連クラスを使用
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 における内部テーブルの構造と機能属性を示します。このトピックでは、テーブルデータ型を取り上げて、その構成や種類などを説明します。
構成
行データ型
通常、内部テーブルのデータ型は構造であり、その構造の各コンポーネントは、それぞれ内部テーブル内の1つの列になります。 ただし、内部テーブルのデータ型の仕様としては、構造以外の任意のデータ型を使用することも可能です。
キー
テーブル行データはキーによって識別されます。キーは、システムからデフォルトで生成されるは標準キーのほかに、ユーザから定義することもできます。ユーザ定義キーはUNIQUE または NON-UNIQUE として指定することができます。
アクセス方法
内部テーブルのアクセス方法は以下三つの種類から指定できます。
- 標準テーブル
標準テーブルは内部的な線型索引を持ちます。
索引を使用して個別のテーブルエントリをアドレス指定する予定がある場合には、これが最適なデータ型です。 - ソートテーブル
ソートテーブルは常にキー別にソートされ、保存されます。ソートテーブルも内部索引を持ちます。
バイナリ検索が求められる場合には、これが最適なデータ型です。 - ハッシュテーブル
ハッシュテーブルは線型索引を持ちません。キーを使用した場合にのみハッシュテーブルにアクセスすることができます。
ハッシュ検索が求められる場合には、これが最適なデータ型です。
分類
完全指定のテーブルデータ型
内部テーブルのアクセス方法が明示されたテーブルデータ型です。
- STANDARD TABLE または TABLE
標準テーブルを登録します。 - SORTED TABLE
ソートテーブルを登録します。 - HASHED TABLE
ハッシュテーブルを登録します。
ジェネリックテーブルデータ型
内部テーブルのアクセス方法が明示されたテーブルデータ型です。
- INDEX TABLE
索引アクセスを使用するジェネリックテーブルデータ型を登録します。 - ANY TABLE
完全なジェネリックテーブルデータ型を登録します。
ジェネリックテーブルデータ型は動的なプログラミングでよく使用されます。
定義
テーブルデータ型は、ローカルまたはグローバルに定義することができます。
ローカル定義
プログラムの中でTYPE命令を使用してテーブルデータ型をローカルに定義することができます。 構文:
TYPES type TYPE|LIKE tabkind OF linetype [WITH key] [INITIAL SIZE n].