axlsx 1.3.3 → 1.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/CHANGELOG.md +14 -0
  2. data/README.md +15 -15
  3. data/Rakefile +1 -1
  4. data/examples/example.rb +106 -35
  5. data/examples/wrap_text.rb +21 -0
  6. data/lib/axlsx/drawing/chart.rb +1 -1
  7. data/lib/axlsx/rels/relationship.rb +1 -1
  8. data/lib/axlsx/util/serialized_attributes.rb +32 -1
  9. data/lib/axlsx/util/validators.rb +1 -0
  10. data/lib/axlsx/version.rb +1 -1
  11. data/lib/axlsx/workbook/workbook.rb +1 -0
  12. data/lib/axlsx/workbook/worksheet/cell.rb +5 -2
  13. data/lib/axlsx/workbook/worksheet/cfvos.rb +0 -3
  14. data/lib/axlsx/workbook/worksheet/color_scale.rb +56 -16
  15. data/lib/axlsx/workbook/worksheet/data_bar.rb +42 -18
  16. data/lib/axlsx/workbook/worksheet/header_footer.rb +54 -0
  17. data/lib/axlsx/workbook/worksheet/worksheet.rb +29 -11
  18. data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +1 -1
  19. data/test/benchmark.rb +1 -2
  20. data/test/example.xlsx +0 -0
  21. data/test/profile.rb +4 -13
  22. data/test/rels/tc_relationship.rb +5 -0
  23. data/test/tc_helper.rb +5 -1
  24. data/test/workbook/worksheet/tc_color_scale.rb +31 -2
  25. data/test/workbook/worksheet/tc_data_bar.rb +7 -0
  26. data/test/workbook/worksheet/tc_header_footer.rb +151 -0
  27. data/test/workbook/worksheet/tc_worksheet.rb +31 -6
  28. data/test/workbook/worksheet/tc_worksheet_hyperlink.rb +1 -1
  29. metadata +11 -49
  30. data/examples/doc/_index.html +0 -88
  31. data/examples/doc/class_list.html +0 -53
  32. data/examples/doc/css/common.css +0 -1
  33. data/examples/doc/css/full_list.css +0 -57
  34. data/examples/doc/css/style.css +0 -328
  35. data/examples/doc/file_list.html +0 -52
  36. data/examples/doc/frames.html +0 -28
  37. data/examples/doc/index.html +0 -88
  38. data/examples/doc/js/app.js +0 -214
  39. data/examples/doc/js/full_list.js +0 -173
  40. data/examples/doc/js/jquery.js +0 -4
  41. data/examples/doc/method_list.html +0 -52
  42. data/examples/doc/top-level-namespace.html +0 -102
  43. data/examples/extractive.pdf +0 -0
  44. data/examples/finance.rb +0 -82
  45. data/examples/hyperlinks.rb +0 -23
  46. data/examples/image1.gif +0 -0
  47. data/examples/image1.jpg +0 -0
  48. data/examples/image1.png +0 -0
  49. data/examples/sample.png +0 -0
  50. data/examples/scraping_html.rb +0 -91
  51. data/examples/sheet_view.rb +0 -34
  52. data/examples/skydrive/axlsx.csv +0 -1
  53. data/examples/skydrive/axlsx.xlsx +0 -0
  54. data/examples/sprk2012/Screen Shot 2012-09-11 at 10.42.06 PM.png +0 -0
  55. data/examples/sprk2012/Screen Shot 2012-09-11 at 11.07.48 PM.png +0 -0
  56. data/examples/sprk2012/Screen Shot 2012-09-11 at 8.31.50 PM.png +0 -0
  57. data/examples/sprk2012/Screen Shot 2012-09-11 at 9.23.27 PM.png +0 -0
  58. data/examples/sprk2012/Screen Shot 2012-09-11 at 9.32.06 PM.png +0 -0
  59. data/examples/sprk2012/Screen Shot 2012-09-11 at 9.33.35 PM.png +0 -0
  60. data/examples/sprk2012/Screen Shot 2012-09-11 at 9.46.44 PM.png +0 -0
  61. data/examples/sprk2012/Screen Shot 2012-09-12 at 5.07.23 PM.png +0 -0
  62. data/examples/sprk2012/basics.rb +0 -11
  63. data/examples/sprk2012/basics.xlsx +0 -0
  64. data/examples/sprk2012/gravatar.jpeg +0 -0
  65. data/examples/sprk2012/hair_club.jpg +0 -0
  66. data/examples/sprk2012/images.rb +0 -9
  67. data/examples/sprk2012/images.xlsx +0 -0
  68. data/examples/sprk2012/line_chart.rb +0 -56
  69. data/examples/sprk2012/line_chart.xlsx +0 -0
  70. data/examples/sprk2012/sprk2012.key +0 -0
  71. data/examples/sprk2012/styles.rb +0 -20
  72. data/examples/sprk2012/styles.xlsx +0 -0
  73. data/examples/two_cell_anchor_image.rb +0 -11
