Excel-Template-XLSX

 view release on metacpan or  search on metacpan

lib/Excel/Template/XLSX.pm  view on Meta::CPAN

        $self->{_dim_rowmin} = undef;
        $self->{_dim_rowmax} = undef;
        $self->{_dim_colmin} = undef;
        $self->{_dim_colmax} = undef;


         $sheet->set_default_row($default_row_height);
         $twig->purge;
      },

      # Default row height
      'sheetFormatPr' => sub {
         my ( $twig, $format ) = @_;
         $default_row_height   //= $format->att('defaultRowHeight');
         $default_column_width //= $format->att('baseColWidth');
         $sheet->set_default_row($default_row_height);
         $twig->purge;
      },

      # Sets (one or more) column widths
      'col' => sub {
         my ( $twig, $col ) = @_;

         my $min =  $col->att('min') - 1;
         my $max =  $col->att('max') - 1;
         $sheet->set_column( $min, $max, $col->att('width') );
         $twig->purge;
      },

      'row' => sub {
         my ( $twig, $row ) = @_;

         # ?? just sets row height.  No formatting yet
         # set_row( $row, $height, $format, $hidden, $level, $collapsed )
         $sheet->set_row( $row->att('r') - 1, $row->att('ht') );
         $twig->purge;
      },

      'sheetView/selection' => sub {
         my ( $twig, $selection ) = @_;
         my $range = $selection->att('sqref')
             // $selection->att('activeCell') // 'A1';
         $sheet->set_selection($range);
         $twig->purge;
      },

      'sheetPr/tabColor' => sub {
         my ( $twig, $tab_color ) = @_;
         $sheet->set_tab_color( $tab_color->att('rgb') );
         $twig->purge;
      }

       }    # return hashref
}
###############################################################################
sub _parse_sheet_pass2 {

=head2 _parse_sheet_pass2

Parses cell contents (first by row, then by column).  Cells can contain
inline strings, string references, direct string values, formulas,
and hyperlinks.  Each cell may also contain formatting information.  
The format is in an index to formatting for borders, shading, alignment,
font, and number formats.

=cut

   my $self = shift;
   my ($sheet) = @_;

   return {
      'sheetData/row' => sub {
         my ( $twig, $row_elt ) = @_;
         my $sheet_idx = $sheet->{_index};
         for my $cell ( $row_elt->children('c') ) {
         
            my $string_index = 0;
            my $a1           = $cell->att('r');           # Cell Address
            my $t            = $cell->att('t') || 'n';    # Cell Type
            my $s            = $cell->att('s') // 0;      # Cell Format Index (e.g. styles)
            my ($r, $c) = $self->_cell_to_row_col($a1);
            $self->{CELL_FORMAT}->[$r][$c] = $s;
            my $val_xml
                = $t eq 'inlineStr'
                ? $cell->first_child('is')->first_child('t')
                : $cell->first_child('v');
            my $val = $val_xml ? $val_xml->text() : undef;


            my $format_idx = $s;
            my $format = $self->{FORMATS}[$format_idx];
            # Formatted cell, no contents
            if ( !defined($val) ) {
               $sheet->write_blank($a1, $format);
               next;
            }

            if ( $t eq 's' ) {
               $string_index = $val;
               $val          = $self->{SHARED_STRINGS}[$val];

               my $is_array = ref($val) eq 'ARRAY';
               my @aval = $is_array ? @$val : ($val);
               if ( my $ref = $self->{MERGED_RANGES}{$sheet_idx}{$a1} ) {
                  my $type = $is_array ? 'rich_string' : 'string';
                  $sheet->merge_range_type($type, $ref, @aval, $format );
                  $self->{MERGED_RANGES}{$sheet_idx}{$a1} = 0; # Flag it as used.  Handle unused ranges at end
                  next;
               }

               # Special case for multiple formats in a cell
               # see _parse_shared_strings for rPr nodes
               if ( $is_array ) {
                  $sheet->write_rich_string( $a1, @aval );
                  next;
               }
               if ( my $url = $self->{HYPERLINKS}{$a1} ) {
                  $sheet->write_url( $a1, $url, $format, $val );
                  next;
               }
               $sheet->write_string( $a1, $val, $format );
               next;
            }

            # In-line string (not seen in practice)
            elsif ( $t eq 'str' ) {
               $val = '=' . $cell->first_child('f')->text();
            }

            # Formulas
            elsif ( $t eq 'n' ) {
               if ( my $form_child = $cell->first_child('f') ) {
                  my $is_array = $form_child->att('t');
                  my $ref      = $form_child->att('ref');
                  my $formula  = $form_child->text() // q[="No Formula Found"];
                  if ($is_array and $ref) {
                     $sheet->write_array_formula( $ref, "=${formula}", $format, $val );
                  }
                  else {
                     if ( my $ref = $self->{MERGED_RANGES}{$sheet_idx}{$a1} ) {
                       $sheet->merge_range_type('formula', $ref, "=${formula}", $format, $val);
                       $self->{MERGED_RANGES}{$sheet_idx}{$a1} = 0; # Flag it as used.  Handle unused ranges at end
                     } else {
                        $sheet->write_formula( $a1, "=${formula}", $format, $val );
                     }
                  }
                  next;
               }

            }
            elsif ( $t eq 'b' ) {
               $val = $val ? "TRUE" : "FALSE";
            }
            elsif ( $t eq 'e' ) {
            }
            elsif ( $t eq 'str' || $t eq 'inlineStr' ) {
            }
            else {
               warn "unimplemented type $t found in cell $a1";    # XXX
            }

            $sheet->write( $a1, $val, $format );
         }

         $twig->purge;
      }
   };
}
###############################################################################
sub _parse_final_pass {

=head2 _parse_final_pass

Make a final pass to process merge_ranges that do not have any cell contents.  
This is it for now, but more may be added in the future.

=cut

  my $self = shift;
  my ($sheet) = @_;
  my $idx = $sheet->{_index};

  foreach my $r (keys %{ $self->{MERGED_RANGES}->{ $idx } } ) {
    my $ref = $self->{MERGED_RANGES}->{ $idx }->{$r};
    next unless $ref;  # Only process merged ranges that have not been referenced yet.
    $sheet->merge_range_type('blank', $ref, $self->{FORMATS}[0]);
    my ($first, $last) = split('\:', $ref);
    my ($rf, $cf) = $self->_cell_to_row_col($first);
    my ($rl, $cl) = $self->_cell_to_row_col($last);
    for my $r ($rf .. $rl) {
      for my $c ($cf .. $cl) {
       my $fid = $self->{CELL_FORMAT}->[$r][$c] // 0;
       $sheet->write_blank($r, $c, $self->{FORMATS}[$fid] );
      }
    }
  }
}
###############################################################################
sub _parse_styles {

=head2 _parse_styles

Parses style information.  
Parses number formats directly.  Calls subroutines to parse 



( run in 0.511 second using v1.01-cache-2.11-cpan-5837b0d9d2c )