caxlsx 2.0.2 → 3.0.4

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 (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