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

このトピックでは、EXCELファイル出力の方法を取り上げて説明します。

ABAPプログラムは、ABAP言語のOLE オートメーション技術を利用して、Excelファイルの読み取り、書き込みを行うことができます。 以下の図でその仕組みを示します。 

  1. OLEサーバとなるデスクトップアプリケーション(ExcelやWordなど)は、フロントエンドマシンに稼働します。
  2. ABAPプログラムはAS ABAPに稼働します。
  3. OLEサーバを直接アクセスするのは同じフロントエンドマシンに稼働するSAP GUIです。
  4. ABAPプログラムのOLE関連命令はAS ABAPによりRFCを通して、フロントエンドマシンに稼働するSAP GUIと連携されます。

ABAPで制御されるアプリケーションはすべて、ABAPシステムに登録しなければなりません。

以下のABAP命令でOLEサーバアプリケーションを制御します。

  • CREATE OBJECT
    OLEサーバアプリケーションのアプリケーションオブジェクトを作成します。
    アプリケーション名が指定されます、例えばExcelアプリケーションの場合は、'Excel.Application'になります。
  • SET PROPERTY
    アプリケーションオブジェクトのプロパティの値を設定します。
  • GET PROPERTY
    アプリケーションオブジェクトのプロパティの値を取得します。
  • CALL METHOD
    アプリケーションオブジェクトのメソッドを呼び出します。

任意テーブルのデータをExcelファイルへエクスポートするツールをサンプルとして取り上げてそのソースを以下に示します。 動的プログラミングのサンプルソースとしても参考できるものです。

REPORT  Y_XXXXX01.
INCLUDE ole2incl.
TYPES: BEGIN OF s_tabstr,
  fieldname TYPE fieldname,
  as4local TYPE as4local,
  POSITION TYPE tabfdpos,
  keyflag TYPE keyflag,
  rollname TYPE rollname,
  datatype TYPE datatype_d,
  leng TYPE ddleng,
  scrtext_s TYPE scrtext_s,
END OF s_tabstr.
 PARAMETERS: p_table TYPE dd02l-tabname obligatory.
 PARAMETERS: p_file TYPE localfile DEFAULT 'c:\temp\test1.xls'.
TABLES: v_username.
DATA: BEGIN OF i_data OCCURS 0.
  INCLUDE STRUCTURE v_username.
DATA: END OF i_data.
START-OF-SELECTION.
  DATA:
        g_tablename TYPE tabname,
        g_filename TYPE localfile,
        g_itab_header TYPE REF TO DATA,
        g_itab_data TYPE REF TO DATA.
g_tablename = p_table.
g_filename = p_file.
* get table header
PERFORM f_get_tablestruc
              USING g_tablename
              CHANGING  g_itab_header.
* get table data
PERFORM f_extract_tabledata
              USING g_tablename
              CHANGING  g_itab_data.
* create and export data to excel file
PERFORM f_export_to_excel
              USING g_itab_header
                        g_itab_data
                        g_filename.
FORM f_get_tablestruc   USING VALUE(u_tabnam) TYPE tabname
                                       CHANGING c_itab TYPE REF TO DATA.
  DATA:
       v_delm TYPE C,
       str_ty TYPE REF TO cl_abap_structdescr,
        t_cm TYPE cl_abap_structdescr=>component_table,
        s_cm LIKE LINE OF t_cm,
        ref_cm TYPE REF TO DATA,
        f_seq TYPE n length 4,
        tabstr TYPE STANDARD TABLE OF s_tabstr.
  FIELD-SYMBOLS:
  <str> TYPE ANY,
  <cmp> TYPE ANY,
  <tabstr> LIKE LINE OF tabstr,
  <lab> TYPE STANDARD TABLE.
  CLEAR: f_seq, t_cm[].
  MOVE cl_abap_char_utilities=>horizontal_tab TO v_delm.
  SELECT fieldname as4local POSITION keyflag rollname datatype leng scrtext_s
  FROM dd03vt
  INTO TABLE tabstr
  WHERE tabname EQ u_tabnam AND ddlanguage EQ sy-langu.
  IF sy-subrc NE 0.
    MESSAGE e004(zasd1) WITH TEXT-e01 u_tabnam space space.
    STOP.
  ENDIF.
  SORT tabstr BY POSITION ASCENDING.
  LOOP AT tabstr ASSIGNING <cmp>.
    CLEAR s_cm.
    f_seq = f_seq + 1.
    CONCATENATE 'col' f_seq INTO s_cm-name.
    s_cm-type = cl_abap_elemdescr=>get_c( 30 ).
    APPEND s_cm TO t_cm.
  ENDLOOP.
  str_ty = cl_abap_structdescr=>create( t_cm ).
  CREATE DATA ref_cm TYPE handle str_ty.
  ASSIGN ref_cm->* TO <str>.
  CREATE DATA c_itab  LIKE STANDARD TABLE OF <str>.
  ASSIGN c_itab->* TO <lab>.
  CLEAR f_seq.
  DATA w_cl TYPE string.
  LOOP AT tabstr ASSIGNING <tabstr>.
    f_seq = f_seq + 1.
    CLEAR w_cl.
    CONCATENATE 'COL' f_seq INTO w_cl.
    ASSIGN COMPONENT w_cl OF STRUCTURE <str> TO <cmp>.
    <cmp> = <tabstr>-scrtext_s.
  ENDLOOP.
  APPEND <str> TO <lab>.
  CLEAR f_seq.
  LOOP AT tabstr ASSIGNING <tabstr>.
    f_seq = f_seq + 1.
    CLEAR w_cl.
    CONCATENATE 'COL' f_seq INTO w_cl.
    ASSIGN COMPONENT w_cl OF STRUCTURE <str> TO <cmp>.
    <cmp> = <tabstr>-fieldname.
  ENDLOOP.
  APPEND <str> TO <lab>.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
ENDFORM.
*
*
FORM f_extract_tabledata   USING VALUE(u_tabnam) TYPE tabname
                                       CHANGING c_itab TYPE REF TO DATA.
  DATA:
        w_file TYPE string,
        tabstr TYPE STANDARD TABLE OF s_tabstr.
  FIELD-symbols:
  <itab>   TYPE STANDARD TABLE.
  CREATE DATA c_itab TYPE STANDARD TABLE OF (u_tabnam).
  ASSIGN c_itab->* TO <itab>.
  SELECT *
  FROM (u_tabnam)
  INTO TABLE <itab>.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
ENDFORM.                    "f_down_proc
FORM f_export_to_excel USING u_itab_header TYPE REF TO DATA
                                             u_itab_data TYPE REF TO DATA
                                             u_filename TYPE localfile.
