write_xlsx 1.08.1 → 1.09.2

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +10 -0
  3. data/Changes +17 -0
  4. data/README.md +1 -1
  5. data/examples/background.rb +19 -0
  6. data/examples/ignore_errors.rb +39 -0
  7. data/examples/keep_leading_zeros.rb +17 -0
  8. data/lib/write_xlsx/chart/axis.rb +3 -3
  9. data/lib/write_xlsx/chart/scatter.rb +0 -15
  10. data/lib/write_xlsx/chart/series.rb +1 -1
  11. data/lib/write_xlsx/chart.rb +28 -28
  12. data/lib/write_xlsx/chartsheet.rb +3 -3
  13. data/lib/write_xlsx/drawing.rb +39 -39
  14. data/lib/write_xlsx/format.rb +11 -179
  15. data/lib/write_xlsx/package/app.rb +2 -2
  16. data/lib/write_xlsx/package/button.rb +8 -8
  17. data/lib/write_xlsx/package/comments.rb +8 -8
  18. data/lib/write_xlsx/package/content_types.rb +18 -9
  19. data/lib/write_xlsx/package/core.rb +5 -5
  20. data/lib/write_xlsx/package/custom.rb +2 -2
  21. data/lib/write_xlsx/package/metadata.rb +159 -0
  22. data/lib/write_xlsx/package/packager.rb +21 -0
  23. data/lib/write_xlsx/package/shared_strings.rb +6 -6
  24. data/lib/write_xlsx/package/styles.rb +11 -11
  25. data/lib/write_xlsx/package/table.rb +23 -23
  26. data/lib/write_xlsx/package/theme.rb +1 -1
  27. data/lib/write_xlsx/package/vml.rb +43 -43
  28. data/lib/write_xlsx/shape.rb +17 -15
  29. data/lib/write_xlsx/sparkline.rb +340 -340
  30. data/lib/write_xlsx/utility.rb +4 -23
  31. data/lib/write_xlsx/version.rb +1 -1
  32. data/lib/write_xlsx/workbook.rb +171 -644
  33. data/lib/write_xlsx/worksheet/cell_data.rb +25 -3
  34. data/lib/write_xlsx/worksheet/data_validation.rb +20 -20
  35. data/lib/write_xlsx/worksheet/hyperlink.rb +4 -4
  36. data/lib/write_xlsx/worksheet/page_setup.rb +12 -12
  37. data/lib/write_xlsx/worksheet.rb +267 -4144
  38. data/test/perl_output/background.xlsx +0 -0
  39. data/test/perl_output/ignore_errors.xlsx +0 -0
  40. data/test/perl_output/keep_leading_zeros.xlsx +0 -0
  41. data/test/perl_output/multi_line.xlsx +0 -0
  42. data/test/regression/images/logo.gif +0 -0
  43. data/test/regression/images/logo.jpg +0 -0
  44. data/test/regression/images/red.gif +0 -0
  45. data/test/regression/test_background01.rb +23 -0
  46. data/test/regression/test_background02.rb +23 -0
  47. data/test/regression/test_background03.rb +24 -0
  48. data/test/regression/test_background04.rb +25 -0
  49. data/test/regression/test_background05.rb +25 -0
  50. data/test/regression/test_background06.rb +31 -0
  51. data/test/regression/test_background07.rb +37 -0
  52. data/test/regression/test_chart_axis47.rb +52 -0
  53. data/test/regression/test_chart_axis48.rb +53 -0
  54. data/test/regression/test_dynamic_array01.rb +25 -0
  55. data/test/regression/test_image56.rb +23 -0
  56. data/test/regression/test_image57.rb +23 -0
  57. data/test/regression/test_set_column10.rb +55 -0
  58. data/test/regression/test_set_column11.rb +48 -0
  59. data/test/regression/test_set_row01.rb +35 -0
  60. data/test/regression/test_set_row02.rb +35 -0
  61. data/test/regression/test_set_row03.rb +35 -0
  62. data/test/regression/test_set_row04.rb +35 -0
  63. data/test/regression/xlsx_files/background01.xlsx +0 -0
  64. data/test/regression/xlsx_files/background02.xlsx +0 -0
  65. data/test/regression/xlsx_files/background03.xlsx +0 -0
  66. data/test/regression/xlsx_files/background04.xlsx +0 -0
  67. data/test/regression/xlsx_files/background05.xlsx +0 -0
  68. data/test/regression/xlsx_files/background06.xlsx +0 -0
  69. data/test/regression/xlsx_files/background07.xlsx +0 -0
  70. data/test/regression/xlsx_files/chart_axis47.xlsx +0 -0
  71. data/test/regression/xlsx_files/chart_axis48.xlsx +0 -0
  72. data/test/regression/xlsx_files/dynamic_array01.xlsx +0 -0
  73. data/test/regression/xlsx_files/image56.xlsx +0 -0
  74. data/test/regression/xlsx_files/image57.xlsx +0 -0
  75. data/test/regression/xlsx_files/set_row01.xlsx +0 -0
  76. data/test/regression/xlsx_files/set_row03.xlsx +0 -0
  77. data/test/test_example_match.rb +73 -0
  78. data/test/worksheet/test_pixels_to_row_col.rb +46 -0
  79. metadata +86 -2
@@ -2,177 +2,20 @@
2
2
  require 'write_xlsx/utility'
3
3
 
4
4
  module Writexlsx
5
- # ==CELL FORMATTING
6
- #
7
- # This section describes the methods and properties that are available
8
- # for formatting cells in Excel. The properties of a cell that can be
9
- # formatted include: fonts, colours, patterns, borders, alignment and
10
- # number formatting.
11
- #
12
- # ===Creating and using a Format object
13
- #
14
- # Cell formatting is defined through a Format object. Format objects
15
- # are created by calling the workbook add_format() method as follows:
16
- #
17
- # format1 = workbook.add_format # Set properties later
18
- # format2 = workbook.add_format(props_hash) # Set at creation
19
- #
20
- # The format object holds all the formatting properties that can be applied
21
- # to a cell, a row or a column. The process of setting these properties is
22
- # discussed in the next section.
23
- #
24
- # Once a Format object has been constructed and its properties have been
25
- # set it can be passed as an argument to the worksheet write methods as
26
- # follows:
27
- #
28
- # worksheet.write( 0, 0, 'One', format )
29
- # worksheet.write_string( 1, 0, 'Two', format )
30
- # worksheet.write_number( 2, 0, 3, format )
31
- # worksheet.write_blank( 3, 0, format )
32
- #
33
- # Formats can also be passed to the worksheet set_row() and set_column()
34
- # methods to define the default property for a row or column.
35
- #
36
- # worksheet.set_row( 0, 15, format )
37
- # worksheet.set_column( 0, 0, 15, format )
38
- #
39
- # ===Format methods and Format properties
40
- #
41
- # The following table shows the Excel format categories, the formatting
42
- # properties that can be applied and the equivalent object method:
43
- #
44
- # Category Description Property Method Name
45
- # -------- ----------- -------- -----------
46
- # Font Font type font set_font()
47
- # Font size size set_size()
48
- # Font color color set_color()
49
- # Bold bold set_bold()
50
- # Italic italic set_italic()
51
- # Underline underline set_underline()
52
- # Strikeout font_strikeout set_font_strikeout()
53
- # Super/Subscript font_script set_font_script()
54
- # Outline font_outline set_font_outline()
55
- # Shadow font_shadow set_font_shadow()
56
- #
57
- # Number Numeric format num_format set_num_format()
58
- #
59
- # Protection Lock cells locked set_locked()
60
- # Hide formulas hidden set_hidden()
61
- #
62
- # Alignment Horizontal align align set_align()
63
- # Vertical align valign set_align()
64
- # Rotation rotation set_rotation()
65
- # Text wrap text_wrap set_text_wrap()
66
- # Justify last text_justlast set_text_justlast()
67
- # Center across center_across set_center_across()
68
- # Indentation indent set_indent()
69
- # Shrink to fit shrink set_shrink()
70
- #
71
- # Pattern Cell pattern pattern set_pattern()
72
- # Background color bg_color set_bg_color()
73
- # Foreground color fg_color set_fg_color()
74
- #
75
- # Border Cell border border set_border()
76
- # Bottom border bottom set_bottom()
77
- # Top border top set_top()
78
- # Left border left set_left()
79
- # Right border right set_right()
80
- # Border color border_color set_border_color()
81
- # Bottom color bottom_color set_bottom_color()
82
- # Top color top_color set_top_color()
83
- # Left color left_color set_left_color()
84
- # Right color right_color set_right_color()
85
- #
86
- # There are two ways of setting Format properties: by using the object
87
- # method interface or by setting the property directly. For example,
88
- # a typical use of the method interface would be as follows:
89
- #
90
- # format = workbook.add_format
91
- # format.set_bold
92
- # format.set_color( 'red' )
93
- #
94
- # By comparison the properties can be set directly by passing a hash
95
- # of properties to the Format constructor:
96
- #
97
- # format = workbook.add_format( :bold => 1, :color => 'red' )
98
- #
99
- # or after the Format has been constructed by means of the
100
- # set_format_properties() method as follows:
101
- #
102
- # format = workbook.add_format
103
- # format.set_format_properties( :bold => 1, :color => 'red' )
104
- #
105
- # You can also store the properties in one or more named hashes and pass
106
- # them to the required method:
107
- #
108
- # font = {
109
- # :font => 'Arial',
110
- # :size => 12,
111
- # :color => 'blue',
112
- # :bold => 1
113
- # }
114
- #
115
- # shading = {
116
- # :bg_color => 'green',
117
- # :pattern => 1
118
- # }
119
- #
120
- # format1 = workbook.add_format( font ) # Font only
121
- # format2 = workbook.add_format( font, shading ) # Font and shading
122
- #
123
- # The provision of two ways of setting properties might lead you to wonder
124
- # which is the best way. The method mechanism may be better is you prefer
125
- # setting properties via method calls (which the author did when the code
126
- # was first written) otherwise passing properties to the constructor has
127
- # proved to be a little more flexible and self documenting in practice.
128
- # An additional advantage of working with property hashes is that it allows
129
- # you to share formatting between workbook objects as shown in the example
130
- # above.
131
- #
132
- # ===Working with formats
133
- #
134
- # The default format is Arial 10 with all other properties off.
135
- #
136
- # Each unique format in WriteXLSX must have a corresponding Format
137
- # object. It isn't possible to use a Format with a write() method and then
138
- # redefine the Format for use at a later stage. This is because a Format
139
- # is applied to a cell not in its current state but in its final state.
140
- # Consider the following example:
141
- #
142
- # format = workbook.add_format
143
- # format.set_bold
144
- # format.set_color( 'red' )
145
- # worksheet.write( 'A1', 'Cell A1', format )
146
- # format.set_color( 'green' )
147
- # worksheet.write( 'B1', 'Cell B1', format )
148
- #
149
- # Cell A1 is assigned the Format format which is initially set to the colour
150
- # red. However, the colour is subsequently set to green. When Excel displays
151
- # Cell A1 it will display the final state of the Format which in this case
152
- # will be the colour green.
153
- #
154
- # In general a method call without an argument will turn a property on,
155
- # for example:
156
- #
157
- # format1 = workbook.add_format
158
- # format1.set_bold # Turns bold on
159
- # format1.set_bold( 1 ) # Also turns bold on
160
- # format1.set_bold( 0 ) # Turns bold off
161
- #
162
5
  class Format
163
6
  include Writexlsx::Utility
164
7
 
165
- attr_reader :xf_index, :dxf_index, :num_format # :nodoc:
8
+ attr_reader :xf_index, :dxf_index, :num_format # :nodoc:
166
9
  attr_reader :underline, :font_script, :size, :theme, :font, :font_family, :hyperlink, :xf_id # :nodoc:
167
- attr_reader :diag_type, :diag_color, :font_only, :color, :color_indexed # :nodoc:
168
- attr_reader :left, :left_color, :right, :right_color, :top, :top_color, :bottom, :bottom_color # :nodoc:
169
- attr_reader :font_scheme # :nodoc:
170
- attr_accessor :num_format_index, :border_index, :font_index # :nodoc:
171
- attr_accessor :fill_index, :font_condense, :font_extend, :diag_border # :nodoc:
172
- attr_accessor :bg_color, :fg_color, :pattern # :nodoc:
10
+ attr_reader :diag_type, :diag_color, :font_only, :color, :color_indexed # :nodoc:
11
+ attr_reader :left, :left_color, :right, :right_color, :top, :top_color, :bottom, :bottom_color # :nodoc:
12
+ attr_reader :font_scheme # :nodoc:
13
+ attr_accessor :num_format_index, :border_index, :font_index # :nodoc:
14
+ attr_accessor :fill_index, :font_condense, :font_extend, :diag_border # :nodoc:
15
+ attr_accessor :bg_color, :fg_color, :pattern # :nodoc:
173
16
 
174
- attr_accessor :dxf_bg_color, :dxf_fg_color # :nodoc:
175
- attr_reader :rotation, :bold, :italic, :font_strikeout
17
+ attr_accessor :dxf_bg_color, :dxf_fg_color # :nodoc:
18
+ attr_reader :rotation, :bold, :italic, :font_strikeout # :nodoc:
176
19
 
177
20
  def initialize(formats, params = {}) # :nodoc:
178
21
  @formats = formats
@@ -268,17 +111,6 @@ module Writexlsx
268
111
  #
269
112
  # Convert hashes of properties to method calls.
270
113
  #
271
- # The properties of an existing Format object can be also be set by means
272
- # of set_format_properties():
273
- #
274
- # format = workbook.add_format
275
- # format.set_format_properties(:bold => 1, :color => 'red');
276
- #
277
- # However, this method is here mainly for legacy reasons. It is preferable
278
- # to set the properties in the format constructor:
279
- #
280
- # format = workbook.add_format(:bold => 1, :color => 'red');
281
- #
282
114
  def set_format_properties(*properties) # :nodoc:
283
115
  return if properties.empty?
284
116
  properties.each do |property|
@@ -747,7 +579,7 @@ module Writexlsx
747
579
  writer.empty_tag('sz', [ ['val', size] ]) unless dxf_format
748
580
 
749
581
  if theme == -1
750
- # Ignore for excel2003_style
582
+ # Ignore for excel2003_style
751
583
  elsif ptrue?(theme)
752
584
  write_color(writer, 'theme', theme)
753
585
  elsif ptrue?(@color_indexed)
@@ -845,7 +677,7 @@ module Writexlsx
845
677
 
846
678
  def write_font_family_scheme(writer)
847
679
  if ptrue?(@font_family)
848
- writer.empty_tag('family', [ ['val', @font_family] ])
680
+ writer.empty_tag('family', [ ['val', @font_family] ])
849
681
  end
850
682
 
851
683
  if ptrue?(@font_charset)
@@ -105,8 +105,8 @@ module Writexlsx
105
105
 
106
106
  schema = 'http://schemas.openxmlformats.org/officeDocument/2006/'
107
107
  attributes = [
108
- ['xmlns', "#{schema}extended-properties"],
109
- ['xmlns:vt', "#{schema}docPropsVTypes"]
108
+ ['xmlns', "#{schema}extended-properties"],
109
+ ['xmlns:vt', "#{schema}docPropsVTypes"]
110
110
  ]
111
111
 
112
112
  @writer.tag_elements('Properties', attributes) { yield }
@@ -50,8 +50,8 @@ module Writexlsx
50
50
  # attributes for <v:fill> element.
51
51
  def fill_attributes
52
52
  [
53
- ['color2', 'buttonFace [67]'],
54
- ['o:detectmouseclick', 't']
53
+ ['color2', 'buttonFace [67]'],
54
+ ['o:detectmouseclick', 't']
55
55
  ]
56
56
  end
57
57
 
@@ -60,9 +60,9 @@ module Writexlsx
60
60
  #
61
61
  def write_rotation_lock
62
62
  attributes = [
63
- ['v:ext', 'edit'],
64
- ['rotation', 't']
65
- ]
63
+ ['v:ext', 'edit'],
64
+ ['rotation', 't']
65
+ ]
66
66
  @writer.empty_tag('o:lock', attributes)
67
67
  end
68
68
 
@@ -71,9 +71,9 @@ module Writexlsx
71
71
  #
72
72
  def write_textbox
73
73
  attributes = [
74
- ['style', 'mso-direction-alt:auto'],
75
- ['o:singleclick', 'f']
76
- ]
74
+ ['style', 'mso-direction-alt:auto'],
75
+ ['o:singleclick', 'f']
76
+ ]
77
77
 
78
78
  @writer.tag_elements('v:textbox', attributes) do
79
79
  # Write the div element.
@@ -177,8 +177,8 @@ module Writexlsx
177
177
  #
178
178
  def write_textbox
179
179
  attributes = [
180
- ['style', 'mso-direction-alt:auto']
181
- ]
180
+ ['style', 'mso-direction-alt:auto']
181
+ ]
182
182
 
183
183
  @writer.tag_elements('v:textbox', attributes) do
184
184
  # Write the div element.
@@ -191,8 +191,8 @@ module Writexlsx
191
191
  #
192
192
  def write_client_data
193
193
  attributes = [
194
- ['ObjectType', 'Note']
195
- ]
194
+ ['ObjectType', 'Note']
195
+ ]
196
196
 
197
197
  @writer.tag_elements('x:ClientData', attributes) do
198
198
  @writer.empty_tag('x:MoveWithCells')
@@ -225,10 +225,10 @@ module Writexlsx
225
225
  @author = options[:author]
226
226
  @start_cell = options[:start_cell]
227
227
  @start_row, @start_col = if @start_cell
228
- substitute_cellref(@start_cell)
229
- else
230
- [ options[:start_row], options[:start_col] ]
231
- end
228
+ substitute_cellref(@start_cell)
229
+ else
230
+ [ options[:start_row], options[:start_col] ]
231
+ end
232
232
  @visible = options[:visible]
233
233
  @x_offset = options[:x_offset] || default_x_offset(col)
234
234
  @y_offset = options[:y_offset] || default_y_offset(row)
@@ -165,9 +165,9 @@ module Writexlsx
165
165
  #
166
166
  def add_table_name(table_name)
167
167
  add_override(
168
- "/xl/tables/#{table_name}.xml",
169
- "#{App_document}spreadsheetml.table+xml"
170
- )
168
+ "/xl/tables/#{table_name}.xml",
169
+ "#{App_document}spreadsheetml.table+xml"
170
+ )
171
171
  end
172
172
 
173
173
  #
@@ -187,6 +187,15 @@ module Writexlsx
187
187
  add_override(custom, "#{App_document}custom-properties+xml")
188
188
  end
189
189
 
190
+ #
191
+ # Add the metadata file to the ContentTypes overrides.
192
+ #
193
+ def add_metadata
194
+ add_override(
195
+ "/xl/metadata.xml",
196
+ "#{App_document}spreadsheetml.sheetMetadata+xml"
197
+ )
198
+ end
190
199
 
191
200
  private
192
201
 
@@ -219,10 +228,10 @@ module Writexlsx
219
228
 
220
229
  def write_default_or_override(tag, param0, a)
221
230
  @writer.empty_tag(tag,
222
- [
223
- [param0, a[0]],
224
- ['ContentType', a[1]]
225
- ])
231
+ [
232
+ [param0, a[0]],
233
+ ['ContentType', a[1]]
234
+ ])
226
235
  end
