TYPES命令
13.2 TYPES命令
2. TYPES命令
TYPES 命令は、データ型(型の設計図)を作る命令です。
変数や構造、内部テーブルなどを作るときに、「どんな形のデータを入れるか」を先に決める命令です。
データ型名は基本的に任意ですが、チーム内で分かりやすい命名で宣言すると可読性が高くなります。
TYPESで作れるデータ型は大きく次の3種類です。
● 基本データ型:1 項目の型(例:商品名、日付、金額 など)
※基本データ型に用いられるものは、
「事前定義済データ型」と「ABAP ディクショナリオブジェクトのデータ型」の 2 つです。
● 構造データ型:複数項目をひとまとめにした型(例:商品コード+商品名+金額)
● テーブルデータ型:同じ構造を行としてたくさん並べる型(一覧表示や集計でよく使う)
「事前定義済データ型」
事前定義済データ型は、ABAP で標準で用意されている基本のデータ型です。 大きく「文字」「数値」「文字列(可変長)」に分かれます。
- 固定長:長さが決まっており、宣言時に長さを指定して使う(例:C、N、P、X)
- 可変長:長さが固定ではなく、必要に応じて伸びる(例:STRING、XSTRING)
たとえば文字列を扱うとき、 「桁(長さ)が決まっている」項目なら C / N、「何文字になるかわからない文章」ならSTRINGのように、用途で使い分けます。 表の「初期値」は、変数を作った直後に自動で入る値です。
「完全ABAPデータ型と不完全データ型」
固定長のデータ型の中には、さらに「完全 ABAP データ型」 と「不完全データ型」があります。
■ 完全 ABAP データ型:長さが決まっている
D(日付=8 桁)、T(時刻=6 桁)、I(整数=4byte)、F(浮動小数点=8byte)などは、基本の長さが決まっているため、通常は長さ指定が不要です。
■ 不完全データ型:長さが決まっていない
C(文字)、N(数値文字)、P(パック数値)、X(16 進数)などは、用途によって必要な長さが変わるため、長さ指定が必要です。
もし長さを省略すると、最小の長さとして扱われます。指定しない場合は、最小の長さとなります。
「ABAPディクショナリオブジェクトのデータ型」
ABAP ディクショナリオブジェクトのデータ型とは、ABAP ディクショナリのデータ型とは、ABAP ディクショナリ
(トランザクションコード:SE11)で定義・管理されているデータ型のことです。
実務では、得意先コード(KUNNR)や通貨(CUKY)など、業務項目として意味を持つ型はディクショナリで統一しておくことが
多く、プログラム側でもそれを参照して使います。
ディクショナリ型をプログラムで使う場合、内部的には ABAP の基本型(C や P など)に変換されて扱われます。
たとえば、CHAR は C(n)、NUMC は N(n)、DATS は D、CURR/DEC は P 型…というように対応します。
基本データ型
基本データ型は、1 つのデータに対するデータ型を指します。 たとえば、「商品名」のように、関連する項目 1 つを扱いたいときに使います。
TYPES命令:基本データ型
また、事前定義済みデータ型を使用した場合の桁数は、
基本データ型が持つ桁数になりますが、自分で決めることも可能です。
その場合、下記の構文の項目長の部分に任意の数字を入れます。
「サンプルコード」①
REPORT Z_SAMPLE131.
*&---------------------------------------------------------------------*
* 型定義
*&---------------------------------------------------------------------*
TYPES:
TY_CHAR1 TYPE C, "Cは省略すると長さ1(固定長)
TY_CHAR8 TYPE C LENGTH 8, "固定長8
TY_CHAR10 TYPE C LENGTH 10, "固定長10
TY_INT TYPE I, "整数
TY_KUNNR TYPE KUNNR. "得意先コード(ALPHA変換対象の代表例)
*&---------------------------------------------------------------------*
* 変数定義
*&---------------------------------------------------------------------*
DATA:
LV_CHAR1 TYPE TY_CHAR1,
LV_CHAR8 TYPE TY_CHAR8,
LV_CHAR10 TYPE TY_CHAR10,
LV_INT TYPE TY_INT,
LV_KUNNR TYPE TY_KUNNR.
*&---------------------------------------------------------------------*
* 主処理
*&---------------------------------------------------------------------*
START-OF-SELECTION.
"値の代入(固定長Cでは、長さを超える分は右側が切り捨てられる)
LV_CHAR1 = '1234567890'. "→ '1'
LV_CHAR8 = '1234567890'. "→ '12345678'
LV_CHAR10 = '1234567890'. "→ そのまま
LV_INT = 123.
"得意先コードは「内部値」と「表示値」が異なることがある(ALPHA変換)
"入力は例として短い値にし、表示時の変換を確認しやすくする
LV_KUNNR = '1000'.
"出力(結果を見比べる)
WRITE:
/ 'C(1) = [', LV_CHAR1, ']',
/ 'C(8) = [', LV_CHAR8, ']',
/ 'C(10) = [', LV_CHAR10, ']',
/ 'I = ', LV_INT,
/ 'KUNNR = [', |{ LV_KUNNR ALPHA = OUT }|, ']'.
END-OF-SELECTION.
実行結果
このサンプルでは、TYPES 命令を使って基本データ型(C/I など)を定義し、長さの違いによって値の扱いが どう変わるかを確認します。固定長の C 型では、定義した長さを超える文字が代入されると右側が切り捨てら れる点に注目してください。 また、得意先コード(KUNNR)のように、表示時に変換(例:ALPHA 変換)される型もあるため、出力 結果の見え方が変わることを合わせて確認しましょう。
「サンプルコード」②
REPORT Z_SAMPLE132.
*&---------------------------------------------------------------------*
* 型定義
*&---------------------------------------------------------------------*
TYPES:
TY_CHAR8 TYPE C LENGTH 8, "固定長8(※長さはバイト長が関係する)
TY_CHAR10 TYPE C LENGTH 10. "固定長10
*&---------------------------------------------------------------------*
* 変数定義
*&---------------------------------------------------------------------*
DATA:
LV_CHAR8 TYPE TY_CHAR8,
LV_CHAR10 TYPE TY_CHAR10.
*&---------------------------------------------------------------------*
* 主処理
*&---------------------------------------------------------------------*
START-OF-SELECTION.
"値の代入(全角文字を固定長Cに入れたときの表示の違いを確認する)
LV_CHAR8 = 'あいうえお'.
LV_CHAR10 = 'あいうえお'.
"出力(観察ポイント)
"固定長Cでは、定義長を超える分は表示しきれないことがある
"全角文字は内部的にバイト長が大きくなるため、途中で欠けて見える場合がある
WRITE:
/ 'C(8) = [', LV_CHAR8, ']',
/ 'C(10) = [', LV_CHAR10, ']'.
END-OF-SELECTION.
実行結果
サンプルコード②の補足
実行結果で、固定長の文字型に全角文字を代入した場合、C LENGTH 8 の項目が「あいうえお」ではな
く、「あいう…」のように途中で欠けて見えることがあります。
(環境によっては > などの記号で「表示しきれない」ことが示される場合もあります)。
これは、WRITE の都合で省略しているというより、固定長の C 型が保持・表示できる長さに上限があるためです。
全角文字は内部的に必要なバイト数が大きくなるため、同じ「5 文字」でも短い固定長項目では収まりきらないことがあります。
このサンプルでは、長さの異なる固定長文字型を 2 種類用意し、同じ全角文字を代入して表示の違いを確認します。
C LENGTH 8:短い固定長
C LENGTH 10:少し長い固定長
実行するときは、「文字数」ではなく「型の長さ(固定長)」の制約によって表示結果が変わる点に注目してください。
「サンプルコード」③
REPORT ZTEST_BASEDATA_KANDA. "-------------------------------------------- " 変数定義(実行結果で比較するための代入先) "-------------------------------------------- DATA: LV_C10 TYPE C LENGTH 10, "C(固定長) LV_NUMC10 TYPE N LENGTH 10, "NUMC(数字文字) LV_DATS TYPE DATS, "DATS(日付) LV_TIMS TYPE TIMS, "TIMS(時刻) LV_I TYPE I, "I(整数) LV_P TYPE P LENGTH 8 DECIMALS 3, "P(固定小数) LV_F TYPE F, "F(浮動小数点) LV_X10 TYPE X LENGTH 10, "X(バイト列:固定長) LV_STRING TYPE STRING, "STRING(文字列:可変長) LV_XSTRING TYPE XSTRING. "XSTRING(バイト列:可変長) "-------------------------------------------- " 選択画面(入力) "-------------------------------------------- PARAMETERS: P_TEXT TYPE C LENGTH 20, "文字 P_INT TYPE I, "整数 P_DEC TYPE P LENGTH 8 DECIMALS 3, "固定小数 P_DATE TYPE DATS, "日付(YYYYMMDD) P_TIME TYPE TIMS, "時刻(HHMMSS) P_HEX10 TYPE X LENGTH 10. "バイト列(固定長) START-OF-SELECTION. "入力値を各型の変数に代入する LV_C10 = P_TEXT. LV_DATS = P_DATE. LV_TIMS = P_TIME. LV_I = P_INT. LV_P = P_DEC. LV_F = P_DEC. LV_X10 = P_HEX10. LV_STRING = P_TEXT. LV_XSTRING = P_HEX10. "表示(結果を見比べる) "Cは固定長のため、長さ10を超える分は切り捨てられる "STRINGは可変長のため、入力した文字列がそのまま保持される "X/XSTRINGはバイト列のため、表示はHEX表現になる ULINE. WRITE: / 'C(10) = [', LV_C10, ']'. WRITE: / 'NUMC(10) = [', LV_NUMC10, ']'. WRITE: / 'DATS = [', LV_DATS, ']'. WRITE: / 'TIMS = [', LV_TIMS, ']'. WRITE: / 'I = ', LV_I. WRITE: / 'P(8,3) = ', LV_P. WRITE: / 'F = ', LV_F. ULINE. WRITE: / 'X(10) = ', LV_X10. WRITE: / 'XSTRING = ', LV_XSTRING. ULINE.
このサンプルでは、選択画面で入力した値を、代表的な ABAP データC/NUMC/DATS/TIMS/I/P/F/X/STRING/XSTRING に代入し、表示結果を比較します。
同じ「数値っぽい入力」でも、NUMC は「数字の文字列」で、桁が足りない場合に 0 埋めされる点が特徴です。
一方、I は計算に使う整数です。
また、P(パック数値)は固定小数として扱えるため、金額や数量のように「桁と小数点以下を正確に扱いたい」場面でよく使われます。
対して、 F(浮動小数点)は計算用途向きですが、丸め誤差が出る場合があるため、金額には通常 P 型を用います。
さらに、X/XSTRING は文字ではなくバイト列です。
X は固定長、XSTRING は可変長という違いがあり、どちらも出力するときは HEX として表示されます。
実行結果
サンプルコード③補足
このサンプルでは、選択画面で入力した値を、代表的な ABAP データ型(C / DATS / TIMS / I / P / F
/ X / STRING / XSTRING)に代入し、表示結果を比較します。
また、NUMC(数字文字)については入力項目を用意せず、整数入力(I)から NUMC(10)を作成して、
0 埋めなどの特徴を確認します。
同じ内容でも、型によって「保持のされ方」や「表示のされ方」が変わる点に注目しながら実行してみましょう。
構造データ型
構造データ型は、複数の項目を1つにまとめた「1レコード分の型」です。 たとえば、「商品名・商品コード・仕入先コード」のように、関連する項目をひとまとまりで扱いたいときに使います。
TYPES命令:構造データ型
構造(ワークエリア、作業領域)を定義する際のデータ型として以下の様に定義します。
構造データ型は 「TYPES … BEGIN OF ~ END OF …」 で定義します。
このとき、構造の中身(各項目)は、基本データ型(C/I など)や ABAP ディクショナリの型
(LIFNR など)を指定して宣言します。
また、構造の項目を参照するときは ハイフン「 – 」 でつなぎます。
例)ty_product-product_code、gs_product-product_code のように書きます。
「サンプルコード」①
EPORT ZFUJII_SAMPLE133.
*&---------------------------------------------------------------------*
* 型定義:1件分(商品情報)の型
*&---------------------------------------------------------------------*
TYPES:
BEGIN OF TY_PRODUCT,
PRODUCT_NAME TYPE C LENGTH 8, "商品名
PRODUCT_CODE TYPE C LENGTH 4, "商品コード
SUPPLIER_ID TYPE LIFNR, "仕入先コード
END OF TY_PRODUCT.
*&---------------------------------------------------------------------*
* 変数定義
*&---------------------------------------------------------------------*
*"構造の各項目型を参照して変数を宣言(型名-項目名)
DATA LS_PRODUCT TYPE TY_PRODUCT.
*&---------------------------------------------------------------------*
* 主処理
*&---------------------------------------------------------------------*
START-OF-SELECTION.
LS_PRODUCT-PRODUCT_NAME = 'りんご'.
LS_PRODUCT-PRODUCT_CODE = 'C001'.
LS_PRODUCT-SUPPLIER_ID = 'L100'.
WRITE:
/ '商品名 :', LS_PRODUCT-PRODUCT_NAME,
/ '商品コード :', LS_PRODUCT-PRODUCT_CODE,
/ '仕入先コード:', LS_PRODUCT-SUPPLIER_ID.
END-OF-SELECTION.
実行結果
テーブルデータ型
テーブルデータ型は、同じ行タイプ(1 行分の型)が複数行並ぶ「内部テーブルの型」です。 実務では「1 行=1 件のデータ」という形で扱うことが多いため、行タイプには 構造データ型 を使うのが一般的です。
ポイント: テーブルデータ型で指定できるのは「変数」ではなく、データ型(型名) です。
たとえば、gv_num のような単一の変数名を、行タイプとして指定することはできません。
一方で、行タイプとして指定できるのは構造データ型だけではなく、基本データ型など さまざまなデータ型です。
(ただし、このテキストでは理解しやすいように、行タイプ=構造の例を中心に扱います。)
TYPES命令:テーブルデータ型
テーブルデータ型を定義する際は以下の様に定義します。
※DBテーブルはデータ型ではないが、SAPシステム上ではDBテーブルの構造を参照するようにSAPシステムの仕様として構築されており、DBテーブルを型として指定すると内部テーブルを作成します。
補足(DB テーブルを指定できる理由)
ABAP ディクショナリ(SE11)の DB テーブル/ビューは、「1 行分の項目構成(行構造)」を持っています。
「STANDARD TABLE OF <DB テーブル名>…」と書くと、ABAP はその 行構造を行タイプとして参照し、内部テーブル型を作成します。
構文②は、「まったく新しい型を作る」というより、「型名を分かりやすく付け替える(別名を作る)」目的で
使うことがあります。
(必須ではありませんが、長い型名を短くしたい場合などに有効です。)
「サンプルコード」①
REPORT Z_SAMPLE134.
*&---------------------------------------------------------------------*
* 型定義
*&---------------------------------------------------------------------*
*構造データ型
TYPES:
BEGIN OF TY_PRODUCT,
PRODUCT_NAME TYPE C LENGTH 8, "商品名
PRODUCT_CODE TYPE C LENGTH 4, "商品コード
SUPPLIER_ID TYPE LIFNR, "仕入先コード
END OF TY_PRODUCT.
* テーブルデータ型(同じ行タイプが複数行並ぶ内部テーブル)
* WITH EMPTY KEY:このサンプルではキーを利用しないことを明示
TYPES TY_PRODUCT_TAB TYPE STANDARD TABLE OF TY_PRODUCT WITH EMPTY KEY.
*&---------------------------------------------------------------------*
* 内部テーブル定義
*&---------------------------------------------------------------------*
DATA LT_PRODUCTS TYPE TY_PRODUCT_TAB.
*&---------------------------------------------------------------------*
* 主処理
*&---------------------------------------------------------------------*
START-OF-SELECTION.
*&---------------------------------------------------------------------*
* データ作成(2件分の行を内部テーブルへ追加)
*&---------------------------------------------------------------------*
* VALUE #( ... ):1行分の構造をその場で作成して追加する(ABAP 7.4以降の記法)
APPEND VALUE #(
PRODUCT_NAME = 'りんご'
PRODUCT_CODE = 'C001'
SUPPLIER_ID = 'L100' ) TO LT_PRODUCTS.
APPEND VALUE #(
PRODUCT_NAME = 'みかん'
PRODUCT_CODE = 'C003'
SUPPLIER_ID = 'L300' ) TO LT_PRODUCTS.
*&---------------------------------------------------------------------*
* 出力処理
*&---------------------------------------------------------------------*
* 観察ポイント:
* ・LOOPで1行ずつ取り出すとき、行は「構造」として扱われる
* ・構造をWRITEすると、項目順に出力される(見比べ用の簡易出力)
LOOP AT LT_PRODUCTS INTO DATA(LS_PRODUCT).
WRITE:
/ '商品名 :', LS_PRODUCT-PRODUCT_NAME,
/ '商品コード :', LS_PRODUCT-PRODUCT_CODE,
/ '仕入先コード:', LS_PRODUCT-SUPPLIER_ID.
ULINE.
ENDLOOP.
END-OF-SELECTION.
実行結果
このサンプルでは、TYPES 命令で「1件分の構造データ型(TY_PRODUCT)」を定義し、それを行タイプとして持つ内部テーブル型(TY_PRODUCT_TAB)を作成します。
次に、「APPEND VALUE …」 を使って2件分の行を内部テーブルに追加し、LOOP で1行ずつ取り出して表示します。
確認ポイントは、「1行=複数項目を持つ構造」であり、それが複数行集まって一覧(内部テーブル)になるという点です。