axlsx 1.0.15 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. data/.yardopts +1 -0
  2. data/CHANGELOG.md +58 -2
  3. data/README.md +425 -207
  4. data/Rakefile +6 -2
  5. data/examples/axlsx.xlsx +0 -0
  6. data/examples/example.csv +1000 -0
  7. data/examples/example.rb +266 -132
  8. data/examples/example.xlsx +0 -0
  9. data/examples/example_streamed.xlsx +0 -0
  10. data/examples/no-use_autowidth.xlsx +0 -0
  11. data/examples/real_example.rb +63 -0
  12. data/examples/sample.png +0 -0
  13. data/examples/shared_strings_example.xlsx +0 -0
  14. data/lib/axlsx/content_type/content_type.rb +13 -12
  15. data/lib/axlsx/content_type/default.rb +10 -6
  16. data/lib/axlsx/content_type/override.rb +13 -8
  17. data/lib/axlsx/doc_props/app.rb +38 -41
  18. data/lib/axlsx/doc_props/core.rb +13 -17
  19. data/lib/axlsx/drawing/axis.rb +39 -19
  20. data/lib/axlsx/drawing/bar_3D_chart.rb +34 -32
  21. data/lib/axlsx/drawing/bar_series.rb +14 -14
  22. data/lib/axlsx/drawing/cat_axis.rb +16 -14
  23. data/lib/axlsx/drawing/cat_axis_data.rb +17 -18
  24. data/lib/axlsx/drawing/chart.rb +40 -41
  25. data/lib/axlsx/drawing/drawing.rb +27 -12
  26. data/lib/axlsx/drawing/graphic_frame.rb +22 -21
  27. data/lib/axlsx/drawing/hlink_click.rb~ +0 -0
  28. data/lib/axlsx/drawing/hyperlink.rb +96 -0
  29. data/lib/axlsx/drawing/hyperlink.rb~ +64 -0
  30. data/lib/axlsx/drawing/line_3D_chart.rb +31 -28
  31. data/lib/axlsx/drawing/line_series.rb +12 -11
  32. data/lib/axlsx/drawing/marker.rb +11 -8
  33. data/lib/axlsx/drawing/named_axis_data.rb +36 -0
  34. data/lib/axlsx/drawing/one_cell_anchor.rb +18 -16
  35. data/lib/axlsx/drawing/pic.rb +47 -33
  36. data/lib/axlsx/drawing/picture_locking.rb +22 -18
  37. data/lib/axlsx/drawing/pie_3D_chart.rb +11 -8
  38. data/lib/axlsx/drawing/pie_series.rb +16 -12
  39. data/lib/axlsx/drawing/scaling.rb +11 -10
  40. data/lib/axlsx/drawing/scatter_chart.rb +69 -0
  41. data/lib/axlsx/drawing/scatter_series.rb +39 -0
  42. data/lib/axlsx/drawing/ser_axis.rb +11 -10
  43. data/lib/axlsx/drawing/series.rb +16 -15
  44. data/lib/axlsx/drawing/series_title.rb +15 -14
  45. data/lib/axlsx/drawing/title.rb +27 -26
  46. data/lib/axlsx/drawing/two_cell_anchor.rb +19 -20
  47. data/lib/axlsx/drawing/val_axis.rb +9 -7
  48. data/lib/axlsx/drawing/val_axis_data.rb +18 -17
  49. data/lib/axlsx/drawing/view_3D.rb +23 -20
  50. data/lib/axlsx/package.rb +117 -52
  51. data/lib/axlsx/rels/relationship.rb +27 -8
  52. data/lib/axlsx/rels/relationships.rb +9 -2
  53. data/lib/axlsx/stylesheet/border.rb +28 -23
  54. data/lib/axlsx/stylesheet/border_pr.rb +17 -15
  55. data/lib/axlsx/stylesheet/cell_alignment.rb +24 -21
  56. data/lib/axlsx/stylesheet/cell_protection.rb +11 -7
  57. data/lib/axlsx/stylesheet/cell_style.rb +9 -5
  58. data/lib/axlsx/stylesheet/color.rb +20 -14
  59. data/lib/axlsx/stylesheet/fill.rb +8 -5
  60. data/lib/axlsx/stylesheet/font.rb +22 -14
  61. data/lib/axlsx/stylesheet/gradient_fill.rb +20 -17
  62. data/lib/axlsx/stylesheet/gradient_stop.rb +10 -6
  63. data/lib/axlsx/stylesheet/num_fmt.rb +13 -6
  64. data/lib/axlsx/stylesheet/pattern_fill.rb +26 -10
  65. data/lib/axlsx/stylesheet/styles.rb +55 -41
  66. data/lib/axlsx/stylesheet/table_style.rb +10 -4
  67. data/lib/axlsx/stylesheet/table_style_element.rb +11 -7
  68. data/lib/axlsx/stylesheet/table_styles.rb +12 -8
  69. data/lib/axlsx/stylesheet/xf.rb +30 -25
  70. data/lib/axlsx/util/cbf.rb +69 -33
  71. data/lib/axlsx/util/constants.rb +39 -20
  72. data/lib/axlsx/util/doc/_index.html +84 -0
  73. data/lib/axlsx/util/doc/class_list.html +47 -0
  74. data/lib/axlsx/util/doc/css/common.css +1 -0
  75. data/lib/axlsx/util/doc/css/full_list.css +55 -0
  76. data/lib/axlsx/util/doc/css/style.css +322 -0
  77. data/lib/axlsx/util/doc/file_list.html +46 -0
  78. data/lib/axlsx/util/doc/frames.html +13 -0
  79. data/lib/axlsx/util/doc/index.html +84 -0
  80. data/lib/axlsx/util/doc/js/app.js +205 -0
  81. data/lib/axlsx/util/doc/js/full_list.js +173 -0
  82. data/lib/axlsx/util/doc/js/jquery.js +16 -0
  83. data/lib/axlsx/util/doc/method_list.html +46 -0
  84. data/lib/axlsx/util/doc/top-level-namespace.html +95 -0
  85. data/lib/axlsx/util/font_tables.rb~ +0 -0
  86. data/lib/axlsx/util/ms_off_crypto.rb +10 -10
  87. data/lib/axlsx/util/parser.rb +1 -0
  88. data/lib/axlsx/util/simple_typed_list.rb +20 -10
  89. data/lib/axlsx/util/storage.rb +1 -1
  90. data/lib/axlsx/util/validators.rb +23 -7
  91. data/lib/axlsx/version.rb +5 -2
  92. data/lib/axlsx/workbook/shared_strings_table.rb +68 -0
  93. data/lib/axlsx/workbook/shared_strings_table.rb~ +69 -0
  94. data/lib/axlsx/workbook/workbook.rb +82 -26
  95. data/lib/axlsx/workbook/worksheet/cell.rb +166 -130
  96. data/lib/axlsx/workbook/worksheet/col.rb +114 -0
  97. data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
  98. data/lib/axlsx/workbook/worksheet/date_time_converter.rb +29 -0
  99. data/lib/axlsx/workbook/worksheet/page_margins.rb +97 -0
  100. data/lib/axlsx/workbook/worksheet/row.rb +53 -21
  101. data/lib/axlsx/workbook/worksheet/shared_strings_table.rb~ +0 -0
  102. data/lib/axlsx/workbook/worksheet/table.rb +96 -0
  103. data/lib/axlsx/workbook/worksheet/table.rb~ +97 -0
  104. data/lib/axlsx/workbook/worksheet/worksheet.rb +275 -124
  105. data/lib/axlsx.rb +41 -14
  106. data/lib/schema/dc.xsd +5 -5
  107. data/lib/schema/dcmitype.xsd +5 -3
  108. data/lib/schema/dcterms.xsd +15 -15
  109. data/lib/schema/opc-coreProperties.xsd +6 -2
  110. data/lib/schema/xml.xsd +7 -8
  111. data/test/benchmark.rb +73 -0
  112. data/test/content_type/tc_content_type.rb +31 -31
  113. data/test/content_type/tc_default.rb +9 -22
  114. data/test/content_type/tc_override.rb +8 -21
  115. data/test/doc_props/tc_app.rb +2 -8
  116. data/test/doc_props/tc_core.rb +6 -7
  117. data/test/drawing/tc_axis.rb +7 -3
  118. data/test/drawing/tc_bar_3D_chart.rb +6 -7
  119. data/test/drawing/tc_bar_series.rb +4 -5
  120. data/test/drawing/tc_cat_axis.rb +2 -3
  121. data/test/drawing/tc_cat_axis_data.rb +2 -3
  122. data/test/drawing/tc_chart.rb +13 -14
  123. data/test/drawing/tc_drawing.rb +7 -8
  124. data/test/drawing/tc_graphic_frame.rb +3 -4
  125. data/test/drawing/tc_hyperlink.rb +69 -0
  126. data/test/drawing/tc_line_3d_chart.rb +5 -6
  127. data/test/drawing/tc_line_series.rb +3 -4
  128. data/test/drawing/tc_marker.rb +3 -4
  129. data/test/drawing/tc_one_cell_anchor.rb +6 -7
  130. data/test/drawing/tc_pic.rb +13 -8
  131. data/test/drawing/tc_picture_locking.rb +2 -3
  132. data/test/drawing/tc_pie_3D_chart.rb +5 -6
  133. data/test/drawing/tc_pie_series.rb +4 -5
  134. data/test/drawing/tc_scaling.rb +3 -4
  135. data/test/drawing/tc_scatter_chart.rb +43 -0
  136. data/test/drawing/tc_scatter_series.rb +20 -0
  137. data/test/drawing/tc_ser_axis.rb +2 -3
  138. data/test/drawing/tc_series.rb +4 -5
  139. data/test/drawing/tc_series_title.rb +4 -5
  140. data/test/drawing/tc_title.rb +4 -5
  141. data/test/drawing/tc_two_cell_anchor.rb +4 -5
  142. data/test/drawing/tc_val_axis.rb +2 -3
  143. data/test/drawing/tc_val_axis_data.rb +2 -3
  144. data/test/drawing/tc_view_3D.rb +6 -7
  145. data/test/profile.rb +34 -0
  146. data/test/rels/tc_relationship.rb +10 -6
  147. data/test/rels/tc_relationships.rb +4 -5
  148. data/test/stylesheet/tc_border.rb +3 -4
  149. data/test/stylesheet/tc_border_pr.rb +3 -4
  150. data/test/stylesheet/tc_cell_alignment.rb +10 -6
  151. data/test/stylesheet/tc_cell_protection.rb +2 -3
  152. data/test/stylesheet/tc_cell_style.rb +2 -3
  153. data/test/stylesheet/tc_color.rb +2 -3
  154. data/test/stylesheet/tc_fill.rb +1 -2
  155. data/test/stylesheet/tc_font.rb +12 -5
  156. data/test/stylesheet/tc_gradient_fill.rb +1 -2
  157. data/test/stylesheet/tc_gradient_stop.rb +1 -2
  158. data/test/stylesheet/tc_num_fmt.rb +1 -2
  159. data/test/stylesheet/tc_pattern_fill.rb +3 -4
  160. data/test/stylesheet/tc_styles.rb +31 -6
  161. data/test/stylesheet/tc_table_style.rb +2 -3
  162. data/test/stylesheet/tc_table_style_element.rb +2 -3
  163. data/test/stylesheet/tc_table_styles.rb +3 -4
  164. data/test/stylesheet/tc_xf.rb +16 -17
  165. data/test/tc_axlsx.rb +39 -0
  166. data/test/tc_helper.rb +3 -0
  167. data/test/tc_package.rb +43 -9
  168. data/test/util/tc_simple_typed_list.rb +8 -9
  169. data/test/util/tc_validators.rb +7 -8
  170. data/test/workbook/tc_shared_strings_table.rb +38 -0
  171. data/test/workbook/tc_workbook.rb +32 -6
  172. data/test/workbook/worksheet/table/tc_table.rb +71 -0
  173. data/test/workbook/worksheet/table/tc_table.rb~ +72 -0
  174. data/test/workbook/worksheet/tc_cell.rb +80 -13
  175. data/test/workbook/worksheet/tc_col.rb +59 -0
  176. data/test/workbook/worksheet/tc_col.rb~ +10 -0
  177. data/test/workbook/worksheet/tc_date_time_converter.rb +132 -0
  178. data/test/workbook/worksheet/tc_page_margins.rb +97 -0
  179. data/test/workbook/worksheet/tc_row.rb +54 -4
  180. data/test/workbook/worksheet/tc_worksheet.rb +205 -31
  181. metadata +78 -84
  182. data/examples/example.rb~ +0 -112
  183. data/test/drawing/tc_line_series.tc~ +0 -34
  184. data/test/drawing/tc_picture_locking.rb~ +0 -77
@@ -1,53 +1,50 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: UTF-8
2
+ require 'cgi'
2
3
  module Axlsx
3
- # A cell in a worksheet.
4
+ # A cell in a worksheet.
4
5
  # Cell stores inforamation requried to serialize a single worksheet cell to xml. You must provde the Row that the cell belongs to and the cells value. The data type will automatically be determed if you do not specify the :type option. The default style will be applied if you do not supply the :style option. Changing the cell's type will recast the value to the type specified. Altering the cell's value via the property accessor will also automatically cast the provided value to the cell's type.
5
- # @example Manually creating and manipulating Cell objects
6
- # ws = Workbook.new.add_worksheet
7
- # # This is the simple, and recommended way to create cells. Data types will automatically be determined for you.
8
- # ws.add_row :values => [1,"fish",Time.now]
9
- #
10
- # # but you can also do this
11
- # r = ws.add_row
12
- # r.add_cell 1
13
- #
14
- # # or even this
15
- # r = ws.add_row
16
- # c = Cell.new row, 1, :value=>integer
17
- #
18
- # # cells can also be accessed via Row#cells. The example here changes the cells type, which will automatically updated the value from 1 to 1.0
19
- # r.cells.last.type = :float
20
- #
21
6
  # @note The recommended way to generate cells is via Worksheet#add_row
22
- #
7
+ #
23
8
  # @see Worksheet#add_row
24
9
  class Cell
25
10
 
11
+
12
+ # An array of available inline styes.
13
+ # TODO change this to a hash where each key defines attr name and validator (and any info the validator requires)
14
+ # then move it out to a module so we can re-use in in other classes.
15
+ # needs to define bla=(v) and bla methods on the class that hook into a
16
+ # set_attr method that kicks the suplied validator and updates the instance_variable
17
+ # for the key
18
+ INLINE_STYLES = ['value', 'type', 'font_name', 'charset',
19
+ 'family', 'b', 'i', 'strike','outline',
20
+ 'shadow', 'condense', 'extend', 'u',
21
+ 'vertAlign', 'sz', 'color', 'scheme']
22
+
26
23
  # The index of the cellXfs item to be applied to this cell.
27
- # @return [Integer]
24
+ # @return [Integer]
28
25
  # @see Axlsx::Styles
29
26
  attr_reader :style
30
27
 
31
28
  # The row this cell belongs to.
32
29
  # @return [Row]
33
30
  attr_reader :row
34
-
35
- # The cell's data type. Currently only four types are supported, :time, :float, :integer and :string.
36
- # Changing the type for a cell will recast the value into that type. If no type option is specified in the constructor, the type is
31
+
32
+ # The cell's data type. Currently only six types are supported, :date, :time, :float, :integer, :string and :boolean.
33
+ # Changing the type for a cell will recast the value into that type. If no type option is specified in the constructor, the type is
37
34
  # automatically determed.
38
35
  # @see Cell#cell_type_from_value
39
- # @return [Symbol] The type of data this cell's value is cast to.
40
- # @raise [ArgumentExeption] Cell.type must be one of [:time, :float, :integer, :string]
41
- # @note
36
+ # @return [Symbol] The type of data this cell's value is cast to.
37
+ # @raise [ArgumentExeption] Cell.type must be one of [:date, time, :float, :integer, :string, :boolean]
38
+ # @note
42
39
  # If the value provided cannot be cast into the type specified, type is changed to :string and the following logic is applied.
43
- # :string to :integer or :float, type coversions always return 0 or 0.0
40
+ # :string to :integer or :float, type conversions always return 0 or 0.0
44
41
  # :string, :integer, or :float to :time conversions always return the original value as a string and set the cells type to :string.
45
42
  # No support is currently implemented for parsing time strings.
46
43
  attr_reader :type
47
44
  # @see type
48
- def type=(v)
49
- RestrictionValidator.validate "Cell.type", [:time, :float, :integer, :string], v
50
- @type=v
45
+ def type=(v)
46
+ RestrictionValidator.validate "Cell.type", [:date, :time, :float, :integer, :string, :boolean], v
47
+ @type=v
51
48
  self.value = @value unless @value.nil?
52
49
  end
53
50
 
@@ -60,103 +57,125 @@ module Axlsx
60
57
  #TODO: consider doing value based type determination first?
61
58
  @value = cast_value(v)
62
59
  end
63
-
60
+
61
+ # Indicates that the cell has one or more of the custom cell styles applied.
62
+ # @return [Boolean]
63
+ def is_text_run?
64
+ @is_text_run ||= false
65
+ end
66
+
67
+ # Indicates if the cell is good for shared string table
68
+ def plain_string?
69
+ @type == :string && # String typed
70
+ !is_text_run? && # No inline styles
71
+ !@value.nil? && # Not nil
72
+ !@value.empty? && # Not empty
73
+ !@value.start_with?('=') # Not a formula
74
+ end
75
+
64
76
  # The inline font_name property for the cell
65
77
  # @return [String]
66
78
  attr_reader :font_name
67
79
  # @see font_name
68
- def font_name=(v) Axlsx::validate_string(v); @font_name = v; end
80
+ def font_name=(v) set_run_style :validate_string, :font_name, v; end
69
81
 
70
82
  # The inline charset property for the cell
71
83
  # @return [String]
72
84
  attr_reader :charset
73
85
  # @see charset
74
- def charset=(v) Axlsx::validate_unsigned_int(v); @charset = v; end
86
+ def charset=(v) set_run_style :validate_unsigned_int, :charset, v; end
75
87
 
76
88
  # The inline family property for the cell
77
89
  # @return [String]
78
90
  attr_reader :family
79
91
  # @see family
80
- def family=(v) Axlsx::validate_string(v); @family = v; end
92
+ def family=(v) set_run_style :validate_string, :family, v; end
81
93
 
82
94
  # The inline bold property for the cell
83
95
  # @return [Boolean]
84
96
  attr_reader :b
85
97
  # @see b
86
- def b=(v) Axlsx::validate_boolean(v); @b = v; end
98
+ def b=(v) set_run_style :validate_boolean, :b, v; end
87
99
 
88
100
  # The inline italic property for the cell
89
101
  # @return [Boolean]
90
102
  attr_reader :i
91
103
  # @see i
92
- def i=(v) Axlsx::validate_boolean(v); @i = v; end
104
+ def i=(v) set_run_style :validate_boolean, :i, v; end
93
105
 
94
106
  # The inline strike property for the cell
95
107
  # @return [Boolean]
96
108
  attr_reader :strike
97
109
  # @see strike
98
- def strike=(v) Axlsx::validate_boolean(v); @strike = v; end
110
+ def strike=(v) set_run_style :validate_boolean, :strike, v; end
99
111
 
100
112
  # The inline outline property for the cell
101
113
  # @return [Boolean]
102
114
  attr_reader :outline
103
115
  # @see outline
104
- def outline=(v) Axlsx::validate_boolean(v); @outline = v; end
116
+ def outline=(v) set_run_style :validate_boolean, :outline, v; end
105
117
 
106
118
  # The inline shadow property for the cell
107
119
  # @return [Boolean]
108
120
  attr_reader :shadow
109
121
  # @see shadow