DATA: w_excel TYPE ole2_object,
      w_workbooks TYPE ole2_object,
      w_workbook TYPE ole2_object,
      w_cell TYPE ole2_object.
DATA: w_row TYPE I,
          w_col  TYPE I,
          type   TYPE C,
          count TYPE I.
  FIELD-SYMBOLS:
  <str> TYPE ANY,
  <cmp> TYPE ANY,
  <fs_itab_header> TYPE STANDARD TABLE,
  <fs_itab_data> TYPE STANDARD TABLE,
  <fs_itab_headrow> TYPE ANY,
  <fs_itab_datarow> TYPE ANY.
* Create OLE automation object of type Excel.Application.
CREATE OBJECT w_excel 'Excel.Application'.
* Add a new Excel Workbook.
CALL METHOD OF w_excel 'Workbooks' = w_workbooks.
CALL METHOD OF w_workbooks 'Add' = w_workbook.
* Display MS-Excel when executing the program.
SET PROPERTY OF w_excel 'Visible' = 1.
* Export title to the Excel sheet.
 ASSIGN u_itab_header->* TO <fs_itab_header>.
 FIELD-SYMBOLS:
  <fs_headrow> TYPE ANY.
w_row = 1.
LOOP AT <fs_itab_header> ASSIGNING <fs_itab_headrow>.
  w_col = 1.
  DESCRIBE FIELD <fs_itab_headrow> TYPE type COMPONENTS count.
  WHILE w_col <= count.
    ASSIGN COMPONENT w_col OF STRUCTURE <fs_itab_headrow> TO <cmp>.
    CALL METHOD OF w_excel 'Cells' = w_cell
       EXPORTING #1 = w_row  #2 = w_col.
    SET PROPERTY OF w_cell 'Value' = <cmp>.
    w_col = w_col + 1.
  ENDWHILE.
  w_row = w_row + 1.
ENDLOOP.
* Export data to the Excel sheet.
 ASSIGN u_itab_data->* TO <fs_itab_data>.
LOOP AT <fs_itab_data> ASSIGNING <fs_itab_datarow>.
  w_col = 1.
  DESCRIBE FIELD <fs_itab_headrow> TYPE type COMPONENTS count.
  WHILE w_col <= count.
    ASSIGN COMPONENT w_col OF STRUCTURE <fs_itab_datarow> TO <cmp>.
    CALL METHOD OF w_excel 'Cells' = w_cell
       EXPORTING #1 = w_row  #2 = w_col.
    SET PROPERTY OF w_cell 'Value' = <cmp>.
    w_col = w_col + 1.
  ENDWHILE.
  w_row = w_row + 1.
ENDLOOP.
* Save file.
CALL METHOD OF w_workbook 'SaveAs'
EXPORTING #1 = u_filename
  #6 = 1.
* Quit Excel.
CALL METHOD OF w_excel 'Quit'.
FREE OBJECT: w_excel,
w_workbooks,
w_workbook,
w_cell.
ENDFORM.

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

このトピックでは、PDFファイル出力の方法を取り上げて説明します。 (このトピックは編集中です。)

*スプール情報をPDFに変換 
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF' 
EXPORTING 
 SRC_SPOOLID = '9999' “スプール番号 
 NO_DIALOG = ' ' 
IMPORTING 
 PDF_BYTECOUNT = WK_SIZE “ファイルサイズ 
TABLES 
 PDF = PDFTAB “PDFデータ 
EXCEPTIONS 
 ERR_NO_ABAP_SPOOLJOB = 1 
 ERR_NO_SPOOLJOB = 2 
 ERR_NO_PERMISSION = 3 
 ERR_CONV_NOT_POSSIBLE = 4 
 ERR_BAD_DESTDEVICE = 5 
 USER_CANCELLED = 6 
 ERR_SPOOLERROR = 7 
 ERR_TEMSEERROR = 8 
 ERR_BTCJOB_OPEN_FAILED = 9 
 ERR_BTCJOB_SUBMIT_FAILED = 10 
 ERR_BTCJOB_CLOSE_FAILED = 11 
 OTHERS = 12.

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

このトピックでは、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.

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

このトピックでは、サーバ側にファイル入出力の方法を取り上げて説明します。

サーバ側でファイル入出力処理を実装するには、事前に論理パスを定義する必要があります。

格納テーブル

論理パス及び物理パスへのマッピングの定義は、以下二つのテーブルに格納されます。

  • FILEPATH
    論理パスの定義
  • PATH
    論理パスの物理パスの定義

トランザクション

論理パスの作成及び物理パスの定義は、FILEトランザクションを利用します。

入力パラメータの実装

選択画面でユーザに論理パスを指定できるようにするには、以下のようにパラメータを定義します。

  p_filpth   TYPE filepath-pathintern OBLIGATORY. 

汎用モジュール

論理パスに関わる汎用モジュールは主に以下のものがあります。

  • FILE_GET_NAME_USING_PATH
    ファイル名と論理パスで完全ファイル名を生成する

ABAPにはファイルを操作するための命令が幾つか用意されております。

ファイルのオープン

アプリケーションサーバ上のファイルをオープンするには、OPEN DATASET命令を使用します。

外部リンク:ファイルのオープン- SAP Help Portal

ファイルの読み取り

アプリケーションサーバ上のファイルを読み取りするには、READ DATASET命令を使用します。

外部リンク:ファイルからのデータの読込 - SAP Help Portal

ファイルの書き込み

アプリケーションサーバ上のファイルを書き込みするには、TRANSFER命令を使用します。

外部リンク:ファイルへのデータの書込- SAP Help Portal

ファイルのクローズ

アプリケーションサーバ上のファイルをクローズするには、CLOSE DATASET命令を使用します。

外部リンク:ファイルのクローズ- SAP Help Portal

ファイルの削除

アプリケーションサーバ上のファイルを削除するには、DELETE DATASET命令を以下のように使用します。

外部リンク:ファイルの削除 - SAP Help Portal

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

業務アプリケーションでは、データベースを更新する際にデータの整合性を保つ必要があります。そこで重要なのが、次の二つです。

  • トランザクション制御
  • 排他制御

トランザクションとは、「ある意味をもった一連の処理のまとまり」のことで、完全に実行するか、またはまったく実行しないようにする必要がある原子性や、実行前後とも常にデータの整合性をを保持しなければならない一貫性という性質をもっております。

普通の意味では、アプリケーションの動作のうち、「ある意味を持った一連の処理のまとまり」のことをトランザクションといいます。そして、トランザクション制御とはこの一つのトランザクション内でデータの整合性が保たれるようにすることです。

SAP ERPでは、正式的な名称として、この「ある意味を持った一連の処理のまとまり」を「トランザクション」ではなく、「作業論理単位(Logical Unit of Work、略するとLUW)」と呼んでいます。関連がありますが、SAPの「トランザクション」は、トランザクションコードを使用して開始するアプリケーションプログラムのことと定義されています。

SAPでは、作業論理単位(LUW)はデータベース作業論理単位(DB LUW)とSAP作業論理単位(SAP LUW)と2種類が存在していますので、次にそれぞれ説明します。

DB LUW

データベース作業論理単位(DB LUW)

DB LUW は、データが常に整合性を持つようにするために、OracleやMSSQLなどのDBMS(データベース管理システム)が使用するメカニズムです。DBMS側では、一般的にこのDB LUWを「トランザクション」と呼んでいます。

SAPのDB LUWは、以下のように動作します。

  • DB LUWは一つのワークプロセスの中に完結しなければなりません
  • ワークプロセスが正常又は異常終了する際に、コミットされていないDB更新に対して、暗黙的なデータベースコミット又はロールバックを行います
  • プログラムが汎用モジュール DB_COMMITを呼び出して明示的にデータベースコミットを行うことができます。
  • プログラムがSAP LUWの命令(COMMIT WORK、ROLLBACK WORK)を呼び出してSAP LUWを終了する同時に、データベースLUWも終了します。
  • 開始されるときや、前のDB LUW がコミット又はロールバックで終了するときに、新しいDB LUWが開始される
  • DB LUW内で実行されるデータベース変更はデータベースロックを起こします、そのデータベースロックはLUWの終了に伴い、自動的に解放されます。

SAP LUW

SAP作業論理単位(SAP LUW)

DB LUWはデータベースに対して分割できない連続したデータ上の操作であり、完全に終了するか、まったく実行しないかのいずれかにする必要があります。SAP LUWは、システムに対して分割できない業務処理であり、その業務処理全体を完了するか、あるいはまったく実行しないかのいずれかにする必要があります。SAP-LUW は通常、複数のダイアログステップや複数のDB LUW に及ぶことがあります。 同じSAP LUW で発生したDBデータ変更要求は、全て最後にデータベースに反映されることになります。

SAP LUWの終了

SAP LUWは、DB LUWのように暗黙的に終了することがありません。「COMMIT WORK」や「ROLLBACK WORK」命令を発行して、明示的に終了させる必要があります。

SAP LUWの原子性

一つのSAP LUWの中の各更新は複数のダイアログステップに跨って発行されることがよくありますが、発行時に即時に実行されるとすれば、別々のDB LUWのDBデータ操作になりますので、トランザクションとしての原子性が完全に崩れてしまうことになります。

SAPは、それらの更新を即時実行せずに、「更新依頼」オブジェクトを登録しておきます。「commit work」命令でSAP LUWがコミットされる際に、登録された「更新依頼」を一つのデータベースLUWで実行することにより、トランザクションとしての原子性を維持します。

但し、下記「エラー処理とデータの整合性」節で説明するように、各更新依頼の種類により完全な原子性が出来ない場合も存在します。

SAP LUWとDB LUW

SAPはワークプロセスごとに、固定データベース接続1 つが割り当てられています。そのデータベース接続でデータベースLUWが実行されますので、ワークプロセスは常に一つのDB LUWと結び付いております。

一方、SAP LUWは論理的な単位を提供しています、SAP LUWにおける各更新依頼は、結局、DB LUWによりデータの変更をデータベースに反映しないといけないですが、そのDB LUWは新たに生成されるものではなく、更新依頼が実行されるワークプロセスの固有のDB LUWとなります。そのDB LUWで発行された別の即時DB更新がもしあれば、同時にコミットされます、なお、エラーが発生する場合も、一緒にロールバックされることになります。

 

SAP LUWの単位

SAP LUW毎に、違う更新キーが割り当てられます、更新依頼はその更新キーと一緒に更新キューに登録されますので、それにより同じSAP LUWのものかどうかを判断できます。

アプリケーションプログラム( TYPE 1、TYPE M)はそれぞれ別のSAP LUWをもっています。但し、トランザクション( 機能)ではなく、「ダイアログモジュール」として起動される場合は、呼び出し元のアプリケーションプログラムのSAP LUWで実行されることになります。

更新依頼の種類と同期化制御

  あとから実行するように登録される更新依頼は、下記のように幾つかの種類が存在します。種類によって、処理が実行されるワークプロセスと同期・非同期の制御などが変ります。 

(1)サブルーチン更新依頼

PERMFORM <サブルーチン名>命令でON COMMITオプションを付けておければ、そのサブルーチンは即時に実行されることがありません、代わりに更新依頼として登録されます。

そのサブルーチン処理は、SAP LUWがcommit work命令でコミットされる際に、COMMIT WORK 命令と同じデータベース LUW の中で、同じワークプロセスによってインラインで実行されます。

同じワークプロセスなので、COMMIT WORK命令はすべてのサブルーチン更新依頼が処理完了するまでブロックされ、つまり同期化になります。

(2)汎用モジュール更新依頼

CALL <汎用モジュール>命令でIN UPDATE TASKオプションを付けておければ、その汎用モジュールは即時に実行されることがありません、その代わりに更新依頼として、汎用モジュール名とそのインタフェースパラメータがVBLOG という名称の特別なデータベーステーブルに格納されます。

その汎用モジュール処理は、SAP LUWがcommit work命令でコミットされる際に、更新プログラムにより実行されます。

デフォルトは、更新プログラムはcommit work命令が発行されたワークプロセスと別に、更新プロセスと呼ばれているバックグラウンドワークプロセスで非同期に処理を実行します。よってcommit work命令は待たずに、すぐ次の処理に入ることになります。

なお、下記のような場合、汎用モジュール更新依頼の実行はcommit work命令と同期になります。

①commit work命令にand waitオプションを付ける 更新プロセスで実行されるままですが、commit work命令は、全ての汎用モジュール更新依頼が処理完了するまでブロックされますので、同期になります。

②SET UPDATE TASK LOCAL

SET UPDATE TASK LOCALでローカル更新スイッチをONに指定された場合、更新プログラムは更新プロセスではなく、perfom … on commitのように、commit workと同じワークプロセスで実行されることになります。

更新用の汎用モジュールはU1(優先順位が高い)とU2(優先順位が低い)との2種類に分けられ、作成時に属性として指定することができます。更新プロセスで実行される時も別々のワークプロセスで実行されることになります。

(3) バックグラウンド更新依頼

