X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FHelper%2FCsv.pm;h=2730502b385d3cdaebc28d5b7aeb73675deb49fb;hb=ad0096b7c71511665bdf9fec9f3ecaae638072cd;hp=c5d2f4aee787fa4a8b249baf9c4b9d15e6d7a7a6;hpb=1870f11e7915b768e83e18f8491f1e13d0702ead;p=kivitendo-erp.git diff --git a/SL/Helper/Csv.pm b/SL/Helper/Csv.pm index c5d2f4aee..2730502b3 100644 --- a/SL/Helper/Csv.pm +++ b/SL/Helper/Csv.pm @@ -111,13 +111,31 @@ sub _check_multiplexed { if (scalar @profile > 1) { # Each profile needs a class and a row_ident my $info_ok = all { defined $_->{class} && defined $_->{row_ident} } @profile; + $self->_push_error([ + 0, + "missing class or row_ident in one of the profiles for multiplexed data", + 0, + 0]) unless $info_ok; # If header is given, there need to be a header for each profile # and no empty headers. if ($info_ok && $self->header) { my @header = @{ $self->header }; - $info_ok = $info_ok && scalar @profile == scalar @header; - $info_ok = $info_ok && all { scalar @$_ > 0} @header; + my $t_ok = scalar @profile == scalar @header; + $self->_push_error([ + 0, + "number of headers and number of profiles must be the same for multiplexed data", + 0, + 0]) unless $t_ok; + $info_ok = $info_ok && $t_ok; + + $t_ok = all { scalar @$_ > 0} @header; + $self->_push_error([ + 0, + "no empty headers are allowed for multiplexed data", + 0, + 0]) unless $t_ok; + $info_ok = $info_ok && $t_ok; } $self->is_multiplexed($info_ok); return $info_ok; @@ -144,7 +162,11 @@ sub _check_header { 0, ]) unless $h; - push @{ $header }, $h; + if ($self->is_multiplexed) { + push @{ $header }, $h; + } else { + $header = $h; + } } } @@ -153,14 +175,19 @@ sub _check_header { # data with a discouraged but valid byte order mark # if not removed, the first header field will not be recognized if ($header) { - my $h = $header->[0]; + my $h = ($self->is_multiplexed)? $header->[0] : $header; + if ($h && $h->[0] && $self->encoding =~ /utf-?8/i) { $h->[0] =~ s/^\x{FEFF}//; } } # check, if all header fields are parsed well - return unless $header && all { $_ } @$header; + if ($self->is_multiplexed) { + return unless $header && all { $_ } @$header; + } else { + return unless $header; + } # Special case: human stupidity # people insist that case sensitivity doesn't exist and try to enter all @@ -170,8 +197,9 @@ sub _check_header { if ($self->case_insensitive_header) { die 'case_insensitive_header is only possible with profile' unless $self->profile; if ($header) { - my $p_num = 0; - foreach my $h (@{ $header }) { + my $h_aref = ($self->is_multiplexed)? $header : [ $header ]; + my $p_num = 0; + foreach my $h (@{ $h_aref }) { my @names = ( keys %{ $self->profile->[$p_num]->{profile} || {} }, ); @@ -229,13 +257,13 @@ sub _header_by_row { # initialize lookup hash if not already done if ($self->is_multiplexed && ! defined $self->_row_header ) { - $self->_row_header({ pairwise { $a->{row_ident} => $b } @{ $self->profile }, @{ $self->header } }); + $self->_row_header({ pairwise { no warnings 'once'; $a->{row_ident} => $b } @{ $self->profile }, @{ $self->header } }); } if ($self->is_multiplexed) { return $self->_row_header->{$row->[0]} } else { - return $self->header->[0]; + return $self->header; } } @@ -304,7 +332,7 @@ SL::Helper::Csv - take care of csv file uploads sep_char => ',', # default ';' quote_char => '\'', # default '"' escape_char => '"', # default '"' - header => [ [qw(id text sellprice word)] ], # see later + header => [ qw(id text sellprice word) ], # see later profile => [ { profile => { sellprice => 'sellprice_as_number'}, class => 'SL::DB::Part' } ], ); @@ -409,21 +437,26 @@ Same as in L =item C
\@HEADERS -If given, it contains an ARRAYREF for each different class type (i.e. one -ARRAYREF if the data is only of one class type). These ARRAYREFS are the header -fields which are an array of columns. In this case the first lines are not used -as a header. Empty header fields will be ignored in objects. +If given, it contains an ARRAY of the header fields for not multiplexed data. +Or an ARRAYREF for each different class type for multiplexed data. These +ARRAYREFS are the header fields which are an array of columns. In this case +the first lines are not used as a header. Empty header fields will be ignored +in objects. If not given, headers are taken from the first n lines of data, where n is the number of different class types. +In case of multiplexed data the first column must be named 'datatype'. This +name must be given in the header. + Examples: classic data of one type: - [ [ 'name', 'street', 'zipcode', 'city' ] ] + [ 'name', 'street', 'zipcode', 'city' ] multiplexed data with two different types - [ [ 'ordernumber', 'customer', 'transdate' ], [ 'partnumber', 'qty', 'sellprice' ] ] + [ [ 'datatype', 'ordernumber', 'customer', 'transdate' ], + [ 'datatype', 'partnumber', 'qty', 'sellprice' ] ] =item C [{profile => \%ACCESSORS, class => class, row_ident => ri},] @@ -464,7 +497,8 @@ If C is present, the line will be handed to the new sub of this class, and the return value used instead of the line itself. C is a string to recognize the right profile and class for each data -line in multiplexed data. +line in multiplexed data. It must match the value in the column 'dataype' for +each class. In case of multiplexed data, C and C must be given. Example: