File Coverage

blib/lib/Excel/Writer/XLSX/Package/Packager.pm
Criterion Covered Total %
statement 446 447 99.7
branch 70 72 97.2
condition 6 6 100.0
subroutine 47 47 100.0
pod 0 1 0.0
total 569 573 99.3


line stmt bran cond sub pod time code
1              
2             ###############################################################################
3             #
4             # Packager - A class for creating the Excel XLSX package.
5             #
6             # Used in conjunction with Excel::Writer::XLSX
7             #
8             # Copyright 2000-2021, John McNamara, jmcnamara@cpan.org
9             #
10             # Documentation after __END__
11             #
12              
13             # perltidy with the following options: -mbl=2 -pt=0 -nola
14              
15             use 5.008002;
16 1124     1124   20714 use strict;
  1124         3395  
17 1124     1124   5344 use warnings;
  1124         2005  
  1124         21775  
18 1124     1124   4553 use Exporter;
  1124         1957  
  1124         25114  
19 1124     1124   4650 use Carp;
  1124         1934  
  1124         28261  
20 1124     1124   4762 use File::Copy;
  1124         2146  
  1124         47860  
21 1124     1124   5426 use Excel::Writer::XLSX::Package::App;
  1124         1955  
  1124         50186  
22 1124     1124   401884 use Excel::Writer::XLSX::Package::Comments;
  1124         2659  
  1124         45536  
23 1124     1124   416246 use Excel::Writer::XLSX::Package::ContentTypes;
  1124         2908  
  1124         48202  
24 1124     1124   410475 use Excel::Writer::XLSX::Package::Core;
  1124         2915  
  1124         47781  
25 1124     1124   403680 use Excel::Writer::XLSX::Package::Custom;
  1124         2870  
  1124         44356  
26 1124     1124   398716 use Excel::Writer::XLSX::Package::Metadata;
  1124         2698  
  1124         42300  
27 1124     1124   378019 use Excel::Writer::XLSX::Package::Relationships;
  1124         2734  
  1124         43298  
28 1124     1124   377226 use Excel::Writer::XLSX::Package::SharedStrings;
  1124         2729  
  1124         42316  
29 1124     1124   378209 use Excel::Writer::XLSX::Package::Styles;
  1124         4295  
  1124         44016  
30 1124     1124   450016 use Excel::Writer::XLSX::Package::Table;
  1124         2949  
  1124         55088  
31 1124     1124   434751 use Excel::Writer::XLSX::Package::Theme;
  1124         2639  
  1124         49461  
32 1124     1124   454557 use Excel::Writer::XLSX::Package::VML;
  1124         5054  
  1124         61909  
33 1124     1124   468914  
  1124         3121  
  1124         3289659  
34             our @ISA = qw(Exporter);
35             our $VERSION = '1.09';
36              
37              
38             ###############################################################################
39             #
40             # Public and private API methods.
41             #
42             ###############################################################################
43              
44              
45             ###############################################################################
46             #
47             # new()
48             #
49             # Constructor.
50             #
51              
52             my $class = shift;
53             my $fh = shift;
54 892     892 0 2639 my $self = Excel::Writer::XLSX::Package::XMLwriter->new( $fh );
55 892         4028  
56 892         3918 $self->{_package_dir} = '';
57             $self->{_workbook} = undef;
58 892         3202 $self->{_worksheet_count} = 0;
59 892         2498 $self->{_chartsheet_count} = 0;
60 892         3603 $self->{_chart_count} = 0;
61 892         2450 $self->{_drawing_count} = 0;
62 892         2674 $self->{_table_count} = 0;
63 892         2162 $self->{_named_ranges} = [];
64 892         2953  
65 892         3758  
66             bless $self, $class;
67              
68 892         2328 return $self;
69             }
70 892         2545  
71              
72             ###############################################################################
73             #
74             # _set_package_dir()
75             #
76             # Set the XLSX OPC package directory.
77             #
78              
79             my $self = shift;
80              
81             $self->{_package_dir} = shift;
82 892     892   1954 }
83              
84 892         2457  
85             ###############################################################################
86             #
87             # _add_workbook()
88             #
89             # Add the Excel::Writer::XLSX::Workbook object to the package.
90             #
91              
92             my $self = shift;
93             my $workbook = shift;
94              
95             $self->{_workbook} = $workbook;
96 892     892   2026 $self->{_chart_count} = scalar @{ $workbook->{_charts} };
97 892         1832 $self->{_drawing_count} = scalar @{ $workbook->{_drawings} };
98             $self->{_num_vml_files} = $workbook->{_num_vml_files};
99 892         4634 $self->{_num_comment_files} = $workbook->{_num_comment_files};
100 892         1880 $self->{_named_ranges} = $workbook->{_named_ranges};
  892         2624  