@@ -145,6 +145,7 @@ module Axlsx
145
145
  RestrictionValidator.validate "cell run style u", [:none, :single, :double, :singleAccounting, :doubleAccounting], v
146
146
  end
147
147
 
148
+ # validates cell style family which must be between 1 and 5
148
149
  def self.validate_family(v)
149
150
  RestrictionValidator.validate "cell run style family", 1..5, v
150
151
  end
@@ -1,5 +1,5 @@
1
1
  module Axlsx
2
2
 
3
3
  # The current version
4
- VERSION = "1.3.3"
4
+ VERSION = "1.3.4"
5
5
  end
@@ -9,6 +9,7 @@ require 'axlsx/workbook/worksheet/cell.rb'
9
9
  require 'axlsx/workbook/worksheet/page_margins.rb'
10
10
  require 'axlsx/workbook/worksheet/page_set_up_pr.rb'
11
11
  require 'axlsx/workbook/worksheet/page_setup.rb'
12
+ require 'axlsx/workbook/worksheet/header_footer.rb'
12
13
  require 'axlsx/workbook/worksheet/print_options.rb'
13
14
  require 'axlsx/workbook/worksheet/cfvo.rb'
14
15
  require 'axlsx/workbook/worksheet/cfvos.rb'
@@ -398,8 +398,8 @@ module Axlsx
398
398
  end
399
399
 
400
400
  # assigns the owning row for this cell.
401
- def row=(v) DataTypeValidator.validate "Cell.row", Row, v; @row=v end
402
-
401
+ def row=(v) @row=v end
402
+
403
403
  # Determines the cell type based on the cell value.
404
404
  # @note This is only used when a cell is created but no :type option is specified, the following rules apply:
405
405
  # 1. If the value is an instance of Date, the type is set to :date
@@ -444,6 +444,9 @@ module Axlsx
444
444
  v ? 1 : 0
445
445
  else
446
446
  @type = :string
447
+ v.to_s
448
+ # TODO find a better way to do this as it accounts for 30% of
449
+ # processing time in benchmarking...
447
450
  ::CGI.escapeHTML(v.to_s)
448
451
  end
449
452
  end
@@ -6,9 +6,6 @@ module Axlsx
6
6
 
7
7
  def initialize
8
8
  super(Cfvo)
9
- @list << Cfvo.new(:type => :min, :val => 0)
10
- @list << Cfvo.new(:type => :max, :val => 0)
11
- lock
12
9
  end
13
10
 
14
11
  def to_xml_string(str='')
@@ -7,6 +7,35 @@ module Axlsx
7
7
  # @see ConditionalFormattingRule#initialize
8
8
  class ColorScale
9
9
 
10
+ class << self
11
+
12
+ # These are the default conditional formatting value objects
13
+ # that define a two tone color gradient.
14
+ def default_cfvos
15
+ [{:type => :min, :val => 0, :color => 'FFFF7128'},
16
+ {:type => :max, :val => 0, :color => 'FFFFEF9C'}]
17
+ end
18
+
19
+ # A builder for two tone color gradient
20
+ # @example
21
+ # # this creates a two tone color scale
22
+ # color_scale = Axlsx::ColorScale.two_tone
23
+ # @see examples/example.rb conditional formatting examples.
24
+ def two_tone
25
+ self.new
26
+ end
27
+
28
+ # A builder for three tone color gradient
29
+ # @example
30
+ # #this creates a three tone color scale
31
+ # color_scale = Axlsx::ColorScale.three_tone
32
+ # @see examples/example.rb conditional formatting examples.
33
+ def three_tone
34
+ self.new({:type => :min, :val => 0, :color => 'FFF8696B'},
35
+ {:type => :percent, :val => '50', :color => 'FFFFEB84'},
36
+ {:type => :max, :val => 0, :color => 'FF63BE7B'})
37
+ end
38
+ end
10
39
  # A simple typed list of cfvos
11
40
  # @return [SimpleTypedList]
12
41
  # @see Cfvo
@@ -17,25 +46,31 @@ module Axlsx
17
46
  # A simple types list of colors
18
47
  # @return [SimpleTypedList]
19
48
  # @see Color
20
- attr_reader :colors
49
+ def colors
50
+ @colors ||= SimpleTypedList.new Color
51
+ end
21
52
 
22
53
  # creates a new ColorScale object.
23
- # This method will yield it self so you can alter the properites of the defauls conditional formating value object (cfvo and colors
24
- # Two value objects and two colors are created on initialization and cannot be deleted.
25
54
  # @see Cfvo
26
55
  # @see Color
27
- def initialize
28
- initialize_colors
56
+ # @example
57
+ # color_scale = Axlsx::ColorScale.new({:type => :num, :val => 0.55, :color => 'fff7696c'})
58
+ def initialize(*cfvos)
59
+ initialize_default_cfvos(cfvos)
29
60
  yield self if block_given?
30
61
  end
31
62
 
32
63
  # adds a new cfvo / color pair to the color scale and returns a hash containing
33
64
  # a reference to the newly created cfvo and color objects so you can alter the default properties.
34
65
  # @return [Hash] a hash with :cfvo and :color keys referencing the newly added objects.
66
+ # @param [Hash] options options for the new cfvo and color objects
67
+ # @option [Symbol] type The type of cfvo you to add
68
+ # @option [Any] val The value of the cfvo to add
69
+ # @option [String] The rgb color for the cfvo
35
70
  def add(options={})
36
71
  value_objects << Cfvo.new(:type => options[:type] || :min, :val => options[:val] || 0)
37
- @colors << Color.new(:rgb => options[:color] || "FF000000")
38
- {:cfvo => value_objects.last, :color => @colors.last}
72
+ colors << Color.new(:rgb => options[:color] || "FF000000")
73
+ {:cfvo => value_objects.last, :color => colors.last}
39
74
  end
40
75
 
41
76
 
@@ -44,7 +79,7 @@ module Axlsx
44
79
  # @note you cannot remove the first two cfvo and color pairs
45
80
  def delete_at(index=2)
46
81
  value_objects.delete_at index
47
- @colors.delete_at index
82
+ colors.delete_at index
48
83
  end
49
84
 
50
85
  # Serialize this color_scale object data to an xml string
@@ -53,18 +88,23 @@ module Axlsx
53
88
  def to_xml_string(str = '')
54
89
  str << '<colorScale>'
55
90
  value_objects.to_xml_string(str)
56
- @colors.each { |color| color.to_xml_string(str) }
91
+ colors.each { |color| color.to_xml_string(str) }
57
92
  str << '</colorScale>'
58
93
  end
59
94
 
60
95
  private
61
-
62
- # creates the initial color objects
63
- def initialize_colors
64
- @colors = SimpleTypedList.new Color
65
- @colors.concat [Color.new(:rgb => "FFFF0000"), Color.new(:rgb => "FF0000FF")]
66
- @colors.lock
96
+ # There has got to be cleaner way of merging these arrays.
97
+ def initialize_default_cfvos(user_cfvos)
98
+ defaults = self.class.default_cfvos
99
+ user_cfvos.each_with_index do |cfvo, index|
100
+ if index < defaults.size
101
+ cfvo = defaults[index].merge(cfvo)
102
+ end
103
+ add cfvo
104
+ end
105
+ while colors.size < defaults.size
106
+ add defaults[colors.size - 1]
107
+ end
67
108
  end
68
-
69
109
  end
70
110
  end
@@ -10,16 +10,27 @@ module Axlsx
10
10
  include Axlsx::OptionsParser
11
11
  include Axlsx::SerializedAttributes
12
12
 
13
+ class << self
14
+ # This differs from ColorScale. There must be exactly two cfvos one color
15
+ def default_cfvos
16
+ [{:type => :min, :val => "0"},
17
+ {:type => :max, :val => "0"}]
18
+ end
19
+ end
20
+
13
21
  # Creates a new data bar conditional formatting object
22
+ # @param [Hash] options
14
23
  # @option options [Integer] minLength
15
24
  # @option options [Integer] maxLength
16
25
  # @option options [Boolean] showValue
17
26
  # @option options [String] color - the rbg value used to color the bars
18
- def initialize(options = {})
27
+ # @param [Array] cfvos hashes defining the gradient interpolation points for this formatting.
28
+ def initialize(options = {}, *cfvos)
19
29
  @min_length = 10
20
30
  @max_length = 90
21
31
  @show_value = true
22
32
  parse_options options
33
+ initialize_cfvos(cfvos)
23
34
  yield self if block_given?
24
35
  end
25
36
 
@@ -70,27 +81,27 @@ module Axlsx
70
81
  end
71
82
  alias :minLength= :min_length=
72
83
 
73
- # @see maxLength
74
- def max_length=(v)
75
- Axlsx.validate_unsigned_int(v)
76
- @max_length = v
77
- end
84
+ # @see maxLength
85
+ def max_length=(v)
86
+ Axlsx.validate_unsigned_int(v)
87
+ @max_length = v
88
+ end
78
89
  alias :maxLength= :max_length=
79
90
 
80
- # @see showValue
81
- def show_value=(v)
82
- Axlsx.validate_boolean(v)
83
- @show_value = v
84
- end
91
+ # @see showValue
92
+ def show_value=(v)
93
+ Axlsx.validate_boolean(v)
94
+ @show_value = v
95
+ end
85
96
  alias :showValue= :show_value=
86
97
 
87
- # Sets the color for the data bars.
88
- # @param [Color|String] v The color object, or rgb string value to apply
89
- def color=(v)
90
- @color = v if v.is_a? Color
91
- self.color.rgb = v if v.is_a? String
92
- @color
93
- end
98
+ # Sets the color for the data bars.
99
+ # @param [Color|String] v The color object, or rgb string value to apply
100
+ def color=(v)
101
+ @color = v if v.is_a? Color
102
+ self.color.rgb = v if v.is_a? String
103
+ @color
104
+ end
94
105
 
95
106
  # Serialize this object to an xml string
96
107
  # @param [String] str
@@ -103,5 +114,18 @@ module Axlsx
103
114
  self.color.to_xml_string(str)
104
115
  str << '</dataBar>'
105
116
  end
117
+
118
+ private
119
+
120
+ def initialize_cfvos(cfvos)
121
+ self.class.default_cfvos.each_with_index.map do |default, index|
122
+ if index < cfvos.size
123
+ value_objects << Cfvo.new(default.merge(cfvos[index]))
124
+ else
125
+ value_objects << Cfvo.new(default)
126
+ end
127
+ end
128
+ end
129
+
106
130
  end
107
131
  end