227
236
 
228
237
  #
@@ -231,8 +240,8 @@ module Writexlsx
231
240
  def write_types
232
241
  xmlns = 'http://schemas.openxmlformats.org/package/2006/content-types'
233
242
  attributes = [
234
- ['xmlns', xmlns]
235
- ]
243
+ ['xmlns', xmlns]
244
+ ]
236
245
 
237
246
  @writer.tag_elements('Types', attributes) { yield }
238
247
  end
@@ -68,11 +68,11 @@ module Writexlsx
68
68
  xmlns_xsi = 'http://www.w3.org/2001/XMLSchema-instance'
69
69
 
70
70
  attributes = [
71
- ['xmlns:cp', xmlns_cp],
72
- ['xmlns:dc', xmlns_dc],
73
- ['xmlns:dcterms', xmlns_dcterms],
74
- ['xmlns:dcmitype', xmlns_dcmitype],
75
- ['xmlns:xsi', xmlns_xsi]
71
+ ['xmlns:cp', xmlns_cp],
72
+ ['xmlns:dc', xmlns_dc],
73
+ ['xmlns:dcterms', xmlns_dcterms],
74
+ ['xmlns:dcmitype', xmlns_dcmitype],
75
+ ['xmlns:xsi', xmlns_xsi]
76
76
  ]
77
77
 
78
78
  @writer.tag_elements('cp:coreProperties', attributes) { yield }
@@ -47,7 +47,7 @@ module Writexlsx
47
47
  @properties.each do |property|
48
48
  # Write the property element.
49
49
  write_property(property)
50
- end
50
+ end
51
51
  end
52
52
  end
53
53
 
@@ -112,7 +112,7 @@ module Writexlsx
112
112
  end
113
113
 
114
114
  @writer.data_element('vt:bool', data)
115
- end
115
+ end
116
116
 
117
117
  #
118
118
  # Write the <vt:filetime> element.
