小池啓仁 ヒロヒト応援ブログ By はてな

小池啓仁(コイケヒロヒト)の動画など。

小池啓仁 ヒロヒト応援ブログ By はてな

PerlでCSV(テキスト)からXLS(エクセル)への最速変換

たとえば、Perl側で普通にセル単位に処理すると約45分かかるCSVからXLS変換がありました。

  • 上記で、ScreenUpdating = Falseを追加すると約30分
  • PerlからEXCELマクロを起動してセル単位に処理すると約1分
  • 以下では、約15秒で処理ができました。

つまり、約45分掛かっていた処理が約15秒になったのです。すごい!

#!/usr/local/bin/perl -w
use strict;
    my $csvFile = 'C:\test_book.csv'; # CSVファイル
    my $xlsFile = 'C:\test_book.xls'; # EXCELブックファイル

    &csv2xls($csvFile, $xlsFile);

sub csv2xls {
    my ($csvFile, $xlsFile) = @_;

    use Win32::OLE;
    # 指定タイプライブラリのコンスタントが参照可能
    use Win32::OLE::Const 'Microsoft Excel';
    # エラー時に本処理を中止し、Perlがエラーメッセージを出力し、本プロセスが終了する
    Win32::OLE->Option(Warn => 3);
    
    my $Excel;

    # EXCEL使用可能かチェック
    eval {
            Win32::OLE->GetActiveObject('Excel.Application');
    };
    if ($@) {
            die "Excelが入っていません。$@";
    }
    # EXCELオブジェクト取得
    eval {
            $Excel = Win32::OLE->GetActiveObject('Excel.Application')
                  || Win32::OLE->new('Excel.Application', 'Quit');
    };
    if ($@) {
            die "EXCELオブジェクト取得エラーです。 $@";
    }
    # Csvファイルオープン
    eval {
           $Excel->Workbooks->OpenText({Filename => "$csvFile"});
    };
    if ($@) {
            die "Csvファイルオープンエラーです。 $@";
    }
    $Excel->ActiveSheet->Cells->{NumberFormatLocal} = "@"; # すべてセルを文字列属性にする。
    $Excel->{DisplayAlerts} = 0; # 上書きのAlertダイアログを出さない。
    eval {
           $Excel->ActiveWorkbook->SaveAs({Filename => "$xlsFile", Fileformat => xlWorkbookNormal});
    };
    if ($@) {
            die "xlsファイル書き込みエラーです。 $@";
    }
    $Excel->ActiveWorkbook->Close();
    $Excel->Quit();
}

留意点:

とにかくEXCELが想定外のデータ変換をすることがあるのでデータのチェックは念入りにね。