CALL <汎用モジュール>命令でIN BACKGROUND TASKオプションを付けておければ、その汎用モジュールは即時に実行されることがありません、その代わりに更新依頼として登録されます。  

その汎用モジュール処理は、SAP LUWがcommit work命令でコミットされる際に、commit work命令が発行されたワークプロセスと別に、バックグラウンドプロセスと呼ばれているワークプロセスで非同期に処理を実行されます。

下記のイメージ図で示されるように、同じSAP LUWの各更新依頼は、(1)→(2)のU1→(2)のU2→(3)の前後順で処理されます。

更新マネージャ「トランザクションコード:SM13」を使えば、更新依頼の処理状況を照会したり、エラーで中止された更新を再実行させたりすることができます。

エラー処理とデータの整合性 

SAP LUWにおける各更新は、実行時エラーによっていずれかが失敗した場合、更新システムは下記のように処理します。

(1)FORM ルーチン内( PERFORM ON COMMIT で呼び出し)

-現在の更新トランザクションですでに実行された更新はロールバックされます。

-他の FORM ルーチンは開始されません。

-更新タスクまたはバックグラウンドタスク機能が開始されることはありません。

-エラーメッセージが画面に表示されます。

(2)V1 更新タスク汎用モジュール内( IN UPDATE TASK を依頼)

- V1 機能ですでに実行された更新はロールバックされます。

-更新タスクの依頼 (V1 または V2) はすべて取り消されます。

-バックグラウンドタスク依頼もすべて取り消されます。

- PERFORM ON COMMIT によって呼び出された サブルーチンですでに実行された更新は、ロールバック されません。

-エラーメッセージを送るようにシステム設定されている場合は、エラーメッセージが画面に表示されます。

(3)V2 更新タスク汎用モジュール内( IN UPDATE TASK を依頼)

-現在の V2 機能ですでに実行された更新はロールバックされません。

-まだ実行しなければならない更新タスク依頼 (V2) はすべて実行します。

-まだ実行しなければならないバックグラウンドタスク依頼はすべて実行します。

-V1 または V2 機能ですでに実行された更新はロールバックされません。

-サブルーチン( ON COMMIT で呼び出し)ですでに実行された更新はロールバックされません。

-エラーメッセージを送るようにシステム設定されている場合は、エラーメッセージが画面に表示されます。

(4)バックグラウンドタスク汎用モジュール内( IN BACKGROUND TASK DESTINATION を依頼)

-同一の DESTINATION のバックグラウンドタスク依頼はすべて取り消しされます 。

-すでに実行された他の更新はロールバックされません。

-エラーメッセージは画面に表示されません。

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

このトピックでは、OpenSQLによりDBデータを検索する方法を取り上げて説明します。

DBデータを検索するには、SELECT命令を使用します。SELECT命令は以下のような分類があります。

  • 「SELECT SINGLE」命令: 一行読込
  • 「SELECT・・・ENDSELECT」命令:一件ずつ複数行読込
  • 「SELECT INTO TABLE」命令:内部テーブルによる複数行一括読込
  • 「SELECT INTO TABLE PACKAGE SIZE ・・・ENDSELECT」命令:内部テーブルによる複数行分割読込
  • 「OPEN CURSOR FOR SELECT」命令: カーソルによる読込

SELECT SINGLE

構文:

SELECT SINGLE 項目 INTO wa  FROM テーブル名  ~.

この命令は、指定したデータベーステーブルから、指定した条件と一致するデータを1件のみ取得します。。INTO句の後ろでは、構造(wa)を指定する必要があります。

取得する事ができれば、システム項目「SY-SUBRC」には0が入ります。取得できたデータの件数(取得できていれば1)は、システム項目「SY-DBCNT」に格納されます。

SELECT...ENDSELECT

構文:

SELECT 項目 INTO wa  FROM テーブル名 ~.
処理内容
ENDSELECT.

この命令は、指定したデータベーステーブルから、指定した条件と一致するデータを1件ずつ取得します。条件と一致するデータがなくなるまで、「ENDSELECT.」の間をループします。NTO句の後ろでは、構造(wa)を指定する必要があります。

1件でもデータを取得する事ができれば、システム項目「SY-SUBRC」には0が入ります。取得できたデータの件数は、システム項目「SY-DBCNT」に格納されます。

SELECT INTO TABLE

構文:

SELECT 項目 INTO TABLE it  FROM テーブル名 ~.

この命令は、指定したデータベーステーブルから、指定した条件と一致するデータを一括で取得します。データをプログラム内で溜めて利用する事ができるのが特徴です。INTO句の後ろでは、内部テーブル(it)を指定する必要があります。

1件でもデータを取得する事ができれば、システム項目「SY-SUBRC」には0が入ります。取得できたデータの件数は、システム項目「SY-DBCNT」に格納されます。

SELECT INTO TABLE PACKAGE SIZE...ENDSELECT

構文:

SELECT 項目 INTO TABLE it. FROM テーブル名 PACKAGE SIZE 行数 ~.
処理内容
LOOP  AT it into  wa.
処理内容
ENDLOOP.
処理内容
ENDSELECT.

この命令は、指定したデータベーステーブルから、指定した条件と一致するデータを、PACKAGE SIZEで指定された行数単位で、複数のパッケージに分けて内部テーブルに読み込みます。

読み込むパッケージがなくなるまで、SELECT~ENDSELECTの間をループします。なお、内部テーブルには常に、いま読み込まれたパッケージの行のみが格納されます。(INTOの代わりにAPPENDINGキーワードを使えば、内部テーブルには各パッケージの行がどんどん溜まっていくことになります)

OPEN CURSOR FOR SELECT

構文:

OPEN CURSOR c FOR  SELECT  項目 FROM テーブル名 ~.
DO.
FETCH NEXT CURSOR c INTO  wa.
処理内容
ENDDO.
CLOSE CURSOR  c

WHERE句

全ての命令のSQL文ではWHERE句を記述することが可能です。

「SELECT SINGLE」命令では、WHERE句でプライマリキーが特定できない場合に警告が出力されます。

ORDERBY句

下記のように「○」が付いている命令のSQL文では、ORDERBY句を記述することが可能です。

  • 「SELECT SINGLE」:×
  • 「SELECT・・・ENDSELECT」:○
  • 「SELECT INTO TABLE」:○
  • 「SELECT INTO TABLE PACKAGE SIZE ・・・ENDSELECT」:○
  • 「OPEN CURSOR FOR SELECT」:○

      

結合検索

全ての命令のSQL文では下記のような結合検索を記述することが可能です。

  • INNER 別テーブル名 ON 結合条件
  • LEFT OUTER JOIN 別テーブル名 ON 結合条件

