caxlsx 2.0.2 → 3.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (210) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +125 -30
  3. data/README.md +65 -151
  4. data/Rakefile +9 -11
  5. data/examples/{image1.jpeg → assets/image1.jpeg} +0 -0
  6. data/examples/generate.rb +15 -0
  7. data/lib/axlsx.rb +35 -17
  8. data/lib/axlsx/content_type/abstract_content_type.rb +1 -1
  9. data/lib/axlsx/content_type/content_type.rb +1 -1
  10. data/lib/axlsx/doc_props/app.rb +1 -1
  11. data/lib/axlsx/doc_props/core.rb +5 -5
  12. data/lib/axlsx/drawing/area_chart.rb +99 -0
  13. data/lib/axlsx/drawing/area_series.rb +110 -0
  14. data/lib/axlsx/drawing/axes.rb +1 -1
  15. data/lib/axlsx/drawing/axis.rb +12 -9
  16. data/lib/axlsx/drawing/bar_3D_chart.rb +13 -13
  17. data/lib/axlsx/drawing/bar_chart.rb +143 -0
  18. data/lib/axlsx/drawing/bar_series.rb +12 -14
  19. data/lib/axlsx/drawing/bubble_chart.rb +59 -0
  20. data/lib/axlsx/drawing/bubble_series.rb +63 -0
  21. data/lib/axlsx/drawing/cat_axis.rb +5 -5
  22. data/lib/axlsx/drawing/chart.rb +52 -8
  23. data/lib/axlsx/drawing/d_lbls.rb +4 -4
  24. data/lib/axlsx/drawing/drawing.rb +6 -1
  25. data/lib/axlsx/drawing/graphic_frame.rb +3 -3
  26. data/lib/axlsx/drawing/hyperlink.rb +1 -3
  27. data/lib/axlsx/drawing/line_3D_chart.rb +2 -2
  28. data/lib/axlsx/drawing/line_chart.rb +10 -10
  29. data/lib/axlsx/drawing/line_series.rb +32 -3
  30. data/lib/axlsx/drawing/marker.rb +1 -1
  31. data/lib/axlsx/drawing/num_data.rb +4 -4
  32. data/lib/axlsx/drawing/num_data_source.rb +6 -6
  33. data/lib/axlsx/drawing/num_val.rb +3 -1
  34. data/lib/axlsx/drawing/one_cell_anchor.rb +3 -2
  35. data/lib/axlsx/drawing/pic.rb +25 -19
  36. data/lib/axlsx/drawing/picture_locking.rb +1 -3
  37. data/lib/axlsx/drawing/pie_3D_chart.rb +5 -6
  38. data/lib/axlsx/drawing/pie_series.rb +6 -6
  39. data/lib/axlsx/drawing/scaling.rb +6 -6
  40. data/lib/axlsx/drawing/scatter_chart.rb +10 -10
  41. data/lib/axlsx/drawing/scatter_series.rb +40 -7
  42. data/lib/axlsx/drawing/ser_axis.rb +2 -2
  43. data/lib/axlsx/drawing/series.rb +3 -3
  44. data/lib/axlsx/drawing/series_title.rb +4 -2
  45. data/lib/axlsx/drawing/str_data.rb +3 -3
  46. data/lib/axlsx/drawing/str_val.rb +3 -1
  47. data/lib/axlsx/drawing/title.rb +23 -4
  48. data/lib/axlsx/drawing/two_cell_anchor.rb +6 -1
  49. data/lib/axlsx/drawing/val_axis.rb +1 -1
  50. data/lib/axlsx/drawing/view_3D.rb +2 -2
  51. data/lib/axlsx/drawing/vml_drawing.rb +1 -1
  52. data/lib/axlsx/package.rb +58 -47
  53. data/lib/axlsx/rels/relationship.rb +27 -26
  54. data/lib/axlsx/rels/relationships.rb +7 -4
  55. data/lib/axlsx/stylesheet/border_pr.rb +2 -2
  56. data/lib/axlsx/stylesheet/cell_alignment.rb +1 -3
  57. data/lib/axlsx/stylesheet/cell_protection.rb +1 -3
  58. data/lib/axlsx/stylesheet/cell_style.rb +1 -3
  59. data/lib/axlsx/stylesheet/color.rb +1 -3
  60. data/lib/axlsx/stylesheet/font.rb +11 -3
  61. data/lib/axlsx/stylesheet/gradient_stop.rb +1 -1
  62. data/lib/axlsx/stylesheet/num_fmt.rb +10 -3
  63. data/lib/axlsx/stylesheet/pattern_fill.rb +1 -1
  64. data/lib/axlsx/stylesheet/styles.rb +7 -7
  65. data/lib/axlsx/stylesheet/table_style_element.rb +1 -3
  66. data/lib/axlsx/util/accessors.rb +6 -6
  67. data/lib/axlsx/util/constants.rb +108 -99
  68. data/lib/axlsx/util/mime_type_utils.rb +11 -0
  69. data/lib/axlsx/util/options_parser.rb +2 -1
  70. data/lib/axlsx/util/serialized_attributes.rb +16 -6
  71. data/lib/axlsx/util/simple_typed_list.rb +28 -52
  72. data/lib/axlsx/util/storage.rb +4 -4
  73. data/lib/axlsx/util/validators.rb +31 -19
  74. data/lib/axlsx/util/zip_command.rb +73 -0
  75. data/lib/axlsx/version.rb +1 -1
  76. data/lib/axlsx/workbook/defined_name.rb +11 -12
  77. data/lib/axlsx/workbook/defined_names.rb +2 -2
  78. data/lib/axlsx/workbook/shared_strings_table.rb +5 -5
  79. data/lib/axlsx/workbook/workbook.rb +36 -20
  80. data/lib/axlsx/workbook/workbook_view.rb +80 -0
  81. data/lib/axlsx/workbook/workbook_views.rb +22 -0
  82. data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +2 -2
  83. data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +1 -3
  84. data/lib/axlsx/workbook/worksheet/break.rb +1 -3
  85. data/lib/axlsx/workbook/worksheet/cell.rb +164 -75
  86. data/lib/axlsx/workbook/worksheet/cell_serializer.rb +63 -43
  87. data/lib/axlsx/workbook/worksheet/cfvo.rb +1 -3
  88. data/lib/axlsx/workbook/worksheet/cfvos.rb +4 -1
  89. data/lib/axlsx/workbook/worksheet/col.rb +14 -13
  90. data/lib/axlsx/workbook/worksheet/col_breaks.rb +2 -2
  91. data/lib/axlsx/workbook/worksheet/cols.rb +5 -2
  92. data/lib/axlsx/workbook/worksheet/comment.rb +5 -6
  93. data/lib/axlsx/workbook/worksheet/comments.rb +9 -12
  94. data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +1 -1
  95. data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +1 -1
  96. data/lib/axlsx/workbook/worksheet/data_bar.rb +4 -6
  97. data/lib/axlsx/workbook/worksheet/data_validation.rb +8 -6
  98. data/lib/axlsx/workbook/worksheet/dimension.rb +2 -2
  99. data/lib/axlsx/workbook/worksheet/header_footer.rb +6 -8
  100. data/lib/axlsx/workbook/worksheet/icon_set.rb +3 -5
  101. data/lib/axlsx/workbook/worksheet/merged_cells.rb +4 -2
  102. data/lib/axlsx/workbook/worksheet/outline_pr.rb +33 -0
  103. data/lib/axlsx/workbook/worksheet/page_margins.rb +1 -3
  104. data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +1 -1
  105. data/lib/axlsx/workbook/worksheet/page_setup.rb +21 -23
  106. data/lib/axlsx/workbook/worksheet/pane.rb +1 -3
  107. data/lib/axlsx/workbook/worksheet/pivot_table.rb +44 -28
  108. data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +4 -4
  109. data/lib/axlsx/workbook/worksheet/print_options.rb +1 -3
  110. data/lib/axlsx/workbook/worksheet/protected_range.rb +1 -3
  111. data/lib/axlsx/workbook/worksheet/protected_ranges.rb +5 -2
  112. data/lib/axlsx/workbook/worksheet/rich_text.rb +55 -0
  113. data/lib/axlsx/workbook/worksheet/rich_text_run.rb +250 -0
  114. data/lib/axlsx/workbook/worksheet/row.rb +42 -52
  115. data/lib/axlsx/workbook/worksheet/row_breaks.rb +2 -2
  116. data/lib/axlsx/workbook/worksheet/selection.rb +1 -3
  117. data/lib/axlsx/workbook/worksheet/sheet_data.rb +3 -1
  118. data/lib/axlsx/workbook/worksheet/sheet_pr.rb +21 -3
  119. data/lib/axlsx/workbook/worksheet/sheet_protection.rb +1 -3
  120. data/lib/axlsx/workbook/worksheet/table.rb +6 -6
  121. data/lib/axlsx/workbook/worksheet/table_style_info.rb +1 -3
  122. data/lib/axlsx/workbook/worksheet/tables.rb +4 -1
  123. data/lib/axlsx/workbook/worksheet/worksheet.rb +76 -81
  124. data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +10 -10
  125. data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +3 -3
  126. data/lib/caxlsx.rb +2 -0
  127. data/test/drawing/tc_area_chart.rb +39 -0
  128. data/test/drawing/tc_area_series.rb +71 -0
  129. data/test/drawing/tc_axis.rb +27 -0
  130. data/test/drawing/tc_bar_chart.rb +71 -0
  131. data/test/drawing/tc_bubble_chart.rb +44 -0
  132. data/test/drawing/tc_bubble_series.rb +21 -0
  133. data/test/drawing/tc_chart.rb +23 -10
  134. data/test/drawing/tc_data_source.rb +6 -0
  135. data/test/drawing/tc_drawing.rb +4 -4
  136. data/test/drawing/tc_hyperlink.rb +1 -1
  137. data/test/drawing/tc_line_chart.rb +5 -5
  138. data/test/drawing/tc_line_series.rb +47 -6
  139. data/test/drawing/tc_one_cell_anchor.rb +1 -1
  140. data/test/drawing/tc_pic.rb +11 -15
  141. data/test/drawing/tc_pie_series.rb +2 -1
  142. data/test/drawing/tc_scatter_series.rb +36 -1
  143. data/test/drawing/tc_series_title.rb +21 -0
  144. data/test/drawing/tc_str_val.rb +9 -0
  145. data/test/drawing/tc_title.rb +21 -0
  146. data/test/fixtures/image1.gif +0 -0
  147. data/test/fixtures/image1.jpeg +0 -0
  148. data/test/fixtures/image1.jpg +0 -0
  149. data/test/fixtures/image1.png +0 -0
  150. data/test/fixtures/image1_fake.jpg +0 -0
  151. data/test/rels/tc_relationship.rb +8 -0
  152. data/test/stylesheet/tc_font.rb +14 -2
  153. data/test/stylesheet/tc_styles.rb +29 -3
  154. data/test/tc_axlsx.rb +37 -0
  155. data/test/tc_helper.rb +2 -0
  156. data/test/tc_package.rb +50 -13
  157. data/test/util/tc_mime_type_utils.rb +13 -0
  158. data/test/util/tc_simple_typed_list.rb +2 -3
  159. data/test/util/tc_validators.rb +35 -11
  160. data/test/workbook/tc_defined_name.rb +12 -4
  161. data/test/workbook/tc_shared_strings_table.rb +16 -1
  162. data/test/workbook/tc_workbook.rb +38 -3
  163. data/test/workbook/tc_workbook_view.rb +50 -0
  164. data/test/workbook/worksheet/auto_filter/tc_filters.rb +1 -1
  165. data/test/workbook/worksheet/tc_break.rb +1 -1
  166. data/test/workbook/worksheet/tc_cell.rb +143 -9
  167. data/test/workbook/worksheet/tc_col.rb +18 -3
  168. data/test/workbook/worksheet/tc_conditional_formatting.rb +2 -2
  169. data/test/workbook/worksheet/tc_data_bar.rb +1 -1
  170. data/test/workbook/worksheet/tc_data_validation.rb +11 -11
  171. data/test/workbook/worksheet/tc_header_footer.rb +2 -2
  172. data/test/workbook/worksheet/tc_icon_set.rb +1 -1
  173. data/test/workbook/worksheet/tc_outline_pr.rb +19 -0
  174. data/test/workbook/worksheet/tc_page_setup.rb +3 -3
  175. data/test/workbook/worksheet/tc_pivot_table.rb +21 -6
  176. data/test/workbook/worksheet/tc_print_options.rb +1 -1
  177. data/test/workbook/worksheet/tc_rich_text.rb +44 -0
  178. data/test/workbook/worksheet/tc_rich_text_run.rb +173 -0
  179. data/test/workbook/worksheet/tc_row.rb +24 -2
  180. data/test/workbook/worksheet/tc_sheet_calc_pr.rb +1 -1
  181. data/test/workbook/worksheet/tc_sheet_format_pr.rb +4 -4
  182. data/test/workbook/worksheet/tc_sheet_pr.rb +26 -4
  183. data/test/workbook/worksheet/tc_sheet_protection.rb +5 -5
  184. data/test/workbook/worksheet/tc_sheet_view.rb +4 -4
  185. data/test/workbook/worksheet/tc_table.rb +2 -3
  186. data/test/workbook/worksheet/tc_worksheet.rb +123 -60
  187. metadata +180 -128
  188. data/examples/2010_comments.rb +0 -17
  189. data/examples/anchor_swapping.rb +0 -28
  190. data/examples/auto_filter.rb +0 -16
  191. data/examples/basic_charts.rb +0 -58
  192. data/examples/chart_colors.rb +0 -88
  193. data/examples/colored_links.rb +0 -59
  194. data/examples/conditional_formatting/example_conditional_formatting.rb +0 -74
  195. data/examples/conditional_formatting/getting_barred.rb +0 -37
  196. data/examples/conditional_formatting/hitting_the_high_notes.rb +0 -37
  197. data/examples/conditional_formatting/scaled_colors.rb +0 -39
  198. data/examples/conditional_formatting/stop_and_go.rb +0 -37
  199. data/examples/data_validation.rb +0 -50
  200. data/examples/example.rb +0 -777
  201. data/examples/extractive.rb +0 -45
  202. data/examples/ios_preview.rb +0 -14
  203. data/examples/page_setup.rb +0 -11
  204. data/examples/pivot_table.rb +0 -39
  205. data/examples/sheet_protection.rb +0 -10
  206. data/examples/skydrive/real_example.rb +0 -63
  207. data/examples/styles.rb +0 -66
  208. data/examples/underline.rb +0 -13
  209. data/examples/wrap_text.rb +0 -21
  210. data/lib/axlsx/util/parser.rb +0 -44