101 892         1754  
  892         2424  
102 892         2307 for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
103 892         2244 if ( $worksheet->{_is_chartsheet} ) {
104 892         2248 $self->{_chartsheet_count}++;
105             }
106 892         1800 else {
  892         3060  
107 1041 100       3744 $self->{_worksheet_count}++;
108 20         57 }
109             }
110             }
111 1021         2990  
112              
113             ###############################################################################
114             #
115             # _create_package()
116             #
117             # Write the xml files that make up the XLXS OPC package.
118             #
119              
120             my $self = shift;
121              
122             $self->_write_worksheet_files();
123             $self->_write_chartsheet_files();
124             $self->_write_workbook_file();
125 892     892   1943 $self->_write_chart_files();
126             $self->_write_drawing_files();
127 892         4188 $self->_write_vml_files();
128 892         58679 $self->_write_comment_files();
129 892         6687 $self->_write_table_files();
130 892         36582 $self->_write_shared_strings_file();
131 892         24527 $self->_write_app_file();
132 892         22830 $self->_write_core_file();
133 892         4025 $self->_write_custom_file();
134 892         5773 $self->_write_content_types_file();
135 892         4128 $self->_write_styles_file();
136 892         15055 $self->_write_theme_file();
137 892         44156 $self->_write_root_rels_file();
138 892         40533 $self->_write_workbook_rels_file();
139 892         3960 $self->_write_worksheet_rels_files();
140 892         41603 $self->_write_chartsheet_rels_files();
141 892         48521 $self->_write_drawing_rels_files();
142 892         35191 $self->_add_image_files();
143 892         39983 $self->_add_vba_project();
144 892         36770 $self->_write_metadata_file();
145 892         24553 }
146 892         4249  
147 892         20850  
148 892         37598 ###############################################################################
149 892         5406 #
150             # _write_workbook_file()
151             #
152             # Write the workbook.xml file.
153             #
154              
155             my $self = shift;
156             my $dir = $self->{_package_dir};
157             my $workbook = $self->{_workbook};
158              
159             _mkdir( $dir . '/xl' );
160              
161 892     892   1713 $workbook->_set_xml_writer( $dir . '/xl/workbook.xml' );
162 892         2059 $workbook->_assemble_xml_file();
163 892         1880 }
164              
165 892         4143  
166             ###############################################################################
167 892         4709 #
168 892         8763 # _write_worksheet_files()
169             #
170             # Write the worksheet files.
171             #
172              
173             my $self = shift;
174             my $dir = $self->{_package_dir};
175              
176             _mkdir( $dir . '/xl' );
177             _mkdir( $dir . '/xl/worksheets' );
178              
179             my $index = 1;
180 892     892   1851 for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
181 892         2226 next if $worksheet->{_is_chartsheet};
182              
183 892         24413 $worksheet->_set_xml_writer(
184 892         4566 $dir . '/xl/worksheets/sheet' . $index++ . '.xml' );
185             $worksheet->_assemble_xml_file();
186 892         2976  
187 892         1933 }
  892         3839  
188 1041 100       11874 }
189              
190 1021         4448  
191             ###############################################################################
192 1021         5022 #
193             # _write_chartsheet_files()
194             #
195             # Write the chartsheet files.
196             #
197              
198             my $self = shift;
199             my $dir = $self->{_package_dir};
200              
201             my $index = 1;
202             for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
203             next unless $worksheet->{_is_chartsheet};
204              
205             _mkdir( $dir . '/xl' );
206 892     892   3500 _mkdir( $dir . '/xl/chartsheets' );
207 892         4613  
208             $worksheet->_set_xml_writer(
209 892         2365 $dir . '/xl/chartsheets/sheet' . $index++ . '.xml' );
210 892         2118 $worksheet->_assemble_xml_file();
  892         4281  
211 1041 100       5524  
212             }
213 20         86 }
214 20         118  
215              
216 20         112 ###############################################################################
217             #
218 20         112 # _write_chart_files()
219             #
220             # Write the chart files.
221             #
222              
223             my $self = shift;
224             my $dir = $self->{_package_dir};
225              
226             return unless @{ $self->{_workbook}->{_charts} };
227              
228             _mkdir( $dir . '/xl' );
229             _mkdir( $dir . '/xl/charts' );
230              
231             my $index = 1;
232 892     892   2242 for my $chart ( @{ $self->{_workbook}->{_charts} } ) {
233 892         2432 $chart->_set_xml_writer(
234             $dir . '/xl/charts/chart' . $index++ . '.xml' );
235 892 100       1621 $chart->_assemble_xml_file();
  892         3894  
236              
237 385         1609 }
238 385         1790 }
239              
240 385         1282  
241 385         819 ###############################################################################
  385         1517  