集計問い合わせ

全ての命令では、下記の集計関数や句を含める集計問い合わせを記述することが可能です。

  • COUNT
  • SUM
  • AVG
  • MAX
  • MIN
  • GROUPBY句
  • HAVING句

DISTINCT

下記のように「○」が付いている命令のSQL文では、DISTINCTを記述することが可能です。

  • 「SELECT SINGLE」:×
  • 「SELECT・・・ENDSELECT」:○
  • 「SELECT INTO TABLE」:○
  • 「SELECT INTO TABLE PACKAGE SIZE ・・・ENDSELECT」:○
  • 「OPEN CURSOR FOR SELECT」:○

読み取る行数を制御

下記のように「○」が付いている命令のSQL文では、[UP TO <n> ROWS]オプションで読み込まれる行数を制限することが可能です。

  • 「SELECT SINGLE」:×
  • 「SELECT・・・ENDSELECT」:○
  • 「SELECT INTO TABLE」:○
  • 「SELECT INTO TABLE PACKAGE SIZE ・・・ENDSELECT」:○
  • 「OPEN CURSOR FOR SELECT」:○

テーブル条件

SELECT 命令の WHERE 句には特殊バリアントがあり、内部テーブルの行および列から条件を導くことができます。

SELECT ...FOR ALL ENTRIES IN <itab> WHERE <cond> ...

<cond> は前述の方法で指定します。内部テーブル <itab> の項目を、条件のオペランドとして指定する場合は、内部テーブルのすべての行をアドレス指定します。その後で、内部テーブルの各行に対して比較が実行されます。各行に対して、条件を満たすデータベーステーブルからの行を選択します。SELECT 命令の結果セットは、内部テーブルの各行に対する個々の選択を結合したものです。重複する行は自動的に結果セットから除外されます。<itab> が空白の場合、オプション FOR ALL ENTRIES が無視され、すべてのエントリが読み込まれます。

内部テーブル <itab> には構造化された行データ型が必要であり、条件 <cond> に登場する各項目は、比較対象のデータベースの列と互換性がなければなりません。内部テーブル項目を使用する比較では、演算子 LIKE 、BETWEEN 、IN を使用しないでください。同じ SELECT 命令では ORDER BY 句を使用しません。

オプション FOR ALL ENTRIES を使用して、ネストされた選択ループを内部テーブルでの操作で置き換えます。これにより、選択したデータの多数のセットに対するパフォーマンスが大幅に向上します。

WHERE句での選択テーブルの使用

WHERE 句で選択テーブルを使用するには、次のように記述します。

......... WHERE <f> IN <seltab>.

<f> はデータベース列の名前で、<seltab> はその項目に割り当てられた選択テーブルです。このように WHERE 句を指定した OPEN SQL 命令は、データベーステーブルの列のうち、項目<f> の内容が <seltab> に格納されている選択基準に合致しているものだけにアクセスします。

REPORT DEMO.
DATA WA_CARRID TYPE SPFLI-CARRID.
SELECT-OPTIONS AIRLINE FOR WA_CARRID.
SELECT CARRID FROM SPFLI INTO WA_CARRID WHERE CARRID IN AIRLINE.
   WRITE WA_CARRID.
ENDSELECT.

選択テーブル AIRLINE はデータベーステーブル SPFLI の CARRID 列にリンクされています。SELECT 命令の WHERE 句により、CARRID 列の内容が AIRLINE に格納された選択基準を満たしているかどうかがチェックされます。

選択テーブルが次のように入力されているとします

SIGNOPTIONLOWHIGH
IBTDLUA
EEQLH-

WHERE句でのRANGES テーブルの使用

RANGES テーブルは選択テーブルと同じデータ型を持ちますが、選択画面の入力項目にリンクされていません。

   下記のように目的に応じて各命令を使い分けることができます。

  • 最大1件のみを取得する場合は「SELECT SINGLE」命令を使います。
  • 複数件を取得し、且つ取得可能な件数が必ず一定の範囲に収まる場合は「SELECT INTO TABLE」命令を使います。
  • 複数件を取得し、取得可能な件数は一定ではない場合は、基本的に「SELECT INTO TABLE PACKAGE SIZE ・・・ENDSELECT」命令を使います。
  • 複数件を取得し、前の行の値によって次の行を取得するかどうかを判断する必要な場合は、「OPEN CURSOR FOR SELECT」命令を使います。
  • 「SELECT・・・ENDSELECT」命令は、基本的に使いません。

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

SAP ECCシステムでは、数量はすべて数量単位と結びつけられます。

基本的な単位処理

単位は長さや広さなどの次元を元に管理されます。同じ次元の単位はシステムテーブルに定義された換算係数を元に換算することができます。なお、次元なしの単位も存在します。

SI単位取得

SI単位を取得するには、汎用モジュールSI_UNIT_GET(ステータス:リリース)を使用することができます。 単位と次元のどちらかをパラメータとして指定可能です。

次元取得又はチェック

次元の取得又はチェックするには、以下の汎用モジュールを使用することができます。

  • DIMENSION_CHECK
    内部測定単位が指定された次元に対応しているかどうかをチェックします。
  • DIMENSION_GET_FOR_UNIT
    内部測定単位の次元を取得します。
  • UNIT_CORRESPONDENCE_CHECK 
    2つの単位が同じ次元に属するかどうかをチェックします。

換算係数取得

単位間の換算係数は、元情報がT006に定義されており、精度を維持するため、分子・分母により表現されます。 例えばインチとメトルの換算係数は、1平方インチ=(0.0254×0.0254=0.00064516)=125/193,752平米のように、分子125と分母193752で定義されています。

単位の換算係数を取得するには、汎用モジュールCONVERSION_FACTOR_GET(ステータス:リリース)を使用することができます。 変換には以下の式が使用されます。 (単位 UNIT_OUT の値) = (単位 UNIT_IN の値) *分子/分母 + 追加定数

REPORT  Y_UNIT_TEST1.
DATA: UNIT_1  LIKE T006-MSEHI,
      UNIT_2  LIKE T006-MSEHI,
      VAR1    TYPE F,
      ZAEHL   TYPE F,
      NENNR   TYPE F,
      ANDEC   LIKE T006-ANDEC,
      DIMID   LIKE T006-DIMID.
UNIT_1 = 'IN2'.
UNIT_2 = 'M2'.
CALL FUNCTION 'CONVERSION_FACTOR_GET'
    EXPORTING
       UNIT_IN      = UNIT_1
       UNIT_OUT     = UNIT_2
