ABAPでのファイル出力:固定長ファイル
0 394

このトピックでは、ABAPでUniCodeのシステムからSJISコードで固定長ファイル出力の方法を取り上げて説明します。

ABAPで文字コードの関係でSJISコードで固定長ファイルを出力するには少し工夫する必要があります。 タブ区切りやカンマ区切りのファイル出力にするほうがだんぜん楽ですが、ふるい既存システムへの連携で固定長ファイルにしなければならない場面がしばしばあります。

固定長ファイル出力の基本は、項目を固定バイト長に出力させることです。

問題点

以下の構造体をファイルに出力することを例とします。

TYPES:
  BEGIN OF typ_row,
    col1       TYPE C LENGTH 10,
    col2       TYPE C LENGTH 12,
  END   OF typ_row.

Unicodeシステムのため、co1に定義されたLENGTH=10はバイト数ではなく文字数ですので、SJISで出力されるバイト数は可変になります。 一番少ないのは、すべて半角文字の場合であり、出力バイト数が10×1半角文字1バイト=10バイトになります。 一番多いのは、すべて全角文字の場合であり、出力バイト数が10×1全角文字2バイト=20バイトになります。 col1の固定長出力は以下の2パターンに分けることができます。

  • 固定長>=20バイト
    col1の実際の出力バイト数が20を超えることがないため、カットする処理は必要がありません。
    但し、場合によって後ろにスペースを埋める必要があるため、col1の実際の出力バイト数を計算しなければなりません。
  • 固定長<20バイト、例えば:10バイト
    col1の実際の出力バイト数を計算して、10バイトに未満の場合のスペース埋め処理を実装するほか、10バイトを超えた場合の既存文字列のカット処理も実装しなければなりません。カットする際に、カットが全角文字の真ん中にならないように注意する必要があります。

対応方法

上記の課題を対応するポイントは以下になります。

  • 出力バイト数計算処理
    メソッドcl_abap_list_utilities⇒dynamic_output_lengthを利用して、出力バイト数を計算します。
    このメソッドは各文字が全角文字か半角文字かを判断して、全角文字なら2、半角文字なら1というアルゴリズムで出力長を計算しています。
  • 文字列カット処理
    メソッドcl_abap_list_utilities⇒read_from_display_layoutを利用して、文字列のカット処理を行います。
    このメソッドはカットされる箇所に全角文字が跨っている場合、文字化けにならないように該当全角文字を丸ごと捨てるようにしております。
  • スペース埋め処理 \\ CONCATENATE命令は文字列を連結する際に、デフォルトで文字列の後ろのスペースを削除するため、スペース埋め処理を行う時は、RESPECTING BLANKSオプションをつける必要があります。

固定バイト数で文字列を出力するサブルーチンのサンプルコードです。

*&---------------------------------------------------------------------*
*&      Form  F_OUTPUT_FIXED_BYTES
*&---------------------------------------------------------------------*
*       固定バイト数で文字列出力
*----------------------------------------------------------------------*
*      -->U_LEN   :  出力バイト長
*      -->U_FIELD : 入力値
*      -->C_STR   : 出力文字列
*----------------------------------------------------------------------*
FORM f_output_fixed_bytes
  USING
    u_len   TYPE i
    u_field
  CHANGING
    c_str.

DATA:
l_len TYPE i, "length
l_cnt TYPE i,
l_rc TYPE abap_list_repl_rc.
CLEAR: c_str,
l_cnt.

  • byte数取得
    CALL METHOD cl_abap_list_utilities=>dynamic_output_length
    EXPORTING
    field = u_field
    RECEIVING
    len = l_cnt.
  • データ長が出力バイト長を超えた場合、出力バイト長で文字列をカット
    IF l_cnt > u_len.
    TRY.
    CALL METHOD cl_abap_list_utilities=>read_from_display_layout
    EXPORTING
    display_data = u_field
    display_offset = 0
    display_length = u_len
    IMPORTING
    field = c_str
    rc = l_rc.
    CATCH cx_parameter_invalid_range .
    ENDTRY.
  • byte数再取得 (カット箇所に全角文字が跨っているケースを考慮)
    CALL METHOD cl_abap_list_utilities=>dynamic_output_length
    EXPORTING
    field = c_str
    RECEIVING
    len = l_cnt.
  • バイト数が足りない場合は、後ろにスペースを埋める
    WHILE l_cnt < u_len.
    CONCATENATE c_str
    ' '
    INTO c_str
    RESPECTING BLANKS.
    l_cnt = l_cnt + 1.
    ENDWHILE.
    ENDIF.
    ENDFORM.

0 394
みんなのツイート (0)

関連サマリー


  • プログラミング基礎 0 Votes 157 閲覧数


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

    概要

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

    格納テーブルNRIV
    番号範囲間隔
    メンテナンスSNRO
    番号範囲オブジェクト


    SM56
    番号範囲バッファの管理汎用モジュール

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

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


  • プログラミング基礎 0 Votes 532 閲覧数


    フィールドシンボルとは、物理的なメモリを占有せずに、任意の変数(単一変数、構造、内部テーブルなど)に 割り当てる(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.


  • プログラミング基礎 0 Votes 385 閲覧数


    概要バリアントとは

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

    バリアント変数とは

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

    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:パラメータ


  • プログラミング基礎 0 Votes 51 閲覧数


    背景

    編集中

    型の作成

    編集中

    基本型

    数値や文字列などの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 )."動的な型を取得


  • プログラミング基礎 0 Votes 112 閲覧数


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

    割当

    内部テーブルの割り当ては、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
    内部テーブルの種類を取得します。


  • プログラミング基礎 0 Votes 297 閲覧数


    テーブルデータ型は、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を取り上げてそのイメージを示します。


  • プログラミング基礎 0 Votes 127 閲覧数


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

    動的な名称とは

    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>.


  • プログラミング基礎 0 Votes 316 閲覧数


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

    動的なデータオブジェクトとは

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

    プログラムの宣言部分において 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>.