242 426         4253 #
243             # _write_drawing_files()
244 426         3726 #
245             # Write the drawing files.
246             #
247              
248             my $self = shift;
249             my $dir = $self->{_package_dir};
250              
251             return unless $self->{_drawing_count};
252              
253             _mkdir( $dir . '/xl' );
254             _mkdir( $dir . '/xl/drawings' );
255              
256             my $index = 1;
257             for my $drawing ( @{ $self->{_workbook}->{_drawings} } ) {
258 892     892   1881 $drawing->_set_xml_writer(
259 892         2331 $dir . '/xl/drawings/drawing' . $index++ . '.xml' );
260             $drawing->_assemble_xml_file();
261 892 100       3109 }
262             }
263 485         2446  
264 485         2390  
265             ###############################################################################
266 485         1651 #
267 485         987 # _write_vml_files()
  485         2118  
268 523         3380 #
269             # Write the comment VML files.
270 523         2753 #
271              
272             my $self = shift;
273             my $dir = $self->{_package_dir};
274              
275             my $index = 1;
276             for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
277              
278             next if !$worksheet->{_has_vml} and !$worksheet->{_has_header_vml};
279              
280             _mkdir( $dir . '/xl' );
281             _mkdir( $dir . '/xl/drawings' );
282              
283 892     892   1976 if ( $worksheet->{_has_vml} ) {
284 892         2196 my $vml = Excel::Writer::XLSX::Package::VML->new();
285              
286 892         1783 $vml->_set_xml_writer(
287 892         2571 $dir . '/xl/drawings/vmlDrawing' . $index . '.vml' );
  892         3438  
288             $vml->_assemble_xml_file(
289 1041 100 100     7138 $worksheet->{_vml_data_id}, $worksheet->{_vml_shape_id},
290             $worksheet->{_comments_array}, $worksheet->{_buttons_array},
291 80         323 undef
292 80         368 );
293              
294 80 100       393 $index++;
295 58         529 }
296              
297 58         192 if ( $worksheet->{_has_header_vml} ) {
298             my $vml = Excel::Writer::XLSX::Package::VML->new();
299              
300             $vml->_set_xml_writer(
301             $dir . '/xl/drawings/vmlDrawing' . $index . '.vml' );
302             $vml->_assemble_xml_file(
303 58         382 $worksheet->{_vml_header_id},
304             $worksheet->{_vml_header_id} * 1024,
305 58         3022 undef, undef, $worksheet->{_header_images_array}
306             );
307              
308 80 100       549 $self->_write_vml_drawing_rels_file($worksheet, $index);
309 24         220  
310             $index++;
311 24         82 }
312             }
313             }
314              
315              
316             ###############################################################################
317 24         200 #
318             # _write_comment_files()
319 24         1090 #
320             # Write the comment files.
321 24         1159 #
322              
323             my $self = shift;
324             my $dir = $self->{_package_dir};
325              
326             my $index = 1;
327             for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
328             next unless $worksheet->{_has_comments};
329              
330             my $comment = Excel::Writer::XLSX::Package::Comments->new();
331              
332             _mkdir( $dir . '/xl' );
333             _mkdir( $dir . '/xl/drawings' );
334              
335 892     892   1835 $comment->_set_xml_writer( $dir . '/xl/comments' . $index++ . '.xml' );
336 892         1892 $comment->_assemble_xml_file( $worksheet->{_comments_array} );
337             }
338 892         1549 }
339 892         1631  
  892         3099  