*NO_TYP_CHECK = ' '
    IMPORTING
      ADD_CONST   = VAR1
      NUMERATOR   = ZAEHL
      DENOMINATOR = NENNR
      DECIMALS    = ANDEC
      DIMENSION   = DIMID
    EXCEPTIONS
      CONVERSION_NOT_FOUND    = 01
      OVERFLOW                = 02
      TYPE_INVALID            = 03
      UNITS_MISSING           = 04
      UNIT_IN_NOT_FOUND       = 05
      UNIT_OUT_NOT_FOUND      = 06.
WRITE :/ '平方インチから平米へ変換'.
WRITE :/ ' 次元キー:', DIMID.
WRITE :/ ' 変換係数(分子):',ZAEHL DECIMALS 0  EXPONENT  0.
WRITE :/ ' 変換係数(分母):',NENNR DECIMALS 0  EXPONENT  0.
WRITE :/ ' 追加定数:', VAR1 DECIMALS 0  EXPONENT  0.

数量換算

異なる単位間の数量換算を行うには、以下の汎用モジュールを使用することができます。

  • UNIT_CONVERSION_WITH_FACTOR(ステータス:リリース)
    換算係数はパラメータにより指定されます。
  • UNIT_CONVERSION_SIMPLE(ステータス:リリース)
    換算係数はシステムテーブルT006から自動的に取得されます。

内部表現⇔外部表現変換

単位の内部表現と外部表現を変換するには、以下の汎用モジュールを使用することができます。

  • CONVERSION_EXIT_CUNIT_INPUT
    商用測定単位(3文字の外部測定単位)に対応する内部測定単位を取得します
  • CONVERSION_EXIT_CUNIT_OUTPUT
    内部測定単位に対応する商用測定単位(3文字の外部測定単位)を取得します
  • CONVERSION_EXIT_LUNIT_INPUT
    技術測定単位(6文字の外部測定単位)に対応する内部測定単位を取得します
  • CONVERSION_EXIT_LUNIT_OUTPUT
    内部測定単位に対応する技術測定単位(6文字の外部測定単位)を取得します

SAP単位⇔ISO単位変換

SAP単位とISO単位変換を変換するには、以下の汎用モジュールを使用することができます。

  • UNIT_OF_MEASURE_ISO_TO_SAP
    ISO単位からSAP単位を取得します
  • UNIT_OF_MEASURE_SAP_TO_ISO
    SAP単位からISO単位を取得します

品目は、品目固有の単位換算数式を品目マスタ画面で入力管理することができます。その情報を元に、品目の単位換算を行う汎用モジュールは標準から用意されております。

基本数量単位への変換

「基本数量単位への変換」を行なうには、汎用モジュール「MATERIAL_UNIT_CONVERSION」を使用します。

CALL FUNCTION 'MATERIAL_UNIT_CONVERSION'
	EXPORTING
		MATNR = vl_matnr     	 "品目
 		INPUT =  vl_source_value "変換数量
		MEINH = vl_source_meinf	 "変換前数量単位
 	IMPORTING
 		OUTPUT = vl_target_value "変換後数量
  	EXCEPTIONS
 		OTHERS = 1.

数量単位間の変換

「基本単位に限らない二つの単位間の変換」をなうには、汎用モジュール「MD_CONVERT_MATERIAL_UNIT」を使用します。

CALL FUNCTION 'MD_CONVERT_MATERIAL_UNIT'
  EXPORTING
    i_matnr      = vl_matnr         "品目
    i_in_me      = vl_source_unit   "変換前単位
    i_out_me     = vl_target_unit   "変換後単位
    i_menge      = vl_source_value  "変換前数量
  IMPORTING
    e_menge      = vl_target_value  "変換後数量
  EXCEPTIONS
    OTHERS       = 1.

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

ABAPにおける金額項目は常に特定の通貨と結び付けられています。異なる通貨の金額換算や、内部書式と外部書式間の変換など、SAP標準から様々な汎用モジュールを用意されています。 このトピックでは、金額処理に関わる様々な方法を目的毎に纏めて説明します。

通貨換算係数取得

CURRENCY_CONVERTING_FACTOR

通貨換算係数を取得する関数。

DATA: WK_WAERS TYPE VBRK-WAERK. 
DATA: WK_FACTOR TYPE P DECIMALS 3.
CALL FUNCTION 'CURRENCY_CONVERTING_FACTOR'  
EXPORTING   
 CURRENCY = WK_WAERS “ 通貨コード  
IMPORTING   
 FACTOR = WK_FACTOR ” 通貨換算係数  
EXCEPTIONS   
 TOO_MANY_DECIMALS = 1   
 OTHERS = 2.

為替レート換算係数取得

READ_EXCHANGE_RATE

為替レート取得

READ_EXCHANGE_RATE

外貨通貨→国内通貨

外貨通貨金額から国内通貨金額を換算するには、汎用モジュールCONVERT_TO_LOCAL_CURRENCYを利用できます。

REPORT  Y_TEST_XXXX.
DATA:
      F_CURR       TYPE TCURR-FCURR,
      L_CURR       TYPE TCURR-TCURR,
      F_VALUE      TYPE P LENGTH 8 DECIMALS 2,
      L_VALUE      TYPE P LENGTH 8 DECIMALS 2,
      EX_RATE      TYPE TCURR-UKURS,
      F_FACTOR     TYPE TCURR-FFACT,
      L_FACTOR     TYPE TCURR-TFACT.
F_CURR  = 'JPY'.
L_CURR  = 'THB'.
F_VALUE = '0.02'.
CALL FUNCTION 'CONVERT_TO_LOCAL_CURRENCY'
  EXPORTING
*   CLIENT           = SY-MANDT
    DATE             = SY-DATUM  "為替レート自動取得時の基準日
    FOREIGN_AMOUNT   = F_VALUE   "外貨通貨金額
    FOREIGN_CURRENCY = F_CURR    "外貨通貨
    LOCAL_CURRENCY   = L_CURR    "国内通貨
*    RATE            = '29.36'   "為替レートを指定する場合は、このパラメータを利用すると
                                 "ともにREAD_TCURRを''にする
    TYPE_OF_RATE     = 'B'       "為替レートタイプ B:
    READ_TCURR       = 'X'       "'X':為替レートはTCURRより取得、'':為替レートは
                                 "RATEパラメータの値を使用
  IMPORTING
    EXCHANGE_RATE       = EX_RATE   "換算時の為替レート
    FOREIGN_FACTOR      = F_FACTOR  "換算時の換算係数(外貨)
    LOCAL_AMOUNT        = L_VALUE   "換算後国内通貨金額
    LOCAL_FACTOR        = L_FACTOR  "換算時の換算係数(国内通貨)