@@ -0,0 +1,54 @@
1
+ module Axlsx
2
+ # Header/Footer options for printing a worksheet. All settings are optional.
3
+ #
4
+ # Headers and footers are generated using a string which is a combination
5
+ # of plain text and control characters. A fairly comprehensive list of control
6
+ # characters can be found here:
7
+ # https://github.com/randym/axlsx/blob/master/notes_on_header_footer.md
8
+ #     
9
+ # @note The recommended way of managing header/footers is via Worksheet#header_footer
10
+ # @see Worksheet#initialize
11
+ class HeaderFooter
12
+
13
+ include Axlsx::OptionsParser
14
+ include Axlsx::SerializedAttributes
15
+ include Axlsx::Accessors
16
+
17
+ # Creates a new HeaderFooter object
18
+ # @option options [String] odd_header The content for headers on odd numbered pages.
19
+ # @option options [String] odd_footer The content for footers on odd numbered pages.
20
+ # @option options [String] even_header The content for headers on even numbered pages.
21
+ # @option options [String] even_footer The content for footers on even numbered pages.
22
+ # @option options [String] first_header The content for headers on even numbered pages.
23
+ # @option options [String] first_footer The content for footers on even numbered pages.
24
+ # @option options [Boolean] different_odd_even Setting this to true will show different headers/footers on odd and even pages. When false, the odd headers/footers are used on each page. (Default: false)
25
+ # @option options [Boolean] different_first If true, will use the first header/footer on page 1. Otherwise, the odd header/footer is used.
26
+ def initialize(options = {})
27
+ parse_options options
28
+ end
29
+
30
+ serializable_attributes :different_odd_even, :different_first
31
+ serializable_element_attributes :odd_header, :odd_footer, :even_header, :even_footer, :first_header, :first_footer
32
+ string_attr_accessor :odd_header, :odd_footer, :even_header, :even_footer, :first_header, :first_footer
33
+ boolean_attr_accessor :different_odd_even, :different_first
34
+
35
+ # Set some or all header/footers at once.
36
+ # @param [Hash] options The header/footer options to set (possible keys are :odd_header, :odd_footer, :even_header, :even_footer, :first_header, :first_footer, :different_odd_even, and :different_first).
37
+ def set(options)
38
+ parse_options options
39
+ end
40
+
41
+ # Serializes the header/footer object.
42
+ # @param [String] str
43
+ # @return [String]
44
+ def to_xml_string(str = '')
45
+ str << "<headerFooter "
46
+ serialized_attributes str
47
+ str << ">"
48
+ serialized_element_attributes(str) do |value|
49
+ value = ::CGI.escapeHTML(value)
50
+ end
51
+ str << "</headerFooter>"
52
+ end
53
+ end
54
+ end
@@ -9,7 +9,8 @@ module Axlsx
9
9
  # This is used for autowidth calculations
10
10
  # @return [String]
11
11
  def self.thin_chars
12
- @thin_chars ||= "^.acefijklrstxyzFIJL()-"
12
+ # removed 'e' and 'y' from this list - as a GUESS
13
+ @thin_chars ||= "^.acfijklrstxzFIJL()-"
13
14
  end
14
15
 
15
16
  # Creates a new worksheet.
@@ -18,6 +19,7 @@ module Axlsx
18
19
  # @option options [String] name The name of this worksheet.
19
20
  # @option options [Hash] page_margins A hash containing page margins for this worksheet. @see PageMargins
20
21
  # @option options [Hash] print_options A hash containing print options for this worksheet. @see PrintOptions
22
+ # @option options [Hash] header_footer A hash containing header/footer options for this worksheet. @see HeaderFooter
21
23
  # @option options [Boolean] show_gridlines indicates if gridlines should be shown for this sheet.
22
24
  def initialize(wb, options={})
23
25
  self.workbook = wb
@@ -34,6 +36,7 @@ module Axlsx
34
36
  @page_margins = PageMargins.new options[:page_margins] if options[:page_margins]
35
37
  @page_setup = PageSetup.new options[:page_setup] if options[:page_setup]
36
38
  @print_options = PrintOptions.new options[:print_options] if options[:print_options]
39
+ @header_footer = HeaderFooter.new options[:header_footer] if options[:header_footer]
37
40
  end
38
41
 
39
42
  # The name of the worksheet
@@ -41,7 +44,7 @@ module Axlsx
41
44
  def name
42
45
  @name ||= "Sheet" + (index+1).to_s
43
46
  end
44
-
47
+
45
48
  # The sheet calculation properties
46
49
  # @return [SheetCalcPr]
47
50
  def sheet_calc_pr
@@ -104,7 +107,7 @@ module Axlsx
104
107
  # An range that excel will apply an autfilter to "A1:B3"
105
108
  # This will turn filtering on for the cells in the range.