340 1041 100       4145  
341             ###############################################################################
342 44         403 #
343             # _write_shared_strings_file()
344 44         178 #
345 44         204 # Write the sharedStrings.xml file.
346             #
347 44         189  
348 44         213 my $self = shift;
349             my $dir = $self->{_package_dir};
350             my $sst = Excel::Writer::XLSX::Package::SharedStrings->new();
351              
352             my $total = $self->{_workbook}->{_str_total};
353             my $unique = $self->{_workbook}->{_str_unique};
354             my $sst_data = $self->{_workbook}->{_str_array};
355              
356             return unless $total > 0;
357              
358             _mkdir( $dir . '/xl' );
359              
360             $sst->_set_string_count( $total );
361 892     892   1834 $sst->_set_unique_count( $unique );
362 892         2044 $sst->_add_strings( $sst_data );
363 892         8713  
364             $sst->_set_xml_writer( $dir . '/xl/sharedStrings.xml' );
365 892         2550 $sst->_assemble_xml_file();
366 892         2186 }
367 892         2101  
368              
369 892 100       9955 ###############################################################################
370             #
371 247         1111 # _write_app_file()
372             #
373 247         1915 # Write the app.xml file.
374 247         1021 #
375 247         945  
376             my $self = shift;
377 247         761 my $dir = $self->{_package_dir};
378 247         1195 my $properties = $self->{_workbook}->{_doc_properties};
379             my $app = Excel::Writer::XLSX::Package::App->new();
380              
381             _mkdir( $dir . '/docProps' );
382              
383             # Add the Worksheet heading pairs.
384             $app->_add_heading_pair( [ 'Worksheets', $self->{_worksheet_count} ] );
385              
386             # Add the Chartsheet heading pairs.
387             $app->_add_heading_pair( [ 'Charts', $self->{_chartsheet_count} ] );
388              
389             # Add the Worksheet parts.
390 892     892   2254 for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
391 892         2558 next if $worksheet->{_is_chartsheet};
392 892         2855 $app->_add_part_name( $worksheet->get_name() );
393 892         7669 }
394              
395 892         3874 # Add the Chartsheet parts.
396             for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
397             next unless $worksheet->{_is_chartsheet};
398 892         8460 $app->_add_part_name( $worksheet->get_name() );
399             }
400              
401 892         5327 # Add the Named Range heading pairs.
402             if ( my $range_count = scalar @{ $self->{_named_ranges} } ) {
403             $app->_add_heading_pair( [ 'Named Ranges', $range_count ] );
404 892         2255 }
  892         3861  
405 1041 100       4001  
406 1021         4859 # Add the Named Ranges parts.
407             for my $named_range ( @{ $self->{_named_ranges} } ) {
408             $app->_add_part_name( $named_range );
409             }
410 892         1873  
  892         3147  
411 1041 100       3866 $app->_set_properties( $properties );
412 20         151 $app->{_doc_security} = $self->{_workbook}->{_read_only};
413              
414             $app->_set_xml_writer( $dir . '/docProps/app.xml' );
415             $app->_assemble_xml_file();
416 892 100       1916 }
  892         3932  
417 18         123  
418              
419             ###############################################################################
420             #
421 892         1913 # _write_core_file()
  892         2598  
422 38         110 #
423             # Write the core.xml file.
424             #
425 892         3821  
426 892         1983 my $self = shift;
427             my $dir = $self->{_package_dir};
428 892         3683 my $properties = $self->{_workbook}->{_doc_properties};
429 892         4115 my $core = Excel::Writer::XLSX::Package::Core->new();
430              
431             _mkdir( $dir . '/docProps' );
432              
433             $core->_set_properties( $properties );
434             $core->_set_xml_writer( $dir . '/docProps/core.xml' );
435             $core->_assemble_xml_file();
436             }
437              
438              
439             ###############################################################################
440             #
441 892     892   2119 # _write_metadata_file()
442 892         2622 #
443 892         2203 # Write the metadata.xml file.
444 892         7440 #
445              
446 892         3714 my $self = shift;
447             my $dir = $self->{_package_dir};
448 892         6126 my $metadata = Excel::Writer::XLSX::Package::Metadata->new();
449 892         3374  
450 892         4923 return if !$self->{_workbook}->{_has_metadata};
451              
452             _mkdir( $dir . '/xl' );
453              
454             $metadata->_set_xml_writer( $dir . '/xl/metadata.xml' );
455             $metadata->_assemble_xml_file();
456             }
457              
458              
459             ###############################################################################
460             #
461             # _write_custom_file()
462 892     892   1821 #
463 892         1944 # Write the custom.xml file.
464 892         7477 #
465              
466 892 100       10436 my $self = shift;
467             my $dir = $self->{_package_dir};
468 1         4 my $properties = $self->{_workbook}->{_custom_properties};
469             my $custom = Excel::Writer::XLSX::Package::Custom->new();
470 1         6  
471 1         6 return if !@$properties;
472              
473             _mkdir( $dir . '/docProps' );
474              
475             $custom->_set_properties( $properties );
476             $custom->_set_xml_writer( $dir . '/docProps/custom.xml' );
477             $custom->_assemble_xml_file();
478             }
479              
480              
481             ###############################################################################
482             #
483 892     892   2698 # _write_content_types_file()
484 892         2353 #
485 892         2338 # Write the ContentTypes.xml file.
486 892         7100 #
487              
488 892 100       7204 my $self = shift;
489             my $dir = $self->{_package_dir};
490 4         15 my $content = Excel::Writer::XLSX::Package::ContentTypes->new();
491              
492 4         24 $content->_add_image_types( %{ $self->{_workbook}->{_image_types} } );
493 4         12  
494 4         18 my $worksheet_index = 1;
495             my $chartsheet_index = 1;
496             for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
497             if ( $worksheet->{_is_chartsheet} ) {
498             $content->_add_chartsheet_name( 'sheet' . $chartsheet_index++ );
499             }
500             else {
501             $content->_add_worksheet_name( 'sheet' . $worksheet_index++ );
502             }
503             }
504              
505             for my $i ( 1 .. $self->{_chart_count} ) {
506 892     892   1855 $content->_add_chart_name( 'chart' . $i );
507 892         2045 }
508 892         6523  
509             for my $i ( 1 .. $self->{_drawing_count} ) {
510 892         2393 $content->_add_drawing_name( 'drawing' . $i );
  892         6104  
511             }
512 892         1967  
513 892         1729 if ( $self->{_num_vml_files} ) {
514 892         2002 $content->_add_vml_name();
  892         2999  
515 1041 100       3871 }
516 20         95  
517             for my $i ( 1 .. $self->{_table_count} ) {
518             $content->_add_table_name( 'table' . $i );
519 1021         5713 }
520              
521             for my $i ( 1 .. $self->{_num_comment_files} ) {
522             $content->_add_comment_name( 'comments' . $i );
523 892         4122 }
524 426         2144  
525             # Add the sharedString rel if there is string data in the workbook.
526             if ( $self->{_workbook}->{_str_total} ) {
527 892         3457 $content->_add_shared_strings();
528 523         2618 }
529              
530             # Add vbaProject if present.
531 892 100       3437 if ( $self->{_workbook}->{_vba_project} ) {
532 63         232 $content->_add_vba_project();
533             }
534              
535 892         3321 # Add the custom properties if present.
536 37         216 if ( @{ $self->{_workbook}->{_custom_properties} } ) {
537             $content->_add_custom_properties();
538             }
539 892         2997  
540 44         240 # Add the metadata file if present.
541             if ( $self->{_workbook}->{_has_metadata} ) {
542             $content->_add_metadata();
543             }
544 892 100       3406  
545 247         1118 $content->_set_xml_writer( $dir . '/[Content_Types].xml' );
546             $content->_assemble_xml_file();
547             }
548              
549 892 100       3470  
550 6         142 ###############################################################################
551             #
552             # _write_styles_file()
553             #
554 892 100       1859 # Write the style xml file.
  892         3824  
