「csv」タグアーカイブ

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/\$/,,/"

csv を CQRlog に取り込み

CQRlog を知る前は LibreOffice Calc に記録していた、
そして 30 QTH 近い移動運用も行っていた。

今 CQRlog に 40,000 を超えるログ・エントリーがあるが、SSB QSO は 4,000 余でしかない。それで Calc から csv に落として取り込もうと考えた。

win では csv も読み込める AdifMaster という優れたツールがあるが、Linux には存在しない。
と思っていたら adifmerg というツールがあるが、csv to adif を念頭に置いたものではなく、csv ヘッダーも特殊なスタイルだった。 単純に QSO を取り込むだけならソレでもいいのだが。
名前、QTH, JCC/JCG なども記録があるので・・・。

この adifmerg はアプリケーションではなく Perl スクリプトであることがわかった。 しかし Perl の素養は全くナシ。 それで AI に相談した。

AI が最初に提示したのが

#!/usr/bin/perl

use strict;
use warnings;

# CSVファイルのパスを指定
my $csv_file = 'input.csv';

# 出力するADIF形式のファイル名
my $adif_file = 'output.adif';

# CSVファイルを開く
open my $csv_fh, '<', $csv_file or die "Cannot open $csv_file: $!";

# ADIF形式のファイルを開く
open my $adif_fh, '>', $adif_file or die "Cannot open $adif_file: $!";

# ADIFヘッダーを出力
print $adif_fh "ADIF Export\n";

# CSVのヘッダーを読み込む
my $header = <$csv_fh>;
chomp $header;
my @fields = split ',', $header;

# CSVファイルからデータを読み込んでADIF形式に変換して出力
while (my $line = <$csv_fh>) {
    chomp $line;
    my @values = split ',', $line;
    print $adif_fh "<QSO_DATE:$values[1]>".$values[2]."<TIME_ON:$values[3]>".$values[4]."<CALL:$values[5]>".$values[6]."<QTH:$values[7]>".$values[8]."<GRIDSQUARE:$values[9]>".$values[10]."<DXCC:$values[11]>".$values[12]."<MODE:$values[13]>".$values[14]."<QSL_S:$values[15]>".$values[16]."<QSL_R:$values[17]>\n";
}

# ファイルを閉じる
close $csv_fh;
close $adif_fh;

print "Conversion completed.\n";

しかし CQRlog にはインポートできなかった。

  • 日本語文字が 3 byte で扱われている
  • 文字数カウントがないのも致命的
  • <eor> が抜けているのが致命的

私のログに中国局が漢字で記録されているエントリーが完全に「文字数カウント」であることがわかった。
そして csv ヘッダーは adif タグと同一でなければならず、日本語文字が入るところは連続して並べると、前者が無視されるので、最終的には影響の小さいアイテムを日本語項目の後ろに置くことにした。
則ち Calc 側で予め列の移動が必要になる。
私の場合 adif の日付や時刻の仕様を踏まえたカタチで Calc にインプットしていたので、今回新たに変換する作業が省略できた。

call,qso_date,time_on,freq,band,mode,rst_sent,rst_rcvd,cnty,gridsquare,qth_intl,\
app_cqrlog_qsls,app_cqrlog_qslr,my_gridsquare,name_intl,comment,notes,award

で app_cqrlog_qsls は「ビューロー発送済み」の B なので、group edit で B を入れた。 award は私の場合 DIG を選んでいるので、対象が少ないから手で追加しても良いとした。
comment も古い QSO には殆どないし、JAG/ACC 或いは YL は notes でよいとした。

インポートした adif のカタチ(サイレントキー):

<call:6>JA4XZR <qso_date:8>19940102 <time_on:4>0357 <freq:7>18.1300 <band:3>17m <mode:3>SSB <rst_sent:2>59 <rst_rcvd:2>59 <cnty:4>3102 <gridsquare:0> <qth_intl:3>倉敷市 <app_cqrlog_qsls:1>B <app_cqrlog_qslr:1>Q <my_gridsquare:6>QN04ua <name_intl:2>福岡 <comment:0> <notes:8>JAG#0028 <award:8>DIG#5237 <eor>

インポート後 B 挿入後の adif のカタチ:

<qso_date:8>19940102 <time_on:4>0357 <call:6>JA4XZR<mode:3>SSB <freq:5>18.13 <band:3>17m <rst_sent:2>59 <rst_rcvd:2>59 <name_intl:2>福岡 <qth_intl:3>倉敷市 <qsl_rcvd:1>Y <iota:6>AS-007 <award:8>DIG#5237 <app_cqrlog_dxcc:2>JA <dxcc:3>339 <notes:8>JAG#0028 <ituz:2>45 <cqz:2>25 <cnty:4>3102 <app_cqrlog_qslr:1>Q <eor>

