write_xlsx 1.08.1 → 1.09.2

Sign up to get free protection for your applications and to get access to all the features.
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)