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