106
109
  # The first row is considered the header, while subsequent rows are considerd to be data.
107
- # @return String
110
+ # @return String
108
111
  def auto_filter
109
112
  @auto_filter ||= AutoFilter.new self
110
113
  end
@@ -193,6 +196,21 @@ module Axlsx
193
196
  @print_options
194
197
  end
195
198
 
199
+ # Options for headers and footers.
200
+ # @example
201
+ # wb = Axlsx::Package.new.workbook
202
+ # # would generate something like: "file.xlsx : sheet_name 2 of 7 date with timestamp"
203
+ # header = {:different_odd_ => false, :odd_header => "&L&F : &A&C&Pof%N%R%D %T"}
204
+ # ws = wb.add_worksheet :header_footer => header
205
+ #
206
+ # @see HeaderFooter#initialize
207
+ # @return [HeaderFooter]
208
+ def header_footer
209
+ @header_footer ||= HeaderFooter.new
210
+ yield @header_footer if block_given?
211
+ @header_footer
212
+ end
213
+
196
214
  # convinience method to access all cells in this worksheet
197
215
  # @return [Array] cells
198
216
  def cells
@@ -280,7 +298,7 @@ module Axlsx
280
298
 
281
299
  # The name of the worksheet
282
300
  # The name of a worksheet must be unique in the workbook, and must not exceed 31 characters
283
- # @param [String] name
301
+ # @param [String] name
284
302
  def name=(name)
285
303
  validate_sheet_name name
286
304
  @name=Axlsx::coder.encode(name)
@@ -388,7 +406,7 @@ module Axlsx
388
406
  cf = ConditionalFormatting.new( :sqref => cells )
389
407
  cf.add_rules rules
390
408
  conditional_formattings << cf
391
- conditional_formattings
409
+ conditional_formattings
392
410
  end
393
411
 
394
412
  # Add data validation to this worksheet.
@@ -513,7 +531,7 @@ module Axlsx
513
531
  def sanitize(str)
514
532
  str.gsub(CONTROL_CHAR_REGEX, '')
515
533
  end
516
-
534
+
517
535
  # The worksheet relationships. This is managed automatically by the worksheet
518
536
  # @return [Relationships]
519
537
  def relationships
@@ -570,12 +588,12 @@ module Axlsx
570
588
 
571
589
 
572
590
  private
573
-
591
+
574
592
  def validate_sheet_name(name)
575
593
  DataTypeValidator.validate "Worksheet.name", String, name
576
594
  raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % name) if name.size > 31
577
595
  raise ArgumentError, (ERR_SHEET_NAME_COLON_FORBIDDEN % name) if name.include? ':'
578
- name = Axlsx::coder.encode(name)
596
+ name = Axlsx::coder.encode(name)
579
597
  sheet_names = @workbook.worksheets.map { |s| s.name }
580
598
  raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME % name) if sheet_names.include?(name)
581
599
  end
@@ -586,7 +604,7 @@ module Axlsx
586
604
  sheet_data, sheet_calc_pr, @sheet_protection, protected_ranges,
587
605
  auto_filter, merged_cells, conditional_formattings,
588
606
  data_validations, hyperlinks, print_options, page_margins,
589
- page_setup, worksheet_drawing, worksheet_comments,
607
+ page_setup, header_footer, worksheet_drawing, worksheet_comments,
590
608
  tables]
591
609
  end
592
610
 
@@ -606,7 +624,7 @@ module Axlsx
606
624
  # @see Worksheet#protect_range
607
625
  # @return [SimpleTypedList] The protected ranges for this worksheet
608
626
  def protected_ranges
609
- @protected_ranges ||= ProtectedRanges.new self
627
+ @protected_ranges ||= ProtectedRanges.new self
610
628
  # SimpleTypedList.new ProtectedRange
611
629
  end
612
630
 
@@ -619,7 +637,7 @@ module Axlsx
619
637
  # data validations array
620
638
  # @return [Array]
621
639
  def data_validations
622
- @data_validations ||= DataValidations.new self
640
+ @data_validations ||= DataValidations.new self
623
641
  end
624
642
 
625
643
  # merged cells array