555 4         16 #
556              
557             my $self = shift;
558             my $dir = $self->{_package_dir};
559 892 100       3467 my $xf_formats = $self->{_workbook}->{_xf_formats};
560 1         4 my $palette = $self->{_workbook}->{_palette};
561             my $font_count = $self->{_workbook}->{_font_count};
562             my $num_format_count = $self->{_workbook}->{_num_format_count};
563 892         3898 my $border_count = $self->{_workbook}->{_border_count};
564 892         4422 my $fill_count = $self->{_workbook}->{_fill_count};
565             my $custom_colors = $self->{_workbook}->{_custom_colors};
566             my $dxf_formats = $self->{_workbook}->{_dxf_formats};
567             my $has_comments = $self->{_workbook}->{_has_comments};
568              
569             my $rels = Excel::Writer::XLSX::Package::Styles->new();
570              
571             _mkdir( $dir . '/xl' );
572              
573             $rels->_set_style_properties(
574             $xf_formats,
575             $palette,
576 892     892   2268 $font_count,
577 892         2186 $num_format_count,
578 892         2324 $border_count,
579 892         2119 $fill_count,
580 892         2153 $custom_colors,
581 892         1849 $dxf_formats,
582 892         1912 $has_comments,
583 892         1877 );
584 892         2030  
585 892         1846 $rels->_set_xml_writer( $dir . '/xl/styles.xml' );
586 892         1808 $rels->_assemble_xml_file();
587             }
588 892         7060  
589              
590 892         3600 ###############################################################################
591             #
592 892         6617 # _write_theme_file()
593             #
594             # Write the style xml file.
595             #
596              
597             my $self = shift;
598             my $dir = $self->{_package_dir};
599             my $rels = Excel::Writer::XLSX::Package::Theme->new();
600              
601             _mkdir( $dir . '/xl' );
602             _mkdir( $dir . '/xl/theme' );
603              
604 892         2701 $rels->_set_xml_writer( $dir . '/xl/theme/theme1.xml' );
605 892         4254 $rels->_assemble_xml_file();
606             }
607              
608              
609             ###############################################################################
610             #
611             # _write_table_files()
612             #
613             # Write the table files.
614             #
615              
616             my $self = shift;
617 892     892   2180 my $dir = $self->{_package_dir};
618 892         2134  
619 892         7978 my $index = 1;
620             for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
621 892         3834 my @table_props = @{ $worksheet->{_tables} };
622 892         4414  
623             next unless @table_props;
624 892         4767  
625 892         4177 _mkdir( $dir . '/xl' );
626             _mkdir( $dir . '/xl/tables' );
627              
628             for my $table_props ( @table_props ) {
629              
630             my $table = Excel::Writer::XLSX::Package::Table->new();
631              
632             $table->_set_xml_writer(
633             $dir . '/xl/tables/table' . $index++ . '.xml' );
634              
635             $table->_set_properties( $table_props );
636              
637 892     892   1679 $table->_assemble_xml_file();
638 892         2017  
639             $self->{_table_count}++;
640 892         1629 }
641 892         1732 }
  892         2865  
