CSV-Helfer: Leere Zeilen ignorieren.
authorBernd Bleßmann <bernd@kivitendo-premium.de>
Wed, 30 May 2018 13:26:18 +0000 (15:26 +0200)
committerBernd Bleßmann <bernd@kivitendo-premium.de>
Wed, 30 May 2018 13:32:33 +0000 (15:32 +0200)
Als leere Zeilen hier gelten auch Zeilen, die nur das Trennzeichen enthalten.

Mit leeren Zeilen gab es immer wieder Probleme, teils mit schwer zu
interpretierenden Fehlermeldungen, teils mit nicht gewünschtem Verhalten, z.B.
beim Warenimport das Anlegen neuer Artikel für jede leere Zeile.

SL/Helper/Csv.pm
t/helper/csv.t

index 2444225..cea43ae 100644 (file)
@@ -239,6 +239,10 @@ sub _check_multiplex_datatype_position {
   }
 }
 
+sub _is_empty_row {
+  return !!all { !$_ } @{$_[0]};
+}
+
 sub _parse_data {
   my ($self, %params) = @_;
   my (@data, @errors);
@@ -246,6 +250,7 @@ sub _parse_data {
   while (1) {
     my $row = $self->_csv->getline($self->_io);
     if ($row) {
+      next if _is_empty_row($row);
       my $header = $self->_header_by_row($row);
       if (!$header) {
         push @errors, [
index e324726..7997fe7 100644 (file)
@@ -1,4 +1,4 @@
-use Test::More tests => 86;
+use Test::More tests => 91;
 
 use lib 't';
 use utf8;
@@ -382,6 +382,39 @@ $csv->parse;
 is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'without profile and class works';
 
 #####
+
+$csv = SL::Helper::Csv->new(
+  file => \<<EOL,
+description;partnumber
+Kaffee;1
+
+;
+ ;
+Tee;3
+EOL
+# Note: The second last line is not empty. The description is a space character.
+);
+ok $csv->parse;
+is_deeply $csv->get_data, [ {partnumber => 1, description => 'Kaffee'}, {partnumber => '', description => ' '}, {partnumber => 3, description => 'Tee'} ], 'ignoring empty lines works (header in csv file)';
+
+#####
+
+$csv = SL::Helper::Csv->new(
+  file => \<<EOL,
+Kaffee;1
+
+;
+ ;
+Tee;3
+EOL
+# Note: The second last line is not empty. The description is a space character.
+  header => ['description', 'partnumber'],
+);
+ok $csv->parse;
+is_deeply $csv->get_data, [ {partnumber => 1, description => 'Kaffee'}, {partnumber => '', description => ' '}, {partnumber => 3, description => 'Tee'} ], 'ignoring empty lines works';
+
+#####
+
 $csv = SL::Helper::Csv->new(
   file    => \"Kaffee;1,50\nSchoke;0,89\n",
   header  => [
@@ -726,6 +759,36 @@ ok $csv->get_objects->[0], 'multiplex: empty path gets ignored in object creatio
 
 #####
 
+$csv = SL::Helper::Csv->new(
+  file => \<<EOL,
+datatype;customernumber;name
+datatype;description;partnumber
+C;1000;Meier
+P;Kaffee;1
+
+;;
+C
+P; ;
+C;2000;Meister
+P;Tee;3
+EOL
+  ignore_unknown_columns => 1,
+  profile => [ { class => 'SL::DB::Customer', row_ident => 'C' },
+               { class => 'SL::DB::Part',     row_ident => 'P' },
+  ],
+);
+$csv->parse;
+is_deeply $csv->get_data, [
+  {datatype => 'C', customernumber => 1000, name => 'Meier'},
+  {datatype => 'P', partnumber => 1, description => 'Kaffee'},
+  {datatype => 'C', customernumber => undef, name => undef},
+  {datatype => 'P', partnumber => '', description => ' '},
+  {datatype => 'C', customernumber => 2000, name => 'Meister'},
+  {datatype => 'P', partnumber => '3', description => 'Tee'},
+], 'ignoring empty lines works (multiplex data)';
+
+#####
+
 # Mappings
 # simple case
 $csv = SL::Helper::Csv->new(