読者です 読者をやめる 読者になる 読者になる

Pythonで写真を集計2

import click
import csv
from operator import itemgetter


@click.command()
@click.option('--title', '-t', help='Title Mode', is_flag=True)
@click.argument('input_file', type=click.File('r'))
@click.argument('output_file', default='result.csv', required=False, type=click.File('w'))
def cmd(title, input_file, output_file):

    with input_file as fr:

        reader = csv.reader(fr)

        data = []
        header = next(reader)

        # 写真タイトルの重複チェック
        t = set()
        duplication = [x for x in header if x in t or t.add(x)]

        if duplication and title:
            print('エラー:写真タイトルが重複しています')
            print(*duplication)
            exit(1)

        for row in reader:

            for i, name in enumerate(row[1:], start=1):

                if name:

                    if title:
                        # タイトル名
                        data.append([name, header[i], 1])
                    else:
                        # 通し番号
                        data.append([name, i, 1])

    # ソート(名前・番号順)
    data.sort(key=itemgetter(0, 1))

    with output_file as fw:

        writer = csv.writer(fw, lineterminator='\n')
        writer.writerows(data)

if __name__ == '__main__':
    cmd()
pip install pyinstaller

pyinstaller --onefile aggregate.py

EXE化したがclickだと動かないのでargparseにすると動いた。

import csv
import argparse
from operator import itemgetter


def cmd(title, input_file, output_file):

    with input_file as fr:

        reader = csv.reader(fr)

        data = []
        header = next(reader)

        # 写真タイトルの重複チェック
        t = set()
        duplication = [x for x in header if x in t or t.add(x)]

        if duplication and title:
            print('エラー:写真タイトルが重複しています')
            print(*duplication)
            exit(1)

        for row in reader:

            for i, name in enumerate(row[1:], start=1):

                if name:

                    if title:
                        # 写真タイトル
                        data.append([name, header[i], 1])
                    else:
                        # 通し番号
                        data.append([name, i, 1])

    # ソート(名前・番号順)
    data.sort(key=itemgetter(0, 1))

    with output_file as fw:

        writer = csv.writer(fw, lineterminator='\n')
        writer.writerows(data)


if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='Photo List to Table')
    parser.add_argument(
        '-t', '--title', action='store_true', help='title mode')
    parser.add_argument('input_file', type=argparse.FileType('r'))
    parser.add_argument('output_file', nargs='?',
                        type=argparse.FileType('w'), default='result.csv')
    args = parser.parse_args()

    cmd(args.title, args.input_file, args.output_file)

クラスと名前の名簿からクラスを追加

.mode csv

-- 写真リストを読み込み
create table photo(name text, number integer, count integer);
.import name_sort.csv photo

-- 名簿リストを読み込み
create table meibo(class text, name text);
.import meibo_list.csv meibo

-- CSV保存用にヘッダー表示
.headers on

-- クラス・名前・写真番号・枚数の一覧表作成

.output photo_total.csv
select meibo.class, photo.name, photo.number, photo.count
from photo inner join meibo on photo.name = meibo.name
order by meibo.class asc, photo.name asc, photo.number asc;

-- クラス・名前・枚数・金額・写真番号すべての一覧表作成

.output photo_class.csv

-- * 50の部分は単価のため単価変更
select meibo.class, photo.name, sum(photo.count) as total, sum(photo.count) * 50 as price, group_concat(photo.number, ',') as numbers
from photo inner join meibo on photo.name = meibo.name
group by photo.name
order by meibo.class asc, photo.name asc;