適用した pl ファイル(csv と adif ファイル名指定して処理)

#!/usr/bin/perl

use strict;
use warnings;

# 入力ファイルのパスをユーザーに尋ねる
print "Enter input CSV file path: ";
my $csv_file = <STDIN>;
chomp $csv_file;

# 出力ファイルのパスをユーザーに尋ねる
print "Enter output ADIF file path: ";
my $adif_file = <STDIN>;
chomp $adif_file;

# CSVファイルを開く
open my $csv_fh, '<:encoding(utf8)', $csv_file or die "Cannot open $csv_file: $!";

# ADIF形式のファイルを開く
open my $adif_fh, '>:encoding(utf8)', $adif_file or die "Cannot open $adif_file: $!";

# ADIFヘッダーを出力
print $adif_fh "ADIF Export\n";

# CSVのヘッダーを読み込む
my $header = <$csv_fh>;
chomp $header;
my @fields = split ',', $header;

# CSVファイルからデータを読み込んでADIF形式に変換して出力
while (my $line = <$csv_fh>) {
    chomp $line;
    my @values = split ',', $line;
    foreach my $field (@fields) {
        my $value = shift @values // ''; # 未初期化の値を防ぐためにデフォルト値を設定
        my $tag = lc $field; # タグを小文字に
        my $length = length($value); # フィールドの文字数を取得
        # 2 バイト文字を 2 文字としてカウント
        my $byte_length = (() = $value =~ /./g); # 文字列内の文字数をカウント
        print $adif_fh "<$tag:$byte_length>$value ";
    }
    print $adif_fh "<eor>\n"; # ADIFレコードの終わりを追加
}

# ファイルを閉じる
close $csv_fh;
close $adif_fh;

print "Conversion completed.\n";

pl 文のコメントにも「# 2 バイト文字を 2 文字としてカウント」、これは「# 2 バイト文字を 1 文字としてカウント」の誤りでしょうね。

それにしてもこういうとき、AI に完全丸投げでも、パーフェクトな回答を得られるものではないんですね。 <eor> が抜けるなんて人間並じゃありませんか。 尤も有料サービスならこんなこともないんでしょうが。

所謂 2 バイト文字は 3 バイトに換算されるようで、コンパイルツールである lazarus や fpc でも日本語文字の扱いがまだパーフェクトな段階に至ってないらしい。 となれば、CQRlog が影響を受けるのは致し方ないのかも知れない。
その辺をキラって JA のエントリーも英文字で行うというのも頷ける。

QSL プリント

昨年 6 月 JT65 を始めて以来、ログは CQRlog であるが、このアプリケーションには QSL プリントはシールプリントしかない。 ダイレクト・プリントには非対応である。
それで暫くは LibreOffice Calc との二重ログでやっていた。
しかし、転記ミスも起こしかねないし、寧ろ大儀になってきたというのが正直なところ。

プリントは gLabels に csv ファイルを読み込んで行うので、adif から csv に変換するコンバーターがあればいいのだが、ADIF to Excel to ADIF Converter といったものもあるけど、 Ubuntu では VB ランタイムの関係からかどうも成功しない。

以前は他になかったような記憶があるが、探してみると AD1C なる windows ソフト があるようで、それを試してみる。
作者コールサインが AD1C。 操作は単純で 600 QSO のデータも即座に出力された。

しかし Ubuntu に帰って gedit に読み込ませて唖然とした。
文字コードのエラーはともあれ、元々の時刻が引用符に囲まれ、更に時分区切りのコロンが消えていた。
文字コードに ISO-8859-1 を追加してやれば、正常に gedit は対応した。

Calc に読み込むと、時刻の 00:05 がただの 5 と表示され,どうすれば正常に表示できるか悩んだ。
結果的には 0 を先行させ、あとはユーザー定義で 00:00 スタイルにするだけの話だった。 MS-Excel では =VALUE(TEXT(B1,”00!:00″)) といった関数で行うとのことだった。

JARL 転送枠は以前は手動でやっていたが、これも関数を使うことでミス防止ができた。
プリフィックス・トップレターは =LEFT{A1,1) でゲットでき、セカンドレターは =MID(A1,2,1) でできることを知った。

一月は仕事をしていたので、やや少なかった QSO が二月のエブリデイ・サンデイによってやや多かった。
QSL プリントしなくっちゃ。