@@ -1,5 +1,5 @@
1
1
  module Axlsx
2
2
 
3
3
  # The current version
4
- VERSION = "2.0.2"
4
+ VERSION = "3.0.4"
5
5
  end
@@ -24,16 +24,16 @@
24
24
  # </xsd:simpleContent>
25
25
 
26
26
  module Axlsx
27
- # This element defines the defined names that are defined within this workbook.
27
+ # This element defines the defined names that are defined within this workbook.
28
28
  # Defined names are descriptive text that is used to represents a cell, range of cells, formula, or constant value.
29
29
  # Use easy-to-understand names, such as Products, to refer to hard to understand ranges, such as Sales!C20:C30.
30
- # A defined name in a formula can make it easier to understand the purpose of the formula.
30
+ # A defined name in a formula can make it easier to understand the purpose of the formula.
31
31
  # @example
32
32
  # The formula =SUM(FirstQuarterSales) might be easier to identify than =SUM(C20:C30
33
33
  #
34
34
  # Names are available to any sheet.
35
35
  # @example
36
- # If the name ProjectedSales refers to the range A20:A30 on the first worksheet in a workbook,
36
+ # If the name ProjectedSales refers to the range A20:A30 on the first worksheet in a workbook,
37
37
  # you can use the name ProjectedSales on any other sheet in the same workbook to refer to range A20:A30 on the first worksheet.
38
38
  # Names can also be used to represent formulas or values that do not change (constants).
39
39
  #
@@ -71,7 +71,7 @@ module Axlsx
71
71
  # applied. This represents the source data range, unfiltered.
72
72
  # b. This defined name refers to a range to which an AutoFilter has been
73
73
  # applied.
74
- # _xlnm.Extract: this defined name refers to the range containing the filtered output
74
+ # _xlnm.Extract: this defined name refers to the range containing the filtered output
75
75
  # values resulting from applying an advanced filter criteria to a source range.
76
76
  # Miscellaneous
77
77
  # _xlnm.Consolidate_Area: the defined name refers to a consolidation area.
@@ -88,14 +88,14 @@ module Axlsx
88
88
  # This attribute is used when there is an add-in or other code project associated with the file.
89
89
  # @option [Boolean] vb_proceedure - Specifies a boolean value that indicates whether the defined name is related to an external function, command, or other executable code.
90
90
  # @option [Boolean] xlm - Specifies a boolean value that indicates whether the defined name is related to an external function, command, or other executable code.
91
- # @option [Integer] function_group_id - Specifies the function group index if the defined name refers to a function.
91
+ # @option [Integer] function_group_id - Specifies the function group index if the defined name refers to a function.
92
92
  # The function group defines the general category for the function.
93
93
  # This attribute is used when there is an add-in or other code project associated with the file.
94
94
  # See Open Office XML Part 1 for more info.
95
95
  # @option [String] short_cut_key - Specifies the keyboard shortcut for the defined name.
96
- # @option [Boolean] publish_to_server - Specifies a boolean value that indicates whether the defined name is included in the
96
+ # @option [Boolean] publish_to_server - Specifies a boolean value that indicates whether the defined name is included in the
97
97
  # version of the workbook that is published to or rendered on a Web or application server.
98
- # @option [Boolean] workbook_parameter - Specifies a boolean value that indicates that the name is used as a workbook parameter on a
98
+ # @option [Boolean] workbook_parameter - Specifies a boolean value that indicates that the name is used as a workbook parameter on a
99
99
  # version of the workbook that is published to or rendered on a Web or application server.
100
100
  def initialize(formula, options={})
101
101
  @formula = formula
@@ -116,14 +116,13 @@ module Axlsx
116
116
  boolean_attr_accessor :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden
117
117
 
118
118
  serializable_attributes :short_cut_key, :status_bar, :help, :description, :custom_menu, :comment,
119
- :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden, :name, :local_sheet_id
119
+ :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden, :local_sheet_id
120
120
 
121
121
  def to_xml_string(str='')
122
- raise ArgumentError, 'you must specify the name for this defined name. Please read the documentation for Axlsx::DefinedName for more details' unless name
123
- str << '<definedName '
122
+ raise ArgumentError, 'you must specify the name for this defined name. Please read the documentation for Axlsx::DefinedName for more details' unless name
123
+ str << ('<definedName ' << 'name="' << name << '" ')
124
124
  serialized_attributes str
125
- str << '>' << @formula
126
- str << '</definedName>'
125
+ str << ('>' << @formula << '</definedName>')
127
126
  end
128
127
  end
129
128
  end
@@ -11,8 +11,8 @@ module Axlsx
11
11
  # @param [String] str
