CycleTechLog (サイクルテックログ)

cycling, map and gis technology, and myself.

結合セルあるエクセルをcsv形式にするスクリプトを書きました.

私は他人に整理してもらったエクセルのデータを利用することがよくあるのですが,セルが結合されていると機械的に処理できませんでした.なので,ちまちま結合を解除してから利用している感じでした..(作ってる方はどうなんだろう?)
また,ネットにもVBAぐらいしかいい方法がなかったのでスクリプトを書きました.

必要な条件は以下です.

  1. 結合セルがなくてプレーンな表になること.
  2. 結合セルの内容は解除したあとの全部のセルに残ること.
  3. 作るのも楽をすること.

特にあれなのですが,そのままprintすると日本語が

Wide character in print at ...

がでるので,binmode(STDOUT, ":utf8") にすること.
ただの2次元配列なんだけど,中途半端な感じでやってきたから配列数を取得するところで詰まりました.

$#{$AonA[$i]} 

できた結果は以下です.

#!/file/path/perl
#unmerge.pl
use strict;
use Data::Dumper;
use Spreadsheet::ParseExcel;
binmode(STDOUT, ":utf8");

my $oExcel = new Spreadsheet::ParseExcel;
die "You must provide a filename to $0 to be parsed as an Excel file" unless @ARGV;

my $oBook = $oExcel->Parse($ARGV[0]);

my($iR, $iC, $oWkS, $oWkC);

for(my $iSheet=0; $iSheet < $oBook->{SheetCount} ; $iSheet++) {
    my @merged = $oBook->{Worksheet}[$iSheet]->{MergedArea};

    $oWkS = $oBook->{Worksheet}[$iSheet];
    print "--------- SHEET:", $oWkS->{Name}, "\n";
    for(my $iR = $oWkS->{MinRow} ;
	defined $oWkS->{MaxRow} && $iR <= $oWkS->{MaxRow} ;
	$iR++) {

	for(my $iC = $oWkS->{MinCol} ;
	    defined $oWkS->{MaxCol} && $iC <= $oWkS->{MaxCol} ;
	    $iC++) {

	    $oWkC = $oWkS->{Cells}[$iR][$iC];
	    if($oWkC){
		if( defined $oWkC->{Merged}){
		    my ($mR, $mC) = &check_mergefirst_row_col(
			$iR, $iC, @merged);
		    my $mf = $oWkS->{Cells}[$mR][$mC];
		    print '"'.$mf->Value."\"\t";
		}else{
		    print '"'.$oWkC->Value."\"\t";
		}
	    }
	}
	print "\n";
    }
}

sub check_mergefirst_row_col {
    my $iR = shift;
    my $iC = shift;
    my @merged = @_;

    my ($mR, $mC) = "";

    for(my $i=0; $#{$merged[0]} >= $i; $i++) {
	my $start_row = @merged->[0]->[$i]->[0];
	my $start_col = @merged->[0]->[$i]->[1];
	my $end_row   = @merged->[0]->[$i]->[2];
	my $end_col   = @merged->[0]->[$i]->[3];

	if( $iR >= $start_row &&$end_row >= $iR&&
	    $iC >= $start_col &&$end_col >= $iC ) {
	      $mR = $start_row;
	      $mC = $start_col;
	}
    }
    return ($mR, $mC);
}

実行は以下の感じで

 perl unmerge.pl merge.xls > plane.csv

参考リンク: