web-dev-qa-db-ja.com

PostgreSQLからxlsxファイルにデータをエクスポートできますか?

クエリの結果をxlsxファイル形式にエクスポートしたい。
csvファイルにエクスポートできることはわかっていますが、xlsxファイルにエクスポートしたいと思います。

次のように:

copy(select name_related from hr_employee limit 3) to '/tmp/ABC.xlsx'
delimiter ',' xlsx header;
3

PostgreSQLはこれをネイティブで行うことはできませんが、単純なPerlスクリプトを使用してCSV出力をXLSXファイルに変換できます。

csv2xlsx

このスクリプトを機能させるには、Excel::Writer::XLSXおよびText::CSV Perlモジュールを、apt-get/yumまたはSudo Perl -MCPAN -e 'install Excel::Writer::XLSX'およびSudo Perl -MCPAN -e 'install Text::CSV'を使用してインストールします。

#!/usr/bin/Perl -w
use strict;
use warnings;
use Excel::Writer::XLSX;
use Text::CSV;

my ($filename) = @ARGV;
open my $io, "-" or die "$!";

# Create a new Excel workbook
my $workbook = Excel::Writer::XLSX->new( $filename ) or die "$!";

# Add a worksheet
my $worksheet = $workbook->add_worksheet();

# Data
my $fdata = $workbook->add_format();
$fdata->set_border(1);
$fdata->set_border_color('gray');
$fdata->set_font( 'Segoe UI' );
$fdata->set_size( '8' );

# Titles
my $ftitle = $workbook->add_format();
$ftitle->copy ($fdata);
$ftitle->set_bg_color( '#B0CBF0' );

# Dates
my $fdate = $workbook->add_format();
$fdate->copy($fdata);
$fdate->set_num_format('dd/mm/yyyy' );
my $fdatetime = $workbook->add_format();
$fdatetime->copy($fdata);
$fdatetime->set_num_format('dd/mm/yyyy hh:mm:ss' );

$worksheet->set_column('A:ZZ', 15);

my $csv = Text::CSV->new({ binary => 1, eol => $/ });

my $line = 0;
while (my $row = $csv->getline($io)) {
  my @fields = @$row;
  my $col = 0;
  if($line == 0) {
    foreach my $fld (@fields) {
      $worksheet->write_string( 0, $col++, $fld, $ftitle );
    }
  } else {
    my $col = 0;
    foreach my $fld (@fields) {
      if ($fld =~ /^[0-9]/) {
        if($fld =~ /^-?(0(\.[0-9]{1,14})?|[1-9][0-9]{0,13}(\.[0-9]{1,14})?)$/) {
          $worksheet->write_number( $line, $col, $fld, $fdata );
        } elsif ($fld =~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/) {
          $worksheet->write_date_time( $line, $col, "${fld}T", $fdate );
        } elsif ($fld =~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}[ T][0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?$/) {
          $fld =~ s/ /T/;
          $worksheet->write_date_time( $line, $col, $fld, $fdatetime );
        } else {
          $worksheet->write_string( $line, $col, $fld, $fdata );
        }
      } else {
        $worksheet->write_string( $line, $col, $fld, $fdata );
      }

      $col++;
    }
  }
  $line++;
}

使用例:

psql -c "COPY (SELECT 1 as id, 'foo' as bar, now()::date as date) TO STDOUT CSV HEADER" template1 |\
  ./cvs2xlsx /tmp/ABC