write_xlsx 0.90.0 → 0.97.0
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.
- checksums.yaml +4 -4
- data/Changes +37 -0
- data/README.md +1 -1
- data/examples/a_simple.rb +1 -6
- data/examples/conditional_format.rb +73 -46
- data/examples/demo.rb +1 -7
- data/examples/hyperlink1.rb +4 -11
- data/lib/write_xlsx/chart.rb +81 -205
- data/lib/write_xlsx/chart/axis.rb +2 -2
- data/lib/write_xlsx/chart/caption.rb +3 -1
- data/lib/write_xlsx/chart/pie.rb +2 -0
- data/lib/write_xlsx/chart/series.rb +11 -7
- data/lib/write_xlsx/format.rb +15 -11
- data/lib/write_xlsx/package/conditional_format.rb +351 -38
- data/lib/write_xlsx/package/content_types.rb +10 -0
- data/lib/write_xlsx/package/custom.rb +125 -0
- data/lib/write_xlsx/package/packager.rb +26 -0
- data/lib/write_xlsx/package/styles.rb +53 -21
- data/lib/write_xlsx/package/table.rb +11 -4
- data/lib/write_xlsx/utility.rb +234 -34
- data/lib/write_xlsx/version.rb +1 -1
- data/lib/write_xlsx/workbook.rb +88 -1
- data/lib/write_xlsx/worksheet.rb +247 -23
- data/test/helper.rb +6 -1
- data/test/regression/_test_hyperlink31.rb +26 -0
- data/test/regression/images/zero_dpi.jpg +0 -0
- data/test/regression/test_chart_bar08.rb +3 -0
- data/test/regression/test_chart_bar11.rb +3 -0
- data/test/regression/test_chart_bar14.rb +3 -0
- data/test/regression/test_chart_chartarea05.rb +16 -17
- data/test/regression/test_chart_chartarea06.rb +49 -0
- data/test/regression/test_chart_data_labels25.rb +61 -0
- data/test/regression/test_chart_format26.rb +48 -0
- data/test/regression/test_chart_format27.rb +58 -0
- data/test/regression/test_chart_format28.rb +52 -0
- data/test/regression/test_chart_format29.rb +59 -0
- data/test/regression/test_chart_format30.rb +53 -0
- data/test/regression/test_chart_format31.rb +60 -0
- data/test/regression/test_chart_table03.rb +56 -0
- data/test/regression/test_cond_format14.rb +42 -0
- data/test/regression/test_cond_format15.rb +53 -0
- data/test/regression/test_cond_format16.rb +53 -0
- data/test/regression/test_cond_format17.rb +37 -0
- data/test/regression/test_cond_format18.rb +136 -0
- data/test/regression/test_date_1904_01.rb +1 -1
- data/test/regression/test_escapes04.rb +3 -0
- data/test/regression/test_escapes05.rb +3 -0
- data/test/regression/test_escapes07.rb +3 -0
- data/test/regression/test_escapes08.rb +3 -0
- data/test/regression/test_hyperlink01.rb +3 -0
- data/test/regression/test_hyperlink02.rb +3 -0
- data/test/regression/test_hyperlink03.rb +4 -0
- data/test/regression/test_hyperlink04.rb +3 -0
- data/test/regression/test_hyperlink05.rb +3 -0
- data/test/regression/test_hyperlink06.rb +3 -0
- data/test/regression/test_hyperlink07.rb +3 -0
- data/test/regression/test_hyperlink08.rb +3 -0
- data/test/regression/test_hyperlink09.rb +3 -0
- data/test/regression/test_hyperlink10.rb +3 -0
- data/test/regression/test_hyperlink11.rb +3 -0
- data/test/regression/test_hyperlink12.rb +3 -0
- data/test/regression/test_hyperlink13.rb +3 -0
- data/test/regression/test_hyperlink14.rb +3 -0
- data/test/regression/test_hyperlink15.rb +3 -0
- data/test/regression/test_hyperlink16.rb +3 -0
- data/test/regression/test_hyperlink17.rb +3 -0
- data/test/regression/test_hyperlink18.rb +3 -0
- data/test/regression/test_hyperlink20.rb +3 -0
- data/test/regression/test_hyperlink21.rb +3 -0
- data/test/regression/test_hyperlink22.rb +3 -0
- data/test/regression/test_hyperlink23.rb +3 -0
- data/test/regression/test_hyperlink24.rb +3 -0
- data/test/regression/test_hyperlink25.rb +3 -0
- data/test/regression/test_hyperlink26.rb +3 -0
- data/test/regression/test_hyperlink27.rb +3 -0
- data/test/regression/test_hyperlink28.rb +50 -0
- data/test/regression/test_hyperlink29.rb +27 -0
- data/test/regression/test_hyperlink30.rb +36 -0
- data/test/regression/test_image35.rb +26 -0
- data/test/regression/test_properties01.rb +1 -4
- data/test/regression/test_properties02.rb +1 -4
- data/test/regression/test_properties03.rb +26 -0
- data/test/regression/test_properties04.rb +61 -0
- data/test/regression/test_properties05.rb +30 -0
- data/test/regression/test_table03.rb +3 -0
- data/test/regression/test_table04.rb +3 -0
- data/test/regression/test_table05.rb +3 -0
- data/test/regression/test_table06.rb +3 -0
- data/test/regression/test_table20.rb +34 -0
- data/test/regression/test_table21.rb +36 -0
- data/test/regression/test_table22.rb +32 -0
- data/test/regression/xlsx_files/chart_chartarea05.xlsx +0 -0
- data/test/regression/xlsx_files/chart_chartarea06.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels25.xlsx +0 -0
- data/test/regression/xlsx_files/chart_format26.xlsx +0 -0
- data/test/regression/xlsx_files/chart_format27.xlsx +0 -0
- data/test/regression/xlsx_files/chart_format28.xlsx +0 -0
- data/test/regression/xlsx_files/chart_format29.xlsx +0 -0
- data/test/regression/xlsx_files/chart_format30.xlsx +0 -0
- data/test/regression/xlsx_files/chart_format31.xlsx +0 -0
- data/test/regression/xlsx_files/chart_table03.xlsx +0 -0
- data/test/regression/xlsx_files/cond_format14.xlsx +0 -0
- data/test/regression/xlsx_files/cond_format15.xlsx +0 -0
- data/test/regression/xlsx_files/cond_format16.xlsx +0 -0
- data/test/regression/xlsx_files/cond_format17.xlsx +0 -0
- data/test/regression/xlsx_files/cond_format18.xlsx +0 -0
- data/test/regression/xlsx_files/date_1904_01.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink28.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink29.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink30.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink31.xlsx +0 -0
- data/test/regression/xlsx_files/image35.xlsx +0 -0
- data/test/regression/xlsx_files/properties03.xlsx +0 -0
- data/test/regression/xlsx_files/properties04.xlsx +0 -0
- data/test/regression/xlsx_files/properties05.xlsx +0 -0
- data/test/regression/xlsx_files/table21.xlsx +0 -0
- data/test/regression/xlsx_files/table22.xlsx +0 -0
- data/test/workbook/test_write_workbook_view.rb +81 -0
- data/test/worksheet/test_cond_format_22.rb +266 -0
- data/test/worksheet/test_cond_format_23.rb +242 -0
- data/test/worksheet/test_cond_format_24.rb +303 -0
- data/test/worksheet/test_data_bar_01.rb +53 -0
- data/test/worksheet/test_data_bar_02.rb +79 -0
- data/test/worksheet/test_data_bar_03.rb +147 -0
- data/test/worksheet/test_data_bar_04.rb +145 -0
- data/test/worksheet/test_data_bar_05.rb +147 -0
- data/test/worksheet/test_data_bar_06.rb +145 -0
- data/test/worksheet/test_data_bar_07.rb +146 -0
- data/test/worksheet/test_data_bar_08.rb +54 -0
- data/test/worksheet/test_data_bar_09.rb +80 -0
- data/test/worksheet/test_data_bar_10.rb +165 -0
- data/test/worksheet/test_data_bar_11.rb +167 -0
- data/test/worksheet/test_data_bar_12.rb +104 -0
- data/test/worksheet/test_write_data_validation_02.rb +27 -0
- metadata +135 -2
|
@@ -178,6 +178,16 @@ def add_vba_project
|
|
|
178
178
|
add_default('bin', 'application/vnd.ms-office.vbaProject')
|
|
179
179
|
end
|
|
180
180
|
|
|
181
|
+
#
|
|
182
|
+
# Add the name of a table to the ContentTypes overrides.
|
|
183
|
+
#
|
|
184
|
+
def add_custom_properties
|
|
185
|
+
custom = "/docProps/custom.xml"
|
|
186
|
+
|
|
187
|
+
add_override(custom, "#{App_document}custom-properties+xml")
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
|
|
181
191
|
private
|
|
182
192
|
|
|
183
193
|
def change_the_workbook_xml_content_type_from_xlsx_to_xlsm
|
|
@@ -0,0 +1,125 @@
|
|
|
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
|
+
class Custom
|
|
8
|
+
|
|
9
|
+
include Writexlsx::Utility
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
@writer = Package::XMLWriterSimple.new
|
|
13
|
+
@properties = []
|
|
14
|
+
@pid = 1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def set_xml_writer(filename)
|
|
18
|
+
@writer.set_xml_writer(filename)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def assemble_xml_file
|
|
22
|
+
write_xml_declaration do
|
|
23
|
+
write_properties
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
#
|
|
28
|
+
# Set the document properties.
|
|
29
|
+
#
|
|
30
|
+
def set_properties(properties)
|
|
31
|
+
@properties = properties
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def write_properties
|
|
37
|
+
schema = 'http://schemas.openxmlformats.org/officeDocument/2006/'
|
|
38
|
+
xmlns = "#{schema}custom-properties"
|
|
39
|
+
xmlns_vt = "#{schema}docPropsVTypes"
|
|
40
|
+
|
|
41
|
+
attributes = [
|
|
42
|
+
['xmlns', xmlns],
|
|
43
|
+
['xmlns:vt', xmlns_vt]
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
@writer.tag_elements('Properties', attributes ) do
|
|
47
|
+
@properties.each do |property|
|
|
48
|
+
# Write the property element.
|
|
49
|
+
write_property(property)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def write_property(property)
|
|
55
|
+
fmtid = '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}'
|
|
56
|
+
|
|
57
|
+
@pid += 1
|
|
58
|
+
name, value, type = property
|
|
59
|
+
|
|
60
|
+
attributes = [
|
|
61
|
+
['fmtid', fmtid],
|
|
62
|
+
['pid', @pid],
|
|
63
|
+
['name', name]
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
@writer.tag_elements('property', attributes) do
|
|
67
|
+
if type == 'date'
|
|
68
|
+
# Write the vt:filetime element.
|
|
69
|
+
write_vt_filetime(value)
|
|
70
|
+
elsif type == 'number'
|
|
71
|
+
# Write the vt:r8 element.
|
|
72
|
+
write_vt_r8(value)
|
|
73
|
+
elsif type == 'number_int'
|
|
74
|
+
# Write the vt:i4 element.
|
|
75
|
+
write_vt_i4(value)
|
|
76
|
+
elsif type == 'bool'
|
|
77
|
+
# Write the vt:bool element.
|
|
78
|
+
write_vt_bool(value)
|
|
79
|
+
else
|
|
80
|
+
# Write the vt:lpwstr element.
|
|
81
|
+
write_vt_lpwstr(value)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def write_vt_lpwstr(data)
|
|
87
|
+
@writer.data_element('vt:lpwstr', data)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
#
|
|
91
|
+
# Write the <vt:i4> element.
|
|
92
|
+
#
|
|
93
|
+
def write_vt_i4(data)
|
|
94
|
+
@writer.data_element('vt:i4', data)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
#
|
|
98
|
+
# Write the <vt:r8> element.
|
|
99
|
+
#
|
|
100
|
+
def write_vt_r8(data)
|
|
101
|
+
@writer.data_element('vt:r8', data)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
#
|
|
105
|
+
# Write the <vt:bool> element.
|
|
106
|
+
#
|
|
107
|
+
def write_vt_bool(data)
|
|
108
|
+
if ptrue?(data)
|
|
109
|
+
data = 'true'
|
|
110
|
+
else
|
|
111
|
+
data = 'false'
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
@writer.data_element('vt:bool', data)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# Write the <vt:filetime> element.
|
|
119
|
+
#
|
|
120
|
+
def write_vt_filetime(data)
|
|
121
|
+
@writer.data_element('vt:filetime', data)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
require 'write_xlsx/package/comments'
|
|
6
6
|
require 'write_xlsx/package/content_types'
|
|
7
7
|
require 'write_xlsx/package/core'
|
|
8
|
+
require 'write_xlsx/package/custom'
|
|
8
9
|
require 'write_xlsx/package/relationships'
|
|
9
10
|
require 'write_xlsx/package/shared_strings'
|
|
10
11
|
require 'write_xlsx/package/styles'
|
|
@@ -44,6 +45,7 @@ def create_package
|
|
|
44
45
|
write_shared_strings_file
|
|
45
46
|
write_app_file
|
|
46
47
|
write_core_file
|
|
48
|
+
write_custom_file
|
|
47
49
|
write_content_types_file
|
|
48
50
|
write_styles_file
|
|
49
51
|
write_theme_file
|
|
@@ -172,6 +174,22 @@ def write_core_file
|
|
|
172
174
|
core.assemble_xml_file
|
|
173
175
|
end
|
|
174
176
|
|
|
177
|
+
#
|
|
178
|
+
# Write the custom.xml file.
|
|
179
|
+
#
|
|
180
|
+
def write_custom_file
|
|
181
|
+
properties = @workbook.custom_properties
|
|
182
|
+
custom = Package::Custom.new
|
|
183
|
+
|
|
184
|
+
return if properties.empty?
|
|
185
|
+
|
|
186
|
+
FileUtils.mkdir_p("#{@package_dir}/docProps")
|
|
187
|
+
|
|
188
|
+
custom.set_properties(properties)
|
|
189
|
+
custom.set_xml_writer("#{@package_dir}/docProps/custom.xml")
|
|
190
|
+
custom.assemble_xml_file
|
|
191
|
+
end
|
|
192
|
+
|
|
175
193
|
#
|
|
176
194
|
# Write the ContentTypes.xml file.
|
|
177
195
|
#
|
|
@@ -190,6 +208,8 @@ def write_content_types_file
|
|
|
190
208
|
content.add_shared_strings unless @workbook.shared_strings_empty?
|
|
191
209
|
# Add vbaProject if present.
|
|
192
210
|
content.add_vba_project if @workbook.vba_project
|
|
211
|
+
# Add the custom properties if present.
|
|
212
|
+
content.add_custom_properties unless @workbook.custom_properties.empty?
|
|
193
213
|
|
|
194
214
|
content.set_xml_writer("#{@package_dir}/[Content_Types].xml")
|
|
195
215
|
content.assemble_xml_file
|
|
@@ -239,9 +259,15 @@ def write_root_rels_file
|
|
|
239
259
|
FileUtils.mkdir_p("#{@package_dir}/_rels")
|
|
240
260
|
|
|
241
261
|
rels.add_document_relationship('/officeDocument', 'xl/workbook.xml')
|
|
262
|
+
|
|
242
263
|
rels.add_package_relationship('/metadata/core-properties',
|
|
243
264
|
'docProps/core.xml')
|
|
265
|
+
|
|
244
266
|
rels.add_document_relationship('/extended-properties', 'docProps/app.xml')
|
|
267
|
+
|
|
268
|
+
unless @workbook.custom_properties.empty?
|
|
269
|
+
rels.add_document_relationship('/custom-properties', 'docProps/custom.xml')
|
|
270
|
+
end
|
|
245
271
|
rels.set_xml_writer("#{@package_dir}/_rels/.rels" )
|
|
246
272
|
rels.assemble_xml_file
|
|
247
273
|
end
|
|
@@ -10,14 +10,16 @@ class Styles
|
|
|
10
10
|
|
|
11
11
|
def initialize
|
|
12
12
|
@writer = Package::XMLWriterSimple.new
|
|
13
|
-
@xf_formats
|
|
14
|
-
@palette
|
|
15
|
-
@font_count
|
|
16
|
-
@num_format_count
|
|
17
|
-
@border_count
|
|
18
|
-
@fill_count
|
|
19
|
-
@custom_colors
|
|
20
|
-
@dxf_formats
|
|
13
|
+
@xf_formats = nil
|
|
14
|
+
@palette = []
|
|
15
|
+
@font_count = 0
|
|
16
|
+
@num_format_count = 0
|
|
17
|
+
@border_count = 0
|
|
18
|
+
@fill_count = 0
|
|
19
|
+
@custom_colors = []
|
|
20
|
+
@dxf_formats = []
|
|
21
|
+
@has_hyperlink = 0
|
|
22
|
+
@hyperlink_font_id = 0
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def set_xml_writer(filename)
|
|
@@ -33,7 +35,10 @@ def assemble_xml_file
|
|
|
33
35
|
#
|
|
34
36
|
# Pass in the Format objects and other properties used to set the styles.
|
|
35
37
|
#
|
|
36
|
-
def set_style_properties(
|
|
38
|
+
def set_style_properties(
|
|
39
|
+
xf_formats, palette, font_count, num_format_count, border_count,
|
|
40
|
+
fill_count, custom_colors, dxf_formats
|
|
41
|
+
)
|
|
37
42
|
@xf_formats = xf_formats
|
|
38
43
|
@palette = palette
|
|
39
44
|
@font_count = font_count
|
|
@@ -150,7 +155,11 @@ def write_fonts
|
|
|
150
155
|
|
|
151
156
|
def write_font_base
|
|
152
157
|
@xf_formats.each do |format|
|
|
153
|
-
|
|
158
|
+
if format.has_font?
|
|
159
|
+
format.write_font(@writer, self)
|
|
160
|
+
@has_hyperlink = 1 if ptrue?(format.hyperlink)
|
|
161
|
+
@hyperlink_font_id = format.font_index unless ptrue?(@hyperlink_font_id)
|
|
162
|
+
end
|
|
154
163
|
end
|
|
155
164
|
end
|
|
156
165
|
|
|
@@ -365,11 +374,17 @@ def write_sub_border(type, style = 0, color = nil)
|
|
|
365
374
|
# Write the <cellStyleXfs> element.
|
|
366
375
|
#
|
|
367
376
|
def write_cell_style_xfs
|
|
368
|
-
|
|
377
|
+
count = ptrue?(@has_hyperlink) ? 2 : 1
|
|
378
|
+
|
|
379
|
+
attributes = [ ['count', count] ]
|
|
369
380
|
|
|
370
381
|
@writer.tag_elements('cellStyleXfs', attributes) do
|
|
371
382
|
# Write the style_xf element.
|
|
372
|
-
write_style_xf
|
|
383
|
+
write_style_xf(0, 0)
|
|
384
|
+
|
|
385
|
+
if ptrue?(@has_hyperlink)
|
|
386
|
+
write_style_xf(1, @hyperlink_font_id)
|
|
387
|
+
end
|
|
373
388
|
end
|
|
374
389
|
end
|
|
375
390
|
|
|
@@ -396,15 +411,27 @@ def write_cell_xfs
|
|
|
396
411
|
#
|
|
397
412
|
# Write the style <xf> element.
|
|
398
413
|
#
|
|
399
|
-
def write_style_xf
|
|
414
|
+
def write_style_xf(has_hyperlink, font_id)
|
|
400
415
|
attributes = [
|
|
401
416
|
['numFmtId', 0],
|
|
402
|
-
['fontId',
|
|
417
|
+
['fontId', font_id],
|
|
403
418
|
['fillId', 0],
|
|
404
419
|
['borderId', 0]
|
|
405
420
|
]
|
|
406
421
|
|
|
407
|
-
|
|
422
|
+
if ptrue?(has_hyperlink)
|
|
423
|
+
attributes << ['applyNumberFormat', 0]
|
|
424
|
+
attributes << ['applyFill', 0]
|
|
425
|
+
attributes << ['applyBorder', 0]
|
|
426
|
+
attributes << ['applyAlignment', 0]
|
|
427
|
+
attributes << ['applyProtection', 0]
|
|
428
|
+
@writer.tag_elements('xf', attributes) do
|
|
429
|
+
@writer.empty_tag('alignment', [ ['vertical', 'top'] ])
|
|
430
|
+
@writer.empty_tag('protection', [ ['locked', 0] ])
|
|
431
|
+
end
|
|
432
|
+
else
|
|
433
|
+
@writer.empty_tag('xf', attributes)
|
|
434
|
+
end
|
|
408
435
|
end
|
|
409
436
|
|
|
410
437
|
private
|
|
@@ -450,22 +477,27 @@ def write_xf(format)
|
|
|
450
477
|
# Write the <cellStyles> element.
|
|
451
478
|
#
|
|
452
479
|
def write_cell_styles
|
|
453
|
-
|
|
480
|
+
count = ptrue?(@has_hyperlink) ? 2 : 1
|
|
481
|
+
|
|
482
|
+
attributes = [ ['count', count] ]
|
|
454
483
|
|
|
455
484
|
@writer.tag_elements('cellStyles', attributes) do
|
|
456
485
|
# Write the cellStyle element.
|
|
457
|
-
|
|
486
|
+
if ptrue?(@has_hyperlink)
|
|
487
|
+
write_cell_style('Hyperlink', 1, 8)
|
|
488
|
+
end
|
|
489
|
+
write_cell_style('Normal', 0, 0)
|
|
458
490
|
end
|
|
459
491
|
end
|
|
460
492
|
|
|
461
493
|
#
|
|
462
494
|
# Write the <cellStyle> element.
|
|
463
495
|
#
|
|
464
|
-
def write_cell_style
|
|
496
|
+
def write_cell_style(name, xf_id, builtin_id)
|
|
465
497
|
attributes = [
|
|
466
|
-
['name',
|
|
467
|
-
['xfId',
|
|
468
|
-
['builtinId',
|
|
498
|
+
['name', name],
|
|
499
|
+
['xfId', xf_id],
|
|
500
|
+
['builtinId', builtin_id]
|
|
469
501
|
]
|
|
470
502
|
|
|
471
503
|
@writer.empty_tag('cellStyle', attributes)
|
|
@@ -32,8 +32,9 @@ def initialize(worksheet, *args)
|
|
|
32
32
|
@writer = Package::XMLWriterSimple.new
|
|
33
33
|
|
|
34
34
|
@row1, @row2, @col1, @col2, @param = handle_args(*args)
|
|
35
|
-
@columns
|
|
35
|
+
@columns = []
|
|
36
36
|
@col_formats = []
|
|
37
|
+
@seen_name = {}
|
|
37
38
|
|
|
38
39
|
# Set the data range rows (without the header and footer).
|
|
39
40
|
@first_data_row = @row1
|
|
@@ -95,9 +96,15 @@ def overrite_the_defaults_with_any_use_defined_values(col_id, col_data, col_num)
|
|
|
95
96
|
col_data.name = user_data[:header]
|
|
96
97
|
end
|
|
97
98
|
|
|
99
|
+
# Excel requires unique case insensitive header names.
|
|
100
|
+
if @seen_name[col_data.name.downcase]
|
|
101
|
+
raise "add_table() contains duplicate name: '#{col_data.name}'"
|
|
102
|
+
else
|
|
103
|
+
@seen_name[col_data.name.downcase] = true
|
|
104
|
+
end
|
|
98
105
|
# Get the header format if defined.
|
|
99
106
|
col_data.name_format = user_data[:header_format]
|
|
100
|
-
|
|
107
|
+
|
|
101
108
|
# Handle the column formula.
|
|
102
109
|
handle_the_column_formula(
|
|
103
110
|
col_data, col_num, user_data[:formula], user_data[:format]
|
|
@@ -291,8 +298,8 @@ def set_the_table_name
|
|
|
291
298
|
# Raise if the name looks like a R1C1.
|
|
292
299
|
if name =~ /^[rcRC]$/ || name =~ /^[rcRC]\d+[rcRC]\d+$/
|
|
293
300
|
raise "Invalid name '#{name}' like a RC cell ref in add_table()"
|
|
294
|
-
end
|
|
295
|
-
|
|
301
|
+
end
|
|
302
|
+
|
|
296
303
|
@name = @param[:name]
|
|
297
304
|
end
|
|
298
305
|
end
|
data/lib/write_xlsx/utility.rb
CHANGED
|
@@ -320,7 +320,7 @@ def check_parameter(params, valid_keys, method)
|
|
|
320
320
|
invalids = params.keys - valid_keys
|
|
321
321
|
unless invalids.empty?
|
|
322
322
|
raise WriteXLSXOptionParameterError,
|
|
323
|
-
|
|
323
|
+
"Unknown parameter '#{invalids.join(', ')}' in #{method}."
|
|
324
324
|
end
|
|
325
325
|
true
|
|
326
326
|
end
|
|
@@ -372,7 +372,7 @@ def layout_properties(args, is_text = false)
|
|
|
372
372
|
# Check for valid properties.
|
|
373
373
|
args.keys.each do |key|
|
|
374
374
|
unless properties.include?(key.to_sym)
|
|
375
|
-
|
|
375
|
+
raise "Property '#{key}' not allowed in layout options\n"
|
|
376
376
|
end
|
|
377
377
|
end
|
|
378
378
|
|
|
@@ -405,9 +405,9 @@ def pixels_to_points(vertices)
|
|
|
405
405
|
|
|
406
406
|
def v_shape_attributes_base(id, z_index)
|
|
407
407
|
[
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
408
|
+
['id', "_x0000_s#{id}"],
|
|
409
|
+
['type', type],
|
|
410
|
+
['style', (v_shape_style_base(z_index, vertices) + style_addition).join]
|
|
411
411
|
]
|
|
412
412
|
end
|
|
413
413
|
|
|
@@ -425,17 +425,17 @@ def v_shape_style_base(z_index, vertices)
|
|
|
425
425
|
|
|
426
426
|
def shape_style_base(left_str, top_str, width_str, height_str, z_index_str)
|
|
427
427
|
[
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
428
|
+
'position:absolute;',
|
|
429
|
+
'margin-left:',
|
|
430
|
+
left_str, 'pt;',
|
|
431
|
+
'margin-top:',
|
|
432
|
+
top_str, 'pt;',
|
|
433
|
+
'width:',
|
|
434
|
+
width_str, 'pt;',
|
|
435
|
+
'height:',
|
|
436
|
+
height_str, 'pt;',
|
|
437
|
+
'z-index:',
|
|
438
|
+
z_index_str, ';'
|
|
439
439
|
]
|
|
440
440
|
end
|
|
441
441
|
|
|
@@ -500,10 +500,10 @@ def write_font(font)
|
|
|
500
500
|
color = '#000000'
|
|
501
501
|
|
|
502
502
|
attributes = [
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
503
|
+
['face', face],
|
|
504
|
+
['size', size],
|
|
505
|
+
['color', color]
|
|
506
|
+
]
|
|
507
507
|
@writer.data_element('font', caption, attributes)
|
|
508
508
|
end
|
|
509
509
|
|
|
@@ -612,7 +612,7 @@ def pattern_properties(args) # :nodoc:
|
|
|
612
612
|
'small_check' => 'smCheck',
|
|
613
613
|
'large_check' => 'lgCheck',
|
|
614
614
|
'outlined_diamond' => 'openDmnd',
|
|
615
|
-
'solid_diamond' => 'solidDmnd'
|
|
615
|
+
'solid_diamond' => 'solidDmnd'
|
|
616
616
|
}
|
|
617
617
|
|
|
618
618
|
# Check for valid types.
|
|
@@ -627,7 +627,7 @@ def pattern_properties(args) # :nodoc:
|
|
|
627
627
|
|
|
628
628
|
pattern
|
|
629
629
|
end
|
|
630
|
-
|
|
630
|
+
|
|
631
631
|
def line_fill_properties(params)
|
|
632
632
|
return { :_defined => 0 } unless params
|
|
633
633
|
ret = params.dup
|
|
@@ -690,22 +690,222 @@ def process_workbook_options(*params)
|
|
|
690
690
|
[options.dup, default_format_properties.dup]
|
|
691
691
|
end
|
|
692
692
|
end
|
|
693
|
+
|
|
694
|
+
#
|
|
695
|
+
# Convert user defined font values into private hash values.
|
|
696
|
+
#
|
|
697
|
+
def convert_font_args(params)
|
|
698
|
+
return unless params
|
|
699
|
+
font = params_to_font(params)
|
|
700
|
+
|
|
701
|
+
# Convert font size units.
|
|
702
|
+
font[:_size] *= 100 if font[:_size] && font[:_size] != 0
|
|
703
|
+
|
|
704
|
+
# Convert rotation into 60,000ths of a degree.
|
|
705
|
+
if ptrue?(font[:_rotation])
|
|
706
|
+
font[:_rotation] = 60_000 * font[:_rotation].to_i
|
|
707
|
+
end
|
|
708
|
+
|
|
709
|
+
font
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
def params_to_font(params)
|
|
713
|
+
{
|
|
714
|
+
:_name => params[:name],
|
|
715
|
+
:_color => params[:color],
|
|
716
|
+
:_size => params[:size],
|
|
717
|
+
:_bold => params[:bold],
|
|
718
|
+
:_italic => params[:italic],
|
|
719
|
+
:_underline => params[:underline],
|
|
720
|
+
:_pitch_family => params[:pitch_family],
|
|
721
|
+
:_charset => params[:charset],
|
|
722
|
+
:_baseline => params[:baseline] || 0,
|
|
723
|
+
:_rotation => params[:rotation]
|
|
724
|
+
}
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
#
|
|
728
|
+
# Write the <c:txPr> element.
|
|
729
|
+
#
|
|
730
|
+
def write_tx_pr(horiz, font) # :nodoc:
|
|
731
|
+
rotation = nil
|
|
732
|
+
if font && font[:_rotation]
|
|
733
|
+
rotation = font[:_rotation]
|
|
734
|
+
end
|
|
735
|
+
@writer.tag_elements('c:txPr') do
|
|
736
|
+
# Write the a:bodyPr element.
|
|
737
|
+
write_a_body_pr(rotation, horiz)
|
|
738
|
+
# Write the a:lstStyle element.
|
|
739
|
+
write_a_lst_style
|
|
740
|
+
# Write the a:p element.
|
|
741
|
+
write_a_p_formula(font)
|
|
742
|
+
end
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
#
|
|
746
|
+
# Write the <a:bodyPr> element.
|
|
747
|
+
#
|
|
748
|
+
def write_a_body_pr(rot, horiz = nil) # :nodoc:
|
|
749
|
+
rot = -5400000 if !rot && ptrue?(horiz)
|
|
750
|
+
attributes = []
|
|
751
|
+
attributes << ['rot', rot] if rot
|
|
752
|
+
attributes << ['vert', 'horz'] if ptrue?(horiz)
|
|
753
|
+
|
|
754
|
+
@writer.empty_tag('a:bodyPr', attributes)
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
#
|
|
758
|
+
# Write the <a:lstStyle> element.
|
|
759
|
+
#
|
|
760
|
+
def write_a_lst_style # :nodoc:
|
|
761
|
+
@writer.empty_tag('a:lstStyle')
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
#
|
|
765
|
+
# Write the <a:p> element for formula titles.
|
|
766
|
+
#
|
|
767
|
+
def write_a_p_formula(font = nil) # :nodoc:
|
|
768
|
+
@writer.tag_elements('a:p') do
|
|
769
|
+
# Write the a:pPr element.
|
|
770
|
+
write_a_p_pr_formula(font)
|
|
771
|
+
# Write the a:endParaRPr element.
|
|
772
|
+
write_a_end_para_rpr
|
|
773
|
+
end
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
#
|
|
777
|
+
# Write the <a:pPr> element for formula titles.
|
|
778
|
+
#
|
|
779
|
+
def write_a_p_pr_formula(font) # :nodoc:
|
|
780
|
+
@writer.tag_elements('a:pPr') { write_a_def_rpr(font) }
|
|
781
|
+
end
|
|
782
|
+
|
|
783
|
+
#
|
|
784
|
+
# Write the <a:defRPr> element.
|
|
785
|
+
#
|
|
786
|
+
def write_a_def_rpr(font = nil) # :nodoc:
|
|
787
|
+
write_def_rpr_r_pr_common(
|
|
788
|
+
font,
|
|
789
|
+
get_font_style_attributes(font),
|
|
790
|
+
'a:defRPr'
|
|
791
|
+
)
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
def write_def_rpr_r_pr_common(font, style_attributes, tag) # :nodoc:
|
|
795
|
+
latin_attributes = get_font_latin_attributes(font)
|
|
796
|
+
has_color = ptrue?(font) && ptrue?(font[:_color])
|
|
797
|
+
|
|
798
|
+
if !latin_attributes.empty? || has_color
|
|
799
|
+
@writer.tag_elements(tag, style_attributes) do
|
|
800
|
+
if has_color
|
|
801
|
+
write_a_solid_fill(:color => font[:_color])
|
|
802
|
+
end
|
|
803
|
+
if !latin_attributes.empty?
|
|
804
|
+
write_a_latin(latin_attributes)
|
|
805
|
+
end
|
|
806
|
+
end
|
|
807
|
+
else
|
|
808
|
+
@writer.empty_tag(tag, style_attributes)
|
|
809
|
+
end
|
|
810
|
+
end
|
|
811
|
+
|
|
812
|
+
#
|
|
813
|
+
# Get the font latin attributes from a font hash.
|
|
814
|
+
#
|
|
815
|
+
def get_font_latin_attributes(font)
|
|
816
|
+
return [] unless font
|
|
817
|
+
|
|
818
|
+
attributes = []
|
|
819
|
+
attributes << ['typeface', font[:_name]] if ptrue?(font[:_name])
|
|
820
|
+
attributes << ['pitchFamily', font[:_pitch_family]] if font[:_pitch_family]
|
|
821
|
+
attributes << ['charset', font[:_charset]] if font[:_charset]
|
|
822
|
+
|
|
823
|
+
attributes
|
|
824
|
+
end
|
|
825
|
+
|
|
826
|
+
#
|
|
827
|
+
# Write the <a:solidFill> element.
|
|
828
|
+
#
|
|
829
|
+
def write_a_solid_fill(fill) # :nodoc:
|
|
830
|
+
@writer.tag_elements('a:solidFill') do
|
|
831
|
+
if fill[:color]
|
|
832
|
+
# Write the a:srgbClr element.
|
|
833
|
+
write_a_srgb_clr(color(fill[:color]), fill[:transparency])
|
|
834
|
+
end
|
|
835
|
+
end
|
|
836
|
+
end
|
|
837
|
+
|
|
838
|
+
#
|
|
839
|
+
# Write the <a:srgbClr> element.
|
|
840
|
+
#
|
|
841
|
+
def write_a_srgb_clr(color, transparency = nil) # :nodoc:
|
|
842
|
+
tag = 'a:srgbClr'
|
|
843
|
+
attributes = [ ['val', color] ]
|
|
844
|
+
|
|
845
|
+
if ptrue?(transparency)
|
|
846
|
+
@writer.tag_elements(tag, attributes) do
|
|
847
|
+
write_a_alpha(transparency)
|
|
848
|
+
end
|
|
849
|
+
else
|
|
850
|
+
@writer.empty_tag(tag, attributes)
|
|
851
|
+
end
|
|
852
|
+
end
|
|
853
|
+
|
|
854
|
+
#
|
|
855
|
+
# Convert the user specified colour index or string to a rgb colour.
|
|
856
|
+
#
|
|
857
|
+
def color(color_code) # :nodoc:
|
|
858
|
+
if color_code and color_code =~ /^#[0-9a-fA-F]{6}$/
|
|
859
|
+
# Convert a HTML style #RRGGBB color.
|
|
860
|
+
color_code.sub(/^#/, '').upcase
|
|
861
|
+
else
|
|
862
|
+
index = Format.color(color_code)
|
|
863
|
+
raise "Unknown color '#{color_code}' used in chart formatting." unless index
|
|
864
|
+
palette_color(index)
|
|
865
|
+
end
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
#
|
|
869
|
+
# Get the font style attributes from a font hash.
|
|
870
|
+
#
|
|
871
|
+
def get_font_style_attributes(font)
|
|
872
|
+
return [] unless font
|
|
873
|
+
|
|
874
|
+
attributes = []
|
|
875
|
+
attributes << ['sz', font[:_size]] if ptrue?(font[:_size])
|
|
876
|
+
attributes << ['b', font[:_bold]] if font[:_bold]
|
|
877
|
+
attributes << ['i', font[:_italic]] if font[:_italic]
|
|
878
|
+
attributes << ['u', 'sng'] if font[:_underline]
|
|
879
|
+
|
|
880
|
+
# Turn off baseline when testing fonts that don't have it.
|
|
881
|
+
if font[:_baseline] != -1
|
|
882
|
+
attributes << ['baseline', font[:_baseline]]
|
|
883
|
+
end
|
|
884
|
+
attributes
|
|
885
|
+
end
|
|
886
|
+
|
|
887
|
+
#
|
|
888
|
+
# Write the <a:endParaRPr> element.
|
|
889
|
+
#
|
|
890
|
+
def write_a_end_para_rpr # :nodoc:
|
|
891
|
+
@writer.empty_tag('a:endParaRPr', [ ['lang', 'en-US'] ])
|
|
892
|
+
end
|
|
693
893
|
end
|
|
694
894
|
|
|
695
895
|
module WriteDPtPoint
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
end
|
|
896
|
+
#
|
|
897
|
+
# Write an individual <c:dPt> element. Override the parent method to add
|
|
898
|
+
# markers.
|
|
899
|
+
#
|
|
900
|
+
def write_d_pt_point(index, point)
|
|
901
|
+
@writer.tag_elements('c:dPt') do
|
|
902
|
+
# Write the c:idx element.
|
|
903
|
+
write_idx(index)
|
|
904
|
+
@writer.tag_elements('c:marker') do
|
|
905
|
+
# Write the c:spPr element.
|
|
906
|
+
write_sp_pr(point)
|
|
708
907
|
end
|
|
709
908
|
end
|
|
909
|
+
end
|
|
710
910
|
end
|
|
711
911
|
end
|