12
12
  # @return [String]
13
13
  def to_xml_string(str = '')
14
- return if @list.empty?
15
- str << "<definedNames>"
14
+ return if empty?
15
+ str << '<definedNames>'
16
16
  each { |defined_name| defined_name.to_xml_string(str) }
17
17
  str << '</definedNames>'
18
18
  end
@@ -38,7 +38,7 @@ module Axlsx
38
38
  @xml_space = xml_space
39
39
  @unique_cells = {}
40
40
  @shared_xml_string = ""
41
- shareable_cells = cells.flatten.select{ |cell| cell.plain_string? }
41
+ shareable_cells = cells.flatten.select{ |cell| cell.plain_string? || cell.contains_rich_text? }
42
42
  @count = shareable_cells.size
43
43
  resolve(shareable_cells)
44
44
  end
@@ -47,10 +47,10 @@ module Axlsx
47
47
  # @param [String] str
48
48
  # @return [String]
49
49
  def to_xml_string(str='')
50
- str << '<?xml version="1.0" encoding="UTF-8"?><sst xmlns="' << XML_NS << '"'
51
- str << ' count="' << @count.to_s << '" uniqueCount="' << unique_count.to_s << '"'
52
- str << ' xml:space="' << xml_space.to_s << '">' << @shared_xml_string << '</sst>'
53
- str = Axlsx::sanitize(str)
50
+ Axlsx::sanitize(@shared_xml_string)
51
+ str << ('<?xml version="1.0" encoding="UTF-8"?><sst xmlns="' << XML_NS << '"')
52
+ str << (' count="' << @count.to_s << '" uniqueCount="' << unique_count.to_s << '"')
53
+ str << (' xml:space="' << xml_space.to_s << '">' << @shared_xml_string << '</sst>')
54
54
  end
55
55
 
56
56
  private
@@ -5,10 +5,13 @@ require 'axlsx/workbook/worksheet/auto_filter/auto_filter.rb'
5
5
  require 'axlsx/workbook/worksheet/date_time_converter.rb'
6
6
  require 'axlsx/workbook/worksheet/protected_range.rb'
7
7
  require 'axlsx/workbook/worksheet/protected_ranges.rb'
8
+ require 'axlsx/workbook/worksheet/rich_text_run'
9
+ require 'axlsx/workbook/worksheet/rich_text'
8
10
  require 'axlsx/workbook/worksheet/cell_serializer.rb'
9
11
  require 'axlsx/workbook/worksheet/cell.rb'
10
12
  require 'axlsx/workbook/worksheet/page_margins.rb'
11
13
  require 'axlsx/workbook/worksheet/page_set_up_pr.rb'
14
+ require 'axlsx/workbook/worksheet/outline_pr.rb'
12
15
  require 'axlsx/workbook/worksheet/page_setup.rb'
13
16
  require 'axlsx/workbook/worksheet/header_footer.rb'
14
17
  require 'axlsx/workbook/worksheet/print_options.rb'
@@ -37,7 +40,8 @@ require 'axlsx/workbook/worksheet/worksheet_hyperlinks'
37
40
  require 'axlsx/workbook/worksheet/break'
38
41
  require 'axlsx/workbook/worksheet/row_breaks'
39
42
  require 'axlsx/workbook/worksheet/col_breaks'
40
-
43
+ require 'axlsx/workbook/workbook_view'
44
+ require 'axlsx/workbook/workbook_views'
41
45
 
42
46
 
43
47
  require 'axlsx/workbook/worksheet/worksheet.rb'
@@ -93,6 +97,15 @@ require 'axlsx/workbook/worksheet/selection.rb'
93
97
  @use_shared_strings = v
94
98
  end
95
99
 
100
+ # If true reverse the order in which the workbook is serialized
101
+ # @return [Boolean]
102
+ attr_reader :is_reversed
103
+
104
+ def is_reversed=(v)
105
+ Axlsx::validate_boolean(v)
106
+ @is_reversed = v
107
+ end
108
+
96
109
 
97
110
  # A collection of worksheets associated with this workbook.
98
111
  # @note The recommended way to manage worksheets is add_worksheet
@@ -139,6 +152,10 @@ require 'axlsx/workbook/worksheet/selection.rb'
139
152
  # @return [SimpleTypedList]
140
153
  attr_reader :pivot_tables
141
154
 
155
+ # A collection of views for this workbook
156
+ def views
157
+ @views ||= WorkbookViews.new
158
+ end
142
159
 
143
160
  # A collection of defined names for this workbook
144
161
  # @note The recommended way to manage defined names is Workbook#add_defined_name
@@ -180,15 +197,6 @@ require 'axlsx/workbook/worksheet/selection.rb'
180
197
  @worksheets[index] if index
181
198
  end
182
199
 
183
- # lets come back to this later when we are ready for parsing.
184
- #def self.parse entry
185
- # io = entry.get_input_stream
186
- # w = self.new
187
- # w.parser_xml = Nokogiri::XML(io.read)
188
- # w.parse_string :date1904, "//xmlns:workbookPr/@date1904"
189
- # w
190
- #end
191
-
192
200
  # Creates a new Workbook
193
201
  # The recomended way to work with workbooks is via Package#workbook
194
202
  # @option options [Boolean] date1904. If this is not specified, date1904 is set to false. Office 2011 for Mac defaults to false.
@@ -263,6 +271,14 @@ require 'axlsx/workbook/worksheet/selection.rb'
263
271
  worksheet
264
272
  end
265
273
 
274
+ # Adds a new WorkbookView
275
+ # @return WorkbookViews
276
+ # @option options [Hash] options passed into the added WorkbookView
277
+ # @see WorkbookView#initialize
278
+ def add_view(options={})
279
+ views << WorkbookView.new(options)
280
+ end
281
+
266
282
  # Adds a defined name to this workbook
267
283
  # @return [DefinedName]
268
284
  # @param [String] formula @see DefinedName
@@ -283,7 +299,7 @@ require 'axlsx/workbook/worksheet/selection.rb'
283
299
  end
284
300
  r << Relationship.new(self, STYLES_R, STYLES_PN)
285
301
  if use_shared_strings
286
- r << Relationship.new(self, SHARED_STRINGS_R, SHARED_STRINGS_PN)
302
+ r << Relationship.new(self, SHARED_STRINGS_R, SHARED_STRINGS_PN)
287
303
  end
288
304
  r
289
305
  end
@@ -327,23 +343,23 @@ require 'axlsx/workbook/worksheet/selection.rb'
327
343
  # @param [String] str