*   EXCHANGE_RATEX          =
*   FIXED_RATE              =
*   DERIVED_RATE_TYPE       =
* EXCEPTIONS
*   NO_RATE_FOUND           = 1
*   OVERFLOW                = 2
*   NO_FACTORS_FOUND        = 3
*   NO_SPREAD_FOUND         = 4
*   DERIVED_2_TIMES         = 5
*   OTHERS                  = 6
   .
IF SY-SUBRC <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*         WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
WRITE:/'FOREIGN CURRENCY=', F_CURR,
      /'FOREIGN_FACTOR=', F_FACTOR,
      /'FOREIGN VALUE=', F_VALUE,
      /'EXCHANGE_RATE=', EX_RATE,
      /'LOCAL CURRENCY=', L_CURR,
      /'LOCAL_FACTOR=', L_FACTOR,
      /'LOCAL VALUE=',  L_VALUE.
WRITE:/ F_CURR,F_VALUE  CURRENCY F_CURR.
WRITE:/ L_CURR,L_VALUE  CURRENCY L_CURR.

国内通貨→外貨通貨

CONVERT_TO_FOREIGN_CURRENCY 国内通貨額の外貨への換算

REPORT  Y_TEST_XXXX.
DATA:
      F_CURR       TYPE TCURR-FCURR,
      L_CURR       TYPE TCURR-TCURR,
      F_VALUE      TYPE P LENGTH 8 DECIMALS 2,
      L_VALUE      TYPE P LENGTH 8 DECIMALS 2,
      EX_RATE      TYPE TCURR-UKURS,
      F_FACTOR     TYPE TCURR-FFACT,
      L_FACTOR     TYPE TCURR-TFACT.
F_CURR  = 'JPY'.
L_CURR  = 'THB'.
L_VALUE = '3'.
CALL FUNCTION 'CONVERT_TO_FOREIGN_CURRENCY'
  EXPORTING
*   CLIENT           = SY-MANDT
    DATE             = SY-DATUM  "為替レート自動取得時の基準日
    LOCAL_AMOUNT   = L_VALUE   "国内通貨金額
    FOREIGN_CURRENCY = F_CURR    "外貨通貨
    LOCAL_CURRENCY   = L_CURR    "国内通貨
*    RATE            = '0.07'   "為替レートを指定する場合は、このパラメータを利用すると
                                 "ともにREAD_TCURRを''にする
    TYPE_OF_RATE     = 'B'       "為替レートタイプ B:
    READ_TCURR       = 'X'       "'X':為替レートはTCURRより取得、'':為替レートは
                                 "RATEパラメータの値を使用
  IMPORTING
    EXCHANGE_RATE       = EX_RATE   "換算時の為替レート
    FOREIGN_FACTOR      = F_FACTOR  "換算時の換算係数(外貨)
    FOREIGN_AMOUNT     = F_VALUE   "換算後外貨金額
    LOCAL_FACTOR        = L_FACTOR  "換算時の換算係数(国内通貨)
*   EXCHANGE_RATEX          =
*   FIXED_RATE              =
*   DERIVED_RATE_TYPE       =
* EXCEPTIONS
*   NO_RATE_FOUND           = 1
*   OVERFLOW                = 2
*   NO_FACTORS_FOUND        = 3
*   NO_SPREAD_FOUND         = 4
*   DERIVED_2_TIMES         = 5
*   OTHERS                  = 6
   .
IF SY-SUBRC <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*         WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
WRITE:
      /'LOCAL CURRENCY=', L_CURR,
      /'LOCAL_FACTOR=', L_FACTOR,
      /'LOCAL VALUE=',  L_VALUE,
      /'FOREIGN CURRENCY=', F_CURR,
      /'FOREIGN_FACTOR=', F_FACTOR,
      /'FOREIGN VALUE=', F_VALUE,
      /'EXCHANGE_RATE=', EX_RATE
      .
WRITE:/ L_CURR,L_VALUE  CURRENCY L_CURR.
WRITE:/ F_CURR,F_VALUE  CURRENCY F_CURR.

任意通貨間の換算

任意通貨間の換算に関しては、標準から以下二つの汎用モジュールが提供されていますが、

  • CONVERT_FOREIGN_TO_FOREIGN_CUR 外貨金額の別外貨通貨への換算
  • CONVERT_CURRENCY_BY_RATE 与えられたレートを使用した通貨の変換

いずれも未リリースの属性状態であり、正しく動作しないようです。

SAPシステムでは、多通貨が混在しているため、実際に内部管理された金額値は、通貨毎にそれぞれ異なります。例えば、JPYの通貨型項目は通常本来の値の1/100で内部格納されています。 そのため、金額を入出力する際に、内部⇔外部の間に都度書式を変換する必要があります。

外部書式→内部書式変換

汎用モジュール利用

 
CALL FUNCTION 'BAPI_CURRENCY_CONV_TO_INTERNAL' 
EXPORTING 
currency = 'JPY' 
amount_external = l_external_amount 
max_number_of_digits = 15 
IMPORTING 
amount_internal = l_internal_amount. 

内部書式→外部書式変換

汎用モジュール利用

 
CALL FUNCTION 'BAPI_CURRENCY_CONV_TO_EXTERNAL' 
EXPORTING 
currency = 'JPY' 
amount_internal = l_internal_amount 
IMPORTING 
amount_external = l_external_amount.

命令利用

WRITE XXX TO XXX 'JPY' 

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

このトピックでは、ABAPにおける日付の処理方法を纏めて説明します。

 

日付項目は文字型であり、数値型ではありません。但し、ABAPでは自動的にデータ型変換が実行されるため、日付項目でも数値演算を行うことができます。 なお、SAP標準から様々な日付を計算するための汎用モジュールが用意されているため、それらを利用することもできます。

日付の加減算を行う

指定された日付より何日前又は、何日後の日付を計算するには、日付項目と数値項目の加減算により簡単に実現できます。

DATA:
  W_DATE        TYPE D,
  W_3DAY_BEFORE TYPE D,
  W_5DAY_AFTER  TYPE D.
W_DATE = SY-DATUM.
W_DATE+6(2) = '01'.

日単位だけではなく、月又は年単位で日付の加減算を行うには、汎用モジュールRP_CALC_DATE_IN_INTERVALE(ステータス:未リリース)を使用することができます。

 DATA: l_date TYPE d VALUE '20161201'.
 DO 2 times.
   CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
    EXPORTING
      date       = l_date
       days       = 0
       months     = 1
       signum     = '+'
       years      = 0
    IMPORTING
       calc_date = l_date.
   WRITE: / l_date.
 ENDDO.

月初や月末日付を取得

