COBOLでつくる「売上明細集計プログラム(CSV集計)」

スポンサーリンク
COBOL

今回は、商品名、金額を含む入力ファイル(sales.csv)を読み取り、商品ごとの売上金額を合計し、summary.csv に出力するプログラムをご紹介しよう。

入力ファイル:sales.csv

りんご,100
みかん,150
りんご,120

出力ファイル:summary.csv

りんご           ,000220
みかん           ,000150

プログラム:sales_summary.cob

  
       IDENTIFICATION DIVISION.
       PROGRAM-ID. SALES-SUMMARY.

       *> 入力ファイル:sales.csv(商品名,金額)
       *> 商品ごとの売上金額を合計し、summary.csv に出力


   ENVIRONMENT DIVISION.
   INPUT-OUTPUT SECTION.
   FILE-CONTROL.
       SELECT INPUT-FILE ASSIGN TO "sales.csv"
           ORGANIZATION IS LINE SEQUENTIAL.
       SELECT OUTPUT-FILE ASSIGN TO "summary.csv"
           ORGANIZATION IS LINE SEQUENTIAL.

   DATA DIVISION.
   FILE SECTION.
   FD  INPUT-FILE.
   01  INPUT-RECORD         PIC X(80).

   FD  OUTPUT-FILE.
   01  OUTPUT-RECORD        PIC X(80).

   WORKING-STORAGE SECTION.
   01  WS-EOF               PIC X VALUE "N".
   01  WS-LINE              PIC X(80).
   01  WS-NAME              PIC X(20).
   01  WS-AMOUNT-STR        PIC X(10).
   01  WS-AMOUNT            PIC 9(6) COMP-5.

   01  WS-NAME1             PIC X(20) VALUE SPACES.
   01  WS-TOTAL1            PIC 9(6) VALUE 0.
   01  WS-NAME2             PIC X(20) VALUE SPACES.
   01  WS-TOTAL2            PIC 9(6) VALUE 0.

   PROCEDURE DIVISION.
   MAIN.
       OPEN INPUT INPUT-FILE
       OPEN OUTPUT OUTPUT-FILE

       PERFORM UNTIL WS-EOF = "Y"
           READ INPUT-FILE
               AT END
                   MOVE "Y" TO WS-EOF
               NOT AT END
                   MOVE INPUT-RECORD TO WS-LINE
                   PERFORM PARSE-LINE
                   PERFORM UPDATE-TOTALS
           END-READ
       END-PERFORM

       PERFORM WRITE-TOTALS

       CLOSE INPUT-FILE
       CLOSE OUTPUT-FILE
       STOP RUN.

   PARSE-LINE.
       UNSTRING WS-LINE
           DELIMITED BY ","
           INTO WS-NAME, WS-AMOUNT-STR
       MOVE FUNCTION NUMVAL (WS-AMOUNT-STR) TO WS-AMOUNT.

   UPDATE-TOTALS.
       IF WS-NAME = WS-NAME1
           ADD WS-AMOUNT TO WS-TOTAL1
       ELSE IF WS-NAME1 = SPACES
           MOVE WS-NAME TO WS-NAME1
           MOVE WS-AMOUNT TO WS-TOTAL1
       ELSE IF WS-NAME = WS-NAME2
           ADD WS-AMOUNT TO WS-TOTAL2
       ELSE IF WS-NAME2 = SPACES
           MOVE WS-NAME TO WS-NAME2
           MOVE WS-AMOUNT TO WS-TOTAL2
       END-IF.

   WRITE-TOTALS.
       IF WS-NAME1 NOT = SPACES
           STRING WS-NAME1 DELIMITED BY SIZE
                  "," DELIMITED BY SIZE
                  WS-TOTAL1 DELIMITED BY SIZE
                  INTO OUTPUT-RECORD
           WRITE OUTPUT-RECORD
       END-IF

       IF WS-NAME2 NOT = SPACES
           STRING WS-NAME2 DELIMITED BY SIZE
                  "," DELIMITED BY SIZE
                  WS-TOTAL2 DELIMITED BY SIZE
                  INTO OUTPUT-RECORD
           WRITE OUTPUT-RECORD
       END-IF.

コンパイルと実行

cobc -x -free sales_summary.cob
./sales_summary 

COBOLの -free オプションを使う場合、コメントは *> を使うこと。

 *> 入力ファイル:sales.csv(商品名,金額)
 *> 商品ごとの売上金額を合計し、summary.csv に出力

* だけのコメントは、固定形式ではOKだが、自由形式ではエラーになる。

1. IDENTIFICATION DIVISION

IDENTIFICATION DIVISION.
PROGRAM-ID. SALES-SUMMARY
  • プログラムの識別情報を記述するセクションである。
  • PROGRAM-ID はプログラム名。今回は、SALES-SUMMARYである。

