Text-CSV_XS

 view release on metacpan or  search on metacpan

examples/csv2xlsx  view on Meta::CPAN

use List::Util   qw( first                                    );
use Date::Calc   qw( Delta_Days Days_in_Month                 );
use Encode       qw( from_to                                  );
use Getopt::Long qw(:config bundling passthrough noignorecase );
my $quo = '"';
my $esc = '"';
my $wdt = 4;		# Default minimal column width
my $fac = "diag";	# Formula action (default is warn only)
my $dtf = "dd-mm-yyyy";	# Date format
my $crf = "";		# Currency format, e.g.: $:### ### ##0.00
my $opt_v = 1;
my $dtc;

GetOptions (
    "V|version"		=> sub { say $0 =~ s{.*/}{}r, " [$VERSION]"; exit 0; },
      "help|?"		=> sub { usage (0); },
      "man"		=> sub { pod_nroff (); },
      "info"		=> sub { pod_text  (); },

    "c|s|sep=s"		=> \my $sep, # Set after reading first line in attempt to auto-detect
    "q|quo=s"		=> \$quo,
    "e|esc=s"		=> \$esc,
    "w|width=i"		=> \$wdt,
    "o|x|out=s"		=> \my $xls,
    "d|date-fmt=s"	=> \$dtf,
    "D|date-col=s"	=> \$dtc,
    "C|curr-fmt=s"	=> \$crf,
      "font=s"		=> \my $font,
      "fs|font-size=i"	=> \my $font_size,
    "f|force!"		=> \my $frc,
    "F|formulas!"	=> \my $frm,
      "Fa=s"		=> \$fac,
      "Ft"		=> sub { $fac = "none";		},
      "Fd"		=> sub { $fac = "die";		},
      "Fc"		=> sub { $fac = "croak";	},
      "FD"		=> sub { $fac = "diag";		},
      "Fe"		=> sub { $fac = "empty";	},
      "Fu"		=> sub { $fac = "undef";	},
    "u|utf-8|utf8!"	=> \my $utf,
      "de|fix-utf8!"	=> \my $dutf, # double encoded? \x{c3}\x{ab} => \x{100}
    "m|merge!"		=> \my $mrg,
      "skip-empty!"	=> \my $skip_empty,
    "S|split=s"		=> \my @split,
      "sl|split-label=s"=> \my $split_sl,
    "L|row-limit=i"	=> \my $row_limit,
    "v|verbose:2"	=> \$opt_v,
    ) or usage (1);

sub pod_text {
    require Pod::Text::Color;
    my $m = $ENV{NO_COLOR} ? "Pod::Text" : "Pod::Text::Color";
    my $p = $m->new ();
    open my $fh, ">", \my $out or die "Cannot generate manual: $!\n";
    $p->parse_from_file ($0, $fh);
    close $fh;
    print $out;
    exit 0;
    } # pod_text

sub pod_nroff {
    first { -x "$_/nroff" } grep { -d } split m/:+/ => $ENV{PATH} or pod_text ();

    require Pod::Man;
    my $p = Pod::Man->new ();
    open my $fh, "|-", "nroff", "-man" or die "Cannot generate manual: $!\n";
    $p->parse_from_file ($0, $fh);
    close $fh;
    exit 0;
    } # pod_nroff

if ($mrg) {
    my @csv;
    for (@ARGV) {
	if (m/\.xlsx?$/i) {
	    $xls and usage (1);
	    $xls = $_;
	    next;
	    }
	if (m/\.(?:csv|png|jpe?g|bmp|gif|tiff|xpm)$/i && -s) {
	    push @csv => $_;
	    next;
	    }
	unless ($skip_empty) {
	    warn "Argument $_ is not an existing (CSV) file\n";
	    usage (1);
	    }
	}
    $xls && @csv or usage (1);
    @ARGV = @csv;
    }

sub col2col {
    my $l = shift;
    $l =~ m/^[0-9]/ and return $l;
    my $c = 0;
    while ($l =~ s/^([A-Za-z])//) {
	$c = 26 * $c + 1 + ord (uc $1) - ord ("A");
	}
    $c;
    } # col2col

foreach my $split (@split) {
    my ($col, $operator, $pat) = ($split =~ m{^
	([0-9]+|[A-Z]+|[a-z]+)	# Column: A, AB, 1, 14
	([=/uU<>])		# Operator
	(.*)			# Pattern/string
	\z}x) or usage (1);
    my $case = $col =~ m/^[a-z]/ ? 1 : 0;
    $split = {
	col => col2col ($col),
	op  => $operator,
	str => $pat,
	ic  => $case,
	lbl => undef,
	};
    if ($split_sl) {
	($col) = ($split_sl =~ m/^([0-9]+|[A-Z]+)$/) or usage (1);
	$split->{lbl} = col2col ($col);
	}
    }



( run in 0.869 second using v1.01-cache-2.11-cpan-5511b514fd6 )