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-2020, 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 1081     1081   18265 use 5.008002;
  1081         4711  
17 1081     1081   6511 use strict;
  1081         1921  
  1081         24007  
18 1081     1081   4800 use warnings;
  1081         3097  
  1081         24156  
19 1081     1081   11537 use Carp;
  1081         1889  
  1081         50988  
20 1081     1081   5739 use Excel::Writer::XLSX::Package::XMLwriter;
  1081         4263  
  1081         2996487  
21              
22             our @ISA = qw(Excel::Writer::XLSX::Package::XMLwriter);
23             our $VERSION = '1.07';
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 101     101 0 17350 my $class = shift;
42 101         229 my $fh = shift;
43 101         482 my $self = Excel::Writer::XLSX::Package::XMLwriter->new( $fh );
44              
45 101         227 bless $self, $class;
46              
47 101         249 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 82     82   280 my $self = shift;
60 82         179 my $data_id = shift;
61 82         177 my $vml_shape_id = shift;
62 82         142 my $comments_data = shift;
63 82         167 my $buttons_data = shift;
64 82         148 my $header_images_data = shift;
65 82         135 my $z_index = 1;
66              
67              
68 82         369 $self->_write_xml_namespace;
69              
70             # Write the o:shapelayout element.
71 82         689 $self->_write_shapelayout( $data_id );
72              
73 82 100 100     545 if ( defined $buttons_data && @$buttons_data ) {
74              
75             # Write the v:shapetype element.
76 22         103 $self->_write_button_shapetype();
77              
78 22         61 for my $button ( @$buttons_data ) {
79              
80             # Write the v:shape element.
81 29         132 $self->_write_button_shape( ++$vml_shape_id, $z_index++, $button );
82             }
83             }
84              
85 82 100 100     550 if ( defined $comments_data && @$comments_data ) {
86              
87             # Write the v:shapetype element.
88 44         225 $self->_write_comment_shapetype();
89              
90 44         134 for my $comment ( @$comments_data ) {
91              
92             # Write the v:shape element.
93 4162         7860 $self->_write_comment_shape( ++$vml_shape_id, $z_index++,
94             $comment );
95             }
96             }
97              
98 82 100 66     458 if ( defined $header_images_data && @$header_images_data ) {
99              
100             # Write the v:shapetype element.
101 23         112 $self->_write_image_shapetype();
102              
103 23         48 my $index = 1;
104 23         70 for my $image ( @$header_images_data ) {
105              
106             # Write the v:shape element.
107 45         180 $self->_write_image_shape( ++$vml_shape_id, $index++, $image );
108             }
109             }
110              
111              
112 82         487 $self->xml_end_tag( 'xml' );
113              
114             # Close the XML writer filehandle.
115 82         694 $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 4191     4191   5068 my $self = shift;
135 4191         4761 my $vertices = shift;
136              
137             my (
138 4191         10051 $col_start, $row_start, $x1, $y1,
139             $col_end, $row_end, $x2, $y2,
140             $left, $top, $width, $height
141             ) = @$vertices;
142              
143 4191         6042 for my $pixels ( $left, $top, $width, $height ) {
144 16764         21425 $pixels *= 0.75;
145             }
146              
147 4191         8280 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 82     82   170 my $self = shift;
167 82         566 my $schema = 'urn:schemas-microsoft-com:';
168 82         675 my $xmlns = $schema . 'vml';
169 82         241 my $xmlns_o = $schema . 'office:office';
170 82         386 my $xmlns_x = $schema . 'office:excel';
171              
172 82         546 my @attributes = (
173             'xmlns:v' => $xmlns,
174             'xmlns:o' => $xmlns_o,
175             'xmlns:x' => $xmlns_x,
176             );
177              
178 82         475 $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 83     83   194 my $self = shift;
191 83         164 my $data_id = shift;
192 83         185 my $ext = 'edit';
193              
194 83         427 my @attributes = ( 'v:ext' => $ext );
195              
196 83         343 $self->xml_start_tag( 'o:shapelayout', @attributes );
197              
198             # Write the o:idmap element.
199 83         331 $self->_write_idmap( $data_id );
200              
201 83         392 $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 84     84   168 my $self = shift;
214 84         166 my $ext = 'edit';
215 84         178 my $data_id = shift;
216              
217 84         401 my @attributes = (
218             'v:ext' => $ext,
219             'data' => $data_id,
220             );
221              
222 84         616 $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 45     45   107 my $self = shift;
235 45         220 my $id = '_x0000_t202';
236 45         93 my $coordsize = '21600,21600';
237 45         88 my $spt = 202;
238 45         85 my $path = 'm,l,21600r21600,l21600,xe';
239              
240 45         196 my @attributes = (
241             'id' => $id,
242             'coordsize' => $coordsize,
243             'o:spt' => $spt,
244             'path' => $path,
245             );
246              
247 45         191 $self->xml_start_tag( 'v:shapetype', @attributes );
248              
249             # Write the v:stroke element.
250 45         191 $self->_write_stroke();
251              
252             # Write the v:path element.
253 45         204 $self->_write_comment_path( 't', 'rect' );
254              
255 45         141 $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   60 my $self = shift;
268 23         53 my $id = '_x0000_t201';
269 23         53 my $coordsize = '21600,21600';
270 23         51 my $spt = 201;
271 23         43 my $path = 'm,l,21600r21600,l21600,xe';
272              
273 23         98 my @attributes = (
274             'id' => $id,
275             'coordsize' => $coordsize,
276             'o:spt' => $spt,
277             'path' => $path,
278             );
279              
280 23         93 $self->xml_start_tag( 'v:shapetype', @attributes );
281              
282             # Write the v:stroke element.
283 23         94 $self->_write_stroke();
284              
285             # Write the v:path element.
286 23         102 $self->_write_button_path( 't', 'rect' );
287              
288             # Write the o:lock element.
289 23         292 $self->_write_shapetype_lock();
290              
291 23         72 $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   49 my $self = shift;
304 23         46 my $id = '_x0000_t75';
305 23         40 my $coordsize = '21600,21600';
306 23         58 my $spt = 75;
307 23         43 my $o_preferrelative = 't';
308 23         40 my $path = 'm@4@5l@4@11@9@11@9@5xe';
309 23         44 my $filled = 'f';
310 23         43 my $stroked = 'f';
311              
312 23         132 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         91 $self->xml_start_tag( 'v:shapetype', @attributes );
323              
324             # Write the v:stroke element.
325 23         88 $self->_write_stroke();
326              
327             # Write the v:formulas element.
328 23         99 $self->_write_formulas();
329              
330             # Write the v:path element.
331 23         102 $self->_write_image_path();
332              
333             # Write the o:lock element.
334 23         99 $self->_write_aspect_ratio_lock();
335              
336 23         76 $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 92     92   212 my $self = shift;
349 92         182 my $joinstyle = 'miter';
350              
351 92         320 my @attributes = ( 'joinstyle' => $joinstyle );
352              
353 92         342 $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 4209     4209   5365 my $self = shift;
366 4209         5055 my $gradientshapeok = shift;
367 4209         5053 my $connecttype = shift;
368 4209         5314 my @attributes = ();
369              
370 4209 100       6502 push @attributes, ( 'gradientshapeok' => 't' ) if $gradientshapeok;
371 4209         6419 push @attributes, ( 'o:connecttype' => $connecttype );
372              
373 4209         7175 $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   56 my $self = shift;
386 24         68 my $shadowok = 'f';
387 24         73 my $extrusionok = 'f';
388 24         57 my $strokeok = 'f';
389 24         46 my $fillok = 'f';
390 24         47 my $connecttype = 'rect';
391              
392 24         122 my @attributes = (
393             'shadowok' => $shadowok,
394             'o:extrusionok' => $extrusionok,
395             'strokeok' => $strokeok,
396             'fillok' => $fillok,
397             'o:connecttype' => $connecttype,
398             );
399              
400 24         94 $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   47 my $self = shift;
413 23         62 my $extrusionok = 'f';
414 23         54 my $gradientshapeok = 't';
415 23         47 my $connecttype = 'rect';
416              
417 23         92 my @attributes = (
418             'o:extrusionok' => $extrusionok,
419             'gradientshapeok' => $gradientshapeok,
420             'o:connecttype' => $connecttype,
421             );
422              
423 23         90 $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   50 my $self = shift;
436 23         47 my $ext = 'edit';
437 23         47 my $shapetype = 't';
438              
439 23         93 my @attributes = (
440             'v:ext' => $ext,
441             'shapetype' => $shapetype,
442             );
443              
444 23         89 $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   130 my $self = shift;
457 74         157 my $ext = 'edit';
458 74         139 my $rotation = 't';
459              
460 74         189 my @attributes = (
461             'v:ext' => $ext,
462             'rotation' => $rotation,
463             );
464              
465 74         363 $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   47 my $self = shift;
478 23         43 my $ext = 'edit';
479 23         693 my $aspectratio = 't';
480              
481 23         92 my @attributes = (
482             'v:ext' => $ext,
483             'aspectratio' => $aspectratio,
484             );
485              
486 23         90 $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 4162     4162   5101 my $self = shift;
498 4162         4976 my $id = shift;
499 4162         4762 my $z_index = shift;
500 4162         5155 my $comment = shift;
501 4162         4932 my $type = '#_x0000_t202';
502 4162         4858 my $insetmode = 'auto';
503 4162         4596 my $visibility = 'hidden';
504              
505             # Set the shape index.
506 4162         6065 $id = '_x0000_s' . $id;
507              
508             # Get the comment parameters
509 4162         7797 my $row = $comment->[0];
510 4162         5149 my $col = $comment->[1];
511 4162         5574 my $string = $comment->[2];
512 4162         5523 my $author = $comment->[3];
513 4162         5123 my $visible = $comment->[4];
514 4162         5525 my $fillcolor = $comment->[5];
515 4162         5293 my $vertices = $comment->[9];
516              
517 4162         6977 my ( $left, $top, $width, $height ) = $self->_pixels_to_points( $vertices );
518              
519             # Set the visibility.
520 4162 100       7069 $visibility = 'visible' if $visible;
521              
522 4162         24540 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 4162         10730 my @attributes = (
539             'id' => $id,
540             'type' => $type,
541             'style' => $style,
542             'fillcolor' => $fillcolor,
543             'o:insetmode' => $insetmode,
544             );
545              
546 4162         10180 $self->xml_start_tag( 'v:shape', @attributes );
547              
548             # Write the v:fill element.
549 4162         9695 $self->_write_comment_fill();
550              
551             # Write the v:shadow element.
552 4162         9342 $self->_write_shadow();
553              
554             # Write the v:path element.
555 4162         10647 $self->_write_comment_path( undef, 'none' );
556              
557             # Write the v:textbox element.
558 4162         8829 $self->_write_comment_textbox();
559              
560             # Write the x:ClientData element.
561 4162         9099 $self->_write_comment_client_data( $row, $col, $visible, $vertices );
562              
563 4162         7758 $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   60 my $self = shift;
576 29         57 my $id = shift;
577 29         62 my $z_index = shift;
578 29         77 my $button = shift;
579 29         60 my $type = '#_x0000_t201';
580              
581             # Set the shape index.
582 29         77 $id = '_x0000_s' . $id;
583              
584             # Get the button parameters
585 29         93 my $row = $button->{_row};
586 29         85 my $col = $button->{_col};
587 29         63 my $vertices = $button->{_vertices};
588              
589 29         98 my ( $left, $top, $width, $height ) = $self->_pixels_to_points( $vertices );
590              
591 29         360 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         163 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         132 $self->xml_start_tag( 'v:shape', @attributes );
617              
618             # Write the v:fill element.
619 29         126 $self->_write_button_fill();
620              
621             # Write the o:lock element.
622 29         113 $self->_write_rotation_lock();
623              
624             # Write the v:textbox element.
625 29         127 $self->_write_button_textbox( $button->{_font} );
626              
627             # Write the x:ClientData element.
628 29         108 $self->_write_button_client_data( $button );
629              
630 29         154 $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   80 my $self = shift;
643 45         73 my $id = shift;
644 45         86 my $index = shift;
645 45         76 my $image_data = shift;
646 45         78 my $type = '#_x0000_t75';
647              
648             # Set the shape index.
649 45         105 $id = '_x0000_s' . $id;
650              
651             # Get the image parameters
652 45         96 my $width = $image_data->[0];
653 45         89 my $height = $image_data->[1];
654 45         86 my $name = $image_data->[2];
655 45         100 my $position = $image_data->[3];
656 45         75 my $x_dpi = $image_data->[4];
657 45         76 my $y_dpi = $image_data->[5];
658 45         68 my $ref_id = $image_data->[6];
659              
660             # Scale the height/width by the resolution, relative to 72dpi.
661 45         104 $width = $width * 72 / $x_dpi;
662 45         159 $height = $height * 72 / $y_dpi;
663              
664             # Excel uses a rounding based around 72 and 96 dpi.
665 45         135 $width = 72/96 * int($width * 96/72 + 0.25);
666 45         103 $height = 72/96 * int($height * 96/72 + 0.25);
667              
668 45         338 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         153 my @attributes = (
680             'id' => $position,
681             'o:spid' => $id,
682             'type' => $type,
683             'style' => $style,
684             );
685              
686 45         209 $self->xml_start_tag( 'v:shape', @attributes );
687              
688             # Write the v:imagedata element.
689 45         163 $self->_write_imagedata( $ref_id, $name );
690              
691             # Write the o:lock element.
692 45         144 $self->_write_rotation_lock();
693              
694 45         122 $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 4163     4163   5729 my $self = shift;
706 4163         5191 my $color_2 = '#ffffe1';
707              
708 4163         6407 my @attributes = ( 'color2' => $color_2 );
709              
710 4163         7820 $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   78 my $self = shift;
723 30         54 my $color_2 = 'buttonFace [67]';
724 30         53 my $detectmouseclick = 't';
725              
726 30         93 my @attributes = (
727             'color2' => $color_2,
728             'o:detectmouseclick' => $detectmouseclick,
729             );
730              
731 30         87 $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 4163     4163   5440 my $self = shift;
744 4163         5345 my $on = 't';
745 4163         4962 my $color = 'black';
746 4163         4713 my $obscured = 't';
747              
748 4163         7664 my @attributes = (
749             'on' => $on,
750             'color' => $color,
751             'obscured' => $obscured,
752             );
753              
754 4163         7099 $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 4163     4163   5358 my $self = shift;
767 4163         5269 my $style = 'mso-direction-alt:auto';
768              
769 4163         6320 my @attributes = ( 'style' => $style );
770              
771 4163         9020 $self->xml_start_tag( 'v:textbox', @attributes );
772              
773             # Write the div element.
774 4163         9488 $self->_write_div( 'left' );
775              
776 4163         7594 $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   185 my $self = shift;
789 29         54 my $font = shift;
790 29         59 my $style = 'mso-direction-alt:auto';
791              
792 29         124 my @attributes = ( 'style' => $style, 'o:singleclick' => 'f' );
793              
794 29         106 $self->xml_start_tag( 'v:textbox', @attributes );
795              
796             # Write the div element.
797 29         123 $self->_write_div( 'center', $font );
798              
799 29         75 $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 4193     4193   5249 my $self = shift;
812 4193         5060 my $align = shift;
813 4193         4986 my $font = shift;
814 4193         5521 my $style = 'text-align:' . $align;
815              
816 4193         6275 my @attributes = ( 'style' => $style );
817              
818 4193         8661 $self->xml_start_tag( 'div', @attributes );
819              
820              
821 4193 100       7709 if ( $font ) {
822              
823             # Write the font element.
824 29         92 $self->_write_font( $font );
825             }
826              
827 4193         7614 $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   68 my $self = shift;
839 29         55 my $font = shift;
840 29         65 my $caption = $font->{_caption};
841 29         213 my $face = 'Calibri';
842 29         51 my $size = 220;
843 29         160 my $color = '#000000';
844              
845 29         114 my @attributes = (
846             'face' => $face,
847             'size' => $size,
848             'color' => $color,
849             );
850              
851 29         356 $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 4162     4162   5479 my $self = shift;
864 4162         5252 my $row = shift;
865 4162         4506 my $col = shift;
866 4162         5024 my $visible = shift;
867 4162         5011 my $vertices = shift;
868 4162         5027 my $object_type = 'Note';
869              
870 4162         6319 my @attributes = ( 'ObjectType' => $object_type );
871              
872 4162         8636 $self->xml_start_tag( 'x:ClientData', @attributes );
873              
874             # Write the x:MoveWithCells element.
875 4162         9210 $self->_write_move_with_cells();
876              
877             # Write the x:SizeWithCells element.
878 4162         8509 $self->_write_size_with_cells();
879              
880             # Write the x:Anchor element.
881 4162         8913 $self->_write_anchor( $vertices );
882              
883             # Write the x:AutoFill element.
884 4162         8749 $self->_write_auto_fill();
885              
886             # Write the x:Row element.
887 4162         9442 $self->_write_row( $row );
888              
889             # Write the x:Column element.
890 4162         8944 $self->_write_column( $col );
891              
892             # Write the x:Visible element.
893 4162 100       7545 $self->_write_visible() if $visible;
894              
895 4162         7838 $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   55 my $self = shift;
908 29         166 my $button = shift;
909 29         60 my $row = $button->{_row};
910 29         165 my $col = $button->{_col};
911 29         68 my $macro = $button->{_macro};
912 29         50 my $vertices = $button->{_vertices};
913              
914              
915 29         56 my $object_type = 'Button';
916              
917 29         169 my @attributes = ( 'ObjectType' => $object_type );
918              
919 29         151 $self->xml_start_tag( 'x:ClientData', @attributes );
920              
921             # Write the x:Anchor element.
922 29         114 $self->_write_anchor( $vertices );
923              
924             # Write the x:PrintObject element.
925 29         105 $self->_write_print_object();
926              
927             # Write the x:AutoFill element.
928 29         92 $self->_write_auto_fill();
929              
930             # Write the x:FmlaMacro element.
931 29         104 $self->_write_fmla_macro( $macro );
932              
933             # Write the x:TextHAlign element.
934 29         93 $self->_write_text_halign();
935              
936             # Write the x:TextVAlign element.
937 29         100 $self->_write_text_valign();
938              
939 29         80 $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 4163     4163   5259 my $self = shift;
952              
953 4163         7009 $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 4163     4163   5089 my $self = shift;
966              
967 4163         6579 $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   18 my $self = shift;
980              
981 10         26 $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 4192     4192   5261 my $self = shift;
994 4192         4787 my $vertices = shift;
995              
996 4192         7942 my ( $col_start, $row_start, $x1, $y1, $col_end, $row_end, $x2, $y2 ) =
997             @$vertices;
998              
999 4192         9431 my $data = join ", ",
1000             ( $col_start, $x1, $row_start, $y1, $col_end, $x2, $row_end, $y2 );
1001              
1002 4192         7898 $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 4192     4192   5468 my $self = shift;
1015 4192         5299 my $data = 'False';
1016              
1017 4192         7313 $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 4163     4163   5174 my $self = shift;
1030 4163         5109 my $data = shift;
1031              
1032 4163         7087 $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 4163     4163   5062 my $self = shift;
1045 4163         4864 my $data = shift;
1046              
1047 4163         6706 $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   60 my $self = shift;
1060 29         55 my $data = 'False';
1061              
1062 29         72 $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   63 my $self = shift;
1075 29         48 my $data = 'Center';
1076              
1077 29         82 $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   53 my $self = shift;
1090 29         69 my $data = 'Center';
1091              
1092 29         90 $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   58 my $self = shift;
1105 29         58 my $data = shift;
1106              
1107 29         78 $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   71 my $self = shift;
1119 45         66 my $index = shift;
1120 45         80 my $o_title = shift;
1121              
1122 45         159 my @attributes = (
1123             'o:relid' => 'rId' . $index,
1124             'o:title' => $o_title,
1125             );
1126              
1127 45         136 $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   63 my $self = shift;
1141              
1142 23         101 $self->xml_start_tag( 'v:formulas' );
1143              
1144             # Write the v:f elements.
1145 23         123 $self->_write_f('if lineDrawn pixelLineWidth 0');
1146 23         80 $self->_write_f('sum @0 1 0');
1147 23         82 $self->_write_f('sum 0 0 @1');
1148 23         62 $self->_write_f('prod @2 1 2');
1149 23         68 $self->_write_f('prod @3 21600 pixelWidth');
1150 23         71 $self->_write_f('prod @3 21600 pixelHeight');
1151 23         75 $self->_write_f('sum @0 0 1');
1152 23         67 $self->_write_f('prod @6 1 2');
1153 23         69 $self->_write_f('prod @7 21600 pixelWidth');
1154 23         76 $self->_write_f('sum @8 21600 0');
1155 23         68 $self->_write_f('prod @7 21600 pixelHeight');
1156 23         67 $self->_write_f('sum @10 21600 0');
1157              
1158 23         66 $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   377 my $self = shift;
1171 276         370 my $eqn = shift;
1172              
1173 276         468 my @attributes = ( 'eqn' => $eqn );
1174              
1175 276         512 $self->xml_empty_tag( 'v:f', @attributes );
1176             }
1177              
1178             1;
1179              
1180              
1181             __END__