@@ -0,0 +1,159 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'write_xlsx/package/xml_writer_simple'
3
+ require 'write_xlsx/utility'
4
+
5
+ module Writexlsx
6
+ module Package
7
+ #
8
+ # Metadata - A class for writing the Excel XLSX metadata.xml file.
9
+ #
10
+ class Metadata
11
+ include Writexlsx::Utility
12
+
13
+ def initialize(workbook)
14
+ @writer = Package::XMLWriterSimple.new
15
+ @workbook = workbook
16
+ end
17
+
18
+ def set_xml_writer(filename)
19
+ @writer.set_xml_writer(filename)
20
+ end
21
+
22
+ def assemble_xml_file
23
+ write_xml_declaration do
24
+ # Write the metadata element.
25
+ write_metadata
26
+ # Write the metadataTypes element.
27
+ write_metadata_types
28
+ # Write the futureMetadata element.
29
+ write_future_metadata
30
+ # Write the cellMetadata element.
31
+ write_cell_metadata
32
+ @writer.end_tag('metadata')
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ #
39
+ # Write the <metadata> element.
40
+ #
41
+ def write_metadata
42
+ xmlns = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'
43
+ xmlns_xda =
44
+ 'http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray'
45
+
46
+ attributes = [
47
+ ['xmlns', xmlns],
48
+ ['xmlns:xda', xmlns_xda]
49
+ ]
50
+
51
+ @writer.start_tag('metadata', attributes)
52
+ end
53
+
54
+ #
55
+ # Write the <metadataTypes> element.
56
+ #
57
+ def write_metadata_types
58
+ attributes = [['count', 1 ]]
59
+
60
+ @writer.tag_elements('metadataTypes', attributes) do
61
+ # Write the metadataType element.
62
+ write_metadata_type
63
+ end
64
+ end
65
+
66
+ #
67
+ # Write the <metadataType> element.
68
+ #
69
+ def write_metadata_type
70
+ attributes = [
71
+ ['name', 'XLDAPR'],
72
+ ['minSupportedVersion', 120000],
73
+ ['copy', 1],
74
+ ['pasteAll', 1],
75
+ ['pasteValues', 1],
76
+ ['merge', 1],
77
+ ['splitFirst', 1],
78
+ ['rowColShift', 1],
79
+ ['clearFormats', 1],
80
+ ['clearComments', 1],
81
+ ['assign', 1],
82
+ ['coerce', 1],
83
+ ['cellMeta', 1]
84
+ ]
85
+
86
+ @writer.empty_tag('metadataType', attributes)
87
+ end
88
+
89
+ #
90
+ # Write the <futureMetadata> element.
91
+ #
92
+ def write_future_metadata
93
+ attributes = [
94
+ ['name', 'XLDAPR'],
95
+ ['count', 1]
96
+ ]
97
+
98
+ @writer.tag_elements('futureMetadata', attributes) do
99
+ @writer.tag_elements('bk') do
100
+ @writer.tag_elements('extLst') do
101
+ # Write the ext element.
102
+ write_ext();
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ #
109
+ # Write the <ext> element.
110
+ #
111
+ def write_ext
112
+ attributes = [[ 'uri', '{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}']]
113
+ @writer.tag_elements('ext', attributes) do
114
+ # Write the xda:dynamicArrayProperties element.
115
+ write_xda_dynamic_array_properties
116
+ end
117
+ end
118
+
119
+ #
120
+ # Write the <xda:dynamicArrayProperties> element.
121
+ #
122
+ def write_xda_dynamic_array_properties
123
+ attributes = [
124
+ ['fDynamic', 1],
125
+ ['fCollapsed', 0]
126
+ ]
127
+
128
+ @writer.empty_tag('xda:dynamicArrayProperties', attributes)
129
+ end
130
+
131
+ #
132
+ # Write the <cellMetadata> element.
133
+ #
134
+ def write_cell_metadata
135
+ count = 1
136
+
137
+ attributes = [['count', count]]
138
+
139
+ @writer.tag_elements('cellMetadata', attributes) do
140
+ @writer.tag_elements('bk') do
141
+ # Write the rc element.
142
+ write_rc
143
+ end
144
+ end
145
+ end
146
+
147
+ #
148
+ # Write the <rc> element.
149
+ #
150
+ def write_rc
151
+ attributes = [
152
+ ['t', 1],
153
+ ['v', 0]
154
+ ]
155
+ @writer.empty_tag('rc', attributes)
156
+ end
157
+ end
158
+ end
159
+ end
@@ -6,6 +6,7 @@ require 'write_xlsx/package/comments'
6
6
  require 'write_xlsx/package/content_types'
7
7
  require 'write_xlsx/package/core'
8
8
  require 'write_xlsx/package/custom'
9
+ require 'write_xlsx/package/metadata'
9
10
  require 'write_xlsx/package/relationships'
10
11
  require 'write_xlsx/package/shared_strings'
11
12
  require 'write_xlsx/package/styles'
@@ -56,6 +57,7 @@ module Writexlsx
56
57
  write_drawing_rels_files
57
58
  add_image_files
58
59
  add_vba_project
60
+ write_metadata_file
59
61
  end
60
62
 
61
63
  private
@@ -175,6 +177,20 @@ module Writexlsx
175
177
  core.assemble_xml_file
176
178
  end
177
179
 
180
+ #
181
+ # Write the metadata.xml file.
182
+ #
183
+ def write_metadata_file
184
+ metadata = Package::Metadata.new(@workbook)
185
+
186
+ return unless @workbook.has_metadata?
187
+
188
+ FileUtils.mkdir_p("#{@package_dir}/xl")
189
+
190
+ metadata.set_xml_writer( "#{@package_dir}/xl/metadata.xml")
191
+ metadata.assemble_xml_file
192
+ end
193
+
178
194
  #
179
195
  # Write the custom.xml file.
180
196
  #