642 1041         1791 }
  1041         2793  
643              
644 1041 100       3532  
645             ###############################################################################
646 28         132 #
647 28         159 # _write_root_rels_file()
648             #
649 28         117 # Write the _rels/.rels xml file.
650             #
651 37         366  
652             my $self = shift;
653 37         132 my $dir = $self->{_package_dir};
654             my $rels = Excel::Writer::XLSX::Package::Relationships->new();
655              
656 37         198 _mkdir( $dir . '/_rels' );
657              
658 37         140 $rels->_add_document_relationship( '/officeDocument', 'xl/workbook.xml' );
659              
660 37         1730 $rels->_add_package_relationship( '/metadata/core-properties',
661             'docProps/core.xml' );
662              
663             $rels->_add_document_relationship( '/extended-properties',
664             'docProps/app.xml' );
665              
666             if ( @{ $self->{_workbook}->{_custom_properties} } ) {
667             $rels->_add_document_relationship( '/custom-properties',
668             'docProps/custom.xml' );
669             }
670              
671             $rels->_set_xml_writer( $dir . '/_rels/.rels' );
672             $rels->_assemble_xml_file();
673             }
674 892     892   2424  
675 892         2275  
676 892         8116 ###############################################################################
677             #
678 892         3234 # _write_workbook_rels_file()
679             #
680 892         6373 # Write the _rels/.rels xml file.
681             #
682 892         4049  
683             my $self = shift;
684             my $dir = $self->{_package_dir};
685 892         3070 my $rels = Excel::Writer::XLSX::Package::Relationships->new();
686              
687             _mkdir( $dir . '/xl' );
688 892 100       1810 _mkdir( $dir . '/xl/_rels' );
  892         4128  
689 4         138  
690             my $worksheet_index = 1;
691             my $chartsheet_index = 1;
692              
693 892         3188 for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
694 892         4222 if ( $worksheet->{_is_chartsheet} ) {
695             $rels->_add_document_relationship( '/chartsheet',
696             'chartsheets/sheet' . $chartsheet_index++ . '.xml' );
697             }
698             else {
699             $rels->_add_document_relationship( '/worksheet',
700             'worksheets/sheet' . $worksheet_index++ . '.xml' );
701             }
702             }
703              
704             $rels->_add_document_relationship( '/theme', 'theme/theme1.xml' );
705             $rels->_add_document_relationship( '/styles', 'styles.xml' );
706 892     892   2046  
707 892         2186 # Add the sharedString rel if there is string data in the workbook.
708 892         5534 if ( $self->{_workbook}->{_str_total} ) {
709             $rels->_add_document_relationship( '/sharedStrings',
710 892         3380 'sharedStrings.xml' );
711 892         4402 }
712              
713 892         3024 # Add vbaProject if present.
714 892         1835 if ( $self->{_workbook}->{_vba_project} ) {
715             $rels->_add_ms_package_relationship( '/vbaProject', 'vbaProject.bin' );
716 892         1792 }
  892         3755  
717 1041 100       4137  
718 20         85 # Add the metadata file if required.
719             if ( $self->{_workbook}->{_has_metadata} ) {
720             $rels->_add_document_relationship( '/sheetMetadata', 'metadata.xml' );
721             }
722 1021         6563  
723             $rels->_set_xml_writer( $dir . '/xl/_rels/workbook.xml.rels' );
724             $rels->_assemble_xml_file();
725             }
726              
727 892         3712  
728 892         3034 ###############################################################################
729             #
730             # _write_worksheet_rels_files()
731 892 100       3644 #
732 247         882 # Write the worksheet .rels files for worksheets that contain links to external
733             # data such as hyperlinks or drawings.
734             #
735              
736             my $self = shift;
737 892 100       3645 my $dir = $self->{_package_dir};
738 6         19  
739             my $index = 0;
740             for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
741              
742 892 100       3271 next if $worksheet->{_is_chartsheet};
743 1         2  
744             $index++;
745              
746 892         3235 my @external_links = (
747 892         3832 @{ $worksheet->{_external_hyper_links} },
748             @{ $worksheet->{_external_drawing_links} },
749             @{ $worksheet->{_external_vml_links} },
750             @{ $worksheet->{_external_table_links} },
751             @{ $worksheet->{_external_background_links} },
752             @{ $worksheet->{_external_comment_links} },
753             );
754              
755             next unless @external_links;
756              
757             # Create the worksheet .rels dirs.
758             _mkdir( $dir . '/xl' );
759             _mkdir( $dir . '/xl/worksheets' );
760 892     892   2095 _mkdir( $dir . '/xl/worksheets/_rels' );
761 892         2221  
762             my $rels = Excel::Writer::XLSX::Package::Relationships->new();
763 892         1861  
764 892         1819 for my $link_data ( @external_links ) {
  892         3550  
765             $rels->_add_worksheet_relationship( @$link_data );
766 1041 100       5757 }
767              
768 1021         2028 # Create the .rels file such as /xl/worksheets/_rels/sheet1.xml.rels.
769             $rels->_set_xml_writer(
770             $dir . '/xl/worksheets/_rels/sheet' . $index . '.xml.rels' );
771 1021         2566 $rels->_assemble_xml_file();
772 1021         2256 }
773 1021         2301 }
774 1021         2147  
775 1021         2070  
776 1021         1734 ###############################################################################
  1021         2855  
