/
writeexcel.rb
1159 lines (1159 loc) · 42.8 KB
/
writeexcel.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# -*- coding: utf-8 -*-
###############################################################################
#
# WriteExcel.
#
# WriteExcel - Write to a cross-platform Excel binary file.
#
# Copyright 2000-2010, John McNamara, jmcnamara@cpan.org
#
# original written in Perl by John McNamara
# converted to Ruby by Hideo Nakamura, cxn03651@msj.biglobe.ne.jp
#
require 'writeexcel/biffwriter'
require 'writeexcel/olewriter'
require 'writeexcel/formula'
require 'writeexcel/format'
require 'writeexcel/worksheet'
require "writeexcel/workbook"
require 'writeexcel/chart'
require 'writeexcel/charts/area'
require 'writeexcel/charts/bar'
require 'writeexcel/charts/column'
require 'writeexcel/charts/external'
require 'writeexcel/charts/line'
require 'writeexcel/charts/pie'
require 'writeexcel/charts/scatter'
require 'writeexcel/charts/stock'
require 'writeexcel/storage_lite'
require 'writeexcel/compatibility'
require 'writeexcel/debug_info'
#
# = WriteExcel - Write to a cross-platform Excel binary file.
#
# == Contents
# SYSNOPSYS
# DESCRIPTION
# QUICK START
# WORKBOOK METHODS
# WORKSHEET METHODS
# PAGE SET-UP METHODS
# CELL FORMATTING
# FORMAT METHODS
# COLOURS IN EXCEL
# DATE AND TIME IN EXCEL
# OUTLINES AND GROUPING IN EXCEL
# DATA VALIDATION IN EXCEL
# FORMULAS AND FUNCTIONS IN EXCEL
# CHART
#
# == Synopsis
#
# To write a string, a formatted string, a number and a formula to the first
# worksheet in an Excel workbook called ruby.xls:
#
# require 'WriteExcel'
#
# # Create a new Excel workbook
# workbook = WriteExcel.new('ruby.xls')
#
# # Add a worksheet
# worksheet = workbook.add_worksheet
#
# # Add and define a format
# format = workbook.add_format # Add a format
# format.set_bold()
# format.set_color('red')
# format.set_align('center')
#
# # Write a formatted and unformatted string, row and column notation.
# col = row = 0
# worksheet.write(row, col, 'Hi Excel!', format)
# worksheet.write(1, col, 'Hi Excel!')
#
# # Write a number and a formula using A1 notation
# worksheet.write('A3', 1.2345)
# worksheet.write('A4', '=SIN(PI()/4)')
#
# # Save to ruby.xls
# workbook.close
#
# == Description
#
# WriteExcel can be used to create a cross-platform Excel binary file.
# Multiple worksheets can be added to a workbook and formatting can be applied
# to cells. Text, numbers, formulas, hyperlinks and images can be written to
# the cells.
#
# The Excel file produced by this gem is compatible with 97, 2000, 2002, 2003
# and 2007.
#
# WriteExcel will work on the majority of Windows, UNIX and Mac platforms.
# Generated files are also compatible with the Linux/UNIX spreadsheet
# applications Gnumeric and OpenOffice.org.
#
# This module cannot be used to write to an existing Excel file
#
# This library is converted from Spreadsheet::WriteExcel module of Perl.
# http://search.cpan.org/~jmcnamara/Spreadsheet-WriteExcel-2.37/
#
# == Quick Start
#
# WriteExcel tries to provide an interface to as many of Excel's features as
# possible. As a result there is a lot of documentation to accompany the
# interface and it can be difficult at first glance to see what it important
# and what is not. So for those of you who prefer to assemble Ikea furniture
# first and then read the instructions, here are four easy steps:
#
# 1. Create a new Excel workbook (i.e. file) using new().
#
# 2. Add a worksheet to the new workbook using add_worksheet().
#
# 3. Write to the worksheet using write().
#
# 4. Save to file.
#
# Like this:
#
# require 'WriteExcel' # Step 0
#
# workbook = WriteExcel.new('ruby.xls') # Step 1
# worksheet = workbook.add_worksheet # Step 2
# worksheet.write('A1', 'Hi Excel!') # Step 3
# workbook.close # Step 4
#
# This will create an Excel file called ruby.xls with a single worksheet and the
# text 'Hi Excel!' in the relevant cell. And that's it. Okay, so there is
# actually a zeroth step as well, but use WriteExcel goes without saying. There
# are also many examples that come with the distribution and which you can
# use to get you started. See EXAMPLES.
#
# = Workbook methods
#
# The WriteExcel module provides an object oriented interface
# to a new Excel workbook. The following methods are available through
# a new workbook.
#
# new()
# add_worksheet()
# add_format()
# add_chart()
# add_chart_ext()
# close()
# compatibility_mode()
# set_properties()
# define_name()
# set_tempdir()
# set_custom_color()
# sheets()
# set_1904()
# set_codepage()
#
# = Worksheet methods
#
# A new worksheet is created by calling the add_worksheet() method from
# a workbook object:
#
# worksheet1 = workbook.add_worksheet
# worksheet2 = workbook.add_worksheet
#
# The following methods are available through a new worksheet:
#
# write()
# write_number()
# write_string()
# write_utf16be_string()
# write_utf16le_string()
# keep_leading_zeros()
# write_blank()
# write_row()
# write_col()
# write_date_time()
# write_url()
# write_url_range()
# write_formula()
# store_formula()
# repeat_formula()
# write_comment()
# show_comments()
# add_write_handler() (* not implemented yet)
# insert_image()
# insert_chart()
# data_validation()
# get_name()
# activate()
# select()
# hide()
# set_first_sheet()
# protect()
# set_selection()
# set_row()
# set_column()
# outline_settings()
# freeze_panes()
# split_panes()
# merge_range()
# set_zoom()
# right_to_left()
# hide_zero()
# set_tab_color()
# autofilter()
#
# == Cell notation
# WriteExcel supports two forms of notation to designate the position of cells:
# Row-column notation and A1 notation.
#
# Row-column notation uses a zero based index for both row and column while A1
# notation uses the standard Excel alphanumeric sequence of column letter and
# 1-based row. For example:
#
# (0, 0) # The top left cell in row-column notation.
# ('A1') # The top left cell in A1 notation.
#
# (1999, 29) # Row-column notation.
# ('AD2000') # The same cell in A1 notation.
#
# Row-column notation is useful if you are referring to cells
# programmatically:
#
# (0 .. 10).each do |i|
# worksheet.write(i, 0, 'Hello') # Cells A1 to A10
# end
#
# A1 notation is useful for setting up a worksheet manually and for working
# with formulas:
#
# worksheet.write('H1', 200)
# worksheet.write('H2', '=H1+1')
#
# In formulas and applicable methods you can also use the A:A column notation:
#
# worksheet.write('A1', '=SUM(B:B)')
#
# For simplicity, the parameter lists for the worksheet method calls in the
# following sections are given in terms of row-column notation. In all cases
# it is also possible to use A1 notation.
#
# Note: in Excel it is also possible to use a R1C1 notation. This is not
# supported by WriteExcel.
#
# ==PAGE SET-UP METHODS
#
# Page set-up methods affect the way that a worksheet looks when it is printed.
# They control features such as page headers and footers and margins. These
# methods are really just standard worksheet methods. They are documented
# here in a separate section for the sake of clarity.
#
# The following methods are available for page set-up:
#
# set_landscape()
# set_portrait()
# set_page_view()
# set_paper()
# center_horizontally()
# center_vertically()
# set_margins()
# set_header()
# set_footer()
# repeat_rows()
# repeat_columns()
# hide_gridlines()
# print_row_col_headers()
# print_area()
# print_across()
# fit_to_pages()
# set_start_page()
# set_print_scale()
# set_h_pagebreaks()
# set_v_pagebreaks()
#
# A common requirement when working with WriteExcel is to apply the same page
# set-up features to all of the worksheets in a workbook. To do this you can use
# the sheets() method of the workbook class to access the array of worksheets
# in a workbook:
#
# workbook.sheets.each do |worksheet|
# worksheet.set_landscape
# end
#
# ==CELL FORMATTING
#
# This section describes the methods and properties that are available for
# formatting cells in Excel. The properties of a cell that can be formatted
# include: fonts, colours, patterns, borders, alignment and number formatting.
#
# ===Creating and using a Format object
#
# Cell formatting is defined through a Format object. Format objects are
# created by calling the workbook add_format() method as follows:
#
# format1 = workbook.add_format # Set properties later
# format2 = workbook.add_format(property hash..) # Set at creation
#
# The format object holds all the formatting properties that can be applied
# to a cell, a row or a column. The process of setting these properties is
# discussed in the next section.
#
# Once a Format object has been constructed and it properties have been set
# it can be passed as an argument to the worksheet write methods as follows:
#
# worksheet.write(0, 0, 'One', format)
# worksheet.write_string(1, 0, 'Two', format)
# worksheet.write_number(2, 0, 3, format)
# worksheet.write_blank(3, 0, format)
#
# Formats can also be passed to the worksheet set_row() and set_column()
# methods to define the default property for a row or column.
#
# worksheet.set_row(0, 15, format)
# worksheet.set_column(0, 0, 15, format)
#
# ===Format methods and Format properties
#
# The following table shows the Excel format categories, the formatting
# properties that can be applied and the equivalent object method:
#
# Category Description Property Method Name
# -------- ----------- -------- -----------
# Font Font type font set_font()
# Font size size set_size()
# Font color color set_color()
# Bold bold set_bold()
# Italic italic set_italic()
# Underline underline set_underline()
# Strikeout font_strikeout set_font_strikeout()
# Super/Subscript font_script set_font_script()
# Outline font_outline set_font_outline()
# Shadow font_shadow set_font_shadow()
#
# Number Numeric format num_format set_num_format()
#
# Protection Lock cells locked set_locked()
# Hide formulas hidden set_hidden()
#
# Alignment Horizontal align align set_align()
# Vertical align valign set_align()
# Rotation rotation set_rotation()
# Text wrap text_wrap set_text_wrap()
# Justify last text_justlast set_text_justlast()
# Center across center_across set_center_across()
# Indentation indent set_indent()
# Shrink to fit shrink set_shrink()
#
# Pattern Cell pattern pattern set_pattern()
# Background color bg_color set_bg_color()
# Foreground color fg_color set_fg_color()
#
# Border Cell border border set_border()
# Bottom border bottom set_bottom()
# Top border top set_top()
# Left border left set_left()
# Right border right set_right()
# Border color border_color set_border_color()
# Bottom color bottom_color set_bottom_color()
# Top color top_color set_top_color()
# Left color left_color set_left_color()
# Right color right_color set_right_color()
#
# There are two ways of setting Format properties: by using the object method
# interface or by setting the property directly. For example, a typical use of
# the method interface would be as follows:
#
# format = workbook.add_format
# format.set_bold
# format.set_color('red')
#
# By comparison the properties can be set directly by passing a hash of
# properties to the Format constructor:
#
# format = workbook.add_format(:bold => 1, :color => 'red')
#
# or after the Format has been constructed by means of the
# set_format_properties() method as follows:
#
# format = workbook.add_format
# format.set_format_properties(:bold => 1, :color => 'red')
#
# You can also store the properties in one or more named hashes and pass them
# to the required method:
#
# font = {
# :font => 'Arial',
# :size => 12,
# :color => 'blue',
# :bold => 1
# }
#
# shading = {
# :bg_color => 'green',
# :pattern => 1
# }
#
# format1 = workbook.add_format(font) # Font only
# format2 = workbook.add_format(font, shading) # Font and shading
#
# The provision of two ways of setting properties might lead you to wonder
# which is the best way. The method mechanism may be better is you prefer
# setting properties via method calls (which the author did when they were
# code was first written) otherwise passing properties to the constructor has
# proved to be a little more flexible and self documenting in practice. An
# additional advantage of working with property hashes is that it allows you to
# share formatting between workbook objects as shown in the example above.
#
#--
#
# did not converted ???
#
# The Perl/Tk style of adding properties is also supported:
#
# %font = (
# -font => 'Arial',
# -size => 12,
# -color => 'blue',
# -bold => 1,
# )
#++
#
# ===Working with formats
#
# The default format is Arial 10 with all other properties off.
#
# Each unique format in WriteExcel must have a corresponding
# Format object. It isn't possible to use a Format with a write() method and
# then redefine the Format for use at a later stage. This is because a Format
# is applied to a cell not in its current state but in its final state.
# Consider the following example:
#
# format = workbook.add_format
# format.set_bold
# format.set_color('red')
# worksheet.write('A1', 'Cell A1', format)
# format.set_color('green')
# worksheet.write('B1', 'Cell B1', format)
#
# Cell A1 is assigned the Format _format_ which is initially set to the colour
# red. However, the colour is subsequently set to green. When Excel displays
# Cell A1 it will display the final state of the Format which in this case
# will be the colour green.
#
# In general a method call without an argument will turn a property on,
# for example:
#
# format1 = workbook.add_format
# format1.set_bold # Turns bold on
# format1.set_bold(1) # Also turns bold on
# format1.set_bold(0) # Turns bold off
#
# ==FORMAT METHODS
#
# The Format object methods are described in more detail in the following
# sections. In addition, there is a Ruby program called formats.rb in the
# examples directory of the WriteExcel distribution. This program creates an
# Excel workbook called formats.xls which contains examples of almost all
# the format types.
#
# The following Format methods are available:
#
# set_font()
# set_size()
# set_color()
# set_bold()
# set_italic()
# set_underline()
# set_font_strikeout()
# set_font_script()
# set_font_outline()
# set_font_shadow()
# set_num_format()
# set_locked()
# set_hidden()
# set_align()
# set_rotation()
# set_text_wrap()
# set_text_justlast()
# set_center_across()
# set_indent()
# set_shrink()
# set_pattern()
# set_bg_color()
# set_fg_color()
# set_border()
# set_bottom()
# set_top()
# set_left()
# set_right()
# set_border_color()
# set_bottom_color()
# set_top_color()
# set_left_color()
# set_right_color()
#
# The above methods can also be applied directly as properties. For example
# format.set_bold is equivalent to workbook.add_format(:bold => 1).
#
# ==COLOURS IN EXCEL
#
# Excel provides a colour palette of 56 colours. In WriteExcel these colours
# are accessed via their palette index in the range 8..63. This index is used
# to set the colour of fonts, cell patterns and cell borders. For example:
#
# format = workbook.add_format(
# :color => 12, # index for blue
# :font => 'Arial',
# :size => 12,
# :bold => 1
# )
#
# The most commonly used colours can also be accessed by name. The name acts
# as a simple alias for the colour index:
#
# black => 8
# blue => 12
# brown => 16
# cyan => 15
# gray => 23
# green => 17
# lime => 11
# magenta => 14
# navy => 18
# orange => 53
# pink => 33
# purple => 20
# red => 10
# silver => 22
# white => 9
# yellow => 13
#
# For example:
#
# font = workbook.add_format(:color => 'red')
#
# Users of VBA in Excel should note that the equivalent colour indices are in
# the range 1..56 instead of 8..63.
#
# If the default palette does not provide a required colour you can override
# one of the built-in values. This is achieved by using the set_custom_color()
# workbook method to adjust the RGB (red green blue) components of the colour:
#
# ferrari = workbook.set_custom_color(40, 216, 12, 12)
#
# format = workbook.add_format(
# :bg_color => ferrari,
# :pattern => 1,
# :border => 1
# )
#
# worksheet.write_blank('A1', format)
#
# You may also find the following links helpful:
#
# A detailed look at Excel's colour palette:
# http://www.mvps.org/dmcritchie/excel/colors.htm
#
# A decimal RGB chart: http://www.hypersolutions.org/pages/rgbdec.html
#
# A hex RGB chart: : http://www.hypersolutions.org/pages/rgbhex.html
#
# ==DATES AND TIME IN EXCEL
#
# There are two important things to understand about dates and times in Excel:
#
# 1. A date/time in Excel is a real number plus an Excel number format.
#
# 2. WriteExcel doesn't automatically convert date/time strings in write() to
# an Excel date/time.
#
# These two points are explained in more detail below along with some
# suggestions on how to convert times and dates to the required format.
#
# ===An Excel date/time is a number plus a format
#
# If you write a date string with write() then all you will get is a string:
#
# worksheet.write('A1', '02/03/04') # !! Writes a string not a date. !!
#
# Dates and times in Excel are represented by real numbers, for example
# "Jan 1 2001 12:30 AM" is represented by the number 36892.521.
#
# The integer part of the number stores the number of days since the epoch
# and the fractional part stores the percentage of the day.
#
# A date or time in Excel is just like any other number. To have the number
# display as a date you must apply an Excel number format to it. Here are
# some examples.
#
# #!/usr/bin/ruby -w
#
# require 'writeexcel'
#
# workbook = WriteExcel.new('date_examples.xls')
# worksheet = workbook.add_worksheet
#
# worksheet.set_column('A:A', 30) # For extra visibility.
#
# number = 39506.5
#
# worksheet.write('A1', number) # 39506.5
#
# format2 = workbook.add_format(:num_format => 'dd/mm/yy')
# worksheet.write('A2', number , format2); # 28/02/08
#
# format3 = workbook.add_format(:num_format => 'mm/dd/yy')
# worksheet.write('A3', number , format3); # 02/28/08
#
# format4 = workbook.add_format(:num_format => 'd-m-yyyy')
# worksheet.write('A4', .number , format4) # 28-2-2008
#
# format5 = workbook.add_format(:num_format => 'dd/mm/yy hh:mm')
# worksheet.write('A5', number , format5) # 28/02/08 12:00
#
# format6 = workbook.add_format(:num_format => 'd mmm yyyy')
# worksheet.write('A6', number , format6) # 28 Feb 2008
#
# format7 = workbook.add_format(:num_format => 'mmm d yyyy hh:mm AM/PM')
# worksheet.write('A7', number , format7) # Feb 28 2008 12:00 PM
#
# ===WriteExcel doesn't automatically convert date/time strings
#
# WriteExcel doesn't automatically convert input date strings into Excel's
# formatted date numbers due to the large number of possible date formats
# and also due to the possibility of misinterpretation.
#
# For example, does 02/03/04 mean March 2 2004, February 3 2004 or even March
# 4 2002.
#
# Therefore, in order to handle dates you will have to convert them to numbers
# and apply an Excel format. Some methods for converting dates are listed in
# the next section.
#
# The most direct way is to convert your dates to the ISO8601
# yyyy-mm-ddThh:mm:ss.sss date format and use the write_date_time() worksheet
# method:
#
# worksheet.write_date_time('A2', '2001-01-01T12:20', format)
#
# See the write_date_time() section of the documentation for more details.
#
# A general methodology for handling date strings with write_date_time() is:
#
# 1. Identify incoming date/time strings with a regex.
# 2. Extract the component parts of the date/time using the same regex.
# 3. Convert the date/time to the ISO8601 format.
# 4. Write the date/time using write_date_time() and a number format.
#
# Here is an example:
#
# #!/usr/bin/ruby -w
#
# require 'writeexcel'
#
# workbook = WriteExcel.new('example.xls')
# worksheet = workbook.add_worksheet
#
# # Set the default format for dates.
# date_format = workbook.add_format(:num_format => 'mmm d yyyy')
#
# # Increase column width to improve visibility of data.
# worksheet.set_column('A:C', 20)
#
# data = [
# %w(Item Cost Date),
# %w(Book 10 1/9/2007),
# %w(Beer 4 12/9/2007),
# %w(Bed 500 5/10/2007)
# ]
#
# # Simulate reading from a data source.
# row = 0
#
# data.each do |row_data|
# col = 0
# row_data.each do |item|
#
# # Match dates in the following formats: d/m/yy, d/m/yyyy
# if item =~ %r[^(\d{1,2})/(\d{1,2})/(\d{4})$]
# # Change to the date format required by write_date_time().
# date = sprintf "%4d-%02d-%02dT", $3, $2, $1
# worksheet.write_date_time(row, col, date, date_format)
# else
# # Just plain data
# worksheet.write(row, col, item)
# end
# col += 1
# end
# row += 1
# end
#
#--
# For a slightly more advanced solution you can modify the write() method to
# handle date formats of your choice via the add_write_handler() method. See
# the add_write_handler() section of the docs and the write_handler3.rb and
# write_handler4.rb programs in the examples directory of the distro.
#++
#
# ==OUTLINES AND GROUPING IN EXCEL
#
# Excel allows you to group rows or columns so that they can be hidden or
# displayed with a single mouse click. This feature is referred to as outlines.
#
# Outlines can reduce complex data down to a few salient sub-totals or
# summaries.
#
# This feature is best viewed in Excel but the following is an ASCII
# representation of what a worksheet with three outlines might look like. Rows
# 3-4 and rows 7-8 are grouped at level 2. Rows 2-9 are grouped at level 1.
# The lines at the left hand side are called outline level bars.
#
# ------------------------------------------
# 1 2 3 | | A | B | C | D | ...
# ------------------------------------------
# _ | 1 | A | | | | ...
# | _ | 2 | B | | | | ...
# | | | 3 | (C) | | | | ...
# | | | 4 | (D) | | | | ...
# | - | 5 | E | | | | ...
# | _ | 6 | F | | | | ...
# | | | 7 | (G) | | | | ...
# | | | 8 | (H) | | | | ...
# | - | 9 | I | | | | ...
# - | . | ... | ... | ... | ... | ...
#
# Clicking the minus sign on each of the level 2 outlines will collapse and
# hide the data as shown in the next figure. The minus sign changes to a plus
# sign to indicate that the data in the outline is hidden.
#
# ------------------------------------------
# 1 2 3 | | A | B | C | D | ...
# ------------------------------------------
# _ | 1 | A | | | | ...
# | | 2 | B | | | | ...
# | + | 5 | E | | | | ...
# | | 6 | F | | | | ...
# | + | 9 | I | | | | ...
# - | . | ... | ... | ... | ... | ...
#
# Clicking on the minus sign on the level 1 outline will collapse the
# remaining rows as follows:
#
# ------------------------------------------
# 1 2 3 | | A | B | C | D | ...
# ------------------------------------------
# | 1 | A | | | | ...
# + | . | ... | ... | ... | ... | ...
#
# Grouping in WriteExcel is achieved by setting the outline level via the
# set_row() and set_column() worksheet methods:
#
# set_row(row, height, format, hidden, level, collapsed)
# set_column(first_col, last_col, width, format, hidden, level, collapsed)
#
# The following example sets an outline level of 1 for rows 1 and 2
# (zero-indexed) and columns B to G. The parameters _height_ and _format_ are
# assigned default values since they are undefined:
#
# worksheet.set_row(1, nil, nil, 0, 1)
# worksheet.set_row(2, nil, nil, 0, 1)
# worksheet.set_column('B:G', nil, nil, 0, 1)
#
# Excel allows up to 7 outline levels. Therefore the _level_ parameter should
# be in the range 0 <= _level_ <= 7.
#
# Rows and columns can be collapsed by setting the _hidden_ flag for the hidden
# rows/columns and setting the _collapsed_ flag for the row/column that has
# the collapsed + symbol:
#
# worksheet.set_row(1, nil, nil, 1, 1)
# worksheet.set_row(2, nil, nil, 1, 1)
# worksheet.set_row(3, nil, nil, 0, 0, 1) # Collapsed flag.
#
# worksheet.set_column('B:G', nil, nil, 1, 1)
# worksheet.set_column('H:H', nil, nil, 0, 0, 1) # Collapsed flag.
#
# Note: Setting the _collapsed_ flag is particularly important for
# compatibility with OpenOffice.org and Gnumeric.
#
# For a more complete example see the outline.rb
# and outline_collapsed.rb
# programs in the examples directory of the distro.
#
# Some additional outline properties can be set via the outline_settings()
# worksheet method, see above.
#
# ==DATA VALIDATION IN EXCEL
#
# Data validation is a feature of Excel which allows you to restrict the data
# that a users enters in a cell and to display help and warning messages. It
# also allows you to restrict input to values in a drop down list.
#
# A typical use case might be to restrict data in a cell to integer values in
# a certain range, to provide a help message to indicate the required value and
# to issue a warning if the input data doesn't meet the stated criteria.
# In WriteExcel we could do that as follows:
#
# worksheet.data_validation('B3',
# {
# :validate => 'integer',
# :criteria => 'between',
# :minimum => 1,
# :maximum => 100,
# :input_title => 'Input an integer:',
# :input_message => 'Between 1 and 100',
# :error_message => 'Sorry, try again.'
# })
#
# The above example would look like this in Excel:
# http://homepage.eircom.net/~jmcnamara/perl/data_validation.jpg.
#
# For more information on data validation see the following Microsoft
# support article "Description and examples of data validation in Excel":
# http://support.microsoft.com/kb/211485.
#
# ==FORMULAS AND FUNCTIONS IN EXCEL
#
# ===Caveats
#
# The first thing to note is that there are still some outstanding issues
# with the implementation of formulas and functions:
#
# 1. Writing a formula is much slower than writing the equivalent string.
# 2. You cannot use array constants, i.e. {1;2;3}, in functions.
# 3. Unary minus isn't supported.
# 4. Whitespace is not preserved around operators.
# 5. Named ranges are not supported.
# 6. Array formulas are not supported.
#
# However, these constraints will be removed in future versions. They are
# here because of a trade-off between features and time. Also, it is possible
# to work around issue 1 using the store_formula() and repeat_formula()
# methods as described later in this section.
#
# ===Introduction
#
# The following is a brief introduction to formulas and functions in Excel
# and WriteExcel.
#
# A formula is a string that begins with an equals sign:
#
# '=A1+B1'
# '=AVERAGE(1, 2, 3)'
#
# The formula can contain numbers, strings, boolean values, cell references,
# cell ranges and functions. Named ranges are not supported. Formulas should
# be written as they appear in Excel, that is cells and functions must be
# in uppercase.
#
# Cells in Excel are referenced using the A1 notation system where the
# column is designated by a letter and the row by a number. Columns
# range from A to IV i.e. 0 to 255, rows range from 1 to 65536.
#--
# The WriteExcel::Utility module that is included in the distro
# contains helper functions for dealing with A1 notation, for example:
#
# use Spreadsheet::WriteExcel::Utility;
#
# ($row, $col) = xl_cell_to_rowcol('C2'); # (1, 2)
# $str = xl_rowcol_to_cell(1, 2); # C2
#++
#
# The Excel $ notation in cell references is also supported. This allows you
# to specify whether a row or column is relative or absolute. This only has
# an effect if the cell is copied. The following examples show relative and
# absolute values.
#
# '=A1' # Column and row are relative
# '=$A1' # Column is absolute and row is relative
# '=A$1' # Column is relative and row is absolute
# '=$A$1' # Column and row are absolute
#
# Formulas can also refer to cells in other worksheets of the current
# workbook. For example:
#
# '=Sheet2!A1'
# '=Sheet2!A1:A5'
# '=Sheet2:Sheet3!A1'
# '=Sheet2:Sheet3!A1:A5'
# q{='Test Data'!A1}
# q{='Test Data1:Test Data2'!A1}
#
# The sheet reference and the cell reference are separated by ! the exclamation
# mark symbol. If worksheet names contain spaces, commas o parentheses then Excel
# requires that the name is enclosed in single quotes as shown in the last two
# examples above. In order to avoid using a lot of escape characters you can
# use the quote operator %q{} to protect the quotes. Only valid sheet names that
# have been added using the add_worksheet() method can be used in formulas.
# You cannot reference external workbooks.
#
# The following table lists the operators that are available in Excel's formulas.
# The majority of the operators are the same as Perl's, differences are indicated:
#
# Arithmetic operators:
# =====================
# Operator Meaning Example
# + Addition 1+2
# - Subtraction 2-1
# * Multiplication 2*3
# / Division 1/4
# ^ Exponentiation 2^3 # Equivalent to **
# - Unary minus -(1+2) # Not yet supported
# % Percent (Not modulus) 13% # Not supported, [1]
#
# Comparison operators:
# =====================
# Operator Meaning Example
# = Equal to A1 = B1 # Equivalent to ==
# <> Not equal to A1 <> B1 # Equivalent to !=
# > Greater than A1 > B1
# < Less than A1 < B1
# >= Greater than or equal to A1 >= B1
# <= Less than or equal to A1 <= B1
#
# String operator:
# ================
# Operator Meaning Example
# & Concatenation "Hello " & "World!" # [2]
#
# Reference operators:
# ====================
# Operator Meaning Example
# : Range operator A1:A4 # [3]
# , Union operator SUM(1, 2+2, B3) # [4]
#
# Notes:
# [1]: You can get a percentage with formatting and modulus with MOD().
# [2]: Equivalent to ("Hello " . "World!") in Perl.
# [3]: This range is equivalent to cells A1, A2, A3 and A4.
# [4]: The comma behaves like the list separator in Perl.
#
# The range and comma operators can have different symbols in non-English
# versions of Excel. These will be supported in a later version of WriteExcel.
# European users of Excel take note:
#
# worksheet.write('A1', '=SUM(1; 2; 3)') # Wrong!!
# worksheet.write('A1', '=SUM(1, 2, 3)') # Okay
#
# The following table lists all of the core functions supported by
# Excel 5 and WriteExcel. Any additional functions that are available through
# the "Analysis ToolPak" or other add-ins are not supported. These functions
# have all been tested to verify that they work.
#
# ABS DB INDIRECT NORMINV SLN
# ACOS DCOUNT INFO NORMSDIST SLOPE
# ACOSH DCOUNTA INT NORMSINV SMALL
# ADDRESS DDB INTERCEPT NOT SQRT
# AND DEGREES IPMT NOW STANDARDIZE
# AREAS DEVSQ IRR NPER STDEV
# ASIN DGET ISBLANK NPV STDEVP
# ASINH DMAX ISERR ODD STEYX
# ATAN DMIN ISERROR OFFSET SUBSTITUTE
# ATAN2 DOLLAR ISLOGICAL OR SUBTOTAL
# ATANH DPRODUCT ISNA PEARSON SUM
# AVEDEV DSTDEV ISNONTEXT PERCENTILE SUMIF
# AVERAGE DSTDEVP ISNUMBER PERCENTRANK SUMPRODUCT
# BETADIST DSUM ISREF PERMUT SUMSQ
# BETAINV DVAR ISTEXT PI SUMX2MY2
# BINOMDIST DVARP KURT PMT SUMX2PY2
# CALL ERROR.TYPE LARGE POISSON SUMXMY2
# CEILING EVEN LEFT POWER SYD
# CELL EXACT LEN PPMT T
# CHAR EXP LINEST PROB TAN
# CHIDIST EXPONDIST LN PRODUCT TANH
# CHIINV FACT LOG PROPER TDIST
# CHITEST FALSE LOG10 PV TEXT
# CHOOSE FDIST LOGEST QUARTILE TIME
# CLEAN FIND LOGINV RADIANS TIMEVALUE
# CODE FINV LOGNORMDIST RAND TINV
# COLUMN FISHER LOOKUP RANK TODAY
# COLUMNS FISHERINV LOWER RATE TRANSPOSE
# COMBIN FIXED MATCH REGISTER.ID TREND
# CONCATENATE FLOOR MAX REPLACE TRIM
# CONFIDENCE FORECAST MDETERM REPT TRIMMEAN
# CORREL FREQUENCY MEDIAN RIGHT TRUE
# COS FTEST MID ROMAN TRUNC
# COSH FV MIN ROUND TTEST
# COUNT GAMMADIST MINUTE ROUNDDOWN TYPE
# COUNTA GAMMAINV MINVERSE ROUNDUP UPPER
# COUNTBLANK GAMMALN MIRR ROW VALUE
# COUNTIF GEOMEAN MMULT ROWS VAR
# COVAR GROWTH MOD RSQ VARP
# CRITBINOM HARMEAN MODE SEARCH VDB
# DATE HLOOKUP MONTH SECOND VLOOKUP
# DATEVALUE HOUR N SIGN WEEKDAY
# DAVERAGE HYPGEOMDIST NA SIN WEIBULL
# DAY IF NEGBINOMDIST SINH YEAR
# DAYS360 INDEX NORMDIST SKEW ZTEST
#
#--
# You can also modify the module to support function names in the following
# languages: German, French, Spanish, Portuguese, Dutch, Finnish, Italian and
# Swedish. See the function_locale.pl program in the examples directory of the distro.
#++
#
# For a general introduction to Excel's formulas and an explanation of the
# syntax of the function refer to the Excel help files or the following:
# http://office.microsoft.com/en-us/assistance/CH062528031033.aspx.
#
# If your formula doesn't work in WriteExcel try the following:
#
# 1. Verify that the formula works in Excel (or Gnumeric or OpenOffice.org).
# 2. Ensure that it isn't on the Caveats list shown above.
# 3. Ensure that cell references and formula names are in uppercase.
# 4. Ensure that you are using ':' as the range operator, A1:A4.