「python」タグアーカイブ

JARL の 6 ワク

国産でないログソフトを使う一番のネックは QSL プリントであろうか。
CQRLOG のエクスポートする csv を libreOffice Calc に読み込み、

  • via 列設置、IF 関数で via 入力、
  • 6 ワク設置、LEFT, MID 関数で出力
  • 不適切箇所修正、余分な列削除
  • JA はエリア区分せよとのことで JA 別ファイル。
  • ナンバーでソート

をやって、やっとプリントの準備ができる。

しかしこの作業をするのが、寄る年波に勝てずだんだん億劫に・・・
そこで年も考えず、csv なら python (私はフランス語風にピトンと読む)でできないかと考えたが、無論 python の知識があるわけでない。

AI に相談するも六文字とリマークスの位置関係で全く無駄な一日になったことも。
アキラメてログオフしてから考えた。 不自然だが、六文字の列を末尾にすれば、リマークスが非表示だったりを回避できるのではと考え csv を作り変えてみた。結果成功だった。
となれば、列の入れ替えを AI に相談すればいい。

結果は、via が文字分解されたり、リマークスが文字分解されたり。
どうやら入れ替えによっての列指定がマチガッていると気づいた。
ソレを修正してやると期待通りの cxv を得ることができた。

読み込んだ csv 注意

Date,Time,Call,Mode,Freq,RSTs,RSTr,Rmks,Mgr

因みにここでは /P や KH2/ などは考慮していない。 AI にも相談したが不成功に終わった。

import csv

# 入力ファイル名と出力ファイル名
input_file = 'input.csv'
output_file = 'output.csv'

# データを処理して出力ファイルに書き込む関数
def process_csv(input_file, output_file):
    with open(input_file, 'r', newline='', encoding='utf-8') as infile, \
         open(output_file, 'w', newline='', encoding='utf-8') as outfile:
        
        reader = csv.reader(infile)
        writer = csv.writer(outfile)
        
        for row in reader:
            # 行の長さが足りない場合はスキップする
            if len(row) < 10:
                continue

            # H列が空の場合にC列をコピー
            if not row[7]:
                row[7] = row[2]
            else:
                row.insert(9, 'via')  # H列が空でない場合にJ列に"via"を追加

            # I列とJ列の値を入れ替える
            row[8], row[9] = row[9], row[8]

            # H列のデータをK列以降の列に一文字ずつのデータとして書き込む
            h_chars = list(row[7])
            row[10:10+len(h_chars)] = h_chars
            
            # 出力ファイルに書き込む
            writer.writerow(row)

# CSVファイルの処理を実行
process_csv(input_file, output_file)

最初 9 列の csv だったので

Traceback (most recent call last):
  File "/home/NAME/TEST.py", line 33, in <module>
    process_csv(input_file, output_file)
  File "/home/NAME/TEST.py", line 17, in process_csv
    row[8], row[9] = row[9], row[8]
IndexError: list index out of range

と叱られてしまった。どうやらプラス一列は必要のようだ。
それくらいは sed でやっても知れてる。

sed -e "s/\$/,,/"

AI って何様?

私は一往メール添付 QSL も受け入れている。
GIMP 拡げてデータ・インプットすればソレで済む話だが、
ここんとこちょっと溜めてしまった。

そこで「コマンドで画像に文字入れ」で検索すると、
ImageMagick の convert でできるという。

convert QSLImage.jpg -family 'Monaco-Bold' -style Italic -pointsize 36 -fill Black -annotate +400+497 'CALLSIGN' -style Any -family Monaco -pointsize 24 -fill Black -annotate +140+525 'DATE' -style Any -family Monaco -pointsize 24 -fill Black -annotate +470+525 'TIME' -style Any -family Monaco -pointsize 24 -fill Black -annotate +750+525 'MODE' -style Any -family Monaco -pointsize 24 -fill Black -annotate +140+558 'FREQ' -style Any -family Monaco -pointsize 24 -fill Black -annotate +485+558 'RST' -style Any -family Monaco -pointsize 24 -fill Blue -annotate +45+600 'Rmks' output.jpg

ってな感じだ。

しかし溜めてしまったことで「スクリプトでできないか」と考えた。
Python もこないだやったので、どのように使うかだけ理解した。
ChatGPT に相談した。

一発目の回答、何も表示されない。
何度かのやり取りで AI が「勝手に」出力項目数や出力位置を変更して、トンデモナイ位置に出力しているのに気づいた。人間相手ならケンカ売ってたろう・・・
七箇所もあるのに二個しか出力されていない。こっちは七つもインプットしてるのに。

elif で追加すればいいことを確認して、終了した。勉強にはなったが。

import subprocess

def main():
    items = {}
    item_order = ['call', 'date', 'time', 'mode', 'freq', 'rst', 'rmks']
    for item_name in item_order:
        item_text = input("Enter {}: ".format(item_name))
        items[item_name] = item_text

    output_file = input("Enter the output file name: ")

    cmd = ['convert', 'QSLImage.jpg']
    for item_name, item_text in items.items():
        if item_name == 'call':
            cmd.extend(['-family', 'Monaco-Bold', '-style', 'Italic', '-pointsize', '28', '-weight', 'Bold', '-fill', 'Black', '-annotate',
                        '+400+497', item_text])
        elif item_name == 'date':
            cmd.extend(['-family', 'Monaco', '-weight', 'Normal', '-pointsize', '24', '-fill', 'Black', '-annotate',
                        '+140+525', item_text])
        elif item_name == 'time':
            cmd.extend(['-family', 'Monaco', '-weight', 'Normal', '-pointsize', '24', '-fill', 'Black', '-annotate',
                        '+470+525', item_text])
        elif item_name == 'mode':
            cmd.extend(['-family', 'Monaco', '-weight', 'Normal', '-pointsize', '24', '-fill', 'Black', '-annotate',
 	 		'+750+525',item_text])
        elif item_name == 'freq':
            cmd.extend(['-family', 'Monaco', '-weight', 'Normal', '-pointsize', '24', '-fill', 'Black', '-annotate',
 	 		'+140+558',item_text])
        elif item_name == 'rst':
            cmd.extend(['-family', 'Monaco', '-weight', 'Normal', '-pointsize', '24', '-fill', 'Black', '-annotate',
 	 		'+485+558',item_text]) 	 		                                               
        else:
            cmd.extend(['-family', 'Monaco', '-weight', 'Normal', '-pointsize', '24', '-fill', 'Blue', '-annotate',
                        '+45+600', item_text])

    cmd.append(output_file)

    try:
        subprocess.run(cmd, check=True)
        print("Conversion completed successfully. Output file:", output_file)
    except subprocess.CalledProcessError as e:
        print("Error occurred while running convert command:")
        print(e)


if __name__ == "__main__":
    main()

枚数抜きで pdf ファイルを作ってしまった

ときには片面のカードが 10 枚も遭ったりすると、qsl 枚数は熟しているのにファイル数は 1 しか増えない。
baobab はフォルダ数もカウントするから、500 アイテムあってもそこからサブフォルダ数を引いたのがファイルっ数になる。でもカードは 700 を超えているハズと思う。
そこで pdf のページ数を調べなくってはならない。単体なら pdfinfo でわかる。

LibreOffice でもマクロでできるらしいが、フォルダのファイル群から取得するというのは見当たらなかった。
そこで ChatGPT に相談した。こちらは特定フォルダから、ファイラーを開かずにサブフォルダ名を入力して、ページ数を得たかった。

import os
import PyPDF2

def count_pages(pdf_path):
    with open(pdf_path, 'rb') as pdf_file:
        pdf_reader = PyPDF2.PdfFileReader(pdf_file)
        return pdf_reader.numPages

def process_subfolders(root_folder):
    for subdir, _, files in os.walk(root_folder):
        for filename in files:
            if filename.endswith('.pdf'):
                pdf_path = os.path.join(subdir, filename)
                page_count = count_pages(pdf_path)
                print(f'ファイルパス: {pdf_path}, ページ数: {page_count}')

if __name__ == "__main__":
    relative_folder = input("基準フォルダの相対パスを入力してください: ")
    base_folder = os.path.join("/home/NAME/Documents/XYZ", relative_folder)
    
    if os.path.exists(base_folder):
        process_subfolders(base_folder)
    else:
        print("指定されたフォルダは存在しません。")

で ChatGPT は python count_pages.py と走らせればよいと言った。
が、python3 がインストールしてあるので、python3 count_pages.py とした。
しかし、出力はタイムスタンプのようで、参照するには使いにくい。

$ python3 count_pages.py | sed -e "s/基準フォルダの相対パス を入力してください: //" | sort -k 2 -t ' '

とすれば、ファイル名ソートされて出てくる。

どうせならソートまで python で完結させたいともう一度 ChatGPT に相談。

import os
import PyPDF2

def count_pages(pdf_path):
    with open(pdf_path, 'rb') as pdf_file:
        pdf_reader = PyPDF2.PdfFileReader(pdf_file)
        return pdf_reader.numPages

def process_subfolder(base_folder, subfolder_name):
    subfolder_path = os.path.join(base_folder, subfolder_name)
    pdf_files = []  # ファイル情報を保存するリスト
    for filename in os.listdir(subfolder_path):
        if filename.endswith('.pdf'):
            pdf_path = os.path.join(subfolder_path, filename)
            page_count = count_pages(pdf_path)
            pdf_files.append((pdf_path, page_count))  # ファイル情報をリストに追加

    # ファイル名でソート
    pdf_files.sort(key=lambda x: x[0])

    for pdf_info in pdf_files:
        pdf_path, page_count = pdf_info
        print(f'ファイルパス: {pdf_path}, ページ数: {page_count}')

if __name__ == "__main__":
    base_folder = "/home/NAME/Documents/XYZ"  # 基準フォルダのパス
    subfolder_name = input("サブフォルダ名を入力してください: ")
    process_subfolder(base_folder, subfolder_name)

と結果を得た。

これで枚数を引数としたファイル名にリネームすれば、カード枚数もカウントできるだろう。