2. ENVIRONMENT DIVISION

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT INPUT-FILE ASSIGN TO "sales.csv"
  ORGANIZATION IS LINE SEQUENTIAL.
SELECT OUTPUT-FILE ASSIGN TO "summary.csv"
  ORGANIZATION IS LINE SEQUENTIAL.
  • ファイルの入出力に関する設定をする。
  • sales.csv を読み込み用ファイル、summary.csv を書き込み用ファイルとして指定する。
  • LINE SEQUENTIAL はテキストファイルを1行ずつ処理する形式である。

3. DATA DIVISION

FILE SECTION
FD INPUT-FILE.
01 INPUT-RECORD PIC X(80).

FD OUTPUT-FILE.
01 OUTPUT-RECORD PIC X(80).
  • ファイルのレコード構造を定義する。
  • 各行最大80文字まで読み書き可能である。
WORKING-STORAGE SECTION
01 WS-EOF PIC X VALUE "N".
01 WS-LINE PIC X(80).
01 WS-NAME PIC X(20).
01 WS-AMOUNT-STR PIC X(10).
01 WS-AMOUNT PIC 9(6) COMP-5.
01 WS-NAME1 PIC X(20) VALUE SPACES.
01 WS-TOTAL1 PIC 9(6) VALUE 0.
01 WS-NAME2 PIC X(20) VALUE SPACES.
01 WS-TOTAL2 PIC 9(6) VALUE 0.
  • 作業領域の変数定義をする。
  • WS-EOF はファイルの終端判定する。
  • WS-NAME, WS-AMOUNT-STR はCSVの分解結果である。
  • WS-AMOUNT は数値変換後の金額である。
  • WS-NAME1, WS-NAME2 は商品名(最大2種類)である。
  • 作業領域の変数定義をする。
  • WS-EOF はファイルの終端判定をする。
  • WS-NAME, WS-AMOUNT-STR はCSVの分解結果である。
  • WS-AMOUNT は数値変換後の金額である。
  • WS-NAME1, WS-NAME2 は商品名(最大2種類)である。
  • WS-TOTAL1, WS-TOTAL2 はそれぞれの合計金額である

4. PROCEDURE DIVISION

MAIN処理

OPEN INPUT INPUT-FILE
OPEN OUTPUT OUTPUT-FILE
PERFORM UNTIL WS-EOF = "Y"
  READ INPUT-FILE
    AT END
      MOVE "Y" TO WS-EOF
    NOT AT END
      MOVE INPUT-RECORD TO WS-LINE
      PERFORM PARSE-LINE
      PERFORM UPDATE-TOTALS
END-READ
END-PERFORM
PERFORM WRITE-TOTALS
CLOSE INPUT-FILE
CLOSE OUTPUT-FILE
STOP RUN.
  • ファイルを開いて、1行ずつ読み込む。
  • PARSE-LINE でCSVを分解する。
  • UPDATE-TOTALS で商品ごとの合計を更新する。
  • 最後に WRITE-TOTALS で結果を書き出す。
PARSE-LINE(CSV分解)

UNSTRING WS-LINE
  DELIMITED BY ","
  INTO WS-NAME, WS-AMOUNT-STR
MOVE FUNCTION NUMVAL (WS-AMOUNT-STR) TO WS-AMOUNT.
  • UNSTRING で商品名と金額を分離する。
  • NUMVAL 関数で文字列から数値に変換する。
UPDATE-TOTALS(集計処理)

IF WS-NAME = WS-NAME1
  ADD WS-AMOUNT TO WS-TOTAL1
ELSE IF WS-NAME1 = SPACES
  MOVE WS-NAME TO WS-NAME1
  MOVE WS-AMOUNT TO WS-TOTAL1
ELSE IF WS-NAME = WS-NAME2
  ADD WS-AMOUNT TO WS-TOTAL2
ELSE IF WS-NAME2 = SPACES
  MOVE WS-NAME TO WS-NAME2
  MOVE WS-AMOUNT TO WS-TOTAL2
END-IF.
  • 商品名が既存のものと一致すれば加算する。
  • 初めての名前なら登録して初期化する。
  • 商品は最大2種類まで対応する。
WRITE-TOTALS(出力処理)

IF WS-NAME1 NOT = SPACES
  STRING WS-NAME1 DELIMITED BY SIZE
         "," DELIMITED BY SIZE
         WS-TOTAL1 DELIMITED BY SIZE
    INTO OUTPUT-RECORD
  WRITE OUTPUT-RECORD
END-IF
IF WS-NAME2 NOT = SPACES
  STRING WS-NAME2 DELIMITED BY SIZE
         "," DELIMITED BY SIZE
         WS-TOTAL2 DELIMITED BY SIZE
    INTO OUTPUT-RECORD
  WRITE OUTPUT-RECORD
END-IF.
  • 商品名と合計金額をCSV形式で出力する。
  • STRING で1行を構築し、WRITE で書き込みする。

コメント

タイトルとURLをコピーしました