csv ファイルをオブジェクトとして操作する

## csv ファイルを編集・操作する class

1. `import csv` は csv ファイルアクセス用  `import Enum` はユーザ定義関数のステータス用。
1. CsvFile class は csv ファイルを list で ファイルパスを str で保持。
1. CsvFile class メンバから、ファイル読み書き、行/列/セル 編集操作する。

```python

import csv
from enum import Enum

# csv class のステータス
class CsvStatus(Enum):
    OK = 0
    NG = 1

# csvファイル編集用のclass
class CsvFile:

    __csv_cells:list  # csvをlistで覚えておく
    __file_path:str   # csvファイルパス

    # ファイルパスのproperty
    @property
    def file_path(self):
        return self.__file_path

    @file_path.setter
    def file_path(self, path:str):
        self.__file_path = path

    # constractor
    def __init__(self):
        self.__csv_cells = []
        self.__file_path = ''
        return

    # "行"を挿入する。
    def insert_row(self, row:int, ins_list:list):
        self.__csv_cells.insert(row,ins_list)
        return CsvStatus.OK

    # "列"を挿入する。
    def insert_col(self, col:int, data):
        # 全ての行に対して列を挿入する。
        [ row.insert(col, data) for row in self.__csv_cells ]
        return CsvStatus.OK

    # "行"を削除する。
    def remove_row(self, row:int):
        self.__csv_cells.pop(row)    # clear() 全削除 / remove() 先頭削除
        return CsvStatus.OK

    # "列"を削除する。
    def remove_col(self, col:int):
        # 全ての行に対して列を削除する。
        [ row.pop(col) for row in self.__csv_cells ]
        return CsvStatus.OK

    # セルを更新する。
    def update(self, row:int, col:int, data):
        self.__csv_cells[row][col] = data
        return CsvStatus.OK

    # セルを表示する。
    def print(self):
        for row in self.__csv_cells:
            for cell in row:
                # 改行の変わりにタブを出力し、セル情報のみ出力する。
                print(cell, end='\t')
            # 改行
            print()
        return CsvStatus.OK

    # csv ファイルを読み込む
    def load(self, path:str):

        try:
            # csv ファイルを読み取りで開く。
            with open(path, mode="r", encoding="UTF-8") as file:

                # csv reader を取得する。(書式の指定は dialect でまとめて指定)
                reader = csv.reader(file, dialect=csv.excel_tab)

                # csv をメモリ展開（軽いファイル前提）
                self.__csv_cells = [ row for row in reader ]
        except FileNotFoundError: 
            self.__file_path = ''
            st = CsvStatus.NG
        except:
            self.__file_path = ''
            st = CsvStatus.NG
        else:
            # ファイルパスを覚えておく
            self.__file_path = path
            st = CsvStatus.OK

        return st

    # csv ファイルを保存する
    def save(self):

        try:
            # csv ファイルを新規作成する。
            with open(self.__file_path, mode="w", newline='', encoding="UTF-8") as file:

                # csv writer を取得する。(QUOTE_ALLで、全てクオート("")する)
                writer = csv.writer(file, delimiter='\t', quoting=csv.QUOTE_ALL)

                # データを出力する。
                writer.writerows(self.__csv_cells)
        except FileNotFoundError:
            st = CsvStatus.NG
        except:
            st = CsvStatus.NG
        else:
            st = CsvStatus.OK

        return st
```

## CsvFile class を使って csv ファイルを操作するサンプル

1. CsvFile のインスタンス作成し、load() で csv ファイルを開く。
1. CsvFile オブジェクトを操作する。
1. 別名を設定し、save() で保存する。

```python
import csv_file as cf

csv = cf.CsvFile()

csv.load("./csv/sample.csv")

# csvの内容とファイルパスを表示
csv.print()
print( f'File path is {csv.file_path}' )

# 行を追加する。
csv.insert_row(2, [ 99, '佐藤', 50 ])
csv.print()

# 列を追加する。
csv.insert_col(2, 'Data')
csv.print()

# ファイルパスを変更して保存する。
csv.file_path = "./csv/sample2.csv"
csv.save()
```

:::note info
- class メンバには、他に行/列の取得やコピーなどのメンバがあると便利。
- list で保持しているので、大きなサイズの csv ファイルには向かない。
:::