777             #
778             # _write_chartsheet_rels_files()
779 1021 100       3479 #
780             # Write the chartsheet .rels files for links to drawing files.
781             #
782 644         2390  
783 644         3003 my $self = shift;
784 644         2879 my $dir = $self->{_package_dir};
785              
786 644         5470  
787             my $index = 0;
788 644         1811 for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
789 747         2788  
790             next unless $worksheet->{_is_chartsheet};
791              
792             $index++;
793              
794 644         2204 my @external_links = @{ $worksheet->{_external_drawing_links} };
795 644         2906  
796             next unless @external_links;
797              
798             # Create the chartsheet .rels dir.
799             _mkdir( $dir . '/xl' );
800             _mkdir( $dir . '/xl/chartsheets' );
801             _mkdir( $dir . '/xl/chartsheets/_rels' );
802              
803             my $rels = Excel::Writer::XLSX::Package::Relationships->new();
804              
805             for my $link_data ( @external_links ) {
806             $rels->_add_worksheet_relationship( @$link_data );
807             }
808 892     892   2060  
809 892         2158 # Create the .rels file such as /xl/chartsheets/_rels/sheet1.xml.rels.
810             $rels->_set_xml_writer(
811             $dir . '/xl/chartsheets/_rels/sheet' . $index . '.xml.rels' );
812 892         1754 $rels->_assemble_xml_file();
813 892         1749 }
  892         3211  
814             }
815 1041 100       4236  
816              
817 20         37 ###############################################################################
818             #
819 20         38 # _write_drawing_rels_files()
  20         57  
820             #
821 20 50       61 # Write the drawing .rels files for worksheets that contain charts or drawings.
822             #
823              
824 20         73 my $self = shift;
825 20         95 my $dir = $self->{_package_dir};
826 20         88  
827              
828 20         162 my $index = 0;
829             for my $worksheet ( @{ $self->{_workbook}->{_worksheets} } ) {
830 20         56  
831 20         81 if ( @{ $worksheet->{_drawing_links} } || $worksheet->{_has_shapes} ) {
832             $index++;
833             }
834              
835             next unless @{ $worksheet->{_drawing_links} };
836 20         70  
837 20         74 # Create the drawing .rels dir.
838             _mkdir( $dir . '/xl' );
839             _mkdir( $dir . '/xl/drawings' );
840             _mkdir( $dir . '/xl/drawings/_rels' );
841              
842             my $rels = Excel::Writer::XLSX::Package::Relationships->new();
843              
844             for my $drawing_data ( @{ $worksheet->{_drawing_links} } ) {
845             $rels->_add_document_relationship( @$drawing_data );
846             }
847              
848             # Create the .rels file such as /xl/drawings/_rels/sheet1.xml.rels.
849             $rels->_set_xml_writer(
850 892     892   1749 $dir . '/xl/drawings/_rels/drawing' . $index . '.xml.rels' );
851 892         1892 $rels->_assemble_xml_file();
852             }
853             }
854 892         1637  
855 892         1681  
  892         2798  
856             ###############################################################################
857 1041 100 100     2942 #
  1041         5736  
858 523         942 # _write_vml_drawing_rels_files()
859             #
860             # Write the vmlDdrawing .rels files for worksheets with images in header or
861 1041 100       1825 # footers.
  1041         3635  
862             #
863              
864 513         1869 my $self = shift;
865 513         2465 my $worksheet = shift;
866 513         2236 my $index = shift;
867             my $dir = $self->{_package_dir};
868 513         4070  
869              
870 513         1058 # Create the drawing .rels dir.
  513         1687  