328
344
  # @return [String]
329
345
  def to_xml_string(str='')
330
- add_worksheet unless worksheets.size > 0
346
+ add_worksheet(name: 'Sheet1') unless worksheets.size > 0
331
347
  str << '<?xml version="1.0" encoding="UTF-8"?>'
332
- str << '<workbook xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '">'
333
- str << '<workbookPr date1904="' << @@date1904.to_s << '"/>'
348
+ str << ('<workbook xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '">')
349
+ str << ('<workbookPr date1904="' << @@date1904.to_s << '"/>')
350
+ views.to_xml_string(str)
334
351
  str << '<sheets>'
335
- @worksheets.each_with_index do |sheet, index|
336
- str << '<sheet name="' << sheet.name << '" sheetId="' << (index+1).to_s << '" r:id="' << sheet.rId << '"/>'
337
- if defined_name = sheet.auto_filter.defined_name
338
- add_defined_name defined_name, :name => '_xlnm._FilterDatabase', :local_sheet_id => index, :hidden => 1
339
- end
352
+ if is_reversed
353
+ worksheets.reverse_each { |sheet| sheet.to_sheet_node_xml_string(str) }
354
+ else
355
+ worksheets.each { |sheet| sheet.to_sheet_node_xml_string(str) }
340
356
  end
341
357
  str << '</sheets>'
342
358
  defined_names.to_xml_string(str)
343
359
  unless pivot_tables.empty?
344
360
  str << '<pivotCaches>'
345
361
  pivot_tables.each do |pivot_table|
346
- str << '<pivotCache cacheId="' << pivot_table.cache_definition.cache_id.to_s << '" r:id="' << pivot_table.cache_definition.rId << '"/>'
362
+ str << ('<pivotCache cacheId="' << pivot_table.cache_definition.cache_id.to_s << '" r:id="' << pivot_table.cache_definition.rId << '"/>')
347
363
  end
348
364
  str << '</pivotCaches>'
349
365
  end
@@ -0,0 +1,80 @@
1
+ # <xsd:complexType name="CT_BookView">
2
+ # <xsd:sequence>
3
+ # <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
4
+ # </xsd:sequence>
5
+ # <xsd:attribute name="visibility" type="ST_Visibility" use="optional" default="visible"/>
6
+ # <xsd:attribute name="minimized" type="xsd:boolean" use="optional" default="false"/>
7
+ # <xsd:attribute name="showHorizontalScroll" type="xsd:boolean" use="optional" default="true"/>
8
+ # <xsd:attribute name="showVerticalScroll" type="xsd:boolean" use="optional" default="true"/>
9
+ # <xsd:attribute name="showSheetTabs" type="xsd:boolean" use="optional" default="true"/>
10
+ # <xsd:attribute name="xWindow" type="xsd:int" use="optional"/>
11
+ # <xsd:attribute name="yWindow" type="xsd:int" use="optional"/>
12
+ # <xsd:attribute name="windowWidth" type="xsd:unsignedInt" use="optional"/>
13
+ # <xsd:attribute name="windowHeight" type="xsd:unsignedInt" use="optional"/>
14
+ # <xsd:attribute name="tabRatio" type="xsd:unsignedInt" use="optional" default="600"/>
15
+ # <xsd:attribute name="firstSheet" type="xsd:unsignedInt" use="optional" default="0"/>
16
+ # <xsd:attribute name="activeTab" type="xsd:unsignedInt" use="optional" default="0"/>
17
+ # <xsd:attribute name="autoFilterDateGrouping" type="xsd:boolean" use="optional"
18
+ # default="true"/>
19
+ # </xsd:complexType>
20
+
21
+ module Axlsx
22
+
23
+ # A BookView defines the display properties for a workbook.
24
+ # Units for window widths and other dimensions are expressed in twips.
25
+ # Twip measurements are portable between different display resolutions.
26
+ # The formula is (screen pixels) * (20 * 72) / (logical device dpi),
27
+ # where the logical device dpi can be different for x and y coordinates.
28
+ class WorkbookView
29
+
30
+ include Axlsx::SerializedAttributes
31
+ include Axlsx::OptionsParser
32
+ include Axlsx::Accessors
33
+
34
+
35
+ # Creates a new BookView object
36
+ # @param [Hash] options A hash of key/value pairs that will be mapped to this instances attributes.
37
+ # @option [Symbol] visibility Specifies visible state of the workbook window. The default value for this attribute is :visible.
38
+ # @option [Boolean] minimized Specifies a boolean value that indicates whether the workbook window is minimized.
39
+ # @option [Boolean] show_horizontal_scroll Specifies a boolean value that indicates whether to display the horizontal scroll bar in the user interface.
40
+ # @option [Boolean] show_vertical_scroll Specifies a boolean value that indicates whether to display the vertical scroll bar.
41
+ # @option [Boolean] show_sheet_tabs Specifies a boolean value that indicates whether to display the sheet tabs in the user interface.
42
+ # @option [Integer] tab_ratio Specifies ratio between the workbook tabs bar and the horizontal scroll bar.
43
+ # @option [Integer] first_sheet Specifies the index to the first sheet in this book view.
44
+ # @option [Integer] active_tab Specifies an unsignedInt that contains the index to the active sheet in this book view.
45
+ # @option [Integer] x_window Specifies the X coordinate for the upper left corner of the workbook window. The unit of measurement for this value is twips.
46
+ # @option [Integer] y_window Specifies the Y coordinate for the upper left corner of the workbook window. The unit of measurement for this value is twips.
47
+ # @option [Integer] window_width Specifies the width of the workbook window. The unit of measurement for this value is twips.
48
+ # @option [Integer] window_height Specifies the height of the workbook window. The unit of measurement for this value is twips.
49
+ # @option [Boolean] auto_filter_date_grouping Specifies a boolean value that indicates whether to group dates when presenting the user with filtering options in the user interface.
50
+ def initialize(options={})
51
+ parse_options options
52
+ yield self if block_given?
53
+ end
54
+
55
+
56
+ unsigned_int_attr_accessor :x_window, :y_window, :window_width, :window_height,
57
+ :tab_ratio, :first_sheet, :active_tab
58
+
59
+ validated_attr_accessor [:visibility], :validate_view_visibility
60
+
61
+ serializable_attributes :visibility, :minimized,
62
+ :show_horizontal_scroll, :show_vertical_scroll,
63
+ :show_sheet_tabs, :tab_ratio, :first_sheet, :active_tab,
64
+ :x_window, :y_window, :window_width, :window_height,
65
+ :auto_filter_date_grouping
66
+
67
+ boolean_attr_accessor :minimized, :show_horizontal_scroll, :show_vertical_scroll,
68
+ :show_sheet_tabs, :auto_filter_date_grouping
69
+
70
+
71
+ # Serialize the WorkbookView
72
+ # @param [String] str
73
+ # @return [String]
74
+ def to_xml_string(str = '')
75
+ str << '<workbookView '
76
+ serialized_attributes str
77
+ str << '></workbookView>'
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,22 @@
1
+ module Axlsx
2
+ # a simple types list of BookView objects
3
+ class WorkbookViews < SimpleTypedList
4
+
5
+ # creates the book views object
6
+ def initialize
7
+ super WorkbookView
8
+ end
9
+
10
+ # Serialize to xml
11
+ # @param [String] str
12
+ # @return [String]
13
+ def to_xml_string(str = '')
14
+ return if empty?
15
+ str << "<bookViews>"
16
+ each { |view| view.to_xml_string(str) }
17
+ str << '</bookViews>'
18
+ end
19
+ end
20
+ end
21
+
22
+
@@ -47,8 +47,8 @@ module Axlsx
47
47
  columns.last
48
48
  end
49
49
 
50
- # actually performs the filtering of rows who's cells do not
51
- # match the filter.
50
+ # actually performs the filtering of rows who's cells do not
51
+ # match the filter.
52
52
  def apply
53
53
  first_cell, last_cell = range.split(':')
54
54
  start_point = Axlsx::name_to_indices(first_cell)
@@ -237,9 +237,7 @@ include Axlsx::SerializedAttributes
237
237
  # Serialize the object to xml
238
238
  # @param [String] str The string object this serialization will be concatenated to.
239
239
  def to_xml_string(str = '')
240
- str << '<dateGroupItem '
241
- serialized_attributes str
242
- str << '/>'
240
+ serialized_tag('dateGroupItem', str)
243
241
  end
244
242
  end
245
243
  end
@@ -28,9 +28,7 @@ module Axlsx
28
28
 
29
29
  # serializes the break to xml
30
30
  def to_xml_string(str='')
31
- str << '<brk '
32
- serialized_attributes str
33
- str << '></brk>'
31
+ serialized_tag('brk', str)
34
32
  end
35
33
  end
36
34
  end
@@ -12,7 +12,7 @@ module Axlsx
12
12
 
13
13
  # @param [Row] row The row this cell belongs to.
14
14
  # @param [Any] value The value associated with this cell.
15
- # @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.
15
+ # @option options [Symbol] type The intended data type for this cell. If not specified the data type will be determined internally based on the value provided.
16
16
  # @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.
17
17
  # @option options [String] font_name
18
18
  # @option options [Integer] charset
@@ -30,17 +30,30 @@ module Axlsx
30
30
  # @option options [String] color an 8 letter rgb specification
31
31
  # @option options [Number] formula_value The value to cache for a formula cell.
32
32
  # @option options [Symbol] scheme must be one of :none, major, :minor
33
- def initialize(row, value="", options={})
34
- self.row=row
35
- @value = nil
36
- #@value = @font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
37
- #@formula_value = @condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil
38
- @styles = row.worksheet.workbook.styles
39
- @row.cells << self
40
- parse_options options
41
- @style ||= 0
42
- @type ||= cell_type_from_value(value)
43
- @value = cast_value(value)
33
+ # @option options [Boolean] escape_formulas - Whether to treat a value starting with an equal
34
+ # sign as formula (default) or as simple string.
35
+ # Allowing user generated data to be interpreted as formulas can be dangerous
36
+ # (see https://www.owasp.org/index.php/CSV_Injection for details).
37
+ def initialize(row, value = nil, options = {})
38
+ @row = row
39
+ # Do not use instance vars if not needed to use less RAM
40
+ # And do not call parse_options on frequently used options
41
+ # to get less GC cycles
42
+ type = options.delete(:type) || cell_type_from_value(value)
43
+ self.type = type unless type == :string
44
+
45
+ escape_formulas = options[:escape_formulas]
46
+ self.escape_formulas = escape_formulas unless escape_formulas.nil?
47
+
48
+ val = options.delete(:style)
49
+ self.style = val unless val.nil? || val == 0
50
+ val = options.delete(:formula_value)
51
+ self.formula_value = val unless val.nil?
52
+
53
+ parse_options(options)
54
+
55
+ self.value = value
56
+ value.cell = self if contains_rich_text?
44
57
  end
45
58
 
46
59
  # this is the cached value for formula cells. If you want the values to render in iOS/Mac OSX preview
@@ -53,21 +66,27 @@ module Axlsx
53
66
  # needs to define bla=(v) and bla methods on the class that hook into a
54
67
  # set_attr method that kicks the suplied validator and updates the instance_variable
55
68
  # for the key
56
- INLINE_STYLES = ['value', 'type', 'font_name', 'charset',
57
- 'family', 'b', 'i', 'strike','outline',
58
- 'shadow', 'condense', 'extend', 'u',
59
- 'vertAlign', 'sz', 'color', 'scheme']
69
+ INLINE_STYLES = [:value, :type, :font_name, :charset,
70
+ :family, :b, :i, :strike, :outline,
71
+ :shadow, :condense, :extend, :u,
72
+ :vertAlign, :sz, :color, :scheme].freeze
73
+
74
+ # An array of valid cell types
75
+ CELL_TYPES = [:date, :time, :float, :integer, :richtext,
76
+ :string, :boolean, :iso_8601, :text].freeze
60
77
 
61
78
  # The index of the cellXfs item to be applied to this cell.
62
79
  # @return [Integer]
63
80
  # @see Axlsx::Styles
64
- attr_reader :style
81
+ def style
82
+ defined?(@style) ? @style : 0
83
+ end
65
84
 
66
85
  # The row this cell belongs to.
67
86
  # @return [Row]
68
87
  attr_reader :row
69
88
 
70
- # The cell's data type. Currently only six types are supported, :date, :time, :float, :integer, :string and :boolean.
89
+ # The cell's data type.
71
90
  # 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
72
91
  # automatically determed.
73
92
  # @see Cell#cell_type_from_value
@@ -78,18 +97,33 @@ module Axlsx
78
97
  # :string to :integer or :float, type conversions always return 0 or 0.0
79
98
  # :string, :integer, or :float to :time conversions always return the original value as a string and set the cells type to :string.
80
99
  # No support is currently implemented for parsing time strings.
81
- attr_reader :type
100
+ def type
101
+ defined?(@type) ? @type : :string
102
+ end
103
+
82
104
  # @see type
83
105
  def type=(v)
84
- RestrictionValidator.validate "Cell.type", [:date, :time, :float, :integer, :string, :boolean, :iso_8601], v
85
- @type=v
86
- self.value = @value unless @value.nil?
106
+ RestrictionValidator.validate :cell_type, CELL_TYPES, v
107
+ @type = v
108
+ self.value = @value unless !defined?(@value) || @value.nil?
87
109
  end
88
110
 
111
+ # Whether to treat a value starting with an equal
112
+ # sign as formula (default) or as simple string.
113
+ # Allowing user generated data to be interpreted as formulas can be dangerous
114
+ # (see https://www.owasp.org/index.php/CSV_Injection for details).
115
+ # @return [Boolean]
116
+ attr_reader :escape_formulas
117
+
118
+ def escape_formulas=(v)
119
+ Axlsx.validate_boolean(v)
120
+ @escape_formulas = v
121
+ end
89
122
 
90
123
  # The value of this cell.
91
124
  # @return [String, Integer, Float, Time, Boolean] casted value based on cell's type attribute.
92
125
  attr_reader :value
126
+
93
127
  # @see value
94
128
  def value=(v)
95
129
  #TODO: consider doing value based type determination first?
@@ -99,16 +133,20 @@ module Axlsx
99
133
  # Indicates that the cell has one or more of the custom cell styles applied.
100
134
  # @return [Boolean]
101
135
  def is_text_run?
102
- @is_text_run ||= false
136
+ defined?(@is_text_run) && @is_text_run && !contains_rich_text?
137
+ end
138
+
139
+ def contains_rich_text?
140
+ type == :richtext
103
141
  end
104
142
 
105
143
  # Indicates if the cell is good for shared string table
106
144
  def plain_string?
107
- @type == :string && # String typed
145
+ (type == :string || type == :text) && # String typed
108
146
  !is_text_run? && # No inline styles
109
147
  !@value.nil? && # Not nil
110
148
  !@value.empty? && # Not empty
111
- !@value.start_with?('=') # Not a formula
149
+ !@value.start_with?(?=) # Not a formula
112
150
  end
113
151
 
114
152
  # The inline font_name property for the cell
@@ -231,7 +269,7 @@ module Axlsx
231
269
  attr_reader :vertAlign
232
270
  # @see vertAlign
233
271
  def vertAlign=(v)
234
- RestrictionValidator.validate "Cell.vertAlign", [:baseline, :subscript, :superscript], v
272
+ RestrictionValidator.validate :cell_vertAlign, [:baseline, :subscript, :superscript], v
235
273
  set_run_style nil, :vertAlign, v
236
274
  end
237
275
 
@@ -241,7 +279,7 @@ module Axlsx
241
279
  attr_reader :scheme
242
280
  # @see scheme
243
281
  def scheme=(v)
244
- RestrictionValidator.validate "Cell.schema", [:none, :major, :minor], v
282
+ RestrictionValidator.validate :cell_scheme, [:none, :major, :minor], v
245
283
  set_run_style nil, :scheme, v
246
284
  end
247
285
 
@@ -251,14 +289,14 @@ module Axlsx
251
289
 
252
290
  # @return [Integer] The index of the cell in the containing row.
253
291
  def index
254
- @row.cells.index(self)
292
+ @row.index(self)
255
293
  end
256
294
 
257
295
  # @return [String] The alpha(column)numeric(row) reference for this sell.
258
296
  # @example Relative Cell Reference
259
297
  # ws.rows.first.cells.first.r #=> "A1"
260
298
  def r
261
- Axlsx::cell_r index, @row.index
299
+ Axlsx::cell_r index, @row.row_index
262
300
  end
263
301
 
264
302
  # @return [String] The absolute alpha(column)numeric(row) reference for this sell.
@@ -272,26 +310,26 @@ module Axlsx
272
310
  # @raise [ArgumentError] Invalid cellXfs id if the value provided is not within cellXfs items range.
273
311
  def style=(v)
274
312
  Axlsx::validate_unsigned_int(v)
275
- count = @styles.cellXfs.size
313
+ count = styles.cellXfs.size
276
314
  raise ArgumentError, "Invalid cellXfs id" unless v < count
277
315
  @style = v
278
316
  end
279
317
 
280
- # @return [Array] of x/y coordinates in the cheet for this cell.
318
+ # @return [Array] of x/y coordinates in the sheet for this cell.
281
319
  def pos
282
- [index, row.index]
320
+ [index, row.row_index]
283
321
  end
284
322
 
285
323
  # Merges all the cells in a range created between this cell and the cell or string name for a cell provided
286
324
  # @see worksheet.merge_cells
287
325
  # @param [Cell, String] target The last cell, or str ref for the cell in the merge range
288
326
  def merge(target)
289
- range_end = if target.is_a?(String)
290
- target
291
- elsif(target.is_a?(Cell))
292
- target.r
293
- end
294
- self.row.worksheet.merge_cells "#{self.r}:#{range_end}" unless range_end.nil?
327
+ start, stop = if target.is_a?(String)
328
+ [self.r, target]
329
+ elsif(target.is_a?(Cell))
330
+ Axlsx.sort_cells([self, target]).map { |c| c.r }
331
+ end
332
+ self.row.worksheet.merge_cells "#{start}:#{stop}" unless stop.nil?
295
333
  end
296
334
 
297
335
  # Serializes the cell
@@ -304,17 +342,13 @@ module Axlsx
304
342
  end
305
343
 
306
344
  def is_formula?
307
- @type == :string && @value.to_s.start_with?('=')
345
+ return false if escape_formulas
346
+
347
+ type == :string && @value.to_s.start_with?(?=)
308
348
  end
309
349
 
310
- # This is still not perfect...
311
- # - scaling is not linear as font sizes increst
312
- # - different fonts have different mdw and char widths
313
- def autowidth
314
- return if is_formula? || value == nil
315
- mdw = 1.78 #This is the widest width of 0..9 in arial@10px)
316
- font_scale = (font_size/10.0).to_f
317
- ((value.to_s.count(Worksheet.thin_chars) * mdw + 5) / mdw * 256) / 256.0 * font_scale
350
+ def is_array_formula?
351
+ type == :string && @value.to_s.start_with?('{=') && @value.to_s.end_with?('}')
318
352
  end
319
353
 
320
354
  # returns the absolute or relative string style reference for
@@ -326,21 +360,72 @@ module Axlsx
326
360
  absolute ? r_abs : r
327
361
  end
328
362
 
363
+ # Creates a defined name in the workbook for this cell.
364
+ def name=(label)
365
+ row.worksheet.workbook.add_defined_name "#{row.worksheet.name}!#{r_abs}", name: label
366
+ @name = label
367
+ end
368
+
369
+ # returns the name of the cell
370
+ attr_reader :name
371
+
372
+ # Attempts to determine the correct width for this cell's content
373
+ # @return [Float]
374
+ def autowidth
375
+ return if is_formula? || value.nil?
376
+
377
+ if contains_rich_text?
378
+ string_width('', font_size) + value.autowidth
379
+ elsif styles.cellXfs[style].alignment && styles.cellXfs[style].alignment.wrap_text
380
+ max_width = 0
381
+ value.to_s.split(/\r?\n/).each do |line|
382
+ width = string_width(line, font_size)
383
+ max_width = width if width > max_width
384
+ end
385
+ max_width
386
+ else
387
+ string_width(value, font_size)
388
+ end
389
+ end
390
+
391
+ # Returns the sanatized value
392
+ # TODO find a better way to do this as it accounts for 30% of
393
+ # processing time in benchmarking...
394
+ def clean_value
395
+ if (type == :string || type == :text) && !Axlsx::trust_input
396
+ Axlsx::sanitize(::CGI.escapeHTML(@value.to_s))
397
+ else
398
+ @value.to_s
399
+ end
400
+ end
401
+
329
402
  private
330
403
 
404
+ def styles
405
+ row.worksheet.styles
406
+ end
407
+
408
+ # Returns the width of a string according to the current style
409
+ # This is still not perfect...
410
+ # - scaling is not linear as font sizes increase
411
+ def string_width(string, font_size)
412
+ font_scale = font_size / 10.0
413
+ (string.to_s.size + 3) * font_scale
414
+ end
415
+
331
416
  # we scale the font size if bold style is applied to either the style font or
332
417
  # the cell itself. Yes, it is a bit of a hack, but it is much better than using
333
418
  # imagemagick and loading metrics for every character.
334
419
  def font_size
335
- font = @styles.fonts[@styles.cellXfs[style].fontId] || @styles.fonts[0]
336
- size_from_styles = (font.b || b) ? font.sz * 1.5 : font.sz
337
- sz || size_from_styles
420
+ return sz if sz
421
+ font = styles.fonts[styles.cellXfs[style].fontId] || styles.fonts[0]
422
+ (font.b || (defined?(@b) && @b)) ? (font.sz * 1.5) : font.sz
338
423
  end
339
424
 
340
425
  # Utility method for setting inline style attributes
341
- def set_run_style( validator, attr, value)
342
- return unless INLINE_STYLES.include?(attr.to_s)
343
- Axlsx.send(validator, value) unless validator == nil
426
+ def set_run_style(validator, attr, value)
427
+ return unless INLINE_STYLES.include?(attr.to_sym)
428
+ Axlsx.send(validator, value) unless validator.nil?
344
429
  self.instance_variable_set :"@#{attr.to_s}", value
345
430
  @is_text_run = true
346
431
  end
@@ -351,9 +436,6 @@ module Axlsx
351
436
  @ssti = v
352
437
  end
353
438
 
354
- # assigns the owning row for this cell.
355
- def row=(v) @row=v end
356
-
357
439
  # Determines the cell type based on the cell value.
358
440
  # @note This is only used when a cell is created but no :type option is specified, the following rules apply:
359
441
  # 1. If the value is an instance of Date, the type is set to :date
@@ -369,15 +451,16 @@ module Axlsx
369
451
  :time
370
452
  elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
371
453
  :boolean
372
- elsif v.to_s =~ /\A[+-]?\d+?\Z/ #numeric
454
+ elsif v.to_s =~ Axlsx::NUMERIC_REGEX && v.respond_to?(:to_i)
373
455
  :integer
374
- elsif v.to_s =~ /\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\Z/ #float
456
+ elsif v.to_s =~ Axlsx::SAFE_FLOAT_REGEX && v.respond_to?(:to_f)
375
457
  :float
376
- # \A(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])
377
- # T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?
378
- # (Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?\Z
379
- elsif v.to_s =~/\A(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?\Z/
458
+ elsif (matchdata = v.to_s.match(MAYBE_FLOAT_REGEX)) && (Float::MIN_10_EXP..Float::MAX_10_EXP).cover?(matchdata[:exp].to_i) && v.respond_to?(:to_f)
459
+ :float
460
+ elsif v.to_s =~ Axlsx::ISO_8601_REGEX
380
461
  :iso_8601
462
+ elsif v.is_a? RichText
463
+ :richtext
381
464
  else
382
465
  :string
383
466
  end
@@ -388,27 +471,33 @@ module Axlsx
388
471
  # 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.
389
472
  # @see Axlsx#date1904
390
473
  def cast_value(v)
391
- return nil if v.nil?
392
- if @type == :date
474
+ return v if v.is_a?(RichText) || v.nil?
475
+ case type
476
+ when :date
393
477
  self.style = STYLE_DATE if self.style == 0
394
- v
395
- elsif (@type == :time && v.is_a?(Time)) || (@type == :time && v.respond_to?(:to_time))
478
+ if !v.is_a?(Date) && v.respond_to?(:to_date)
479
+ v.to_date
480
+ else
481
+ v
482
+ end
483
+ when :time
396
484
  self.style = STYLE_DATE if self.style == 0
397
- v.respond_to?(:to_time) ? v.to_time : v
398
- elsif @type == :float
485
+ if !v.is_a?(Time) && v.respond_to?(:to_time)
486
+ v.to_time
487
+ else
488
+ v
489
+ end
490
+ when :float
399
491
  v.to_f
400
- elsif @type == :integer
492
+ when :integer
401
493
  v.to_i
402
- elsif @type == :boolean
494
+ when :boolean
403
495
  v ? 1 : 0
404
- elsif @type == :iso_8601
496
+ when :iso_8601
405
497
  #consumer is responsible for ensuring the iso_8601 format when specifying this type
406
498
  v
407
499
  else
408
- @type = :string
409
- # TODO find a better way to do this as it accounts for 30% of
410
- # processing time in benchmarking...
411
- Axlsx::trust_input ? v.to_s : ::CGI.escapeHTML(v.to_s)
500
+ v.to_s
412
501
  end
413
502
  end
414
503