NasupiiのPerl書抜帳

MS-Excelからのデータ取り込み時のデータ整形プログラムソースコード

Perl ソースコード

# ================================================================================
# 評価用に付けたメインプログラム
# Copyright (C) 2013 Nasupii
# ================================================================================
$FNAME_I = "Book1.txt";   # 入力ファイル名
$FNAME_O = "book1x.txt";  # 出力ファイル名
open(IN, "< $FNAME_I");
$buf = "";
while( $line = <IN>) {
  $buf .= $line;
}
close(IN);
print "\n=====元データ======================\n",$buf;
tr_tabtxt($buf);
print "\n=====変換後データ==================\n",$buf;
open(OUT, "> $FNAME_O");
print OUT $buf;
close(OUT);
exit;

# ================================================================================
# sub tr_tabtxt
# MS-Excelからデータをタブ区切りテキストファイルで出力し
# perlプログラムで取り込むとき問題になる事項を解消する
# このサブプログラムは Shift-JIS 専用とする
# Copyright (C) 2013 Nasupii
# 2013/02/11 初版作成
# 使い方
# 1.メインプログラムでタブ区切りテキストファイルを1つの文字列に読み込む。
# 2.読み込んだ文字列を引き数として、このサブルーチンを呼ぶ。
# 3.引数の文字列が置き換えられれメインルーチンに戻る。
# ================================================================================
# a.セル内に改行がある場合
#    改行を含むセルは、セルの始まりと終わりに " がついて、
#    改行はそのまま出力される。Excelでは1行だったものが複数行になる
#    ので、正しく読み込めない不具合がある。
#    そこで、セル内の改行はシフトJISで割り当てられていない 0xfeに
#    いったん置き換えし、余分についた " を削除したのち、0xfe を
#    $NL で指定した文字に再度置き換える。
#    この例では、_| に置き換えている。
# b.セル内に , (カンマ)が入っている場合
#    , (カンマ)を含むセルは、セルの始まりと終わりに " がついて、
#    カンマはそのまま出力される。
#    そこで、余分についた " を削除する。
# c.セル内に " (二重引用符)が入っている場合
#    " を含むセルは、セルの始まりと終わりに " がついて、
#    "は連続する2この""として出力される。
#    そこで、連続する2この " をシフトJISで割り当てられていない 0xfdに
#    いったん置き換えし、余分な " を削除したのち 0xfd を " に戻す。
# ================================================================================
sub tr_tabtxt {
my($NL, $fd, $fe);
# ====== 初期設定 ======
$NL = "_| ";                # セル内の改行を置き換える文字

$fd = chr(0xfd);
$fe = chr(0xfe);

# セル内の""を0xfdに置き換え
# \A:文字列の先頭  \t:タブ \n:改行 \Z:文字列の終端
$_[0] =~ s/([^\A\t\n])""([^\Z\t\n])/\1$fd\2/gmo;
$_[0] =~ s/([^\A\t\n])""([^\Z\t\n])/\1$fd\2/gmo;

# セル内の \n(改行)を0xfeに置き換え 
do {} while($_[0] =~ s/(\A|\t|\n)"([^"\n]*)\n([^"]*)"(\Z|\t|\n)/\1"\2$fe\3"\4/gm);

# セルの始まりの"を削除
$_[0] =~ s/(\A|\t|\n)"/\1/gm;

# セルの終わりの"を削除
$_[0] =~ s/"(\Z|\t|\n)/\1/gm;

#0xfd を " に置き換え
$_[0] =~ s/$fd/"/gm;

#0xfe を $NL に置き換え
$_[0] =~ s/$fe/$NL/gm;
return();
}