110
- def shadow=(v) Axlsx::validate_boolean(v); @shadow = v; end
122
+ def shadow=(v) set_run_style :validate_boolean, :shadow, v; end
111
123
 
112
124
  # The inline condense property for the cell
113
125
  # @return [Boolean]
114
126
  attr_reader :condense
115
127
  # @see condense
116
- def condense=(v) Axlsx::validate_boolean(v); @condense = v; end
128
+ def condense=(v) set_run_style :validate_boolean, :condense, v; end
117
129
 
118
130
  # The inline extend property for the cell
119
131
  # @return [Boolean]
120
132
  attr_reader :extend
121
133
  # @see extend
122
- def extend=(v) Axlsx::validate_boolean(v); @extend = v; end
134
+ def extend=(v) set_run_style :validate_boolean, :extend, v; end
123
135
 
124
136
  # The inline underline property for the cell
125
137
  # @return [Boolean]
126
138
  attr_reader :u
127
139
  # @see u
128
- def u=(v) Axlsx::validate_boolean(v); @u = v; end
140
+ def u=(v) set_run_style :validate_boolean, :u, v; end
129
141
 
130
142
  # The inline color property for the cell
131
143
  # @return [Color]
132
144
  attr_reader :color
133
145
  # @param [String] The 8 character representation for an rgb color #FFFFFFFF"
134
- def color=(v)
146
+ def color=(v)
135
147
  @color = v.is_a?(Color) ? v : Color.new(:rgb=>v)
148
+ @is_text_run = true
136
149
  end
137
150
 
138
151
  # The inline sz property for the cell
139
152
  # @return [Boolean]
140
153
  attr_reader :sz
141
154
  # @see sz
142
- def sz=(v) Axlsx::validate_unsigned_int(v); @sz = v; end
155
+ def sz=(v) set_run_style :validate_unsigned_int, :sz, v; end
143
156
 
144
157
  # The inline vertical alignment property for the cell
145
158
  # this must be one of [:baseline, :subscript, :superscript]
146
159
  # @return [Symbol]
147
160
  attr_reader :vertAlign
148
161
  # @see vertAlign
149
- def vertAlign=(v) RestrictionValidator.validate "Cell.vertAlign", [:baseline, :subscript, :superscript], v; @vertAlign = v; end
162
+ def vertAlign=(v)
163
+ RestrictionValidator.validate "Cell.vertAlign", [:baseline, :subscript, :superscript], v
164
+ set_run_style nil, :vertAlign, v
165
+ end
150
166
 
151
167
  # The inline scheme property for the cell
152
168
  # this must be one of [:none, major, minor]
153
169
  # @return [Symbol]
154
170
  attr_reader :scheme
155
171
  # @see scheme
156
- def scheme=(v) RestrictionValidator.validate "Cell.schema", [:none, :major, :minor], v; @scheme = v; end
172
+ def scheme=(v)
173
+ RestrictionValidator.validate "Cell.schema", [:none, :major, :minor], v
174
+ set_run_style nil, :scheme, v
175
+ end
157
176
 
158
177
  # @param [Row] row The row this cell belongs to.
159
- # @param [Any] value The value associated with this cell.
178
+ # @param [Any] value The value associated with this cell.
160
179
  # @option options [Symbol] type The intended data type for this cell. If not specified the data type will be determined internally based on the vlue provided.
161
180
  # @option options [Integer] style The index of the cellXfs item to be applied to this cell. If not specified, the default style (0) will be applied.
162
181
  # @option options [String] font_name
@@ -175,9 +194,11 @@ module Axlsx
175
194
  # @option options [String] color an 8 letter rgb specification
176
195
  # @option options [Symbol] scheme must be one of :none, major, :minor
177
196
  def initialize(row, value="", options={})
178
- self.row=row
197
+ self.row=row
198
+ @font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
199
+ @condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil
179
200
  @styles = row.worksheet.workbook.styles
180
- @row.cells << self
201
+ @row.cells << self
181
202
  options.each do |o|
182
203
  self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
183
204
  end
@@ -186,6 +207,10 @@ module Axlsx
186
207
  @value = cast_value(value)
187
208
  end
188
209
 
210
+ # The Shared Strings Table index for this cell
211
+ # @return [Integer]
212
+ attr_reader :ssti
213
+
189
214
  # @return [Integer] The index of the cell in the containing row.
190
215
  def index
191
216
  @row.cells.index(self)
@@ -193,16 +218,16 @@ module Axlsx
193
218
 
194
219
  # @return [String] The alpha(column)numeric(row) reference for this sell.
195
220
  # @example Relative Cell Reference
196
- # ws.rows.first.cells.first.r #=> "A1"
221
+ # ws.rows.first.cells.first.r #=> "A1"
197
222
  def r
198
- "#{col_ref}#{@row.index+1}"
223
+ Axlsx::cell_r index, @row.index
199
224
  end
200
225
 
201
226
  # @return [String] The absolute alpha(column)numeric(row) reference for this sell.
202
227
  # @example Absolute Cell Reference
203
- # ws.rows.first.cells.first.r #=> "$A$1"
228
+ # ws.rows.first.cells.first.r #=> "$A$1"
204
229
  def r_abs
205
- "$#{r.split('').join('$')}"
230
+ "$#{r.match(%r{([A-Z]+)([0-9]+)})[1,2].join('$')}"
206
231
  end
207
232
 
208
233
  # @return [Integer] The cellXfs item index applied to this cell.
@@ -229,97 +254,102 @@ module Axlsx
229
254
  target.r
230
255
  end
231
256
  self.row.worksheet.merge_cells "#{self.r}:#{range_end}" unless range_end.nil?
232
- end
257
+ end
258
+
259
+ # builds an xml text run based on this cells attributes.
260
+ # @param [String] str The string instance this run will be concated to.
261
+ # @return [String]
262
+ def run_xml_string(str = '')
263
+ if is_text_run?
264
+ data = self.instance_values.reject{|key, value| value == nil }
265
+ keys = data.keys & INLINE_STYLES
266
+ keys.delete ['value', 'type']
267
+ str << "<r><rPr>"
268
+ keys.each do |key|
269
+ case key
270
+ when 'font_name'
271
+ str << "<rFont val='"<< @font_name << "'/>"
272
+ when 'color'
273
+ str << data[key].to_xml_string
274
+ else
275
+ "<" << key.to_s << " val='" << data[key].to_s << "'/>"
276
+ end
277
+ end
278
+ str << "</rPr>" << "<t>" << value.to_s << "</t></r>"
279
+ else
280
+ str << "<t>" << value.to_s << "</t>"
281
+ end
282
+ str
283
+ end
233
284
 
234
285
  # Serializes the cell
235
- # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
286
+ # @param [Integer] r_index The row index for the cell
287
+ # @param [Integer] c_index The cell index in the row.
288
+ # @param [String] str The string index the cell content will be appended to. Defaults to empty string.
236
289
  # @return [String] xml text for the cell
237
- # @note
238
- # Shared Strings are not used in this library. All values are set directly in the each sheet.
239
- def to_xml(xml)
240
-
241
- # however nokogiri does a nice 'force_encoding' which we shall remove!
242
- if @type == :string
290
+ def to_xml_string(r_index, c_index, str = '')
291
+ return str if @value.nil?
292
+ str << '<c r="' << Axlsx::cell_r(c_index, r_index) << '" s="' << @style.to_s << '" '
293
+ case @type
294
+ when :string
243
295
  #parse formula
244
296
  if @value.start_with?('=')
245
- xml.c(:r => r, :t=>:str, :s=>style) {
246
- xml.f @value.to_s.gsub('=', '')
247
- }
297
+ str << 't="str"><f>' << @value.to_s.gsub('=', '') << '</f>'
248
298
  else
249
- #parse standard string
250
- #xml.c(:r => r, :t=>:inlineStr, :s=>style) {
251
- # xml.is { xml.t @value.to_s }
252
- #}
253
- #parse styled string
254
- xml.c(:r => r, :s=>style, :t => :inlineStr) {
255
- xml.is {
256
- xml.r {
257
- xml.rPr {
258
- xml.rFont(:val=>@font_name) if @font_name
259
- xml.charset(:val=>@charset) if @charset
260
- xml.family(:val=>@family) if @family
261
- xml.b(:val=>@b) if @b
262
- xml.i(:val=>@i) if @i
263
- xml.strike(:val=>@strike) if @strike
264
- xml.outline(:val=>@outline) if @outline
265
- xml.shadow(:val=>@shadow) if @shadow
266
- xml.condense(:val=>@condense) if @condense
267
- xml.extend(:val=>@extend) if @extend
268
- @color.to_xml(xml) if @color
269
- xml.sz(:val=>@sz) if @sz
270
- xml.u(:val=>@u) if @u
271
- # :baseline, :subscript, :superscript
272
- xml.vertAlign(:val=>@vertAlign) if @verAlign
273
- # :none, major, :minor
274
- xml.scheme(:val=>@scheme) if @scheme
275
- }
276
- xml.t @value.to_s
277
- }
278
- }
279
- }
299
+ #parse shared
300
+ if @ssti
301
+ str << 't="s"><v>' << @ssti.to_s << '</v>'
302
+ else
303
+ str << 't="inlineStr"><is>' << run_xml_string << '</is>'
304
+ end
280
305
  end
281
- elsif @type == :time
282
- # Using hardcoded offsets here as some operating systems will not except a 'negative' offset from the ruby epoc.
283
- # (1970)
284
- epoc1900 = -2209021200 #Time.local(1900, 1, 1)
285
- epoc1904 = -2082877200 #Time.local(1904, 1, 1)
286
- epoc = Workbook.date1904 ? epoc1904 : epoc1900
287
- v = ((@value.localtime.to_f - epoc) /60.0/60.0/24.0).to_f
288
- xml.c(:r => r, :s => style) { xml.v v }
306
+ when :date
307
+ # TODO: See if this is subject to the same restriction as Time below
308
+ str << '><v>' << DateTimeConverter::date_to_serial(@value).to_s << '</v>'
309
+ when :time
310
+ str << '><v>' << DateTimeConverter::time_to_serial(@value).to_s << '</v>'
311
+ when :boolean
312
+ str << 't="b"><v>' << @value.to_s << '</v>'
289
313
  else
290
- xml.c(:r => r, :s => style) { xml.v value }
314
+ str << '><v>' << @value.to_s << '</v>'
291
315
  end
316
+ str << '</c>'
292
317
  end
293
318
 
319
+ private
294
320
 
295
- private
321
+ # Utility method for setting inline style attributes
322
+ def set_run_style( validator, attr, value)
323
+ return unless INLINE_STYLES.include?(attr.to_s)
324
+ Axlsx.send(validator, value) unless validator == nil
325
+ self.instance_variable_set :"@#{attr.to_s}", value
326
+ @is_text_run = true
327
+ end
328
+
329
+ # @see ssti
330
+ def ssti=(v)
331
+ Axlsx::validate_unsigned_int(v)
332
+ @ssti = v
333
+ end
296
334
 
297
335
  # assigns the owning row for this cell.
298
336
  def row=(v) DataTypeValidator.validate "Cell.row", Row, v; @row=v end
299
-
300
- # converts the column index into alphabetical values.
301
- # @note This follows the standard spreadsheet convention of naming columns A to Z, followed by AA to AZ etc.
302
- # @return [String]
303
- def col_ref
304
- chars = []
305
- index = self.index
306
- while index >= 26 do
307
- chars << ((index % 26) + 65).chr
308
- index /= 26
309
- end
310
- chars << ((chars.empty? ? index : index-1) + 65).chr
311
- chars.reverse.join
312
- end
313
337
 
314
- # Determines the cell type based on the cell value.
338
+ # Determines the cell type based on the cell value.
315
339
  # @note This is only used when a cell is created but no :type option is specified, the following rules apply:
316
- # 1. If the value is an instance of Time, the type is set to :time
317
- # 2. :float and :integer types are determined by regular expression matching.
318
- # 3. Anything that does not meet either of the above is determined to be :string.
340
+ # 1. If the value is an instance of Date, the type is set to :date
341
+ # 2. If the value is an instance of Time, the type is set to :time
342
+ # 3. If the value is an instance of TrueClass or FalseClass, the type is set to :boolean
343
+ # 4. :float and :integer types are determined by regular expression matching.
344
+ # 5. Anything that does not meet either of the above is determined to be :string.
319
345
  # @return [Symbol] The determined type
320
- def cell_type_from_value(v)
321
- if v.is_a? Time
346
+ def cell_type_from_value(v)
347
+ if v.is_a?(Date)
348
+ :date
349
+ elsif v.is_a?(Time)
322
350
  :time
351
+ elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
352
+ :boolean
323
353
  elsif v.to_s.match(/\A[+-]?\d+?\Z/) #numeric
324
354
  :integer
325
355
  elsif v.to_s.match(/\A[+-]?\d+\.\d+?\Z/) #float
@@ -329,22 +359,28 @@ module Axlsx
329
359
  end
330
360
  end
331
361
 
332
- # Cast the value into this cells data type.
333
- # @note
362
+ # Cast the value into this cells data type.
363
+ # @note
334
364
  # About Time - Time in OOXML is *different* from what you might expect. The history as to why is interesting, but you can safely assume that if you are generating docs on a mac, you will want to specify Workbook.1904 as true when using time typed values.
335
365
  # @see Axlsx#date1904
336
366
  def cast_value(v)
337
- if (@type == :time && v.is_a?(Time)) || (@type == :time && v.respond_to?(:to_time))
367
+ return nil if v.nil?
368
+ if @type == :date
369
+ self.style = STYLE_DATE if self.style == 0
370
+ v
371
+ elsif (@type == :time && v.is_a?(Time)) || (@type == :time && v.respond_to?(:to_time))
338
372
  self.style = STYLE_DATE if self.style == 0
339
373
  v.respond_to?(:to_time) ? v.to_time : v
340
374
  elsif @type == :float
341
375
  v.to_f
342
376
  elsif @type == :integer
343
377
  v.to_i
378
+ elsif @type == :boolean
379
+ v ? 1 : 0
344
380
  else
345
381
  @type = :string
346
- v.to_s
382
+ ::CGI.escapeHTML(v.to_s)
347
383
  end
348
- end
384
+ end
349
385
  end
350
386
  end
