SIT COBOLは、SIT COBOL専用エディタにおいてCOBOLプログラムを実行することができるが、COBOLプログラムを実行する方法はそれだけではなく、コマンドプロンプト上で、実行することもできる。
この章では、その方法について説明する。
[注意] > SIT COBOLを、コマンドで利用するには、有償ライセンスが必要となる。
最初に、コマンドプロンプトを起動する。起動のしかたは下記のとおりである。
SIT COBOLを起動するには、SIT
COBOLをセットアップしたフォルダ配下にある
‘sitcobol_bat.exe’を起動する。
例えば、SIT
COBOLをセットアップしたフォルダが、D:\sitcobol
にある場合は、次のようにして起動する。
(’\‘は、Windows上では’¥’記号なので注意のこと)
> d:\sitcobol\sitcobol_bat.exe --version
Smart Interpreter Training COBOL Ver11 1.6.0
>
ここで、‘--version’は、SIT
COBOLのバージョンを調べるオプションである。上記では、1.6.0
のバージョンのSIT
COBOLが起動していることがわかる。
sitcobol_bat.exeに指定できることのオプションは、下記のように、’--help’を指定する。
> d:\sitcobol\sitcobol_bat.exe --help
Usage: sitcobol_bat.py [xxx.cob(or xxx.cbl)]... [trace] [lang=[ja|en]] [no_progress]
[copy=dddd] ... [call_path=eeee] ...
[--help] [--version]
xxx.cob/xxx.cbl: COBOL Source Files
dddd: Copy Reference Folder. Multiple specifications are allowed.
eeee: Folder where subprograms exist. Multiple specification are allowd.
trace: Display Execution Lines
lang: Language ja: japanese(default) or en: English
no_progress: Do not display progress
--help: Display Help
--version: Display Version
>
xxx.cobまたはxxx.cblは、SIT COBOLが実行するプログラムを指定する。例えば、次のようなプログラムがあったとする。
D:\test\sample.cob:
000010 IDENTIFICATION DIVISION.
000020 PROGRAM-ID. SAMPLE01.
000030 PROCEDURE DIVISION.
000040 MAIN01.
000050 DISPLAY "HELLO WORLD".
000060 STOP RUN.
上記のプログラムは、sitcobol_bat.exeに、下記のようにプログラム名を指定すると実行される。
> d:\sitcobol\sitcobol_bat.exe d:\test\sample.cob
HELLO WORLD
>
もちろん、相対パス指定も可能である。例えばカレントフォルダを d:\sitcobolに移動して、次のように指定にしてもよい。
> cd d:\sitcobol
> .\sitcobol_bat.exe ..\test\sample.cob
HELLO WORLD
>
また、プログラムは同時に複数指定できる。このとき、プログラムは、指定された順に実行される。
例えば、次のようなプログラムを追加で作成したとする。
D:\test\sample2.cob:
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. SAMPLE02.
000300 PROCEDURE DIVISION.
000400 MAIN02.
000500 DISPLAY "WELCOME".
000600 STOP RUN.
sample.cobとsample2.cobを下記のように指定すると、それぞれの結果が順次出力される。
> d:\sitcobol\sitcobol_bat.exe d:\test\sample.cob d:\test\sample2.cob
HELLO WORLD
WELCOME
>
SIT COBOLは、インタープリタなので、このような動作をするが、通常のCOBOLコンパイラで、このように指定すると2つのプログラムからなる1つの実行形式(EXE)を作成するという指定になるので注意されたい。
traceを指定すると、実行した行が’>’と共に表示される。
> d:\sitcobol\sitcobol_bat.exe d:\test\sample.cob d:\test\sample2.cob trace
>000040 MAIN00.
>000050 display "HELLO WORLD".
HELLO WORLD
>000060 STOP RUN
>000400 MAIN00.
>000500 display "WELCOME".
WELCOME
>000600 STOP RUN
>
メッセージ等の出力の言語タイプを指定する。既定値は日本語(lang=ja)であるが、英語にする場合には、lang=enと指定する。
例えば、次のように存在しないプログラムを指定したときのエラーメッセージは次のようになる。
> d:\sitcobol\sitcobol_bat.exe no-exist-prog.cob
**[致命的] no-exist-prog.cobが見つからない
> d:\sitcobol\sitcobol_bat.exe no-exist-prog.cob lang=en
**[FATAL] no-exist-prog.cob is not found
>
SIT
COBOLは、インタープリタなので、プログラムは一度、中間言語に変換してから実行する。
プログラムがある程度大きくなると、中間言語に変換するのに時間がかかるので、中間言語変換中であることがわかるように次のようなプログレス状態が表示される。(複数行表示されているが、実際は直後の1行に順次表示される)
> \sitcobol\sitcobol_bat.exe long-program.cob
Ready o......... 10%
Ready oo........ 20%
Ready ooo....... 30%
:
Ready oooooooooo 100%
<実行結果>
この表示を不要とするのが、no_progressオプションである。
プログラムの実行結果をリダイレクトした場合に、このプログレス状態もリダイレクション先に出力されることがあり、それを防ぐような場合に指定する。
copyオプションは、登録集原文(コピー原文)の存在場所を指定するオプションである。
例えば、次のようなプログラムがあったとする。
d:\test\copy_test.cob
000010 IDENTIFICATION DIVISION.
000020 PROGRAM-ID. COPY_TEST.
000030 DATA DIVISION.
000040 COPY COPY001.
000050 PROCEDURE DIVISION.
000060 DISPLAY MESS1.
000070 STOP RUN.
d:\test\copy\copy001.cob
000010 01 MESS1 PIC X(20) VALUE "HELLO WORLD".
copy_text.cobが、COPY原文copy001.cobを参照できるようにするには、次のようにcopyオプションでフォルダを指定する。
> d:\sitcobol\sitcobol_bat.exe d:\test\copy_test.cob copy=d:\test\copy
HELLO WORRLD
>
copyオプションは複数個指定することができる。
また、SIT
COBOLが、コピー原文検索する順序は次のとおりである。
(*1)
カレントフォルダは、sitcobol_bat.exeに直接指定されたプログラムが存在するフォルダである。
上記の例では、‘d:\test’
がカレントディレクトリとなる。
call_pathオプションは、CALL文によって呼ばれるプログラムの検索場所を指定するオプションである。
例えば、次のようなプログラムがあったとする。
d:\test\call_test.cob
000010 IDENTIFICATION DIVISION.
000020 PROGRAM-ID. CALL_TEST.
000050 PROCEDURE DIVISION.
000060 CALL "subprog1".
000070 STOP RUN.
d:\others\subprog1.cob
000010 IDENTIFICATION DIVISION.
000020 PROGRAM-ID. SUBPROG1.
000050 PROCEDURE DIVISION.
000060 DISPLAY "HELLO WORLD".
000070 EXIT PROGRAM.
call_test.cobから、subprog1.cobを呼ぶことができるようにするには、次のようにcall_pathオプションを指定する。
> d:\sitcobol\sitcobol_bat.exe d:\test\call_test.cob call_path=d:\others
HELLO WORRLD
>
call_pathオプションは複数指定することができる。
また、SIT
COBOLが、CALLに指定されたプログラムを検索する順序は次のとおりである。
(*1) カレントフォルダは、sitcobol_bat.exeに直接指定されたプログラムが存在するフォルダである。
上記の例では、call_test.cobが存在するフォルダである’d:\test’
がカレントディレクトリとなる。また、CALL文が成功した際には、カレントディレクトリは、呼び出したプログラムが存在するフォルダとなる。すなわち、上記の例では、subprog1.cobが呼ばれたときは、’d:\others’がカレントディレクトリとなる。
さらに、制御がそのsubprog1.cobからcall_test.cobに戻ってきたときは、カレントディレクトリは、subprog1.cobを呼ぶ前の状態に戻る。
なお、SIT
COBOLの場合、CALLに指定するのは、PROGRAM-ID段落で指定されたプログラム名ではなく、COBOLプログラムのファイル名自身である。
すなわち、CALL
“ABC” と指定されていたときは、ファイル’ABC.cob’ , ‘ABC.cbl’
を検索するので注意されたい。
ここでは、バッチ処理の例として在庫管理システムの一部処理を見ていく。
商品(電化商品)の仕入れや販売といったトランザクションにより「在庫マスタ」にある在庫数を増減させていく例である。
まずは、本例で使用する商品マスタ、在庫マスタ、倉庫マスタ、顧客マスタ(いずれも索引ファイル)を作成する。入力はCSVファイルである。
商品マスタとは、1つ1つの商品(商品コード)について、商品名称、その他商品に関する属性をもつファイルである。
商品マスタのレコードは次のような構成になっているものとする。
レコードは便宜上、コピー原文「商品レコード.cob」として参照されるものとする。
主キーは、最初の「M商品コード」である。
000000 01 商品マスタレコード.
000010 COPY 商品レコード.
(商品レコード.cob)
000000 05 M商品コード PIC X(10). *> 商品コード(ユニーク)
000010 05 M商品名 PIC X(30). *> 商品名
000020 05 M商品カテゴリ PIC X(20). *> 商品カテゴリ(テレビ、冷蔵庫など)
000030 05 M仕入先コード PIC X(10). *> 仕入先コード
000040 05 M仕入単価 PIC 9(7). *> 仕入れ単価(整数)
000050 05 M販売単価 PIC 9(7). *> 販売単価(整数)
000060 05 M在庫単位 PIC X(10). *> 在庫単位(個、台など)
000070 05 M保証期間 PIC 9(2). *> 保証期間(月単位)
000080 05 M登録日 PIC 9(8). *> 登録日 (YYYYMMDD)
000090 05 M最終更新日 PIC 9(8). *> 最終更新日 (YYYYMMDD)
商品マスタを作成するためのCSVデータは次のようなデータとする。
商品マスタレコードを構成するデータ項目の内容が、カンマ(‘,’)によって区切られている形式である。
(商品マスタ初期データ.csv)
TV000001,4K OLED テレビ 55インチ,テレビ,SUPP001,25000,55000,台,24,20240301,20240310
TV000002,4K LED テレビ 50インチ,テレビ,SUPP002,18000,45000,台,24,20240302,20240311
TV000003,8K 有機ELテレビ 65インチ,テレビ,SUPP003,35000,75000,台,36,20240303,20240312
FR000004,ノンフロン冷蔵庫 400L,冷蔵庫,SUPP004,30000,65000,台,36,20240304,20240313
FR000005,大型冷蔵庫 600L,冷蔵庫,SUPP005,45000,90000,台,36,20240305,20240314
WM000006,ドラム式洗濯機 10kg,洗濯機,SUPP006,40000,80000,台,24,20240306,20240315
WM000007,縦型洗濯機 8kg,洗濯機,SUPP007,20000,45000,台,24,20240307,20240316
AC000008,エアコン 6畳用,エアコン,SUPP008,28000,60000,台,60,20240308,20240317
AC000009,エアコン 10畳用,エアコン,SUPP009,35000,75000,台,60,20240309,20240318
MV000010,電子レンジ 20L,電子レンジ,SUPP010,10000,25000,台,12,20240310,20240319
MV000011,オーブンレンジ 30L,電子レンジ,SUPP011,15000,35000,台,12,20240311,20240320
IH000012,IHクッキングヒーター,キッチン家電,SUPP012,18000,40000,台,24,20240312,20240321
VC000013,ロボット掃除機,掃除機,SUPP013,25000,55000,台,24,20240313,20240322
VC000014,コードレス掃除機,掃除機,SUPP014,15000,32000,台,24,20240314,20240323
PC000015,ノートパソコン 15インチ,パソコン,SUPP015,50000,110000,台,12,20240315,20240324
PC000016,デスクトップパソコン,パソコン,SUPP016,70000,150000,台,12,20240316,20240325
SP000017,スマートフォン 128GB,スマートフォン,SUPP017,60000,120000,台,12,20240317,20240326
SP000018,スマートフォン 256GB,スマートフォン,SUPP018,80000,150000,台,12,20240318,20240327
TB000019,タブレット 10インチ,タブレット,SUPP019,40000,90000,台,12,20240319,20240328
TB000020,タブレット 12インチ,タブレット,SUPP020,60000,130000,台,12,20240320,20240329
下記が商品マスタを作成するプログラムである。
CSVファイルから商品データを1件1件読み込み、UNSTRING文によりデータをカンマで区切って商品マスタの各項目に値を転記し、商品マスタ(‘商品マスタ.seqlite3’)に書き込んでいる。なお、最後の項目のあとにカンマがないと最後の項目の値が取得できないので、000360行目のSTRING文で強制的に最後にカンマを挿入している。
(商品マスタ作成.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. 商品マスタ作成.
000020 ENVIRONMENT DIVISION.
000030 INPUT-OUTPUT SECTION.
000040 FILE-CONTROL.
000050 SELECT 商品マスタ ASSIGN TO "商品マスタ.sqlite3"
000060 ORGANIZATION IS INDEXED
000070 ACCESS MODE IS DYNAMIC
000080 RECORD KEY IS M商品コード
000090 FILE STATUS IS ファイルステータス.
000100*
000110 SELECT 商品マスタCSV ASSIGN TO "商品マスタ初期データ.CSV"
000120 ORGANIZATION IS LINE SEQUENTIAL.
000130 DATA DIVISION.
000140 FILE SECTION.
000150 FD 商品マスタ.
000160 01 商品マスタレコード.
000170 COPY 商品レコード.
000180 FD 商品マスタCSV.
000190 01 CSVレコード PIC X(100).
000200 WORKING-STORAGE SECTION.
000210 01 ファイルステータス PIC X(2).
000220 01 CSVデータ.
000230 COPY 商品レコード REPLACING //M// BY //WSー//. *> 部分置換指定。先頭の'M'を'WS-'に変える
000240 PROCEDURE DIVISION.
000250 開始処理.
000260 OPEN INPUT 商品マスタCSV.
000270 OPEN OUTPUT 商品マスタ.
000280*
000290 PERFORM FOREVER
000300* CSVファイルを読み込む。AT ENDなら終了
000310 READ 商品マスタCSV
000320 AT END
000330 EXIT PERFORM
000340 END-READ
000350* CSVレコードの最後にカンマ(',')を付与する。
000360 STRING FUNCTION TRIM(CSVレコード) ","
000370 DELIMITED BY SIZE INTO CSVレコード
000380* CSVレコードを項目単位に分解(","で区切る)
000390 UNSTRING CSVレコード
000400 DELIMITED BY ","
000410 INTO WSー商品コード, WSー商品名,
000420 WSー商品カテゴリ,WSー仕入先コード,
000430 WSー仕入単価, WSー販売単価,
000440 WSー在庫単位, WSー保証期間,
000450 WSー登録日, WSー最終更新日
000460 DISPLAY "'" CSVデータ "'"
000470* 商品マスタへの書き込み
000480 WRITE 商品マスタレコード FROM CSVデータ
000490 IF ファイルステータス NOT = "00"
000500 DISPLAY "マスタファイル書き込みエラー "
000510 "ファイルステータス=" ファイルステータス
000520 END-IF
000530 END-PERFORM.
000540*
000550 CLOSE 商品マスタCSV.
000560 CLOSE 商品マスタ.
000570 STOP RUN.
プログラムの実行は次のようにする。
ここで、’D:¥batch_sample’は、本バッチプログラムのサンプルが格納されているフォルダである。
> d:\sitcobol\sitcobol_bat.exe d:\batch_sample\商品マスタ作成.cob
>
在庫マスタとは、1つ1つの商品(商品コード)について、その商品の在庫数、その他在庫関連の属性をもつファイルである。
在庫マスタのレコードは次のような構成になっているものとする。
レコードは便宜上、コピー原文「在庫レコード.cob」として参照されるものとする。
主キーは、最初の「M商品コード」(商品マスタと連携)である。
000160 01 在庫マスタレコード.
000170 COPY 在庫レコード.
(在庫レコード.cob)
000000 05 M商品コード PIC X(10). *> 商品コード(商品マスタと連携)
000010 05 M倉庫コード PIC X(10). *> 倉庫コード
000020 05 M現在庫数 PIC 9(7). *> 現在の在庫数
000030 05 M引当済数 PIC 9(7). *> 引当済数
000040 05 M最終在庫更新日 PIC 9(8). *> 最終在庫更新日 (YYYYMMDD)
在庫マスタを作成するためのCSVデータは次のようなデータとする。
在庫マスタレコードを構成するデータ項目の内容が、カンマ(‘,’)によって区切られている形式である。
(在庫マスタ初期データ.csv)
TV000001,WH001,50,10,20250310
TV000002,WH002,30,5,20250311
TV000003,WH003,20,2,20250312
FR000004,WH001,45,15,20250313
FR000005,WH002,35,10,20250314
WM000006,WH003,40,20,20250315
WM000007,WH001,25,5,20250316
AC000008,WH002,30,10,20250317
AC000009,WH003,15,3,20250318
MV000010,WH001,50,12,20250319
MV000011,WH002,20,5,20250320
IH000012,WH003,35,10,20250321
VC000013,WH001,40,15,20250322
VC000014,WH002,25,7,20250323
PC000015,WH003,10,2,20250324
PC000016,WH001,15,3,20250325
SP000017,WH002,20,5,20250326
SP000018,WH003,10,2,20250327
TB000019,WH001,25,7,20250328
TB000020,WH002,35,10,20250329
下記が在庫マスタを作成するプログラムである。
CSVファイルから在庫データを1件1件読み込み、UNSTRING文によりデータをカンマで区切って在庫マスタの各項目に値を転記し、在庫マスタ(‘在庫マスタ.seqlite3’)に書き込んでいる。なお、最後の項目のあとにカンマがないと最後の項目の値が取得できないので、000360行目のSTRING文で強制的に最後にカンマを挿入している。
(在庫マスタ作成.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. 在庫マスタ作成.
000020 ENVIRONMENT DIVISION.
000030 INPUT-OUTPUT SECTION.
000040 FILE-CONTROL.
000050 SELECT 在庫マスタ ASSIGN TO "在庫マスタ.sqlite3"
000060 ORGANIZATION IS INDEXED
000070 ACCESS MODE IS DYNAMIC
000080 RECORD KEY IS M商品コード
000090 FILE STATUS IS ファイルステータス.
000100*
000110 SELECT 在庫マスタCSV ASSIGN TO "在庫マスタ初期データ.CSV"
000120 ORGANIZATION IS LINE SEQUENTIAL.
000130 DATA DIVISION.
000140 FILE SECTION.
000150 FD 在庫マスタ.
000160 01 在庫マスタレコード.
000170 COPY 在庫レコード.
000180 FD 在庫マスタCSV.
000190 01 CSVレコード PIC X(100).
000200 WORKING-STORAGE SECTION.
000210 01 ファイルステータス PIC X(2).
000220 01 CSVデータ.
000230 COPY 在庫レコード REPLACING //M// BY //WSー//. *> 部分置換指定。先頭の'M'を'WS-'に変える
000240 PROCEDURE DIVISION.
000250 開始処理.
000260 OPEN INPUT 在庫マスタCSV.
000270 OPEN OUTPUT 在庫マスタ.
000280*
000290 PERFORM FOREVER
000300* CSVファイルを読み込む。AT ENDなら終了
000310 READ 在庫マスタCSV
000320 AT END
000330 EXIT PERFORM
000340 END-READ
000350* CSVレコードの最後にカンマ(',')を付与する。
000360 STRING FUNCTION TRIM(CSVレコード) ","
000370 DELIMITED BY SIZE INTO CSVレコード
000380* CSVレコードを項目単位に分解(","で区切る)
000390 UNSTRING CSVレコード
000400 DELIMITED BY ","
000410 INTO WSー商品コード, WSー倉庫コード,
000420 WSー現在庫数, WSー引当済数,
000430 WSー最終在庫更新日
000440 DISPLAY "'" CSVデータ "'"
000450* 在庫マスタへの書き込み
000460 WRITE 在庫マスタレコード FROM CSVデータ
000470 IF ファイルステータス NOT = "00"
000480 DISPLAY "マスタファイル書き込みエラー:"
000490 "ファイルステータス=" ファイルステータス
000500 END-IF
000510 END-PERFORM.
000520*
000530 CLOSE 在庫マスタCSV.
000540 CLOSE 在庫マスタ.
000550 STOP RUN.
プログラムの実行は次のようにする。
ここで、’D:¥batch_sample’は、本バッチプログラムのサンプルが格納されているフォルダである。
> d:\sitcobol\sitcobol_bat.exe d:\batch_sample\在庫マスタ作成.cob
>
倉庫マスタとは、在庫を保有する倉庫について、その倉庫名、所在地等の属性をもつファイルである。
倉庫マスタのレコードは次のような構成になっているものとする。
レコードは便宜上、コピー原文「倉庫レコード.cob」として参照されるものとする。
主キーは、最初の「M倉庫コード」である。
000160 01 倉庫マスタレコード.
000170 COPY 倉庫レコード.
(倉庫レコード.cob)
000000 05 M倉庫コード PIC X(10). *> ユニークな倉庫識別コード
000010 05 M倉庫名 PIC X(20). *> 倉庫の名称
000020 05 M所在地 PIC X(40). *> 倉庫の所在地
000030 05 M電話番号 PIC X(15). *> 倉庫の連絡先電話番号
倉庫マスタを作成するためのCSVデータは次のようなデータとする。
倉庫マスタレコードを構成するデータ項目の内容が、カンマ(‘,’)によって区切られている形式である。
(倉庫マスタ初期データ.csv)
WH001,東京倉庫,東京都江東区,03-1234-5678
WH002,大阪倉庫,大阪府大阪市,06-9876-5432
WH003,福岡倉庫,福岡県福岡市,092-1111-2222
下記が在庫マスタを作成するプログラムである。
CSVファイルから在庫データを1件1件読み込み、UNSTRING文によりデータをカンマで区切って倉庫マスタの各項目に値を転記し、倉庫マスタ(‘倉庫マスタ.seqlite3’)に書き込んでいる。なお、最後の項目のあとにカンマがないと最後の項目の値が取得できないので、000360行目のSTRING文で強制的に最後にカンマを挿入している。
(倉庫マスタ作成.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. 倉庫マスタ作成.
000020 ENVIRONMENT DIVISION.
000030 INPUT-OUTPUT SECTION.
000040 FILE-CONTROL.
000050 SELECT 倉庫マスタ ASSIGN TO "倉庫マスタ.sqlite3"
000060 ORGANIZATION IS INDEXED
000070 ACCESS MODE IS DYNAMIC
000080 RECORD KEY IS M倉庫コード
000090 FILE STATUS IS ファイルステータス.
000100*
000110 SELECT 倉庫マスタCSV ASSIGN TO "倉庫マスタ初期データ.CSV"
000120 ORGANIZATION IS LINE SEQUENTIAL.
000130 DATA DIVISION.
000140 FILE SECTION.
000150 FD 倉庫マスタ.
000160 01 倉庫マスタレコード.
000170 COPY 倉庫レコード.
000180 FD 倉庫マスタCSV.
000190 01 CSVレコード PIC X(100).
000200 WORKING-STORAGE SECTION.
000210 01 ファイルステータス PIC X(2).
000220 01 CSVデータ.
000230 COPY 倉庫レコード REPLACING //M// BY //WSー//. *> 部分置換指定。先頭の'M'を'WS-'に変える
000240 PROCEDURE DIVISION.
000250 開始処理.
000260 OPEN INPUT 倉庫マスタCSV.
000270 OPEN OUTPUT 倉庫マスタ.
000280*
000290 PERFORM FOREVER
000300* CSVファイルを読み込む。AT ENDなら終了
000310 READ 倉庫マスタCSV
000320 AT END
000330 EXIT PERFORM
000340 END-READ
000350* CSVレコードの最後にカンマ(',')を付与する。
000360 STRING FUNCTION TRIM(CSVレコード) ","
000370 DELIMITED BY SIZE INTO CSVレコード
000380* CSVレコードを項目単位に分解(","で区切る)
000390 UNSTRING CSVレコード
000400 DELIMITED BY ","
000410 INTO WSー倉庫コード, WSー倉庫名,
000420 WSー所在地, WSー電話番号
000430 DISPLAY "'" CSVデータ "'"
000440* 倉庫マスタへの書き込み
000450 WRITE 倉庫マスタレコード FROM CSVデータ
000460 IF ファイルステータス NOT = "00"
000470 DISPLAY "マスタファイル書き込みエラー "
000480 "ファイルステータス=" ファイルステータス
000490 END-IF
000500 END-PERFORM.
000510*
000520 CLOSE 倉庫マスタCSV.
000530 CLOSE 倉庫マスタ.
000540 STOP RUN.
プログラムの実行は次のようにする。
ここで、’D:¥batch_sample’は、本バッチプログラムのサンプルが格納されているフォルダである。
> d:\sitcobol\sitcobol_bat.exe d:\batch_sample\倉庫マスタ作成.cob
>
顧客マスタとは、顧客について、顧客名、住所、電話番号等の属性をもつファイルである。
顧客マスタのレコードは次のような構成になっているものとする。
レコードは便宜上、コピー原文「顧客レコード.cob」として参照されるものとする。
主キーは、最初の「M顧客コード」である。
000160 01 顧客マスタレコード.
000170 COPY 顧客レコード.
(顧客レコード.cob)
000000 05 M顧客コード PIC X(10). *> ユニークな顧客識別コード
000010 05 M顧客名 PIC X(20). *> 顧客の氏名
000020 05 M住所 PIC X(40). *> 顧客の住所
000030 05 M電話番号 PIC X(15). *> 顧客の連絡先電話番号
000040 05 Mメールアドレス PIC X(30). *> 顧客のメールアドレス
顧客マスタを作成するためのCSVデータは次のようなデータとする。
顧客マスタレコードを構成するデータ項目の内容が、カンマ(‘,’)によって区切られている形式である。
(顧客マスタ初期データ.csv)
CUST0001,田中 商店,東京都千代田区,03-1234-5678,tanaka@example.com
CUST0002,鈴木 販売店,神奈川県横浜市,045-9876-5432,suzuki@example.com
CUST0003,高橋 ホームセンター,大阪府大阪市,06-1111-2222,takahashi@example.com
CUST0004,佐藤 商店,愛知県名古屋市,052-3333-4444,sato@example.com
CUST0005,山田 販売店,福岡県福岡市,092-5555-6666,yamada@example.com
CUST0006,遠藤 商店,山梨県甲斐市,055-289-3333,endo@example.com
CUST0007,小島 電気店,岡山県岡山市,086-111-2222,kojima@example.com
CUST0008,高田 商会,長野県長野市,026-222-5555,takada@example.com
CUST0009,渋谷 販売店,沖縄県那覇市,098-555-6666,shibuya@example.com
CUST0010,西野 ホームセンター,秋田県秋田市,018-666-7777,nishino@example.com
下記が顧客マスタを作成するプログラムである。
CSVファイルから顧客データを1件1件読み込み、UNSTRING文によりデータをカンマで区切って顧客マスタの各項目に値を転記し、顧客マスタ(‘顧客マスタ.seqlite3’)に書き込んでいる。なお、最後の項目のあとにカンマがないと最後の項目の値が取得できないので、000360行目のSTRING文で強制的に最後にカンマを挿入している。
(顧客マスタ作成.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. 顧客マスタ作成.
000020 ENVIRONMENT DIVISION.
000030 INPUT-OUTPUT SECTION.
000040 FILE-CONTROL.
000050 SELECT 顧客マスタ ASSIGN TO "顧客マスタ.sqlite3"
000060 ORGANIZATION IS INDEXED
000070 ACCESS MODE IS DYNAMIC
000080 RECORD KEY IS M顧客コード
000090 FILE STATUS IS ファイルステータス.
000100*
000110 SELECT 顧客マスタCSV ASSIGN TO "顧客マスタ初期データ.CSV"
000120 ORGANIZATION IS LINE SEQUENTIAL.
000130 DATA DIVISION.
000140 FILE SECTION.
000150 FD 顧客マスタ.
000160 01 顧客マスタレコード.
000170 COPY 顧客レコード.
000180 FD 顧客マスタCSV.
000190 01 CSVレコード PIC X(100).
000200 WORKING-STORAGE SECTION.
000210 01 ファイルステータス PIC X(2).
000220 01 CSVデータ.
000230 COPY 顧客レコード REPLACING //M// BY //WSー//. *> 部分置換指定。先頭の'M'を'WS-'に変える
000240 PROCEDURE DIVISION.
000250 開始処理.
000260 OPEN INPUT 顧客マスタCSV.
000270 OPEN OUTPUT 顧客マスタ.
000280*
000290 PERFORM FOREVER
000300* CSVファイルを読み込む。AT ENDなら終了
000310 READ 顧客マスタCSV
000320 AT END
000330 EXIT PERFORM
000340 END-READ
000350* CSVレコードの最後にカンマ(',')を付与する。
000360 STRING FUNCTION TRIM(CSVレコード) ","
000370 DELIMITED BY SIZE INTO CSVレコード
000380* CSVレコードを項目単位に分解(","で区切る)
000390 UNSTRING CSVレコード
000400 DELIMITED BY ","
000410 INTO WSー顧客コード, WSー顧客名,
000420 WSー住所, WSー電話番号,
000430 WSーメールアドレス
000440 DISPLAY "'" CSVデータ "'"
000450* 顧客マスタへの書き込み
000460 WRITE 顧客マスタレコード FROM CSVデータ
000470 IF ファイルステータス NOT = "00"
000480 DISPLAY "マスタファイル書き込みエラー "
000490 "ファイルステータス=" ファイルステータス
000500 END-IF
000510 END-PERFORM.
000520*
000530 CLOSE 顧客マスタCSV.
000540 CLOSE 顧客マスタ.
000550 STOP RUN.
プログラムの実行は次のようにする。
ここで、’D:¥batch_sample’は、本バッチプログラムのサンプルが格納されているフォルダである。
> d:\sitcobol\sitcobol_bat.exe d:\batch_sample\顧客マスタ作成.cob
>
さて、各マスタができたところで、次にトランザクション処理を行うプログラムを作成する。
トランザクションとは、業務処理の単位となるデータの一連の流れを指す。例えば、商品の入庫や売上による出庫といった処理が該当する。これらの処理は、在庫マスタの情報を更新し、適切な在庫管理を行うために不可欠である。
トランザクションデータは、商品コード、倉庫コード、トランザクション種別(入庫・出庫)、数量、取引日、顧客コード
などの情報を持ち、これをもとに在庫の増減を管理する。
入庫トランザクションでは在庫数を増やし、出庫トランザクションでは在庫数を減らし、必要に応じて引当処理を行う。
次に、トランザクションデータを基に在庫マスタを更新するプログラムを作成する。このプログラムの主な処理は以下の通りである。
トランザクションデータの読み込み
‘トランザクションデータ.csv’
を順次読み込み、各トランザクション(入庫・出庫)を処理する。
在庫マスタの更新
発注帳票作成
’発注.dat’より、発注帳票’発注帳票.txt’を作成する。
欠品帳票作成
欠品情報データである’欠品.dat’をもとに’欠品帳票.txt’を作成する。
このプログラムを実行することで、トランザクションデータを適用し、在庫状況を正しく管理することが可能となる。さらに、在庫不足を自動検知し、発注や欠品管理を行うことで、円滑な在庫運用を実現する。
これら3つのプログラムおよび関連するファイルの関連は下記の図のとおりである。
では、次に、在庫マスタ更新プログラム、発注帳票作成プログラム、欠品帳票作成プログラムを作成していく。
在庫マスタ更新プログラムは、例えば次のようなプログラムとなる。
なお、このプログラムではトランザクション処理が適切に行われているかどうかを確認するため、000730行目のDISPLAYで、入力のトランザクションデータの内容を、また、000740行目のDISPLAYで、在庫マスタレコードの更新前のデータを、000940行目のDISPLAYで更新後のデータをログとして出力している。
(在庫マスタ更新.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. 在庫マスタ更新.
000020 ENVIRONMENT DIVISION.
000030 INPUT-OUTPUT SECTION.
000040 FILE-CONTROL.
000050 SELECT 在庫マスタ ASSIGN TO "在庫マスタ.sqlite3"
000060 ORGANIZATION IS INDEXED
000070 ACCESS MODE IS DYNAMIC
000080 RECORD KEY IS M商品コード
000090 FILE STATUS IS ファイルステータス.
000100 SELECT トランザクションCSV
000110 ASSIGN TO "トランザクションデータ.csv"
000120 ORGANIZATION IS LINE SEQUENTIAL.
000130 SELECT 発注ファイル ASSIGN TO "発注.dat"
000140 ORGANIZATION IS SEQUENTIAL.
000150 SELECT 欠品ファイル ASSIGN TO "欠品.dat"
000160 ORGANIZATION IS SEQUENTIAL.
000170 DATA DIVISION.
000180 FILE SECTION.
000190 FD 在庫マスタ.
000200 01 在庫マスタレコード.
000210 COPY 在庫レコード.
000220 FD トランザクションCSV.
000230 01 CSVレコード PIC X(50).
000240 FD 発注ファイル.
000250 01 発注レコード.
000260 COPY 発注レコード.
000270 FD 欠品ファイル.
000280 01 欠品レコード.
000290 COPY 欠品レコード.
000300 WORKING-STORAGE SECTION.
000310 01 ファイルステータス PIC X(2).
000320 01 CSVデータ.
000330 05 WS-商品コード PIC X(10).
000340 05 WS-倉庫コード PIC X(10).
000350 05 WS-トランザクション種別 PIC X(4). *> 入庫 or 出庫
000360 05 WS-数量 PIC 9(7).
000370 05 WS-取引日 PIC 9(8).
000380 05 WS-顧客コード PIC X(10).
000390 01 閾値 PIC 9(7) VALUE 10.
000400 PROCEDURE DIVISION.
000410 開始処理.
000420 OPEN INPUT トランザクションCSV.
000430 OPEN I-O 在庫マスタ.
000440 OPEN OUTPUT 発注ファイル.
000450 OPEN OUTPUT 欠品ファイル.
000460
000470 PERFORM FOREVER
000480* CSVファイルを読み込む。AT ENDなら終了
000490 READ トランザクションCSV
000500 AT END
000510 EXIT PERFORM
000520 END-READ
000530* CSVレコードの最後にカンマ(',')を付与する。
000540 STRING FUNCTION TRIM(CSVレコード) ","
000550 DELIMITED BY SIZE INTO CSVレコード
000560* CSVレコードを項目単位に分解(","で区切る)
000570 UNSTRING CSVレコード
000580 DELIMITED BY ","
000590 INTO WS-商品コード, WS-倉庫コード,
000600 WS-トランザクション種別, WS-数量,
000610 WS-取引日, WS-顧客コード
000620* 在庫マスタの照合
000630* 商品が見つからない場合はログを出力して次の繰り返しへ
000640 MOVE WS-商品コード TO M商品コード
000650 READ 在庫マスタ
000660 INVALID KEY
000670 DISPLAY "不明商品: 商品コード=" WS-商品コード
000680 EXIT PERFORM CYCLE
000690 END-READ
000700* 在庫マスタの更新、および欠品データ、発注データの出力
000710 PERFORM 在庫調整処理
000720 END-PERFORM.
000730
000740 CLOSE トランザクションCSV.
000750 CLOSE 在庫マスタ.
000760 CLOSE 発注ファイル.
000770 CLOSE 欠品ファイル.
000780 STOP RUN.
000790
000800 在庫調整処理.
000810 DISPLAY "".
000820 DISPLAY "'" CSVデータ "'".
000830 DISPLAY " BEFORE:" 在庫マスタレコード.
000840* トランザクションの種別が「入庫」の場合
000850 IF WS-トランザクション種別 = "入庫"
000860 ADD WS-数量 TO M現在庫数
000870* トランザクションの種別が「出庫」の場合
000880 ELSE
000890* すべての数量を引き当てられる場合は、在庫量を減らす。
000900 IF M現在庫数 >= WS-数量
000910 SUBTRACT WS-数量 FROM M現在庫数
000920 ADD WS-数量 TO M引当済数
000930* すべてを引き当てられない場合は欠品情報を出力する。
000940 ELSE
000950 MOVE WS-商品コード TO 欠品商品コード
000960 MOVE WS-倉庫コード TO 欠品倉庫コード
000970 COMPUTE 欠品数 = WS-数量 - M現在庫数
000980 MOVE WS-取引日 TO 欠品日
000990 MOVE WS-顧客コード TO 欠品顧客コード
001000 WRITE 欠品レコード
001010 MOVE 0 TO M現在庫数
001020 END-IF
001030 END-IF
001040* 最終在庫更新日を更新して、在庫マスタを更新する
001050 MOVE WS-取引日 TO M最終在庫更新日.
001060 REWRITE 在庫マスタレコード.
001070 DISPLAY " AFTER: " 在庫マスタレコード.
001080* 在庫が閾値よりもすくないときは、発注データを出力する。
001090 IF M現在庫数 < 閾値
001100 MOVE WS-商品コード TO 発注商品コード
001110 MOVE WS-倉庫コード TO 発注倉庫コード
001120 MOVE 20 TO 発注数
001130 MOVE WS-取引日 TO 発注日
001140 WRITE 発注レコード
001150 END-IF.
ここで、’トランザクションデータ.csv’は、具体的には次のようなデータである。
VC000014,WH001,入庫,6,20250310,
FR000005,WH001,入庫,23,20250329,
TV000001,WH002,出庫,16,20250308,CUST0005
VC000014,WH003,出庫,11,20250320,CUST0003
AC000009,WH002,出庫,8,20250328,CUST0009
MV000010,WH002,入庫,7,20250318,
WM000006,WH003,入庫,11,20250312,
TB000020,WH003,入庫,14,20250321,
TV000001,WH002,入庫,17,20250308,
:
また、発注レコード.cob、欠品レコード.cobは次のような内容とする。
(発注レコード.cob)
000000 05 発注商品コード PIC X(10).
000010 05 発注倉庫コード PIC X(10).
000020 05 発注数 PIC 9(7).
000030 05 発注日 PIC 9(8).
(欠品レコード.cob)
000000 05 欠品商品コード PIC X(10).
000010 05 欠品倉庫コード PIC X(10).
000020 05 欠品数 PIC 9(7).
000030 05 欠品日 PIC 9(8).
000040 05 欠品顧客コード PIC X(10).
実行結果は以下のとおりである。
> d:\sitcobol\sitcobol_bat.exe d:\batch_sample\顧客マスタ更新.cob
'PC000015 WH001 出庫 000000820250314CUST0007 '
BEFORE:PC000015 WH003 0000010000000220250324
AFTER: PC000015 WH003 0000002000001020250314
'IH000012 WH002 出庫 000001620250317CUST0007 '
BEFORE:IH000012 WH003 0000035000001020250321
AFTER: IH000012 WH003 0000019000002620250317
'FR000005 WH001 出庫 000000920250307CUST0009 '
BEFORE:FR000005 WH002 0000035000001020250314
AFTER: FR000005 WH002 0000026000001920250307
'TV000003 WH001 入庫 000000720250303 '
BEFORE:TV000003 WH003 0000020000000220250312
AFTER: TV000003 WH003 0000027000000220250303
: (省略)
>
発注帳票作成プログラムは、発注データを入力し、発注一覧を作成するプログラムである。
今回は次のようなイメージの帳票を作成する。
------------------------------------------------------------------------------------------
項番 商品コード 商品名 倉庫名 発注数 発注日
------------------------------------------------------------------------------------------
1 PC000015 ノートパソコン 15インチ 東京倉庫 20 25/03/14
2 AC000009 エアコン 10畳用 大阪倉庫 20 25/03/28
3 PC000015 ノートパソコン 15インチ 福岡倉庫 20 25/03/08
4 PC000016 デスクトップパソコン 福岡倉庫 20 25/03/11
5 PC000016 デスクトップパソコン 大阪倉庫 20 25/03/12
6 TV000002 4K LED テレビ 50インチ 大阪倉庫 20 25/03/27
7 AC000009 エアコン 10畳用 東京倉庫 20 25/03/15
8 PC000015 ノートパソコン 15インチ 東京倉庫 20 25/03/25
9 PC000015 ノートパソコン 15インチ 大阪倉庫 20 25/03/19
10 PC000016 デスクトップパソコン 福岡倉庫 20 25/03/13
------------------------------------------------------------------------------------------
発注帳票作成プログラムは次のようになる。
(発注帳票作成.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. 発注帳票作成.
000020 ENVIRONMENT DIVISION.
000030 INPUT-OUTPUT SECTION.
000040 FILE-CONTROL.
000050 SELECT 発注ファイル ASSIGN TO "発注.dat"
000060 ORGANIZATION IS SEQUENTIAL.
000070
000080 SELECT 商品マスタ ASSIGN TO "商品マスタ.sqlite3"
000090 ORGANIZATION IS INDEXED
000100 ACCESS MODE IS DYNAMIC
000110 RECORD KEY IS M商品コード.
000120
000130 SELECT 倉庫マスタ ASSIGN TO "倉庫マスタ.sqlite3"
000140 ORGANIZATION IS INDEXED
000150 ACCESS MODE IS DYNAMIC
000160 RECORD KEY IS M倉庫コード.
000170
000180 SELECT 発注帳票 ASSIGN TO "発注帳票.txt"
000190 ORGANIZATION IS LINE SEQUENTIAL.
000200
000210 DATA DIVISION.
000220 FILE SECTION.
000230 FD 発注ファイル.
000240 01 発注レコード.
000250 COPY 発注レコード.
000260
000270 FD 商品マスタ.
000280 01 商品マスタレコード.
000290 COPY 商品レコード.
000300
000310 FD 倉庫マスタ.
000320 01 倉庫マスタレコード.
000330 COPY 倉庫レコード.
000340
000350 FD 発注帳票.
000360 01 発注帳票レコード PIC X(90).
000370
000380 WORKING-STORAGE SECTION.
000390 01 ヘッダ行 PIC X(90) VALUE
000400 "項番 商品コード "
000410 & "商品名 "
000420 & "倉庫名 "
000430 & "発注数 発注日".
000440 01 区切り線 PIC X(90) VALUE ALL "-".
000450 01 明細行.
000460 02 明細項番 PIC ZZZ9 VALUE 1.
000470 02 PIC X(1) VALUE SPACE.
000480 02 明細商品コード PIC X(10).
000490 02 PIC X(1) VALUE SPACE.
000500 02 明細商品名 PIC N(18).
000510 02 PIC X(1) VALUE SPACE.
000520 02 明細倉庫名 PIC N(10).
000530 02 PIC X(1) VALUE SPACE.
000540 02 明細発注数 PIC ZZZZ9.
000550 02 PIC X(1) VALUE SPACE.
000560 02 明細発注日 PIC 99/99/99.
000570
000580 PROCEDURE DIVISION.
000590 開始処理.
000600 OPEN INPUT 発注ファイル.
000610 OPEN INPUT 商品マスタ.
000620 OPEN INPUT 倉庫マスタ.
000630 OPEN OUTPUT 発注帳票.
000640
000650 WRITE 発注帳票レコード FROM 区切り線.
000660 WRITE 発注帳票レコード FROM ヘッダ行.
000670 WRITE 発注帳票レコード FROM 区切り線.
000680
000690 PERFORM FOREVER
000700* 発注ファイル読込。AT ENDとなったら終了。
000710 READ 発注ファイル
000720 AT END
000730 EXIT PERFORM
000740 END-READ
000750 MOVE SPACES TO 明細商品名
000760 MOVE SPACES TO 明細倉庫名
000770* 商品マスタより商品名を検索
000780 MOVE 発注商品コード TO M商品コード
000790 READ 商品マスタ
000800 INVALID KEY
000810 MOVE "不明" TO 明細商品名
000820 DISPLAY "不明:" 発注商品コード
000830 NOT INVALID KEY
000840 MOVE M商品名 OF 商品マスタ TO 明細商品名 *> 英数字項目から日本語項目への転記なので
000850 *> 半角文字は空白も含めて全角文字になる
000860 END-READ
000870* 倉庫マスタより倉庫名を検索。
000880 MOVE 発注倉庫コード TO M倉庫コード
000890 READ 倉庫マスタ
000900 INVALID KEY
000910 MOVE "不明" TO 明細倉庫名
000920 DISPLAY "不明:" 発注倉庫コード
000930 NOT INVALID KEY
000940 MOVE M倉庫名 TO 明細倉庫名 *> 英数字項目から日本語項目への転記なので
000950 *> 半角文字は空白も含めて全角文字になる
000960 END-READ
000970* 明細行の作成
000980 MOVE 発注商品コード TO 明細商品コード
000990 MOVE 発注数 TO 明細発注数
001000 MOVE 発注日 TO 明細発注日
001010 WRITE 発注帳票レコード FROM 明細行
001020
001030 ADD 1 TO 明細項番
001040
001050 END-PERFORM.
001060 WRITE 発注帳票レコード FROM 区切り線.
001070
001080 CLOSE 発注ファイル.
001090 CLOSE 商品マスタ.
001100 CLOSE 倉庫マスタ.
001110 CLOSE 発注帳票.
001120 STOP RUN.
(補足)
発注帳票をよく見ると、例えば「ノートパソコン 15インチ
東京倉庫」は、2回出力されている。
これはトランザクションデータの中に同じ商品の取引が何度もあり、その都度在庫数をチェックし、閾値以下であれば発注データとして繰り返し出力しているからである。
本来は修正が必要であるが、どのように修正するかは、ぜひ課題として取り組んでいただきたい。
実行結果は次のとおりである。
> d:\sitcobol\sitcobol_bat.exe d:\batch_sample\発注帳票作成.cob
>
発注帳票作成プログラムは、欠品データを入力し、欠品一覧を作成するプログラムである。
今回は次のようなイメージの帳票を作成する。
----------------------------------------------------------------------------------------------------
項番 顧客コード 顧客名 商品コード 商品名 倉庫名 欠品数 欠品日
----------------------------------------------------------------------------------------------------
1 CUST0005 山田 販売店 PC000015 ノートパソコン 15インチ 福岡倉庫 13 25/03/08
2 CUST0006 遠藤 ホームセンター PC000016 デスクトップパソコン 福岡倉庫 1 25/03/11
3 CUST0001 田中 商店 PC000015 ノートパソコン 15インチ 東京倉庫 16 25/03/25
4 CUST0003 高橋 ホームセンター PC000016 デスクトップパソコン 福岡倉庫 22 25/03/13
----------------------------------------------------------------------------------------------------
欠品帳票作成プログラムは次のようになる。
(欠品帳票作成.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. 欠品帳票作成.
000020 ENVIRONMENT DIVISION.
000030 INPUT-OUTPUT SECTION.
000040 FILE-CONTROL.
000050 SELECT 欠品ファイル ASSIGN TO "欠品.dat"
000060 ORGANIZATION IS SEQUENTIAL.
000070
000080 SELECT 商品マスタ ASSIGN TO "商品マスタ.sqlite3"
000090 ORGANIZATION IS INDEXED
000100 ACCESS MODE IS DYNAMIC
000110 RECORD KEY IS M商品コード.
000120
000130 SELECT 倉庫マスタ ASSIGN TO "倉庫マスタ.sqlite3"
000140 ORGANIZATION IS INDEXED
000150 ACCESS MODE IS DYNAMIC
000160 RECORD KEY IS M倉庫コード.
000170
000180 SELECT 顧客マスタ ASSIGN TO "顧客マスタ.sqlite3"
000190 ORGANIZATION IS INDEXED
000200 ACCESS MODE IS DYNAMIC
000210 RECORD KEY IS M顧客コード.
000220
000230 SELECT 欠品帳票 ASSIGN TO "欠品帳票.txt"
000240 ORGANIZATION IS LINE SEQUENTIAL.
000250
000260 DATA DIVISION.
000270 FILE SECTION.
000280 FD 欠品ファイル.
000290 01 欠品レコード.
000300 COPY 欠品レコード.
000310
000320 FD 商品マスタ.
000330 01 商品マスタレコード.
000340 COPY 商品レコード.
000350
000360 FD 倉庫マスタ.
000370 01 倉庫マスタレコード.
000380 COPY 倉庫レコード.
000390
000400 FD 顧客マスタ.
000410 01 顧客マスタレコード.
000420 COPY 顧客レコード.
000430
000440 FD 欠品帳票.
000450 01 欠品帳票レコード PIC X(120).
000460
000470 WORKING-STORAGE SECTION.
000480 01 ヘッダ行 PIC X(90) VALUE
000490 "項番 顧客コード 顧客名 "
000500 & "商品コード "
000510 & "商品名 "
000520 & "倉庫名 "
000530 & "欠品数 欠品日".
000540 01 区切り線 PIC X(100) VALUE ALL "-".
000550 01 明細行.
000560 02 明細項番 PIC ZZZ9 VALUE 1.
000570 02 PIC X(1) VALUE SPACE.
000580 02 明細顧客コード PIC X(10).
000590 02 PIC X(1) VALUE SPACE.
000600 02 明細顧客名 PIC N(10).
000610 02 PIC X(1) VALUE SPACE.
000620 02 明細商品コード PIC X(10).
000630 02 PIC X(1) VALUE SPACE.
000640 02 明細商品名 PIC N(13).
000650 02 PIC X(1) VALUE SPACE.
000660 02 明細倉庫名 PIC N(5).
000670 02 PIC X(1) VALUE SPACE.
000680 02 明細発注数 PIC ZZZZ9.
000690 02 PIC X(1) VALUE SPACE.
000700 02 明細発注日 PIC 99/99/99.
000710
000720 PROCEDURE DIVISION.
000730 開始処理.
000740 OPEN INPUT 欠品ファイル.
000750 OPEN INPUT 商品マスタ.
000760 OPEN INPUT 倉庫マスタ.
000770 OPEN INPUT 顧客マスタ.
000780 OPEN OUTPUT 欠品帳票.
000790
000800 WRITE 欠品帳票レコード FROM 区切り線.
000810 WRITE 欠品帳票レコード FROM ヘッダ行.
000820 WRITE 欠品帳票レコード FROM 区切り線.
000830
000840 PERFORM FOREVER
000850* 発注ファイル読込。AT ENDとなったら終了。
000860 READ 欠品ファイル
000870 AT END
000880 EXIT PERFORM
000890 END-READ
000900 MOVE SPACES TO 明細商品名
000910 MOVE SPACES TO 明細倉庫名
000920* 商品マスタより商品名を検索
000930 MOVE 欠品商品コード TO M商品コード
000940 READ 商品マスタ
000950 INVALID KEY
000960 MOVE "不明" TO 明細商品名
000970 DISPLAY "不明:" 欠品商品コード
000980 NOT INVALID KEY
000990 MOVE M商品名 OF 商品マスタ TO 明細商品名 *> 英数字項目から日本語項目への転記なので
001000 *> 半角文字は空白も含めて全角文字になる
001010 END-READ
001020* 倉庫マスタより倉庫名を検索。
001030 MOVE 欠品倉庫コード TO M倉庫コード
001040 READ 倉庫マスタ
001050 INVALID KEY
001060 MOVE "不明" TO 明細倉庫名
001070 DISPLAY "不明:" 欠品倉庫コード
001080 NOT INVALID KEY
001090 MOVE M倉庫名 TO 明細倉庫名 *> 英数字項目から日本語項目への転記なので
001100 *> 半角文字は空白も含めて全角文字になる
001110 END-READ
001120* 顧客マスタより顧客名を検索。
001130 MOVE 欠品顧客コード TO M顧客コード
001140 READ 顧客マスタ
001150 INVALID KEY
001160 MOVE "不明" TO 明細顧客名
001170 DISPLAY "不明:" 欠品顧客コード
001180 NOT INVALID KEY
001190 MOVE M顧客名 TO 明細顧客名 *> 英数字項目から日本語項目への転記なので
001200 *> 半角文字は空白も含めて全角文字になる
001210 END-READ
001220* 明細行の作成
001230 MOVE 欠品商品コード TO 明細商品コード
001240 MOVE 欠品顧客コード TO 明細顧客コード
001250 MOVE 欠品数 TO 明細発注数
001260 MOVE 欠品日 TO 明細発注日
001270 WRITE 欠品帳票レコード FROM 明細行
001280
001290 ADD 1 TO 明細項番
001300
001310 END-PERFORM.
001320 WRITE 欠品帳票レコード FROM 区切り線.
001330
001340 CLOSE 欠品ファイル.
001350 CLOSE 商品マスタ.
001360 CLOSE 倉庫マスタ.
001370 CLOSE 顧客マスタ.
001380 CLOSE 欠品帳票.
001390 STOP RUN.
(補足)
出力された欠品帳票は、明細が顧客コードの昇順ではない。これは、入力の欠品データが、トランザクション発生順に出力されているからである。
明細を、顧客コード順に出力するには修正が必要であるが、その修正は、ぜひ課題として取り組んでいただきたい。
実行結果は次のとおりである。
> d:\sitcobol\sitcobol_bat.exe d:\batch_sample\欠品帳票作成.cob
>
さて、以上で、「在庫マスタ更新」、「発注帳票作成」、「欠品帳票作成」の3つのプログラムの用意が出来たが、これらの3つのプログラムは、一連の流れで実行する必要がある。
そもそも、コンピュータの処理は、単一のプログラムだけで完結することは少ない。業務においては、複数の処理を決まった順序で実行する必要がある。たとえば、このトランザクション処理例のように、在庫情報を更新した後に、発注すべき商品を洗い出し、さらにその結果を元に帳票を出力する、といった一連の処理である。
このように、複数のプログラムや処理ステップをひとまとまりの「ジョブ(JOB)」として定義し、順序通りに実行させる仕組みを「ジョブ制御」と呼ぶ。そして、ジョブ制御を行うための記述言語を「ジョブ制御言語(JCL: Job Control Language)」といい、主に汎用機(メインフレーム)環境において利用されている。
一方で、Windows環境において同様の役割を果たすものとしては、バッチファイル(.bat)やPowerShellスクリプト(.ps1)が存在する。これらも、複数のプログラムを順序通りに呼び出し、必要なファイル操作を行いながら処理を進めるという点で、JCLと極めてよく似た性質を持つ。
例えば、次のようなバッチファイルが、本例の一連のプログラムを実行するバッチファイルとなる。
(バッチ処理サンプル.bat)
----
@echo off
rem コマンドプロンプトのコード系をutf-8に設定
chcp 65001
rem 環境変数の設定
set sitcobol=d:\sitcobol\sitcobol_bat.exe
set prg_path=d:\batch_sample
rem 在庫マスタ更新
%sitcobol% %prg_path%\在庫マスタ更新.cob
if errorlevel 1 goto ERROR
rem 発注帳票作成
%sitcobol% %prg_path%\発注帳票作成.cob
if errorlevel 1 goto ERROR
rem 欠品帳票作成
%sitcobol% %prg_path%\欠品帳票作成.cob
if errorlevel 1 goto ERROR
goto END
:ERROR
echo エラーが発生しました。
exit /b 1
:END
echo 正常に終了しました。
(注意)
このバッチプログラムを並列で実行する場合、どのような弊害が発生するかを考えてみよう。
まず第一に、在庫マスタが複数からアクセス更新されるので、排他制御が必要である。ただし、SITCOBOLでは索引ファイルはsqlite3で実現しており、sqliteは基本的に単一プロセスからのアクセスしか許容しないので、ここでは問題が発生する可能性があることの言及までに留めておく。
さらなる弊害を考えると、入力トランザクションである「トランザクション.csv」、テンポラリ的な中間ファイルである「欠品.dat」、「発注.dat」、「発注帳票.txt」、「欠品帳票.txt」のファイル名が固定なので、並列で実行した場合、あるプロセスで作成したこれらのファイルを、別プロセスで参照してしまうということが発生する。
この問題を解決するにはどうしたらよいか?
これらの実ファイル名が、実行時にシステム上で一意となるような名前にすればよい。
それでは、システム上で一意となるものは何か?いくつか考えられるが、自分自身のプロセスID(pid)や自分の親のプロセスID(ppid)を元に作られている名前であればバッチプログラム走行時点では、システム上で一意となるであろう。
ただ、PowerシェルであればプロセスIDの取得は容易いが、バッチファイルの場合、プロセスIDを取得するすべがない。
そこで、バッチシェルのプロセスIDをプログラム終了状態(すなわちerrorlevel)として返すようなプログラムを用意する。
(PPID取得.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. PPID取得.
000020 DATA DIVISION.
000030 WORKING-STORAGE SECTION.
000040 01 PPID PIC 9(5) comp-3.
000050 PROCEDURE DIVISION.
000060 CALL "CBL_GET_PPID" USING PPID.
000070 MOVE PPID TO RETURN-CODE.
000080 STOP RUN.
プログラムは単純で、組み込みサブルーチンCBL_GET_PPIDを呼んで、親プロセス(すなわちバッチファイル)のプロセスIDをプログラム終了コードとして返却するものである。
バッチファイル上での使い方は次のようになる。
:
REM プロセスIDの取得
%sitcobol% %prg_path%PPID取得.cob
set pid=%errorlevel%
REM PIDを表示してみる
echo pid=%pid%
このpidを元に「トランザクション.csv」、「発注.dat」、「欠品.dat」、「発注帳票.dat」、「欠品帳票.dat」に対応する一意名をつけるとしたら例えば次のようになるであろう。
そしてこれらの名前を、環境変数経由でCOBOLプログラムに引き渡せばよい。
具体的なバッチファイルは次のようになる。
(バッチ処理サンプル2.bat)
@echo off
rem コマンドプロンプトのコード系をutf-8に設定
chcp 65001
rem 環境変数の設定
set sitcobol=d:\sitcobol\sitcobol_bat.exe
set prg_path=d:\batch_sample
rem PID取得
%sitcobol% %prg_path%\PPID取得.cob
set pid=%errorlevel%
rem トランザクションCSVの用意:本体は前段のジョブから取得すべきデータであるが
rem ここでは元ファイルをコピーするのみとする
copy %prg_path%\トランザクションデータ.csv %prg_path%\%pid%_トランザクションデータ.csv
rem 環境変数の設定(COBOL側で参照)
set tran_file=%prg_path%\%pid%_トランザクションデータ.csv
set order_file=%prg_path%\%pid%_発注.dat
set order_text=%prg_path%\%pid%_発注帳票.txt
set out_of_stock_file=%prg_path%\%pid%_欠品.dat
set out_of_stock_text=%prg_path%\%pid%_欠品帳票.txt
rem 在庫マスタ更新
%sitcobol% %prg_path%\在庫マスタ更新2.cob
if errorlevel 1 goto ERROR
rem 発注帳票作成
%sitcobol% %prg_path%\発注帳票作成2.cob
if errorlevel 1 goto ERROR
rem 欠品帳票作成
%sitcobol% %prg_path%\欠品帳票作成2.cob
if errorlevel 1 goto ERROR
rem 不必要となったファイルの削除
del %prg_path%\%pid%_トランザクションデータ.csv
del %prg_path%\%pid%_発注.dat
del %prg_path%\%pid%_欠品.dat
goto END
:ERROR
echo エラーが発生しました。
exit /b 1
:END
echo 正常に終了しました。
上記バッチファイルでは最後に 「%pid%_発注帳票.txt」および「%pid%_欠品帳票.txt」を残しているが、これらの帳票はこの時点で印刷や電子化が終了していないからである。
さて、バッチファイル側はこれでよいとして、プログラム側は、それぞれのファイル名を環境変数経由で取得するようにする改造が必要である。
具体的には、各ファイルのASSIGN文をデータ指定にし、ACCEPT
FROM
ENVIROMENT文で取得した実ファイル名を、そのデータ名に設定するのみである。
(在庫マスタ更新2.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. 在庫マスタ更新2.
000020 ENVIRONMENT DIVISION.
000030 INPUT-OUTPUT SECTION.
000040 FILE-CONTROL.
000050 SELECT 在庫マスタ ASSIGN TO "在庫マスタ.sqlite3"
000060 ORGANIZATION IS INDEXED
000070 ACCESS MODE IS DYNAMIC
000080 RECORD KEY IS M商品コード
000090 FILE STATUS IS ファイルステータス.
000100 SELECT トランザクションCSV
000110 ASSIGN TO TRAN-FILE *> 実ファイル名をデータ名TRAN-FILEに変更
000120 ORGANIZATION IS LINE SEQUENTIAL.
000130 SELECT 発注ファイル ASSIGN TO ORDER-FILE *> 実ファイル名をデータ名ORDER-FILEに変更
000140 ORGANIZATION IS SEQUENTIAL.
000150 SELECT 欠品ファイル ASSIGN TO OUT-OF-STOCK-FILE *> 実ファイル名をデータ名OUT-OF-STOCK-FILEに変更
000160 ORGANIZATION IS SEQUENTIAL.
:
000300 WORKING-STORAGE SECTION.
:
000400 01 TRAN-FILE PIC X(100). *> トランザクションファイルの実ファイル名用
000410 01 ORDER-FILE PIC X(100). *> 発注ファイルの実ファイル名用
000420 01 OUT-OF-STOCK-FILE PIC X(100). *> 欠品ファイルの実ファイル名用
:
000430 PROCEDURE DIVISION.
000440 開始処理.
000450* ファイル名の取得
000460 ACCEPT TRAN-FILE FROM ENVIRONMENT "tran_file". *> 環境変数tarn_fileの値をTRAN-FILEに設定する
000470 ACCEPT ORDER-FILE FROM ENVIRONMENT "order_file". *> 環境変数order_fileの値をORDER-FILEに設定する
000480 ACCEPT OUT-OF-STOCK-FILE FROM ENVIRONMENT *> 環境変数out_of_stock_fileの値を
000490 "out_of_stock_file". *> OUT-OF-STOCK-FILEに設定する
000500 DISPLAY "TRAN-FILE= " TRAN-FILE.
000510 DISPLAY "ORDER-FILE= " ORDER-FILE.
000520 DISPLAY "OUT-OF-STOCK-FILE= " OUT-OF-STOCK-FILE.
000530* ファイルを開く
000540 OPEN INPUT トランザクションCSV.
000550 OPEN I-O 在庫マスタ.
000560 OPEN OUTPUT 発注ファイル.
000570 OPEN OUTPUT 欠品ファイル.
:
発注帳票作成.cob 、欠品帳票作成.cobも同様に実ファイル名を環境変数経由で取得するように変更する。
(発注帳票作成2.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. 発注帳票作成2.
000020 ENVIRONMENT DIVISION.
000030 INPUT-OUTPUT SECTION.
000040 FILE-CONTROL.
000050 SELECT 発注ファイル ASSIGN TO ORDER-FILE *> 実ファイル名をORDER-FILEに変更
000060 ORGANIZATION IS SEQUENTIAL.
:
000170
000180 SELECT 発注帳票 ASSIGN TO ORDER-TEXT *> 実ファイル名をORDER-TEXTに変更
000190 ORGANIZATION IS LINE SEQUENTIAL.
:
000380 WORKING-STORAGE SECTION.
:
000580 01 ORDER-FILE PIC X(100). *> 発注ファイルの実ファイル名用
000590 01 ORDER-TEXT PIC X(100). *> 発注帳票テキストの実ファイル名用
:
000600 PROCEDURE DIVISION.
000610 開始処理.
000620 ACCEPT ORDER-FILE FROM ENVIRONMENT "order_file". *> 環境変数order_fileの値を取得
000630 ACCEPT ORDER-TEXT FROM ENVIRONMENT "order_text". *> 環境変数order_textの値を取得
000640*
000650 OPEN INPUT 発注ファイル.
000660 OPEN INPUT 商品マスタ.
000670 OPEN INPUT 倉庫マスタ.
000680 OPEN OUTPUT 発注帳票.
:
(欠品帳票作成2.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. 欠品帳票作成2.
000020 ENVIRONMENT DIVISION.
000030 INPUT-OUTPUT SECTION.
000040 FILE-CONTROL.
000050 SELECT 欠品ファイル ASSIGN TO OUT-OF-STOCK-FILE *> 実ファイル名をOUT-OF-STOCK-FILEに変更
000060 ORGANIZATION IS SEQUENTIAL.
:
000230 SELECT 欠品帳票 ASSIGN TO OUT-OF-STOCK-TEXT *> 実ファイル名をOUT-OF-STOCK-TEXTに変更
000240 ORGANIZATION IS LINE SEQUENTIAL.
:
000470 WORKING-STORAGE SECTION.
:
000720 01 OUT-OF-STOCK-FILE PIC X(100). *> 欠品ファイルの実ファイル名用
000730 01 OUT-OF-STOCK-TEXT PIC X(100). *> 欠品帳票の実ファイル名用
:
000740 PROCEDURE DIVISION.
000750 開始処理.
000760 ACCEPT OUT-OF-STOCK-FILE FROM ENVIRONMENT
000770 "out_of_stock_file".
000780 ACCEPT OUT-OF-STOCK-TEXT FROM ENVIRONMENT
000790 "out_of_stock_text".
000800*
000810 OPEN INPUT 欠品ファイル.
000820 OPEN INPUT 商品マスタ.
000830 OPEN INPUT 倉庫マスタ.
000840 OPEN INPUT 顧客マスタ.
000850 OPEN OUTPUT 欠品帳票.
:
前節では、ジョブ制御言語として、バッチファイルを使用したが、SITCOBOLはある程度機能を持っているので、バッチファイルを使用しないで、すべてCOBOLで記述することもできることがある。
例えば、バッチファイルに相当するプログラムは次のようになる。
最初に、000130行において’CBL_GET_PID’で自分自身のプロセスIDを取得しているが、これは、呼ぶプログラムと呼ばれるプログラムは常に同じプロセス空間で実行され、親子関係がないからである。
環境変数設定においては、STRING文で、PIDから始まるファイル名を作成して、それを、SET
ENVIRONMENT文で環境変数に設定している。(000150~000390行)
また、各COBOLプログラムを呼び出したときのプログラムの終了状態は、RETURN-CODEで参照できる。RETURN-CODEが0でない場合はエラーを表示してL-ERROR段落に制御を移すようにしている。(000580~000610行など)
また、不要なファイルの削除は、組み込みサブルーチン”CBL_DELETE_FILE”によって削除を行っている。(000790行など)
なお、本章の最初に記述したが、SITCOBOLでは、CALL文に指定するのは、ファイル名である。
すなわち、’CALL
“ABC”’と記述したときは、SITCOBOLは、ABC.cob または
ABC.cblというプログラムを検索して、それを呼び出す。また、呼び出すプログラムを検索するフォルダはcall_pathパラメータで指定が可能である。
(バッチ処理サンプル.cob)
000000 IDENTIFICATION DIVISION.
000010 PROGRAM-ID. バッチ処理サンプル.
000020 DATA DIVISION.
000030 WORKING-STORAGE SECTION.
000040 01 PID PIC 9(10).
000050 01 トランザクションデータ PIC X(100).
000060 01 発注ファイル名 PIC X(100).
000070 01 発注帳票名 PIC X(100).
000080 01 欠品ファイル名 PIC X(100).
000090 01 欠品帳票名 PIC X(100).
000100 PROCEDURE DIVISION.
000110 MAIN00.
000120* プロセスIDの取得
000130 CALL "CBL_GET_PID" USING PID.
000140
000150* 環境変数の設定
000160* set tran_file=%pid%_トランザクションデータ.csv
000170 STRING FUNCTION TRIM(PID) "_トランザクションデータ.csv"
000180 DELIMITED BY SIZE INTO トランザクションデータ.
000190 SET ENVIRONMENT "tran_file" TO トランザクションデータ.
000200
000210* set order_file=%pid%_発注.dat
000220 STRING FUNCTION TRIM(PID) "_発注.dat" DELIMITED BY SIZE
000230 INTO 発注ファイル名.
000240 SET ENVIRONMENT "order_file" TO 発注ファイル名.
000250
000260* set order_text=%pid%_発注帳票.txt
000270 STRING FUNCTION TRIM(PID) "_発注帳票.txt" DELIMITED BY SIZE
000280 INTO 発注帳票名.
000290 SET ENVIRONMENT "order_text" TO 発注帳票名.
000300
000310* set out_of_stock_file=%pid%_欠品.dat
000320 STRING FUNCTION TRIM(PID) "_欠品.dat" DELIMITED BY SIZE
000330 INTO 欠品ファイル名.
000340 SET ENVIRONMENT "out_of_stock_file" TO 欠品ファイル名.
000350
000360* set out_of_stock_text=%pid%_欠品帳票.txt
000370 STRING FUNCTION TRIM(PID) "_欠品帳票.txt" DELIMITED BY SIZE
000380 INTO 欠品帳票名.
000390 SET ENVIRONMENT "out_of_stock_text" TO 欠品帳票名.
000400
000410 DISPLAY "トランザクションデータ: " トランザクションデータ.
000420 DISPLAY "発注ファイル名: " 発注ファイル名.
000430 DISPLAY "欠品ファイル名: " 欠品ファイル名.
000440 DISPLAY "発注帳票名: " 発注帳票名.
000450 DISPLAY "欠品帳票名: " 欠品帳票名.
000460
000470* トランザクションデータの用意
000480 CALL "CBL_COPY_FILE" USING "トランザクションデータ.csv"
000490 トランザクションデータ.
000500 IF RETURN-CODE NOT = 0
000510 DISPLAY "トランザクションのコピーに失敗した code="
000520 RETURN-CODE
000530 GO TO L-ERROR
000540 END-IF.
000550
000560* 在庫マスタ更新
000570 CALL "在庫マスタ更新2".
000580 IF RETURN-CODE NOT = 0
000590 DISPLAY "在庫マスタ更新が失敗した code=" RETURN-CODE
000600 GO TO L-ERROR
000610 END-IF.
000620
000630* 発注帳票作成
000640 CALL "発注帳票作成2".
000650 IF RETURN-CODE NOT = 0
000660 DISPLAY "発注帳票作成が失敗した code=" RETURN-CODE
000670 GO TO L-ERROR
000680 END-IF.
000690
000700* 欠品帳票作成
000710 CALL "欠品帳票作成2".
000720 IF RETURN-CODE NOT = 0
000730 DISPLAY "欠品帳票作成が失敗した code=" RETURN-CODE
000740 GO TO L-ERROR
000750 END-IF.
000760
000770 L-ERROR.
000780* 不要となったファイルの削除
000790 CALL "CBL_DELETE_FILE" USING トランザクションデータ.
000800 IF RETURN-CODE NOT = 0
000810 DISPLAY "トランザクションデータの削除に失敗した: "
000820 "ファイル名=" トランザクションデータ
000830 ", code=" RETURN-CODE
000840 END-IF.
000850*
000860 CALL "CBL_DELETE_FILE" USING 発注ファイル名.
000870 IF RETURN-CODE NOT = 0
000880 DISPLAY "発注ファイルの削除に失敗した: "
000890 "ファイル名=" 発注ファイル名
000900 ", code=" RETURN-CODE
000910 END-IF.
000920*
000930 CALL "CBL_DELETE_FILE" USING 欠品ファイル名.
000940 IF RETURN-CODE NOT = 0
000950 DISPLAY "欠品ファイルの削除に失敗した: "
000960 "ファイル名=" 欠品ファイル名
000970 ", code=" RETURN-CODE
000980 END-IF.
000990
001000 STOP RUN.
さらに、呼び出される3つのプログラム「在庫マスタ更新2.cob」、「発注帳票作成2.cob」、「欠品帳票作成2.cob」は最後がSTOP RUNとなっているので、それらを EXIT PROGRAMに修正する必要がある。
在庫マスタ更新2.cobの場合、このプログラムを主プログラムとして呼び出すことも想定して、STOP RUNは残してある。それは主プログラムとして実行されたとき、EXIT PROGRAMは特に何もせず次のステップへ制御を移し、「在庫調整処理」段落の手続きを実行してしまうからである。
(在庫マスタ更新2.cob)
000860 CLOSE トランザクションCSV.
000870 CLOSE 在庫マスタ.
000880 CLOSE 発注ファイル.
000890 CLOSE 欠品ファイル.
000900 EXIT PROGRAM. *> 副プログラムの場合は呼ばれたプログラムに戻る
000910 STOP RUN. *> 主プログラムの場合は終了
000920
000930 在庫調整処理.
:
発注帳票作成2.cob、欠品帳票作成2.cobについては、一番最後の行に EXIT PROGAMを入れたが、これで主プログラムとして呼ばれたら終了となるし、副プログラムとして呼ばれたら呼ばれたプログラムに戻るが、実は EXIT PROGAMは書かなくともプログラムの最後の行には、暗黙の EXIT PROGRAMがあるとみなされる。
(発注帳票作成2.cob)
001130 CLOSE 発注ファイル.
001140 CLOSE 商品マスタ.
001150 CLOSE 倉庫マスタ.
001160 CLOSE 発注帳票.
001170 EXIT PROGRAM. *> 副プログラムの場合は呼ばれたプログラムに戻る
(欠品帳票作成2.cob)
001340 CLOSE 欠品ファイル.
001350 CLOSE 商品マスタ.
001360 CLOSE 倉庫マスタ.
001370 CLOSE 顧客マスタ.
001380 CLOSE 欠品帳票.
001390 EXIT PROGRAM.
このように、SITCOBOLは、ファイルやフォルダ、プロセスIDなどを制御する機能を備えており、バッチファイル等を使わなくても、ある程度有用なアプリケーションを構築することができる。