summaryrefslogtreecommitdiffstats
path: root/lib/Spreadsheet/Template/Generator/Parser/Excel.pm
blob: c9a128a262b0f0a9b73034769544c2442b63d68d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package Spreadsheet::Template::Generator::Parser::Excel;
use Moose::Role;

with 'Spreadsheet::Template::Generator::Parser';

requires '_build_excel';

has excel => (
    is      => 'ro',
    isa     => 'Object',
    lazy    => 1,
    builder => '_build_excel',
);

sub parse {
    my $self = shift;
    return $self->_parse_workbook;
}

sub _parse_workbook {
    my $self = shift;

    my $data = {
        worksheets => [],
    };

    for my $sheet ($self->excel->worksheets) {
        push @{ $data->{worksheets} }, $self->_parse_worksheet($sheet);
    }

    return $data;
}

sub _parse_worksheet {
    my $self = shift;
    my ($sheet) = @_;

    my $data = {
        name          => $sheet->get_name,
        row_heights   => [ $sheet->get_row_heights ],
        column_widths => [ $sheet->get_col_widths ],
        # XXX Spreadsheet::ParseExcel doesn't currently support extracting the
        # currently selected cells or worksheets
        cells         => [],
    };

    my ($rmin, $rmax) = $sheet->row_range;
    my ($cmin, $cmax) = $sheet->col_range;

    splice @{ $data->{row_heights} }, $rmax + 1;
    splice @{ $data->{column_widths} }, $cmax + 1;

    for my $row (0..$rmin - 1) {
        push @{ $data->{cells} }, [];
    }

    for my $row ($rmin..$rmax) {
        my $row_data = [];
        for my $col (0..$cmin - 1) {
            push @$row_data, {};
        }
        for my $col ($cmin..$cmax) {
            if (my $cell = $sheet->get_cell($row, $col)) {
                push @$row_data, $self->_parse_cell($cell);
            }
            else {
                push @$row_data, {};
            }
        }
        push @{ $data->{cells} }, $row_data
    }

    return $data;
}

sub _parse_cell {
    my $self = shift;
    my ($cell) = @_;

    my $contents = $cell->unformatted;
    my $type = $cell->type;
    my $formula = $cell->{Formula}; # XXX

    if ($type eq 'Numeric') {
        $type = 'number';
    }
    elsif ($type eq 'Text') {
        $type = 'string';
    }
    elsif ($type eq 'Date') {
        $type = 'date_time';
    }
    else {
        die "unknown type $type";
    }

    my $data = {
        contents => $self->_filter_cell_contents($contents, $type),
        type     => $type,
        ($formula ? (formula => $formula) : ()),
    };

    return $data;
}

sub _filter_cell_contents {
    my $self = shift;
    my ($contents) = @_;
    return $contents;
}

no Moose::Role;

1;