@@ -0,0 +1,114 @@
1
+ # encoding: UTF-8
2
+ module Axlsx
3
+
4
+ # The Col class defines column attributes for columns in sheets.
5
+ class Col
6
+
7
+ # First column affected by this 'column info' record.
8
+ # @return [Integer]
9
+ attr_reader :min
10
+
11
+ # Last column affected by this 'column info' record.
12
+ # @return [Integer]
13
+ attr_reader :max
14
+
15
+ # Flag indicating if the specified column(s) is set to 'best fit'. 'Best fit' is set to true under these conditions:
16
+ # The column width has never been manually set by the user, AND The column width is not the default width
17
+ # 'Best fit' means that when numbers are typed into a cell contained in a 'best fit' column, the column width should
18
+ # automatically resize to display the number. [Note: In best fit cases, column width must not be made smaller, only larger. end note]
19
+ # @return [Boolean]
20
+ attr_reader :bestFit
21
+
22
+ # Flag indicating if the outlining of the affected column(s) is in the collapsed state.
23
+ # @return [Boolean]
24
+ attr_reader :collapsed
25
+
26
+ # Flag indicating if the affected column(s) are hidden on this worksheet.
27
+ # @return [Boolean]
28
+ attr_reader :hidden
29
+
30
+ # Outline level of affected column(s). Range is 0 to 7.
31
+ # @return [Integer]
32
+ attr_reader :outlineLevel
33
+
34
+ # Flag indicating if the phonetic information should be displayed by default for the affected column(s) of the worksheet.
35
+ # @return [Boolean]
36
+ attr_reader :phonetic
37
+
38
+ # Default style for the affected column(s). Affects cells not yet allocated in the column(s). In other words, this style applies to new columns.
39
+ # @return [Integer]
40
+ attr_reader :style
41
+
42
+ # The width of the column
43
+ # @return [Numeric]
44
+ attr_reader :width
45
+
46
+ # @return [Boolean]
47
+ attr_reader :customWidth
48
+
49
+ # @see Col#collapsed
50
+ def collapsed=(v)
51
+ Axlsx.validate_boolean(v)
52
+ @collapsed = v
53
+ end
54
+
55
+ # @see Col#hidden
56
+ def hidden=(v)
57
+ Axlsx.validate_boolean(v)
58
+ @hidden = v
59
+ end
60
+
61
+ # @see Col#outline
62
+ def outlineLevel=(v)
63
+ Axlsx.validate_boolean(v)
64
+ @outlineLevel = v
65
+ end
66
+
67
+ # @see Col#phonetic
68
+ def phonetic=(v)
69
+ Axlsx.validate_boolean(v)
70
+ @phonetic = v
71
+ end
72
+
73
+ # @see Col#style
74
+ def style=(v)
75
+ Axlsx.validate_unsigned_int(v)
76
+ @style = v
77
+ end
78
+
79
+ # @see Col#width
80
+ def width=(v)
81
+ Axlsx.validate_unsigned_numeric(v) unless v == nil
82
+ @customWidth = @bestFit = v != nil
83
+ @width = v
84
+ end
85
+
86
+ # Create a new Col objects
87
+ # @param min First column affected by this 'column info' record.
88
+ # @param max Last column affected by this 'column info' record.
89
+ # @option options [Boolean] collapsed see Col#collapsed
90
+ # @option options [Boolean] hidden see Col#hidden
91
+ # @option options [Boolean] outlineLevel see Col#outlineLevel
92
+ # @option options [Boolean] phonetic see Col#phonetic
93
+ # @option options [Integer] style see Col#style
94
+ # @option options [Numeric] width see Col#width
95
+ def initialize(min, max, options={})
96
+ Axlsx.validate_unsigned_int(max)
97
+ Axlsx.validate_unsigned_int(min)
98
+ @min = min
99
+ @max = max
100
+ options.each do |o|
101
+ self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
102
+ end
103
+ end
104
+
105
+ # Serialize this columns data to an xml string
106
+ # @param [String] str
107
+ # @return [String]
108
+ def to_xml_string(str = '')
109
+ attrs = self.instance_values.reject{ |key, value| value == nil }
110
+ str << '<col ' << attrs.map { |key, value| '' << key << '="' << value.to_s << '"' }.join(' ') << '/>'
111
+ end
112
+
113
+ end
114
+ end
File without changes
@@ -0,0 +1,29 @@
1
+ # encoding: UTF-8
2
+ require "date"
3
+
4
+ module Axlsx
5
+ # The DateTimeConverter class converts both data and time types to their apprpriate excel serializations
6
+ class DateTimeConverter
7
+
8
+ # The date_to_serial method converts Date objects to the equivelant excel serialized forms
9
+ # @param [Date] date the date to be serialized
10
+ # @return [Numeric]
11
+ def self.date_to_serial(date)
12
+ epoch = Axlsx::Workbook::date1904 ? Date.new(1904) : Date.new(1899, 12, 30)
13
+ (date-epoch).to_f
14
+ end
15
+
16
+ # The time_to_serial methond converts a Time object its excel serialized form.
17
+ # @param [Time] time the time to be serialized
18
+ # @return [Numeric]
19
+ def self.time_to_serial(time)
20
+ # Using hardcoded offsets here as some operating systems will not except
21
+ # a 'negative' offset from the ruby epoch.
22
+ epoch1900 = -2209161600 # Time.utc(1899, 12, 30).to_i
23
+ epoch1904 = -2082844800 # Time.utc(1904, 1, 1).to_i
24
+ seconds_per_day = 86400 # 60*60*24
25
+ epoch = Axlsx::Workbook::date1904 ? epoch1904 : epoch1900
26
+ (time.to_f - epoch)/seconds_per_day
27
+ end
28
+ end
29
+ end