Format.pm 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. # DISCLAIMER OF WARRANTY
  2. # Because this software is licensed free of charge, there is no warranty for the software,
  3. # to the extent permitted by applicable law. Except when otherwise stated in writing
  4. # the copyright holders and/or other parties provide the software "as is" without
  5. # warranty of any kind, either expressed or implied, including, but not limited to,
  6. # the implied warranties of merchantability and fitness for a particular purpose.
  7. # The entire risk as to the quality and performance of the software is with you.
  8. # Should the software prove defective, you assume the cost of all necessary
  9. # servicing, repair, or correction.
  10. # In no event unless required by applicable law or agreed to in writing will any
  11. # copyright holder, or any other party who may modify and/or redistribute the software
  12. # as permitted by the above licence, be liable to you for damages, including any general,
  13. # special, incidental, or consequential damages arising out of the use or inability
  14. # to use the software (including but not limited to loss of data or data being rendered
  15. # inaccurate or losses sustained by you or third parties or a failure of the software
  16. # to operate with any other software), even if such holder or other party
  17. # has been advised of the possibility of such damages.
  18. # AUTHOR
  19. # John McNamara jmcnamara@cpan.org
  20. # COPYRIGHT
  21. # Copyright MM-MMX, John McNamara.
  22. # All Rights Reserved. This module is free software. It may be used,
  23. # redistributed and/or modified under the terms of
  24. # the Artistic License(full text of the Artistic License http://dev.perl.org/licenses/artistic.html).
  25. package Spreadsheet::WriteExcel::Format;
  26. ###############################################################################
  27. #
  28. # Format - A class for defining Excel formatting.
  29. #
  30. #
  31. # Used in conjunction with Spreadsheet::WriteExcel
  32. #
  33. # Copyright 2000-2010, John McNamara, jmcnamara@cpan.org
  34. #
  35. # Documentation after __END__
  36. #
  37. use Exporter;
  38. use strict;
  39. use Carp;
  40. use vars qw($AUTOLOAD $VERSION @ISA);
  41. @ISA = qw(Exporter);
  42. $VERSION = '2.37';
  43. ###############################################################################
  44. #
  45. # new()
  46. #
  47. # Constructor
  48. #
  49. sub new {
  50. my $class = shift;
  51. my $self = {
  52. _xf_index => shift || 0,
  53. _type => 0,
  54. _font_index => 0,
  55. _font => 'Arial',
  56. _size => 10,
  57. _bold => 0x0190,
  58. _italic => 0,
  59. _color => 0x7FFF,
  60. _underline => 0,
  61. _font_strikeout => 0,
  62. _font_outline => 0,
  63. _font_shadow => 0,
  64. _font_script => 0,
  65. _font_family => 0,
  66. _font_charset => 0,
  67. _font_encoding => 0,
  68. _num_format => 0,
  69. _num_format_enc => 0,
  70. _hidden => 0,
  71. _locked => 1,
  72. _text_h_align => 0,
  73. _text_wrap => 0,
  74. _text_v_align => 2,
  75. _text_justlast => 0,
  76. _rotation => 0,
  77. _fg_color => 0x40,
  78. _bg_color => 0x41,
  79. _pattern => 0,
  80. _bottom => 0,
  81. _top => 0,
  82. _left => 0,
  83. _right => 0,
  84. _bottom_color => 0x40,
  85. _top_color => 0x40,
  86. _left_color => 0x40,
  87. _right_color => 0x40,
  88. _indent => 0,
  89. _shrink => 0,
  90. _merge_range => 0,
  91. _reading_order => 0,
  92. _diag_type => 0,
  93. _diag_color => 0x40,
  94. _diag_border => 0,
  95. _font_only => 0,
  96. # Temp code to prevent merged formats in non-merged cells.
  97. _used_merge => 0,
  98. };
  99. bless $self, $class;
  100. # Set properties passed to Workbook::add_format()
  101. $self->set_format_properties(@_) if @_;
  102. return $self;
  103. }
  104. ###############################################################################
  105. #
  106. # copy($format)
  107. #
  108. # Copy the attributes of another Spreadsheet::WriteExcel::Format object.
  109. #
  110. sub copy {
  111. my $self = shift;
  112. my $other = $_[0];
  113. return unless defined $other;
  114. return unless (ref($self) eq ref($other));
  115. # Store the properties that we don't want overwritten.
  116. my $xf = $self->{_xf_index};
  117. my $merge_range = $self->{_merge_range};
  118. my $used_merge = $self->{_used_merge};
  119. %$self = %$other; # Copy properties
  120. # Restore saved properties.
  121. $self->{_xf_index} = $xf;
  122. $self->{_merge_range} = $merge_range;
  123. $self->{_used_merge} = $used_merge;
  124. }
  125. ###############################################################################
  126. #
  127. # get_xf($style)
  128. #
  129. # Generate an Excel BIFF XF record.
  130. #
  131. sub get_xf {
  132. use integer; # Avoid << shift bug in Perl 5.6.0 on HP-UX
  133. my $self = shift;
  134. my $record; # Record identifier
  135. my $length; # Number of bytes to follow
  136. my $ifnt; # Index to FONT record
  137. my $ifmt; # Index to FORMAT record
  138. my $style; # Style and other options
  139. my $align; # Alignment
  140. my $indent; #
  141. my $icv; # fg and bg pattern colors
  142. my $border1; # Border line options
  143. my $border2; # Border line options
  144. my $border3; # Border line options
  145. # Set the type of the XF record and some of the attributes.
  146. if ($self->{_type} == 0xFFF5) {
  147. $style = 0xFFF5;
  148. }
  149. else {
  150. $style = $self->{_locked};
  151. $style |= $self->{_hidden} << 1;
  152. }
  153. # Flags to indicate if attributes have been set.
  154. my $atr_num = ($self->{_num_format} != 0);
  155. my $atr_fnt = ($self->{_font_index} != 0);
  156. my $atr_alc = ($self->{_text_h_align} != 0 ||
  157. $self->{_text_v_align} != 2 ||
  158. $self->{_shrink} != 0 ||
  159. $self->{_merge_range} != 0 ||
  160. $self->{_text_wrap} != 0 ||
  161. $self->{_indent} != 0) ? 1 : 0;
  162. my $atr_bdr = ($self->{_bottom} != 0 ||
  163. $self->{_top} != 0 ||
  164. $self->{_left} != 0 ||
  165. $self->{_right} != 0 ||
  166. $self->{_diag_type} != 0) ? 1: 0;
  167. my $atr_pat = ($self->{_fg_color} != 0x40 ||
  168. $self->{_bg_color} != 0x41 ||
  169. $self->{_pattern} != 0x00) ? 1 : 0;
  170. my $atr_prot = ($self->{_hidden} != 0 ||
  171. $self->{_locked} != 1) ? 1 : 0;
  172. # Set attribute changed flags for the style formats.
  173. if ($self->{_xf_index} != 0 and $self->{_type} == 0xFFF5) {
  174. if ($self->{_xf_index} >= 16) {
  175. $atr_num = 0;
  176. $atr_fnt = 1;
  177. }
  178. else {
  179. $atr_num = 1;
  180. $atr_fnt = 0;
  181. }
  182. $atr_alc = 1;
  183. $atr_bdr = 1;
  184. $atr_pat = 1;
  185. $atr_prot = 1;
  186. }
  187. # Set a default diagonal border style if none was specified.
  188. $self->{_diag_border} = 1 if !$self->{_diag_border} and $self->{_diag_type};
  189. # Reset the default colours for the non-font properties
  190. $self->{_fg_color} = 0x40 if $self->{_fg_color} == 0x7FFF;
  191. $self->{_bg_color} = 0x41 if $self->{_bg_color} == 0x7FFF;
  192. $self->{_bottom_color} = 0x40 if $self->{_bottom_color} == 0x7FFF;
  193. $self->{_top_color} = 0x40 if $self->{_top_color} == 0x7FFF;
  194. $self->{_left_color} = 0x40 if $self->{_left_color} == 0x7FFF;
  195. $self->{_right_color} = 0x40 if $self->{_right_color} == 0x7FFF;
  196. $self->{_diag_color} = 0x40 if $self->{_diag_color} == 0x7FFF;
  197. # Zero the default border colour if the border has not been set.
  198. $self->{_bottom_color} = 0 if $self->{_bottom} == 0;
  199. $self->{_top_color} = 0 if $self->{_top} == 0;
  200. $self->{_right_color} = 0 if $self->{_right} == 0;
  201. $self->{_left_color} = 0 if $self->{_left} == 0;
  202. $self->{_diag_color} = 0 if $self->{_diag_type} == 0;
  203. # The following 2 logical statements take care of special cases in relation
  204. # to cell colours and patterns:
  205. # 1. For a solid fill (_pattern == 1) Excel reverses the role of foreground
  206. # and background colours.
  207. # 2. If the user specifies a foreground or background colour without a
  208. # pattern they probably wanted a solid fill, so we fill in the defaults.
  209. #
  210. if ($self->{_pattern} <= 0x01 and
  211. $self->{_bg_color} != 0x41 and
  212. $self->{_fg_color} == 0x40 )
  213. {
  214. $self->{_fg_color} = $self->{_bg_color};
  215. $self->{_bg_color} = 0x40;
  216. $self->{_pattern} = 1;
  217. }
  218. if ($self->{_pattern} <= 0x01 and
  219. $self->{_bg_color} == 0x41 and
  220. $self->{_fg_color} != 0x40 )
  221. {
  222. $self->{_bg_color} = 0x40;
  223. $self->{_pattern} = 1;
  224. }
  225. # Set default alignment if indent is set.
  226. $self->{_text_h_align} = 1 if $self->{_indent} and
  227. $self->{_text_h_align} == 0;
  228. $record = 0x00E0;
  229. $length = 0x0014;
  230. $ifnt = $self->{_font_index};
  231. $ifmt = $self->{_num_format};
  232. $align = $self->{_text_h_align};
  233. $align |= $self->{_text_wrap} << 3;
  234. $align |= $self->{_text_v_align} << 4;
  235. $align |= $self->{_text_justlast} << 7;
  236. $align |= $self->{_rotation} << 8;
  237. $indent = $self->{_indent};
  238. $indent |= $self->{_shrink} << 4;
  239. $indent |= $self->{_merge_range} << 5;
  240. $indent |= $self->{_reading_order} << 6;
  241. $indent |= $atr_num << 10;
  242. $indent |= $atr_fnt << 11;
  243. $indent |= $atr_alc << 12;
  244. $indent |= $atr_bdr << 13;
  245. $indent |= $atr_pat << 14;
  246. $indent |= $atr_prot << 15;
  247. $border1 = $self->{_left};
  248. $border1 |= $self->{_right} << 4;
  249. $border1 |= $self->{_top} << 8;
  250. $border1 |= $self->{_bottom} << 12;
  251. $border2 = $self->{_left_color};
  252. $border2 |= $self->{_right_color} << 7;
  253. $border2 |= $self->{_diag_type} << 14;
  254. $border3 = $self->{_top_color};
  255. $border3 |= $self->{_bottom_color} << 7;
  256. $border3 |= $self->{_diag_color} << 14;
  257. $border3 |= $self->{_diag_border} << 21;
  258. $border3 |= $self->{_pattern} << 26;
  259. $icv = $self->{_fg_color};
  260. $icv |= $self->{_bg_color} << 7;
  261. my $header = pack("vv", $record, $length);
  262. my $data = pack("vvvvvvvVv", $ifnt, $ifmt, $style,
  263. $align, $indent,
  264. $border1, $border2, $border3,
  265. $icv);
  266. return($header . $data);
  267. }
  268. ###############################################################################
  269. #
  270. # Note to porters. The majority of the set_property() methods are created
  271. # dynamically via Perl' AUTOLOAD sub, see below. You may prefer/have to specify
  272. # them explicitly in other implementation languages.
  273. #
  274. ###############################################################################
  275. #
  276. # get_font()
  277. #
  278. # Generate an Excel BIFF FONT record.
  279. #
  280. sub get_font {
  281. my $self = shift;
  282. my $record; # Record identifier
  283. my $length; # Record length
  284. my $dyHeight; # Height of font (1/20 of a point)
  285. my $grbit; # Font attributes
  286. my $icv; # Index to color palette
  287. my $bls; # Bold style
  288. my $sss; # Superscript/subscript
  289. my $uls; # Underline
  290. my $bFamily; # Font family
  291. my $bCharSet; # Character set
  292. my $reserved; # Reserved
  293. my $cch; # Length of font name
  294. my $rgch; # Font name
  295. my $encoding; # Font name character encoding
  296. $dyHeight = $self->{_size} * 20;
  297. $icv = $self->{_color};
  298. $bls = $self->{_bold};
  299. $sss = $self->{_font_script};
  300. $uls = $self->{_underline};
  301. $bFamily = $self->{_font_family};
  302. $bCharSet = $self->{_font_charset};
  303. $rgch = $self->{_font};
  304. $encoding = $self->{_font_encoding};
  305. # Handle utf8 strings in perl 5.8.
  306. if ($] >= 5.008) {
  307. require Encode;
  308. if (Encode::is_utf8($rgch)) {
  309. $rgch = Encode::encode("UTF-16BE", $rgch);
  310. $encoding = 1;
  311. }
  312. }
  313. $cch = length $rgch;
  314. # Handle Unicode font names.
  315. if ($encoding == 1) {
  316. croak "Uneven number of bytes in Unicode font name" if $cch % 2;
  317. $cch /= 2 if $encoding;
  318. $rgch = pack 'v*', unpack 'n*', $rgch;
  319. }
  320. $record = 0x31;
  321. $length = 0x10 + length $rgch;
  322. $reserved = 0x00;
  323. $grbit = 0x00;
  324. $grbit |= 0x02 if $self->{_italic};
  325. $grbit |= 0x08 if $self->{_font_strikeout};
  326. $grbit |= 0x10 if $self->{_font_outline};
  327. $grbit |= 0x20 if $self->{_font_shadow};
  328. my $header = pack("vv", $record, $length);
  329. my $data = pack("vvvvvCCCCCC", $dyHeight, $grbit, $icv, $bls,
  330. $sss, $uls, $bFamily,
  331. $bCharSet, $reserved, $cch, $encoding);
  332. return($header . $data . $rgch);
  333. }
  334. ###############################################################################
  335. #
  336. # get_font_key()
  337. #
  338. # Returns a unique hash key for a font. Used by Workbook->_store_all_fonts()
  339. #
  340. sub get_font_key {
  341. my $self = shift;
  342. # The following elements are arranged to increase the probability of
  343. # generating a unique key. Elements that hold a large range of numbers
  344. # e.g. _color are placed between two binary elements such as _italic
  345. #
  346. my $key = "$self->{_font}$self->{_size}";
  347. $key .= "$self->{_font_script}$self->{_underline}";
  348. $key .= "$self->{_font_strikeout}$self->{_bold}$self->{_font_outline}";
  349. $key .= "$self->{_font_family}$self->{_font_charset}";
  350. $key .= "$self->{_font_shadow}$self->{_color}$self->{_italic}";
  351. $key .= "$self->{_font_encoding}";
  352. $key =~ s/ /_/g; # Convert the key to a single word
  353. return $key;
  354. }
  355. ###############################################################################
  356. #
  357. # get_xf_index()
  358. #
  359. # Returns the used by Worksheet->_XF()
  360. #
  361. sub get_xf_index {
  362. my $self = shift;
  363. return $self->{_xf_index};
  364. }
  365. ###############################################################################
  366. #
  367. # _get_color()
  368. #
  369. # Used in conjunction with the set_xxx_color methods to convert a color
  370. # string into a number. Color range is 0..63 but we will restrict it
  371. # to 8..63 to comply with Gnumeric. Colors 0..7 are repeated in 8..15.
  372. #
  373. sub _get_color {
  374. my %colors = (
  375. aqua => 0x0F,
  376. cyan => 0x0F,
  377. black => 0x08,
  378. blue => 0x0C,
  379. brown => 0x10,
  380. magenta => 0x0E,
  381. fuchsia => 0x0E,
  382. gray => 0x17,
  383. grey => 0x17,
  384. green => 0x11,
  385. lime => 0x0B,
  386. navy => 0x12,
  387. orange => 0x35,
  388. pink => 0x21,
  389. purple => 0x14,
  390. red => 0x0A,
  391. silver => 0x16,
  392. white => 0x09,
  393. yellow => 0x0D,
  394. );
  395. # Return the default color, 0x7FFF, if undef,
  396. return 0x7FFF unless defined $_[0];
  397. # or the color string converted to an integer,
  398. return $colors{lc($_[0])} if exists $colors{lc($_[0])};
  399. # or the default color if string is unrecognised,
  400. return 0x7FFF if ($_[0] =~ m/\D/);
  401. # or an index < 8 mapped into the correct range,
  402. return $_[0] + 8 if $_[0] < 8;
  403. # or the default color if arg is outside range,
  404. return 0x7FFF if $_[0] > 63;
  405. # or an integer in the valid range
  406. return $_[0];
  407. }
  408. ###############################################################################
  409. #
  410. # set_type()
  411. #
  412. # Set the XF object type as 0 = cell XF or 0xFFF5 = style XF.
  413. #
  414. sub set_type {
  415. my $self = shift;
  416. my $type = $_[0];
  417. if (defined $_[0] and $_[0] eq 0) {
  418. $self->{_type} = 0x0000;
  419. }
  420. else {
  421. $self->{_type} = 0xFFF5;
  422. }
  423. }
  424. ###############################################################################
  425. #
  426. # set_align()
  427. #
  428. # Set cell alignment.
  429. #
  430. sub set_align {
  431. my $self = shift;
  432. my $location = $_[0];
  433. return if not defined $location; # No default
  434. return if $location =~ m/\d/; # Ignore numbers
  435. $location = lc($location);
  436. $self->set_text_h_align(1) if ($location eq 'left');
  437. $self->set_text_h_align(2) if ($location eq 'centre');
  438. $self->set_text_h_align(2) if ($location eq 'center');
  439. $self->set_text_h_align(3) if ($location eq 'right');
  440. $self->set_text_h_align(4) if ($location eq 'fill');
  441. $self->set_text_h_align(5) if ($location eq 'justify');
  442. $self->set_text_h_align(6) if ($location eq 'center_across');
  443. $self->set_text_h_align(6) if ($location eq 'centre_across');
  444. $self->set_text_h_align(6) if ($location eq 'merge'); # S:WE name
  445. $self->set_text_h_align(7) if ($location eq 'distributed');
  446. $self->set_text_h_align(7) if ($location eq 'equal_space'); # ParseExcel
  447. $self->set_text_v_align(0) if ($location eq 'top');
  448. $self->set_text_v_align(1) if ($location eq 'vcentre');
  449. $self->set_text_v_align(1) if ($location eq 'vcenter');
  450. $self->set_text_v_align(2) if ($location eq 'bottom');
  451. $self->set_text_v_align(3) if ($location eq 'vjustify');
  452. $self->set_text_v_align(4) if ($location eq 'vdistributed');
  453. $self->set_text_v_align(4) if ($location eq 'vequal_space'); # ParseExcel
  454. }
  455. ###############################################################################
  456. #
  457. # set_valign()
  458. #
  459. # Set vertical cell alignment. This is required by the set_format_properties()
  460. # method to differentiate between the vertical and horizontal properties.
  461. #
  462. sub set_valign {
  463. my $self = shift;
  464. $self->set_align(@_);
  465. }
  466. ###############################################################################
  467. #
  468. # set_center_across()
  469. #
  470. # Implements the Excel5 style "merge".
  471. #
  472. sub set_center_across {
  473. my $self = shift;
  474. $self->set_text_h_align(6);
  475. }
  476. ###############################################################################
  477. #
  478. # set_merge()
  479. #
  480. # This was the way to implement a merge in Excel5. However it should have been
  481. # called "center_across" and not "merge".
  482. # This is now deprecated. Use set_center_across() or better merge_range().
  483. #
  484. #
  485. sub set_merge {
  486. my $self = shift;
  487. $self->set_text_h_align(6);
  488. }
  489. ###############################################################################
  490. #
  491. # set_bold()
  492. #
  493. # Bold has a range 0x64..0x3E8.
  494. # 0x190 is normal. 0x2BC is bold. So is an excessive use of AUTOLOAD.
  495. #
  496. sub set_bold {
  497. my $self = shift;
  498. my $weight = $_[0];
  499. $weight = 0x2BC if not defined $weight; # Bold text
  500. $weight = 0x2BC if $weight == 1; # Bold text
  501. $weight = 0x190 if $weight == 0; # Normal text
  502. $weight = 0x190 if $weight < 0x064; # Lower bound
  503. $weight = 0x190 if $weight > 0x3E8; # Upper bound
  504. $self->{_bold} = $weight;
  505. }
  506. ###############################################################################
  507. #
  508. # set_border($style)
  509. #
  510. # Set cells borders to the same style
  511. #
  512. sub set_border {
  513. my $self = shift;
  514. my $style = $_[0];
  515. $self->set_bottom($style);
  516. $self->set_top($style);
  517. $self->set_left($style);
  518. $self->set_right($style);
  519. }
  520. ###############################################################################
  521. #
  522. # set_border_color($color)
  523. #
  524. # Set cells border to the same color
  525. #
  526. sub set_border_color {
  527. my $self = shift;
  528. my $color = $_[0];
  529. $self->set_bottom_color($color);
  530. $self->set_top_color($color);
  531. $self->set_left_color($color);
  532. $self->set_right_color($color);
  533. }
  534. ###############################################################################
  535. #
  536. # set_rotation($angle)
  537. #
  538. # Set the rotation angle of the text. An alignment property.
  539. #
  540. sub set_rotation {
  541. my $self = shift;
  542. my $rotation = $_[0];
  543. # Argument should be a number
  544. return if $rotation !~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;
  545. # The arg type can be a double but the Excel dialog only allows integers.
  546. $rotation = int $rotation;
  547. if ($rotation == 270) {
  548. $rotation = 255;
  549. }
  550. elsif ($rotation >= -90 or $rotation <= 90) {
  551. $rotation = -$rotation +90 if $rotation < 0;
  552. }
  553. else {
  554. carp "Rotation $rotation outside range: -90 <= angle <= 90";
  555. $rotation = 0;
  556. }
  557. $self->{_rotation} = $rotation;
  558. }
  559. ###############################################################################
  560. #
  561. # set_format_properties()
  562. #
  563. # Convert hashes of properties to method calls.
  564. #
  565. sub set_format_properties {
  566. my $self = shift;
  567. my %properties = @_; # Merge multiple hashes into one
  568. while (my($key, $value) = each(%properties)) {
  569. # Strip leading "-" from Tk style properties e.g. -color => 'red'.
  570. $key =~ s/^-//;
  571. # Create a sub to set the property.
  572. my $sub = \&{"set_$key"};
  573. $sub->($self, $value);
  574. }
  575. }
  576. # Renamed rarely used set_properties() to set_format_properties() to avoid
  577. # confusion with Workbook method of the same name. The following acts as an
  578. # alias for any code that uses the old name.
  579. *set_properties = *set_format_properties;
  580. ###############################################################################
  581. #
  582. # AUTOLOAD. Deus ex machina.
  583. #
  584. # Dynamically create set methods that aren't already defined.
  585. #
  586. sub AUTOLOAD {
  587. my $self = shift;
  588. # Ignore calls to DESTROY
  589. return if $AUTOLOAD =~ /::DESTROY$/;
  590. # Check for a valid method names, i.e. "set_xxx_yyy".
  591. $AUTOLOAD =~ /.*::set(\w+)/ or die "Unknown method: $AUTOLOAD\n";
  592. # Match the attribute, i.e. "_xxx_yyy".
  593. my $attribute = $1;
  594. # Check that the attribute exists
  595. exists $self->{$attribute} or die "Unknown method: $AUTOLOAD\n";
  596. # The attribute value
  597. my $value;
  598. # There are two types of set methods: set_property() and
  599. # set_property_color(). When a method is AUTOLOADED we store a new anonymous
  600. # sub in the appropriate slot in the symbol table. The speeds up subsequent
  601. # calls to the same method.
  602. #
  603. no strict 'refs'; # To allow symbol table hackery
  604. if ($AUTOLOAD =~ /.*::set\w+color$/) {
  605. # For "set_property_color" methods
  606. $value = _get_color($_[0]);
  607. *{$AUTOLOAD} = sub {
  608. my $self = shift;
  609. $self->{$attribute} = _get_color($_[0]);
  610. };
  611. }
  612. else {
  613. $value = $_[0];
  614. $value = 1 if not defined $value; # The default value is always 1
  615. *{$AUTOLOAD} = sub {
  616. my $self = shift;
  617. my $value = shift;
  618. $value = 1 if not defined $value;
  619. $self->{$attribute} = $value;
  620. };
  621. }
  622. $self->{$attribute} = $value;
  623. }
  624. 1;
  625. __END__
  626. =head1 NAME
  627. Format - A class for defining Excel formatting.
  628. =head1 SYNOPSIS
  629. See the documentation for Spreadsheet::WriteExcel
  630. =head1 DESCRIPTION
  631. This module is used in conjunction with Spreadsheet::WriteExcel.
  632. =head1 AUTHOR
  633. John McNamara jmcnamara@cpan.org
  634. =head1 COPYRIGHT
  635. © MM-MMX, John McNamara.
  636. All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.