871 574         1791 _mkdir( $dir . '/xl' );
872             _mkdir( $dir . '/xl/drawings' );
873             _mkdir( $dir . '/xl/drawings/_rels' );
874              
875             my $rels = Excel::Writer::XLSX::Package::Relationships->new();
876 513         1839  
877 513         1913 for my $drawing_data ( @{ $worksheet->{_vml_drawing_links} } ) {
878             $rels->_add_document_relationship( @$drawing_data );
879             }
880              
881             # Create the .rels file such as /xl/drawings/_rels/vmlDrawing1.vml.rels.
882             $rels->_set_xml_writer(
883             $dir . '/xl/drawings/_rels/vmlDrawing' . $index . '.vml.rels' );
884             $rels->_assemble_xml_file();
885              
886             }
887              
888              
889             ###############################################################################
890             #
891 24     24   51 # _add_image_files()
892 24         46 #
893 24         50 # Write the /xl/media/image?.xml files.
894 24         57 #
895              
896             my $self = shift;
897             my $dir = $self->{_package_dir};
898 24         104 my $workbook = $self->{_workbook};
899 24         148 my $index = 1;
900 24         115  
901             for my $image ( @{ $workbook->{_images} } ) {
902 24         263 my $filename = $image->[0];
903             my $extension = '.' . $image->[1];
904 24         47  
  24         84  
905 36         116 _mkdir( $dir . '/xl' );
906             _mkdir( $dir . '/xl/media' );
907              
908             copy( $filename, $dir . '/xl/media/image' . $index++ . $extension );
909             }
910 24         83 }
911 24         114  
912              
913             ###############################################################################
914             #
915             # _add_vba_project()
916             #
917             # Write the vbaProject.bin file.
918             #
919              
920             my $self = shift;
921             my $dir = $self->{_package_dir};
922             my $vba_project = $self->{_workbook}->{_vba_project};
923              
924 892     892   1964 return unless $vba_project;
925 892         2043  
926 892         1874 _mkdir( $dir . '/xl' );
927 892         1732  
928             copy( $vba_project, $dir . '/xl/vbaProject.bin' );
929 892         1641 }
  892         3231  
930 155         10604  
931 155         413  
932             ###############################################################################
933 155         524 #
934 155         666 # _mkdir()
935             #
936 155         736 # Wrapper function for Perl's mkdir to allow error trapping.
937             #
938              
939             my $dir = shift;
940              
941             return if -e $dir;
942              
943             my $ret = mkdir( $dir );
944              
945             if ( !$ret ) {
946             croak "Couldn't create sub directory $dir: $!";
947             }
948             }
949 892     892   1758  
950 892         1945  
951 892         2060 1;
952              
953 892 100       3365  
954              
955 6         19 =pod
956              
957 6         32 =head1 NAME
958              
959             Packager - A class for creating the Excel XLSX package.
960              
961             =head1 SYNOPSIS
962              
963             See the documentation for L<Excel::Writer::XLSX>.
964              
965             =head1 DESCRIPTION
966              
967             This module is used in conjunction with L<Excel::Writer::XLSX> to create an Excel XLSX container file.
968              
969 16067     16067   124395 From Wikipedia: I<The Open Packaging Conventions (OPC) is a container-file technology initially created by Microsoft to store a combination of XML and non-XML files that together form a single entity such as an Open XML Paper Specification (OpenXPS) document>. L<http://en.wikipedia.org/wiki/Open_Packaging_Conventions>.
970              
971 16067 100       214231 At its simplest an Excel XLSX file contains the following elements:
972              
973 7536         312492 ____ [Content_Types].xml
974             |
975 7536 50       34816 |____ docProps
976 0           | |____ app.xml
977             | |____ core.xml
978             |
979             |____ xl
980             | |____ workbook.xml
981             | |____ worksheets
982             | | |____ sheet1.xml
983             | |
984             | |____ styles.xml
985             | |
986             | |____ theme
987             | | |____ theme1.xml
988             | |
989             | |_____rels
990             | |____ workbook.xml.rels
991             |
992             |_____rels
993             |____ .rels
994              
995              
996             The C<Excel::Writer::XLSX::Package::Packager> class co-ordinates the classes that represent the elements of the package and writes them into the XLSX file.
997              
998             =head1 AUTHOR
999              
1000             John McNamara jmcnamara@cpan.org
1001              
1002             =head1 COPYRIGHT
1003              
1004             (c) MM-MMXXI, John McNamara.
1005              
1006             All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.
1007              
1008             =head1 LICENSE
1009              
1010             Either the Perl Artistic Licence L<http://dev.perl.org/licenses/artistic.html> or the GPL L<http://www.opensource.org/licenses/gpl-license.php>.
1011              
1012             =head1 DISCLAIMER OF WARRANTY
1013              
1014             See the documentation for L<Excel::Writer::XLSX>.
1015              
1016             =cut