指定された日付の月初や月末日付を取得するには、汎用モジュールHR_JP_MONTH_BEGIN_END_DATE(ステータス:未リリース)を使用することができます。

DATA:
  W_DATE               TYPE   D,
  W_MONTH_FIRST_DATE   TYPE   D,
  W_MONTH_LAST_DATE    TYPE   D.
W_DATE = SY-DATUM.
CALL FUNCTION 'HR_JP_MONTH_BEGIN_END_DATE'
EXPORTING
  IV_DATE = W_DATE
IMPORTING
  EV_MONTH_BEGIN_DATE = W_MONTH_FIRST_DATE
  EV_MONTH_END_DATE   = W_MONTH_LAST_DATE.

月初日付だけを取得する場合では、汎用モジュールよりも、日付を文字列としてDAYの部分を'01'に置き換えることで簡単に実現できます。 なお、月末日だけを取得する場合では、汎用モジュールLAST_DAY_OF_MONTHS(ステータス:未リリース)を利用することも可能です。

DATA:
  W_DATE   TYPE D.
W_DATE = SY-DATUM.
W_DATE+6(2) = '01'.

週を取得

指定された日付がその年の1月1日から数えて何週目かを判断するには、汎用モジュール「DATE_GET_WEEK」を使用できます。 その何週目の情報は、年・週(yyyyww)の形式で汎用モジュールから返却されます。

DATA: 
  W_DATE TYPE SCAL-DATE,
  W_WEEK TYPE SCAL-WEEK.
WK_DATE = SY-DATUM.
CALL FUNCTION 'DATE_GET_WEEK'
EXPORTING
  DATE = W_DATE
IMPORTING
  WEEK = W_WEEK
EXCEPTIONS
  DATE_INVALID = 1
  OTHERS = 2.

週の初日を取得

汎用モジュールWEEK_GET_FIRST_DAY(ステータス:リリース)を使用すれば、年と週番号から、該当の週の月曜日の日付を取得することができます。

DATA: 
 DATUM LIKE SCAL-DATE,
 WOCHE LIKE SCAL-WEEK.
 WOCHE = '201521'. "2015年21週目
 CALL FUNCTION 'WEEK_GET_FIRST_DAY'
   EXPORTING 
     WEEK = WOCHE
   IMPORTING 
     DATE = DATUM  "2015/05/18が戻される
   EXCEPTIONS 
     WEEK_INVALID = 1.

日付の妥当性をチェック

  • DATE_CHECK_PLAUSIBILITY
    入力された日付が正しいかチェックする
  • DATE_COMPUTE_DAY
    日付に対して平日を戻す
  • DATE_CONVERT_TO_FACTORYDATE
    日付に対して稼働日カレンダを戻す
  • FACTORYDATE_CONVERT_TO_DATE
    稼働日のシリアル番号とカレンダーから日付を返す
  • BAPI_CCODE_GET_FIRSTDAY_PERIOD
    会計期間の初日を取得
  • BAPI_COMPANYCODE_GET_PERIOD
    会計年度と会計日付を取得
  • CONVERSION_EXIT_PDATE_OUTPUT
    日付型の内部書式を外部書式(YYYY/MM/DD)に変換
  • CONVERT_DATE_TO_INTERNAL
    日付の文字列をR/3内部表現に変換する

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

このトピックでは、ABAP言語で文字列処理の方法を取り上げて説明します。

文字列の長さを取得

文字列の長さを取得するには、関数STRLENを使用することができます。

例:

DATA : l_v(20) TYPE C,
       l_i     TYPE I.
l_v = 'ABCDEFG'.
l_i = STRLEN( l_v ). "変数に「7」が保持されることになる

全角半角チェック

文字列に全角文字や半角文字が入っていないかをチェックするには、以下の手順で行うことができます。

  • 汎用モジュールSTRING_LENGTHで文字列の表示長(全角:2、半角:1)を取得 
    このモジュールは、 CL_ABAP_LIST_UTILITIESクラスのDYNAMIC_OUTPUT_LENGTHメソッドを実行しています。
  • 関数STRLENで文字列の文字数を取得
  • 文字数と表示長を比較

文字列の内容検索

文字列の内容を検索するには、命令FINDを使用することができます。 オプションを使って、探したい値の開始位置を調べるときに使うことが多いです。

文字列のオフセット

文字列のオフセット処理は、ABAP言語固有の仕様に取り込まれています。 構文:文字列+開始位置(指定桁数)  ※開始位置は0から

例:

DATA: l_v TYPE string,
      l_r TYPE string.  
l_v = 'w,f,mj'.
l_r = l_v+2(2)."変数に「f,」が保持されることになる

文字列の置換

文字列の一部を他の文字列で置換するには、命令REPLACEを使用することができます。 構文: REPLACE <置換前> WITH <置換後> INTO <置換対象文字列>.

例:

DATA: l_v TYPE string.

l_v = 'w,f,mj'.
REPLACE ',' WITH ';' INTO l_v."変数に「w;f;mj」が保持されることになる

文字列の分割

一つの文字列を区切り文字の指定により複数の文字列に分割するには、命令SPLITを使用することができます。

例:


DATA: l_s1 TYPE string,
l_sx TYPE string.
DATA: lt_r TYPE TABLE CHAR10.
l_s1 = 'w,f,mj'.
l_sx = ','.
SPLIT l_s1 AT l_sx INTO TABLE lt_r.

  • 「lt_r」には、1行目に「w」2行目に「f」3行目に「mj」が保持されることになる

文字列のシフト

文字列を指定文字数分移動するには、命令SHIFTを使用することができます。 構文: SHIFT <移動対象文字列> [BY <移動文字数> PLACES] [モード].

例:

DATA: l_v TYPE string.
l_v = 'abcdefghij''.
SHIFT l_v BY 3 PLACES CIRCULAR. "変数に「defghijabc」が保持されることになる

文字列の結合

2つ以上の文字列を一つに結合するには、命令CONCATENATEを使用することができます。

例:


DATA: l_s1 TYPE string,
l_s2 TYPE string,
l_s TYPE string.
l_s1 = 'w'.
l_s2 = 'f'.
CONCATENATE l_s1 l_s2 INTO l_s SEPARATED BY space. "変数に「w f」が保持されることになる

空白の削除

文字列に入っている空白を削除するには、命令CONDENSE を使用することができます。

例:

DATA: l_v TYPE string.
l_v = 'a bf c d'.
CONDENCE l_v."変数に「a bf c d」が保持されることになる、文字列と文字列の間に一つの空白が残る 
CONDENCE l_v NO-GAPS."変数に「abfcd」が保持されることになる、すべての空白が削除される