File Coverage

blib/lib/Excel/Writer/XLSX/Package/VML.pm
Criterion Covered Total %
statement 344 344 100.0
branch 14 14 100.0
condition 8 9 88.8
subroutine 47 47 100.0
pod 0 1 0.0
total 413 415 99.5


line stmt bran cond sub pod time code
1             package Excel::Writer::XLSX::Package::VML;
2              
3             ###############################################################################
4             #
5             # VML - A class for writing the Excel XLSX VML files.
6             #
7             # Used in conjunction with Excel::Writer::XLSX
8             #
9             # Copyright 2000-2019, John McNamara, jmcnamara@cpan.org
10             #
11             # Documentation after __END__
12             #
13              
14             # perltidy with the following options: -mbl=2 -pt=0 -nola
15              
16 1040     1040   19402 use 5.008002;
  1040         4850  
17 1040     1040   8168 use strict;
  1040         3352  
  1040         22755  
18 1040     1040   6336 use warnings;
  1040         3269  
  1040         30722  
19 1040     1040   7099 use Carp;
  1040         1928  
  1040         56186  
20 1040     1040   7283 use Excel::Writer::XLSX::Package::XMLwriter;
  1040         2037  
  1040         3124745  
21              
22             our @ISA = qw(Excel::Writer::XLSX::Package::XMLwriter);
23             our $VERSION = '1.03';
24              
25              
26             ###############################################################################
27             #
28             # Public and private API methods.
29             #
30             ###############################################################################
31              
32              
33             ###############################################################################
34             #
35             # new()
36             #
37             # Constructor.
38             #
39             sub new {
40              
41 97     97 0 18355 my $class = shift;
42 97         224 my $fh = shift;
43 97         766 my $self = Excel::Writer::XLSX::Package::XMLwriter->new( $fh );
44              
45 97         378 bless $self, $class;
46              
47 97         304 return $self;
48             }
49              
50              
51             ###############################################################################
52             #
53             # _assemble_xml_file()
54             #
55             # Assemble and write the XML file.
56             #
57             sub _assemble_xml_file {
58              
59 78     78   252 my $self = shift;
60 78         167 my $data_id = shift;
61 78         272 my $vml_shape_id = shift;
62 78         283 my $comments_data = shift;
63 78         167 my $buttons_data = shift;
64 78         171 my $header_images_data = shift;
65 78         240 my $z_index = 1;
66              
67              
68 78         342 $self->_write_xml_namespace;
69              
70             # Write the o:shapelayout element.
71 78         452 $self->_write_shapelayout( $data_id );
72              
73 78 100 100     549 if ( defined $buttons_data && @$buttons_data ) {
74              
75             # Write the v:shapetype element.
76 22         115 $self->_write_button_shapetype();
77              
78 22         93 for my $button ( @$buttons_data ) {
79              
80             # Write the v:shape element.
81 29         125 $self->_write_button_shape( ++$vml_shape_id, $z_index++, $button );
82             }
83             }
84              
85 78 100 100     678 if ( defined $comments_data && @$comments_data ) {
86              
87             # Write the v:shapetype element.
88 40         279 $self->_write_comment_shapetype();
89              
90 40         285 for my $comment ( @$comments_data ) {
91              
92             # Write the v:shape element.
93 4154         9939 $self->_write_comment_shape( ++$vml_shape_id, $z_index++,
94             $comment );
95             }
96             }
97              
98 78 100 66     460 if ( defined $header_images_data && @$header_images_data ) {
99              
100             # Write the v:shapetype element.
101 23         110 $self->_write_image_shapetype();
102              
103 23         64 my $index = 1;
104 23         79 for my $image ( @$header_images_data ) {
105              
106             # Write the v:shape element.
107 45         185 $self->_write_image_shape( ++$vml_shape_id, $index++, $image );
108             }
109             }
110              
111              
112 78         348 $self->xml_end_tag( 'xml' );
113              
114             # Close the XML writer filehandle.
115 78         552 $self->xml_get_fh()->close();
116             }
117              
118              
119             ###############################################################################
120             #
121             # Internal methods.
122             #
123             ###############################################################################
124              
125              
126             ###############################################################################
127             #
128             # _pixels_to_points()
129             #
130             # Convert comment vertices from pixels to points.
131             #
132             sub _pixels_to_points {
133              
134 4183     4183   6670 my $self = shift;
135 4183         5759 my $vertices = shift;
136              
137             my (
138 4183         15484 $col_start, $row_start, $x1, $y1,
139             $col_end, $row_end, $x2, $y2,
140             $left, $top, $width, $height
141             ) = @$vertices;
142              
143 4183         7594 for my $pixels ( $left, $top, $width, $height ) {
144 16732         25057 $pixels *= 0.75;
145             }
146              
147 4183         9980 return ( $left, $top, $width, $height );
148             }
149              
150              
151             ###############################################################################
152             #
153             # XML writing methods.
154             #
155             ###############################################################################
156              
157              
158             ###############################################################################
159             #
160             # _write_xml_namespace()
161             #
162             # Write the element. This is the root element of VML.
163             #
164             sub _write_xml_namespace {
165              
166 78     78   168 my $self = shift;
167 78         313 my $schema = 'urn:schemas-microsoft-com:';
168 78         280 my $xmlns = $schema . 'vml';
169 78         227 my $xmlns_o = $schema . 'office:office';
170 78         455 my $xmlns_x = $schema . 'office:excel';
171              
172 78         367 my @attributes = (
173             'xmlns:v' => $xmlns,
174             'xmlns:o' => $xmlns_o,
175             'xmlns:x' => $xmlns_x,
176             );
177              
178 78         577 $self->xml_start_tag( 'xml', @attributes );
179             }
180              
181              
182             ##############################################################################
183             #
184             # _write_shapelayout()
185             #
186             # Write the element.
187             #
188             sub _write_shapelayout {
189              
190 79     79   197 my $self = shift;
191 79         170 my $data_id = shift;
192 79         199 my $ext = 'edit';
193              
194 79         319 my @attributes = ( 'v:ext' => $ext );
195              
196 79         354 $self->xml_start_tag( 'o:shapelayout', @attributes );
197              
198             # Write the o:idmap element.
199 79         365 $self->_write_idmap( $data_id );
200              
201 79         383 $self->xml_end_tag( 'o:shapelayout' );
202             }
203              
204              
205             ##############################################################################
206             #
207             # _write_idmap()
208             #
209             # Write the element.
210             #
211             sub _write_idmap {
212              
213 80     80   209 my $self = shift;
214 80         184 my $ext = 'edit';
215 80         171 my $data_id = shift;
216              
217 80         323 my @attributes = (
218             'v:ext' => $ext,
219             'data' => $data_id,
220             );
221              
222 80         502 $self->xml_empty_tag( 'o:idmap', @attributes );
223             }
224              
225              
226             ##############################################################################
227             #
228             # _write_comment_shapetype()
229             #
230             # Write the element.
231             #
232             sub _write_comment_shapetype {
233              
234 41     41   105 my $self = shift;
235 41         115 my $id = '_x0000_t202';
236 41         125 my $coordsize = '21600,21600';
237 41         97 my $spt = 202;
238 41         96 my $path = 'm,l,21600r21600,l21600,xe';
239              
240 41         186 my @attributes = (
241             'id' => $id,
242             'coordsize' => $coordsize,
243             'o:spt' => $spt,
244             'path' => $path,
245             );
246              
247 41         204 $self->xml_start_tag( 'v:shapetype', @attributes );
248              
249             # Write the v:stroke element.
250 41         186 $self->_write_stroke();
251              
252             # Write the v:path element.
253 41         211 $self->_write_comment_path( 't', 'rect' );
254              
255 41         161 $self->xml_end_tag( 'v:shapetype' );
256             }
257              
258              
259             ##############################################################################
260             #
261             # _write_button_shapetype()
262             #
263             # Write the element.
264             #
265             sub _write_button_shapetype {
266              
267 23     23   68 my $self = shift;
268 23         70 my $id = '_x0000_t201';
269 23         59 my $coordsize = '21600,21600';
270 23         45 my $spt = 201;
271 23         51 my $path = 'm,l,21600r21600,l21600,xe';
272              
273 23         90 my @attributes = (
274             'id' => $id,
275             'coordsize' => $coordsize,
276             'o:spt' => $spt,
277             'path' => $path,
278             );
279              
280 23         126 $self->xml_start_tag( 'v:shapetype', @attributes );
281              
282             # Write the v:stroke element.
283 23         110 $self->_write_stroke();
284              
285             # Write the v:path element.
286 23         123 $self->_write_button_path( 't', 'rect' );
287              
288             # Write the o:lock element.
289 23         116 $self->_write_shapetype_lock();
290              
291 23         131 $self->xml_end_tag( 'v:shapetype' );
292             }
293              
294              
295             ##############################################################################
296             #
297             # _write_image_shapetype()
298             #
299             # Write the element.
300             #
301             sub _write_image_shapetype {
302              
303 23     23   67 my $self = shift;
304 23         49 my $id = '_x0000_t75';
305 23         46 my $coordsize = '21600,21600';
306 23         45 my $spt = 75;
307 23         57 my $o_preferrelative = 't';
308 23         54 my $path = 'm@4@5l@4@11@9@11@9@5xe';
309 23         55 my $filled = 'f';
310 23         41 my $stroked = 'f';
311              
312 23         131 my @attributes = (
313             'id' => $id,
314             'coordsize' => $coordsize,
315             'o:spt' => $spt,
316             'o:preferrelative' => $o_preferrelative,
317             'path' => $path,
318             'filled' => $filled,
319             'stroked' => $stroked,
320             );
321              
322 23         115 $self->xml_start_tag( 'v:shapetype', @attributes );
323              
324             # Write the v:stroke element.
325 23         103 $self->_write_stroke();
326              
327             # Write the v:formulas element.
328 23         115 $self->_write_formulas();
329              
330             # Write the v:path element.
331 23         128 $self->_write_image_path();
332              
333             # Write the o:lock element.
334 23         122 $self->_write_aspect_ratio_lock();
335              
336 23         108 $self->xml_end_tag( 'v:shapetype' );
337             }
338              
339              
340             ##############################################################################
341             #
342             # _write_stroke()
343             #
344             # Write the element.
345             #
346             sub _write_stroke {
347              
348 88     88   244 my $self = shift;
349 88         226 my $joinstyle = 'miter';
350              
351 88         277 my @attributes = ( 'joinstyle' => $joinstyle );
352              
353 88         392 $self->xml_empty_tag( 'v:stroke', @attributes );
354             }
355              
356              
357             ##############################################################################
358             #
359             # _write_comment_path()
360             #
361             # Write the element.
362             #
363             sub _write_comment_path {
364              
365 4197     4197   6822 my $self = shift;
366 4197         5995 my $gradientshapeok = shift;
367 4197         6425 my $connecttype = shift;
368 4197         6662 my @attributes = ();
369              
370 4197 100       8166 push @attributes, ( 'gradientshapeok' => 't' ) if $gradientshapeok;
371 4197         7909 push @attributes, ( 'o:connecttype' => $connecttype );
372              
373 4197         8832 $self->xml_empty_tag( 'v:path', @attributes );
374             }
375              
376              
377             ##############################################################################
378             #
379             # _write_button_path()
380             #
381             # Write the element.
382             #
383             sub _write_button_path {
384              
385 24     24   71 my $self = shift;
386 24         55 my $shadowok = 'f';
387 24         57 my $extrusionok = 'f';
388 24         59 my $strokeok = 'f';
389 24         49 my $fillok = 'f';
390 24         50 my $connecttype = 'rect';
391              
392 24         106 my @attributes = (
393             'shadowok' => $shadowok,
394             'o:extrusionok' => $extrusionok,
395             'strokeok' => $strokeok,
396             'fillok' => $fillok,
397             'o:connecttype' => $connecttype,
398             );
399              
400 24         85 $self->xml_empty_tag( 'v:path', @attributes );
401             }
402              
403              
404             ##############################################################################
405             #
406             # _write_image_path()
407             #
408             # Write the element.
409             #
410             sub _write_image_path {
411              
412 23     23   63 my $self = shift;
413 23         54 my $extrusionok = 'f';
414 23         48 my $gradientshapeok = 't';
415 23         57 my $connecttype = 'rect';
416              
417 23         101 my @attributes = (
418             'o:extrusionok' => $extrusionok,
419             'gradientshapeok' => $gradientshapeok,
420             'o:connecttype' => $connecttype,
421             );
422              
423 23         427 $self->xml_empty_tag( 'v:path', @attributes );
424             }
425              
426              
427             ##############################################################################
428             #
429             # _write_shapetype_lock()
430             #
431             # Write the element.
432             #
433             sub _write_shapetype_lock {
434              
435 23     23   60 my $self = shift;
436 23         64 my $ext = 'edit';
437 23         69 my $shapetype = 't';
438              
439 23         83 my @attributes = (
440             'v:ext' => $ext,
441             'shapetype' => $shapetype,
442             );
443              
444 23         108 $self->xml_empty_tag( 'o:lock', @attributes );
445             }
446              
447              
448             ##############################################################################
449             #
450             # _write_rotation_lock()
451             #
452             # Write the element.
453             #
454             sub _write_rotation_lock {
455              
456 74     74   167 my $self = shift;
457 74         160 my $ext = 'edit';
458 74         137 my $rotation = 't';
459              
460 74         233 my @attributes = (
461             'v:ext' => $ext,
462             'rotation' => $rotation,
463             );
464              
465 74         233 $self->xml_empty_tag( 'o:lock', @attributes );
466             }
467              
468              
469             ##############################################################################
470             #
471             # _write_aspect_ratio_lock()
472             #
473             # Write the element.
474             #
475             sub _write_aspect_ratio_lock {
476              
477 23     23   55 my $self = shift;
478 23         52 my $ext = 'edit';
479 23         45 my $aspectratio = 't';
480              
481 23         94 my @attributes = (
482             'v:ext' => $ext,
483             'aspectratio' => $aspectratio,
484             );
485              
486 23         91 $self->xml_empty_tag( 'o:lock', @attributes );
487             }
488              
489             ##############################################################################
490             #
491             # _write_comment_shape()
492             #
493             # Write the element.
494             #
495             sub _write_comment_shape {
496              
497 4154     4154   6333 my $self = shift;
498 4154         6492 my $id = shift;
499 4154         5773 my $z_index = shift;
500 4154         6875 my $comment = shift;
501 4154         6348 my $type = '#_x0000_t202';
502 4154         5897 my $insetmode = 'auto';
503 4154         5820 my $visibility = 'hidden';
504              
505             # Set the shape index.
506 4154         7715 $id = '_x0000_s' . $id;
507              
508             # Get the comment parameters
509 4154         11485 my $row = $comment->[0];
510 4154         6465 my $col = $comment->[1];
511 4154         7963 my $string = $comment->[2];
512 4154         6514 my $author = $comment->[3];
513 4154         6638 my $visible = $comment->[4];
514 4154         6295 my $fillcolor = $comment->[5];
515 4154         7509 my $vertices = $comment->[9];
516              
517 4154         8378 my ( $left, $top, $width, $height ) = $self->_pixels_to_points( $vertices );
518              
519             # Set the visibility.
520 4154 100       8921 $visibility = 'visible' if $visible;
521              
522 4154         29822 my $style =
523             'position:absolute;'
524             . 'margin-left:'
525             . $left . 'pt;'
526             . 'margin-top:'
527             . $top . 'pt;'
528             . 'width:'
529             . $width . 'pt;'
530             . 'height:'
531             . $height . 'pt;'
532             . 'z-index:'
533             . $z_index . ';'
534             . 'visibility:'
535             . $visibility;
536              
537              
538 4154         11929 my @attributes = (
539             'id' => $id,
540             'type' => $type,
541             'style' => $style,
542             'fillcolor' => $fillcolor,
543             'o:insetmode' => $insetmode,
544             );
545              
546 4154         12183 $self->xml_start_tag( 'v:shape', @attributes );
547              
548             # Write the v:fill element.
549 4154         11691 $self->_write_comment_fill();
550              
551             # Write the v:shadow element.
552 4154         10951 $self->_write_shadow();
553              
554             # Write the v:path element.
555 4154         11099 $self->_write_comment_path( undef, 'none' );
556              
557             # Write the v:textbox element.
558 4154         10685 $self->_write_comment_textbox();
559              
560             # Write the x:ClientData element.
561 4154         11348 $self->_write_comment_client_data( $row, $col, $visible, $vertices );
562              
563 4154         9189 $self->xml_end_tag( 'v:shape' );
564             }
565              
566              
567             ##############################################################################
568             #
569             # _write_button_shape()
570             #
571             # Write the element.
572             #
573             sub _write_button_shape {
574              
575 29     29   68 my $self = shift;
576 29         201 my $id = shift;
577 29         67 my $z_index = shift;
578 29         180 my $button = shift;
579 29         62 my $type = '#_x0000_t201';
580              
581             # Set the shape index.
582 29         85 $id = '_x0000_s' . $id;
583              
584             # Get the button parameters
585 29         93 my $row = $button->{_row};
586 29         75 my $col = $button->{_col};
587 29         84 my $vertices = $button->{_vertices};
588              
589 29         131 my ( $left, $top, $width, $height ) = $self->_pixels_to_points( $vertices );
590              
591 29         366 my $style =
592             'position:absolute;'
593             . 'margin-left:'
594             . $left . 'pt;'
595             . 'margin-top:'
596             . $top . 'pt;'
597             . 'width:'
598             . $width . 'pt;'
599             . 'height:'
600             . $height . 'pt;'
601             . 'z-index:'
602             . $z_index . ';'
603             . 'mso-wrap-style:tight';
604              
605              
606 29         185 my @attributes = (
607             'id' => $id,
608             'type' => $type,
609             'style' => $style,
610             'o:button' => 't',
611             'fillcolor' => 'buttonFace [67]',
612             'strokecolor' => 'windowText [64]',
613             'o:insetmode' => 'auto',
614             );
615              
616 29         137 $self->xml_start_tag( 'v:shape', @attributes );
617              
618             # Write the v:fill element.
619 29         252 $self->_write_button_fill();
620              
621             # Write the o:lock element.
622 29         151 $self->_write_rotation_lock();
623              
624             # Write the v:textbox element.
625 29         166 $self->_write_button_textbox( $button->{_font} );
626              
627             # Write the x:ClientData element.
628 29         148 $self->_write_button_client_data( $button );
629              
630 29         96 $self->xml_end_tag( 'v:shape' );
631             }
632              
633              
634             ##############################################################################
635             #
636             # _write_image_shape()
637             #
638             # Write the element.
639             #
640             sub _write_image_shape {
641              
642 45     45   82 my $self = shift;
643 45         102 my $id = shift;
644 45         103 my $index = shift;
645 45         76 my $image_data = shift;
646 45         110 my $type = '#_x0000_t75';
647              
648             # Set the shape index.
649 45         129 $id = '_x0000_s' . $id;
650              
651             # Get the image parameters
652 45         121 my $width = $image_data->[0];
653 45         97 my $height = $image_data->[1];
654 45         89 my $name = $image_data->[2];
655 45         89 my $position = $image_data->[3];
656 45         93 my $x_dpi = $image_data->[4];
657 45         93 my $y_dpi = $image_data->[5];
658 45         89 my $ref_id = $image_data->[6];
659              
660             # Scale the height/width by the resolution, relative to 72dpi.
661 45         135 $width = $width * 72 / $x_dpi;
662 45         87 $height = $height * 72 / $y_dpi;
663              
664             # Excel uses a rounding based around 72 and 96 dpi.
665 45         199 $width = 72/96 * int($width * 96/72 + 0.25);
666 45         140 $height = 72/96 * int($height * 96/72 + 0.25);
667              
668 45         357 my $style =
669             'position:absolute;'
670             . 'margin-left:0;'
671             . 'margin-top:0;'
672             . 'width:'
673             . $width . 'pt;'
674             . 'height:'
675             . $height . 'pt;'
676             . 'z-index:'
677             . $index;
678              
679 45         215 my @attributes = (
680             'id' => $position,
681             'o:spid' => $id,
682             'type' => $type,
683             'style' => $style,
684             );
685              
686 45         180 $self->xml_start_tag( 'v:shape', @attributes );
687              
688             # Write the v:imagedata element.
689 45         175 $self->_write_imagedata( $ref_id, $name );
690              
691             # Write the o:lock element.
692 45         185 $self->_write_rotation_lock();
693              
694 45         154 $self->xml_end_tag( 'v:shape' );
695             }
696              
697             ##############################################################################
698             #
699             # _write_comment_fill()
700             #
701             # Write the element.
702             #
703             sub _write_comment_fill {
704              
705 4155     4155   6441 my $self = shift;
706 4155         6513 my $color_2 = '#ffffe1';
707              
708 4155         8323 my @attributes = ( 'color2' => $color_2 );
709              
710 4155         9291 $self->xml_empty_tag( 'v:fill', @attributes );
711             }
712              
713              
714             ##############################################################################
715             #
716             # _write_button_fill()
717             #
718             # Write the element.
719             #
720             sub _write_button_fill {
721              
722 30     30   87 my $self = shift;
723 30         202 my $color_2 = 'buttonFace [67]';
724 30         84 my $detectmouseclick = 't';
725              
726 30         120 my @attributes = (
727             'color2' => $color_2,
728             'o:detectmouseclick' => $detectmouseclick,
729             );
730              
731 30         104 $self->xml_empty_tag( 'v:fill', @attributes );
732             }
733              
734              
735             ##############################################################################
736             #
737             # _write_shadow()
738             #
739             # Write the element.
740             #
741             sub _write_shadow {
742              
743 4155     4155   6447 my $self = shift;
744 4155         6554 my $on = 't';
745 4155         6337 my $color = 'black';
746 4155         5822 my $obscured = 't';
747              
748 4155         9652 my @attributes = (
749             'on' => $on,
750             'color' => $color,
751             'obscured' => $obscured,
752             );
753              
754 4155         8691 $self->xml_empty_tag( 'v:shadow', @attributes );
755             }
756              
757              
758             ##############################################################################
759             #
760             # _write_comment_textbox()
761             #
762             # Write the element.
763             #
764             sub _write_comment_textbox {
765              
766 4155     4155   6337 my $self = shift;
767 4155         6621 my $style = 'mso-direction-alt:auto';
768              
769 4155         7467 my @attributes = ( 'style' => $style );
770              
771 4155         10811 $self->xml_start_tag( 'v:textbox', @attributes );
772              
773             # Write the div element.
774 4155         10813 $self->_write_div( 'left' );
775              
776 4155         9226 $self->xml_end_tag( 'v:textbox' );
777             }
778              
779              
780             ##############################################################################
781             #
782             # _write_button_textbox()
783             #
784             # Write the element.
785             #
786             sub _write_button_textbox {
787              
788 29     29   68 my $self = shift;
789 29         71 my $font = shift;
790 29         63 my $style = 'mso-direction-alt:auto';
791              
792 29         99 my @attributes = ( 'style' => $style, 'o:singleclick' => 'f' );
793              
794 29         121 $self->xml_start_tag( 'v:textbox', @attributes );
795              
796             # Write the div element.
797 29         137 $self->_write_div( 'center', $font );
798              
799 29         92 $self->xml_end_tag( 'v:textbox' );
800             }
801              
802              
803             ##############################################################################
804             #
805             # _write_div()
806             #
807             # Write the
element.
808             #
809             sub _write_div {
810              
811 4185     4185   6576 my $self = shift;
812 4185         6537 my $align = shift;
813 4185         6120 my $font = shift;
814 4185         7081 my $style = 'text-align:' . $align;
815              
816 4185         7647 my @attributes = ( 'style' => $style );
817              
818 4185         10539 $self->xml_start_tag( 'div', @attributes );
819              
820              
821 4185 100       9484 if ( $font ) {
822              
823             # Write the font element.
824 29         160 $self->_write_font( $font );
825             }
826              
827 4185         9275 $self->xml_end_tag( 'div' );
828             }
829              
830             ##############################################################################
831             #
832             # _write_font()
833             #
834             # Write the element.
835             #
836             sub _write_font {
837              
838 29     29   65 my $self = shift;
839 29         94 my $font = shift;
840 29         74 my $caption = $font->{_caption};
841 29         65 my $face = 'Calibri';
842 29         179 my $size = 220;
843 29         71 my $color = '#000000';
844              
845 29         247 my @attributes = (
846             'face' => $face,
847             'size' => $size,
848             'color' => $color,
849             );
850              
851 29         250 $self->xml_data_element( 'font', $caption, @attributes );
852             }
853              
854              
855             ##############################################################################
856             #
857             # _write_comment_client_data()
858             #
859             # Write the element.
860             #
861             sub _write_comment_client_data {
862              
863 4154     4154   6287 my $self = shift;
864 4154         6522 my $row = shift;
865 4154         5883 my $col = shift;
866 4154         5742 my $visible = shift;
867 4154         5926 my $vertices = shift;
868 4154         5871 my $object_type = 'Note';
869              
870 4154         7502 my @attributes = ( 'ObjectType' => $object_type );
871              
872 4154         10810 $self->xml_start_tag( 'x:ClientData', @attributes );
873              
874             # Write the x:MoveWithCells element.
875 4154         10670 $self->_write_move_with_cells();
876              
877             # Write the x:SizeWithCells element.
878 4154         10247 $self->_write_size_with_cells();
879              
880             # Write the x:Anchor element.
881 4154         10769 $self->_write_anchor( $vertices );
882              
883             # Write the x:AutoFill element.
884 4154         10453 $self->_write_auto_fill();
885              
886             # Write the x:Row element.
887 4154         11477 $self->_write_row( $row );
888              
889             # Write the x:Column element.
890 4154         11109 $self->_write_column( $col );
891              
892             # Write the x:Visible element.
893 4154 100       9189 $self->_write_visible() if $visible;
894              
895 4154         9725 $self->xml_end_tag( 'x:ClientData' );
896             }
897              
898              
899             ##############################################################################
900             #
901             # _write_button_client_data()
902             #
903             # Write the element.
904             #
905             sub _write_button_client_data {
906              
907 29     29   70 my $self = shift;
908 29         58 my $button = shift;
909 29         68 my $row = $button->{_row};
910 29         65 my $col = $button->{_col};
911 29         69 my $macro = $button->{_macro};
912 29         62 my $vertices = $button->{_vertices};
913              
914              
915 29         58 my $object_type = 'Button';
916              
917 29         108 my @attributes = ( 'ObjectType' => $object_type );
918              
919 29         125 $self->xml_start_tag( 'x:ClientData', @attributes );
920              
921             # Write the x:Anchor element.
922 29         143 $self->_write_anchor( $vertices );
923              
924             # Write the x:PrintObject element.
925 29         144 $self->_write_print_object();
926              
927             # Write the x:AutoFill element.
928 29         143 $self->_write_auto_fill();
929              
930             # Write the x:FmlaMacro element.
931 29         119 $self->_write_fmla_macro( $macro );
932              
933             # Write the x:TextHAlign element.
934 29         174 $self->_write_text_halign();
935              
936             # Write the x:TextVAlign element.
937 29         108 $self->_write_text_valign();
938              
939 29         111 $self->xml_end_tag( 'x:ClientData' );
940             }
941              
942              
943             ##############################################################################
944             #
945             # _write_move_with_cells()
946             #
947             # Write the element.
948             #
949             sub _write_move_with_cells {
950              
951 4155     4155   6381 my $self = shift;
952              
953 4155         8744 $self->xml_empty_tag( 'x:MoveWithCells' );
954             }
955              
956              
957             ##############################################################################
958             #
959             # _write_size_with_cells()
960             #
961             # Write the element.
962             #
963             sub _write_size_with_cells {
964              
965 4155     4155   6386 my $self = shift;
966              
967 4155         8329 $self->xml_empty_tag( 'x:SizeWithCells' );
968             }
969              
970              
971             ##############################################################################
972             #
973             # _write_visible()
974             #
975             # Write the element.
976             #
977             sub _write_visible {
978              
979 10     10   15 my $self = shift;
980              
981 10         23 $self->xml_empty_tag( 'x:Visible' );
982             }
983              
984              
985             ##############################################################################
986             #
987             # _write_anchor()
988             #
989             # Write the element.
990             #
991             sub _write_anchor {
992              
993 4184     4184   6585 my $self = shift;
994 4184         5826 my $vertices = shift;
995              
996 4184         9950 my ( $col_start, $row_start, $x1, $y1, $col_end, $row_end, $x2, $y2 ) =
997             @$vertices;
998              
999 4184         10878 my $data = join ", ",
1000             ( $col_start, $x1, $row_start, $y1, $col_end, $x2, $row_end, $y2 );
1001              
1002 4184         9955 $self->xml_data_element( 'x:Anchor', $data );
1003             }
1004              
1005              
1006             ##############################################################################
1007             #
1008             # _write_auto_fill()
1009             #
1010             # Write the element.
1011             #
1012             sub _write_auto_fill {
1013              
1014 4184     4184   7022 my $self = shift;
1015 4184         6555 my $data = 'False';
1016              
1017 4184         8699 $self->xml_data_element( 'x:AutoFill', $data );
1018             }
1019              
1020              
1021             ##############################################################################
1022             #
1023             # _write_row()
1024             #
1025             # Write the element.
1026             #
1027             sub _write_row {
1028              
1029 4155     4155   7071 my $self = shift;
1030 4155         6292 my $data = shift;
1031              
1032 4155         8586 $self->xml_data_element( 'x:Row', $data );
1033             }
1034              
1035              
1036             ##############################################################################
1037             #
1038             # _write_column()
1039             #
1040             # Write the element.
1041             #
1042             sub _write_column {
1043              
1044 4155     4155   6468 my $self = shift;
1045 4155         6101 my $data = shift;
1046              
1047 4155         8248 $self->xml_data_element( 'x:Column', $data );
1048             }
1049              
1050              
1051             ##############################################################################
1052             #
1053             # _write_print_object()
1054             #
1055             # Write the element.
1056             #
1057             sub _write_print_object {
1058              
1059 29     29   63 my $self = shift;
1060 29         61 my $data = 'False';
1061              
1062 29         92 $self->xml_data_element( 'x:PrintObject', $data );
1063             }
1064              
1065              
1066             ##############################################################################
1067             #
1068             # _write_text_halign()
1069             #
1070             # Write the element.
1071             #
1072             sub _write_text_halign {
1073              
1074 29     29   60 my $self = shift;
1075 29         68 my $data = 'Center';
1076              
1077 29         86 $self->xml_data_element( 'x:TextHAlign', $data );
1078             }
1079              
1080              
1081             ##############################################################################
1082             #
1083             # _write_text_valign()
1084             #
1085             # Write the element.
1086             #
1087             sub _write_text_valign {
1088              
1089 29     29   60 my $self = shift;
1090 29         58 my $data = 'Center';
1091              
1092 29         73 $self->xml_data_element( 'x:TextVAlign', $data );
1093             }
1094              
1095              
1096             ##############################################################################
1097             #
1098             # _write_fmla_macro()
1099             #
1100             # Write the element.
1101             #
1102             sub _write_fmla_macro {
1103              
1104 29     29   70 my $self = shift;
1105 29         134 my $data = shift;
1106              
1107 29         111 $self->xml_data_element( 'x:FmlaMacro', $data );
1108             }
1109              
1110             ##############################################################################
1111             #
1112             # _write_imagedata()
1113             #
1114             # Write the element.
1115             #
1116             sub _write_imagedata {
1117              
1118 45     45   90 my $self = shift;
1119 45         88 my $index = shift;
1120 45         87 my $o_title = shift;
1121              
1122 45         165 my @attributes = (
1123             'o:relid' => 'rId' . $index,
1124             'o:title' => $o_title,
1125             );
1126              
1127 45         140 $self->xml_empty_tag( 'v:imagedata', @attributes );
1128             }
1129              
1130              
1131              
1132             ##############################################################################
1133             #
1134             # _write_formulas()
1135             #
1136             # Write the element.
1137             #
1138             sub _write_formulas {
1139              
1140 23     23   60 my $self = shift;
1141              
1142 23         96 $self->xml_start_tag( 'v:formulas' );
1143              
1144             # Write the v:f elements.
1145 23         122 $self->_write_f('if lineDrawn pixelLineWidth 0');
1146 23         124 $self->_write_f('sum @0 1 0');
1147 23         103 $self->_write_f('sum 0 0 @1');
1148 23         86 $self->_write_f('prod @2 1 2');
1149 23         94 $self->_write_f('prod @3 21600 pixelWidth');
1150 23         75 $self->_write_f('prod @3 21600 pixelHeight');
1151 23         99 $self->_write_f('sum @0 0 1');
1152 23         92 $self->_write_f('prod @6 1 2');
1153 23         95 $self->_write_f('prod @7 21600 pixelWidth');
1154 23         98 $self->_write_f('sum @8 21600 0');
1155 23         92 $self->_write_f('prod @7 21600 pixelHeight');
1156 23         82 $self->_write_f('sum @10 21600 0');
1157              
1158 23         101 $self->xml_end_tag( 'v:formulas' );
1159             }
1160              
1161              
1162             ##############################################################################
1163             #
1164             # _write_f()
1165             #
1166             # Write the element.
1167             #
1168             sub _write_f {
1169              
1170 276     276   424 my $self = shift;
1171 276         431 my $eqn = shift;
1172              
1173 276         538 my @attributes = ( 'eqn' => $eqn );
1174              
1175 276         632 $self->xml_empty_tag( 'v:f', @attributes );
1176             }
1177              
1178             1;
1179              
1180              
1181             __END__