@@ -211,6 +227,8 @@ module Writexlsx
211
227
  content.add_vba_project if @workbook.vba_project
212
228
  # Add the custom properties if present.
213
229
  content.add_custom_properties unless @workbook.custom_properties.empty?
230
+ # Add the metadata file if present.
231
+ content.add_metadata if @workbook.has_metadata?
214
232
 
215
233
  content.set_xml_writer("#{@package_dir}/[Content_Types].xml")
216
234
  content.assemble_xml_file
@@ -305,6 +323,9 @@ module Writexlsx
305
323
  rels.add_ms_package_relationship('/vbaProject', 'vbaProject.bin')
306
324
  end
307
325
 
326
+ # Add the metadata file if required.
327
+ rels.add_document_relationship('/sheetMetadata', 'metadata.xml') if @workbook.has_metadata?
328
+
308
329
  rels.set_xml_writer("#{@package_dir}/xl/_rels/workbook.xml.rels")
309
330
  rels.assemble_xml_file
310
331
  end
@@ -63,9 +63,9 @@ module Writexlsx
63
63
 
64
64
  attributes =
65
65
  [
66
- ['xmlns', schema + '/spreadsheetml/2006/main'],
67
- ['count', total_count],
68
- ['uniqueCount', unique_count]
66
+ ['xmlns', schema + '/spreadsheetml/2006/main'],
67
+ ['count', total_count],
68
+ ['uniqueCount', unique_count]
69
69
  ]
70
70
 
71
71
  @writer.tag_elements('sst', attributes) { yield }
@@ -94,9 +94,9 @@ module Writexlsx
94
94
 
95
95
  # Convert control character to the _xHHHH_ escape.
96
96
  string = string.gsub(
97
- /([\x00-\x08\x0B-\x1F])/,
98
- sprintf("_x%04X_", $1.ord)
99
- ) if string =~ /([\x00-\x08\x0B-\x1F])/
97
+ /([\x00-\x08\x0B-\x1F])/,
98
+ sprintf("_x%04X_", $1.ord)
99
+ ) if string =~ /([\x00-\x08\x0B-\x1F])/
100
100
 
101
101
  # Convert character to \xC2\xxx or \xC3\xxx
102
102
  if string.bytesize == 1 && 0x80 <= string.ord && string.ord <= 0xFF
@@ -56,11 +56,11 @@ module Writexlsx
56
56
  # based on the default or user defined values in the Workbook palette.
57
57
  #
58
58
  def palette_color(index)
59
- if index.to_s =~ /^#([0-9A-F]{6})$/i
60
- "FF#{$1.upcase}"
61
- else
62
- "FF#{super(index)}"
63
- end
59
+ if index.to_s =~ /^#([0-9A-F]{6})$/i
60
+ "FF#{$1.upcase}"
61
+ else
62
+ "FF#{super(index)}"
63
+ end
64
64
  end
65
65
 
66
66
  #
@@ -526,9 +526,9 @@ module Writexlsx
526
526
  #
527
527
  def write_cell_style(name, xf_id, builtin_id)
528
528
  attributes = [
529
- ['name', name],
530
- ['xfId', xf_id],
531
- ['builtinId', builtin_id]
529
+ ['name', name],
530
+ ['xfId', xf_id],
531
+ ['builtinId', builtin_id]
532
532
  ]
533
533
 
534
534
  @writer.empty_tag('cellStyle', attributes)
@@ -570,9 +570,9 @@ module Writexlsx
570
570
  #
571
571
  def write_table_styles
572
572
  attributes = [
573
- ['count', 0],
574
- ['defaultTableStyle', 'TableStyleMedium9'],
575
- ['defaultPivotStyle', 'PivotStyleLight16']
573
+ ['count', 0],
574
+ ['defaultTableStyle', 'TableStyleMedium9'],
575
+ ['defaultPivotStyle', 'PivotStyleLight16']
576
576
  ]
577
577
 
578
578
  @writer.empty_tag('tableStyles', attributes)