write_xlsx 0.72.2 → 0.72.3.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/{README.rdoc → Changes} +3 -94
- data/README.md +96 -0
- data/lib/write_xlsx/chart.rb +115 -259
- data/lib/write_xlsx/chart/axis.rb +4 -4
- data/lib/write_xlsx/chart/bar.rb +1 -1
- data/lib/write_xlsx/chart/column.rb +1 -1
- data/lib/write_xlsx/chart/pie.rb +3 -3
- data/lib/write_xlsx/chart/radar.rb +1 -1
- data/lib/write_xlsx/chart/scatter.rb +1 -1
- data/lib/write_xlsx/chart/series.rb +0 -37
- data/lib/write_xlsx/chartsheet.rb +25 -37
- data/lib/write_xlsx/col_name.rb +40 -0
- data/lib/write_xlsx/drawing.rb +95 -85
- data/lib/write_xlsx/format.rb +32 -32
- data/lib/write_xlsx/package/app.rb +18 -23
- data/lib/write_xlsx/package/button.rb +15 -12
- data/lib/write_xlsx/package/comments.rb +33 -30
- data/lib/write_xlsx/package/conditional_format.rb +18 -14
- data/lib/write_xlsx/package/content_types.rb +22 -17
- data/lib/write_xlsx/package/core.rb +19 -24
- data/lib/write_xlsx/package/relationships.rb +10 -13
- data/lib/write_xlsx/package/shared_strings.rb +8 -16
- data/lib/write_xlsx/package/styles.rb +59 -64
- data/lib/write_xlsx/package/table.rb +27 -37
- data/lib/write_xlsx/package/vml.rb +23 -21
- data/lib/write_xlsx/package/xml_writer_simple.rb +3 -6
- data/lib/write_xlsx/sheets.rb +4 -4
- data/lib/write_xlsx/sparkline.rb +22 -22
- data/lib/write_xlsx/utility.rb +61 -33
- data/lib/write_xlsx/version.rb +1 -1
- data/lib/write_xlsx/workbook.rb +46 -50
- data/lib/write_xlsx/worksheet.rb +149 -133
- data/lib/write_xlsx/worksheet/cell_data.rb +8 -6
- data/lib/write_xlsx/worksheet/data_validation.rb +14 -14
- data/lib/write_xlsx/worksheet/hyperlink.rb +97 -65
- data/lib/write_xlsx/worksheet/page_setup.rb +23 -22
- data/test/chart/test_write_a_latin.rb +3 -3
- data/test/regression/test_chart_font01.rb +1 -1
- data/test/regression/test_chart_font02.rb +1 -1
- data/test/regression/test_chart_font03.rb +1 -1
- data/test/regression/test_chart_font04.rb +1 -1
- data/test/regression/test_chart_font05.rb +1 -1
- data/test/regression/test_chart_font06.rb +1 -1
- data/test/test_xml_writer_simple.rb +3 -3
- data/test/worksheet/test_write_hyperlink.rb +4 -4
- data/test/worksheet/test_write_worksheet_attributes.rb +3 -3
- data/write_xlsx.gemspec +2 -1
- metadata +9 -8
- data/test/package/table/test_write_xml_declaration.rb +0 -20
@@ -14,17 +14,19 @@ class CellData # :nodoc:
|
|
14
14
|
#
|
15
15
|
def cell_attributes #:nodoc:
|
16
16
|
xf_index = xf ? xf.get_xf_index : 0
|
17
|
-
attributes = [
|
17
|
+
attributes = [
|
18
|
+
['r', xl_rowcol_to_cell(row, col)]
|
19
|
+
]
|
18
20
|
|
19
21
|
# Add the cell format index.
|
20
22
|
if xf_index != 0
|
21
|
-
attributes << 's'
|
23
|
+
attributes << ['s', xf_index]
|
22
24
|
elsif @worksheet.set_rows[row] && @worksheet.set_rows[row][1]
|
23
25
|
row_xf = @worksheet.set_rows[row][1]
|
24
|
-
attributes << 's'
|
26
|
+
attributes << ['s', row_xf.get_xf_index]
|
25
27
|
elsif @worksheet.col_formats[col]
|
26
28
|
col_xf = @worksheet.col_formats[col]
|
27
|
-
attributes << 's'
|
29
|
+
attributes << ['s', col_xf.get_xf_index]
|
28
30
|
end
|
29
31
|
attributes
|
30
32
|
end
|
@@ -63,7 +65,7 @@ def data
|
|
63
65
|
|
64
66
|
def write_cell
|
65
67
|
attributes = cell_attributes
|
66
|
-
attributes << 't'
|
68
|
+
attributes << ['t', 's']
|
67
69
|
@worksheet.writer.tag_elements('c', attributes) do
|
68
70
|
@worksheet.write_cell_value(token)
|
69
71
|
end
|
@@ -87,7 +89,7 @@ def data
|
|
87
89
|
def write_cell
|
88
90
|
attributes = cell_attributes
|
89
91
|
if @result && !(@result.to_s =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/)
|
90
|
-
attributes << 't'
|
92
|
+
attributes << ['t', 'str']
|
91
93
|
end
|
92
94
|
@worksheet.writer.tag_elements('c', attributes) do
|
93
95
|
@worksheet.write_cell_formula(token)
|
@@ -128,23 +128,23 @@ def attributes
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
-
attributes << 'type'
|
132
|
-
attributes << 'operator'
|
131
|
+
attributes << ['type', @validate]
|
132
|
+
attributes << ['operator', @criteria] if @criteria != 'between'
|
133
133
|
|
134
134
|
if @error_type
|
135
|
-
attributes << 'errorStyle'
|
136
|
-
attributes << 'errorStyle'
|
135
|
+
attributes << ['errorStyle', 'warning'] if @error_type == 1
|
136
|
+
attributes << ['errorStyle', 'information'] if @error_type == 2
|
137
137
|
end
|
138
|
-
attributes << 'allowBlank'
|
139
|
-
attributes << 'showDropDown'
|
140
|
-
attributes << 'showInputMessage'
|
141
|
-
attributes << 'showErrorMessage'
|
142
|
-
|
143
|
-
attributes << 'errorTitle'
|
144
|
-
attributes << 'error'
|
145
|
-
attributes << 'promptTitle'
|
146
|
-
attributes << 'prompt'
|
147
|
-
attributes << 'sqref'
|
138
|
+
attributes << ['allowBlank', 1] if @ignore_blank != 0
|
139
|
+
attributes << ['showDropDown', 1] if @dropdown == 0
|
140
|
+
attributes << ['showInputMessage', 1] if @show_input != 0
|
141
|
+
attributes << ['showErrorMessage', 1] if @show_error != 0
|
142
|
+
|
143
|
+
attributes << ['errorTitle', @error_title] if @error_title
|
144
|
+
attributes << ['error', @error_message] if @error_message
|
145
|
+
attributes << ['promptTitle', @input_title] if @input_title
|
146
|
+
attributes << ['prompt', @input_message] if @input_message
|
147
|
+
attributes << ['sqref', sqref]
|
148
148
|
end
|
149
149
|
|
150
150
|
def has_key?(key)
|
@@ -8,104 +8,136 @@ class Hyperlink # :nodoc:
|
|
8
8
|
attr_reader :url, :link_type, :str, :url_str
|
9
9
|
attr_accessor :tip, :display
|
10
10
|
|
11
|
-
def
|
12
|
-
link_type = 1
|
13
|
-
|
14
|
-
# Remove the URI scheme from internal links.
|
11
|
+
def self.factory(url, str = nil)
|
15
12
|
if url =~ /^internal:/
|
16
|
-
|
17
|
-
link_type = 2
|
18
|
-
# Remove the URI scheme from external links.
|
13
|
+
InternalHyperlink.new(url, str)
|
19
14
|
elsif url =~ /^external:/
|
20
|
-
|
21
|
-
|
15
|
+
ExternalHyperlink.new(url, str)
|
16
|
+
else
|
17
|
+
new(url, str)
|
22
18
|
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(url, str = nil)
|
22
|
+
@link_type = 1
|
23
23
|
|
24
24
|
# The displayed string defaults to the url string.
|
25
25
|
str ||= url.dup
|
26
26
|
|
27
|
-
# For external links change the directory separator from Unix to Dos.
|
28
|
-
if link_type == 3
|
29
|
-
url = url.gsub(%r|/|, '\\')
|
30
|
-
str.gsub!(%r|/|, '\\')
|
31
|
-
end
|
32
|
-
|
33
27
|
# Strip the mailto header.
|
34
28
|
str.sub!(/^mailto:/, '')
|
35
29
|
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
# different characteristics that we have to account for.
|
41
|
-
if link_type == 1
|
42
|
-
# Escape URL unless it looks already escaped.
|
43
|
-
unless url =~ /%[0-9a-fA-F]{2}/
|
44
|
-
# Escape the URL escape symbol.
|
45
|
-
url = url.gsub(/%/, "%25")
|
46
|
-
|
47
|
-
# Escape whitespae in URL.
|
48
|
-
url = url.gsub(/[\s\x00]/, '%20')
|
49
|
-
|
50
|
-
# Escape other special characters in URL.
|
51
|
-
re = /(["<>\[\]`^{}])/
|
52
|
-
while re =~ url
|
53
|
-
match = $~[1]
|
54
|
-
url = url.sub(re, sprintf("%%%x", match.ord))
|
55
|
-
end
|
56
|
-
end
|
30
|
+
# Escape URL unless it looks already escaped.
|
31
|
+
unless url =~ /%[0-9a-fA-F]{2}/
|
32
|
+
# Escape the URL escape symbol.
|
33
|
+
url = url.gsub(/%/, "%25")
|
57
34
|
|
58
|
-
#
|
59
|
-
|
60
|
-
elsif link_type == 3
|
61
|
-
# External Workbook links need to be modified into the right format.
|
62
|
-
# The URL will look something like 'c:\temp\file.xlsx#Sheet!A1'.
|
63
|
-
# We need the part to the left of the # as the URL and the part to
|
64
|
-
# the right as the "location" string (if it exists).
|
65
|
-
url, url_str = url.split(/#/)
|
66
|
-
|
67
|
-
# Add the file:/// URI to the url if non-local.
|
68
|
-
if url =~ %r![:]! || # Windows style "C:/" link.
|
69
|
-
url =~ %r!^\\\\! # Network share.
|
70
|
-
url = "file:///#{url}"
|
71
|
-
end
|
72
|
-
|
73
|
-
# Convert a ./dir/file.xlsx link to dir/file.xlsx.
|
74
|
-
url = url.sub(%r!^.\\!, '')
|
35
|
+
# Escape whitespae in URL.
|
36
|
+
url = url.gsub(/[\s\x00]/, '%20')
|
75
37
|
|
76
|
-
#
|
77
|
-
|
38
|
+
# Escape other special characters in URL.
|
39
|
+
re = /(["<>\[\]`^{}])/
|
40
|
+
while re =~ url
|
41
|
+
match = $~[1]
|
42
|
+
url = url.sub(re, sprintf("%%%x", match.ord))
|
43
|
+
end
|
78
44
|
end
|
79
45
|
|
80
46
|
# Excel limits escaped URL to 255 characters.
|
81
47
|
if url.bytesize > 255
|
82
48
|
raise "URL '#{url}' > 255 characters, it exceeds Excel's limit for URLS."
|
83
49
|
end
|
50
|
+
|
84
51
|
@url = url
|
85
|
-
@link_type = link_type
|
86
52
|
@str = str
|
87
|
-
@url_str =
|
53
|
+
@url_str = nil
|
88
54
|
end
|
89
55
|
|
90
56
|
def write_external_attributes(row, col, id)
|
91
57
|
ref = xl_rowcol_to_cell(row, col)
|
92
58
|
|
93
|
-
attributes = ['ref', ref]
|
94
|
-
attributes
|
59
|
+
attributes = [ ['ref', ref] ]
|
60
|
+
attributes << r_id_attributes(id)
|
95
61
|
|
96
|
-
attributes << 'location'
|
97
|
-
attributes << 'display'
|
98
|
-
attributes << 'tooltip'
|
62
|
+
attributes << ['location', url_str] if url_str
|
63
|
+
attributes << ['display', display] if display
|
64
|
+
attributes << ['tooltip', tip] if tip
|
99
65
|
attributes
|
100
66
|
end
|
101
67
|
|
102
68
|
def write_internal_attributes(row, col)
|
103
69
|
ref = xl_rowcol_to_cell(row, col)
|
104
70
|
|
105
|
-
attributes = [
|
71
|
+
attributes = [
|
72
|
+
['ref', ref],
|
73
|
+
['location', url]
|
74
|
+
]
|
75
|
+
|
76
|
+
attributes << ['tooltip', tip] if tip
|
77
|
+
attributes << ['display', str]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class InternalHyperlink < Hyperlink
|
82
|
+
def initialize(url, str)
|
83
|
+
@link_type = 2
|
84
|
+
@url = url.sub(/^internal:/, '')
|
85
|
+
|
86
|
+
# The displayed string defaults to the url string.
|
87
|
+
str ||= @url.dup
|
88
|
+
|
89
|
+
# Strip the mailto header.
|
90
|
+
@str = str.sub(/^mailto:/, '')
|
91
|
+
|
92
|
+
# Copy string for use in hyperlink elements.
|
93
|
+
@url_str = @str.dup
|
94
|
+
|
95
|
+
# Excel limits escaped URL to 255 characters.
|
96
|
+
if @url.bytesize > 255
|
97
|
+
raise "URL '#{@url}' > 255 characters, it exceeds Excel's limit for URLS."
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class ExternalHyperlink < Hyperlink
|
103
|
+
def initialize(url, str = nil)
|
104
|
+
@link_type = 1
|
105
|
+
|
106
|
+
# Remove the URI scheme from internal links.
|
107
|
+
url = url.sub(/^external:/, '')
|
108
|
+
|
109
|
+
# The displayed string defaults to the url string.
|
110
|
+
str ||= url.dup
|
106
111
|
|
107
|
-
|
108
|
-
|
112
|
+
# For external links change the directory separator from Unix to Dos.
|
113
|
+
url = url.gsub(%r|/|, '\\')
|
114
|
+
str.gsub!(%r|/|, '\\')
|
115
|
+
|
116
|
+
# Strip the mailto header.
|
117
|
+
str.sub!(/^mailto:/, '')
|
118
|
+
|
119
|
+
# External Workbook links need to be modified into the right format.
|
120
|
+
# The URL will look something like 'c:\temp\file.xlsx#Sheet!A1'.
|
121
|
+
# We need the part to the left of the # as the URL and the part to
|
122
|
+
# the right as the "location" string (if it exists).
|
123
|
+
url, url_str = url.split(/#/)
|
124
|
+
|
125
|
+
# Add the file:/// URI to the url if non-local.
|
126
|
+
if url =~ %r![:]! || # Windows style "C:/" link.
|
127
|
+
url =~ %r!^\\\\! # Network share.
|
128
|
+
url = "file:///#{url}"
|
129
|
+
end
|
130
|
+
|
131
|
+
# Convert a ./dir/file.xlsx link to dir/file.xlsx.
|
132
|
+
url = url.sub(%r!^.\\!, '')
|
133
|
+
|
134
|
+
# Excel limits escaped URL to 255 characters.
|
135
|
+
if url.bytesize > 255
|
136
|
+
raise "URL '#{url}' > 255 characters, it exceeds Excel's limit for URLS."
|
137
|
+
end
|
138
|
+
@url = url
|
139
|
+
@str = str
|
140
|
+
@url_str = url_str
|
109
141
|
end
|
110
142
|
end
|
111
143
|
end
|
@@ -95,18 +95,19 @@ def write_page_setup(writer) #:nodoc:
|
|
95
95
|
return unless @page_setup_changed
|
96
96
|
|
97
97
|
attributes = []
|
98
|
-
attributes << 'paperSize'
|
99
|
-
attributes << 'scale'
|
100
|
-
attributes << 'fitToWidth'
|
101
|
-
attributes << 'fitToHeight'
|
102
|
-
attributes << 'pageOrder'
|
103
|
-
attributes << 'orientation'
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
98
|
+
attributes << ['paperSize', @paper_size] if @paper_size
|
99
|
+
attributes << ['scale', @scale] if @scale != 100
|
100
|
+
attributes << ['fitToWidth', @fit_width] if @fit_page && @fit_width != 1
|
101
|
+
attributes << ['fitToHeight', @fit_height] if @fit_page && @fit_height != 1
|
102
|
+
attributes << ['pageOrder', "overThenDown"] if @across
|
103
|
+
attributes << ['orientation',
|
104
|
+
if @orientation
|
105
|
+
'portrait'
|
106
|
+
else
|
107
|
+
'landscape'
|
108
|
+
end
|
109
|
+
]
|
110
|
+
attributes << ['useFirstPageNumber', @page_start] if ptrue?(@page_start)
|
110
111
|
|
111
112
|
writer.empty_tag('pageSetup', attributes)
|
112
113
|
end
|
@@ -125,10 +126,10 @@ def write_print_options(writer) #:nodoc:
|
|
125
126
|
return unless @print_options_changed
|
126
127
|
|
127
128
|
attributes = []
|
128
|
-
attributes << 'horizontalCentered'
|
129
|
-
attributes << 'verticalCentered'
|
130
|
-
attributes << 'headings'
|
131
|
-
attributes << 'gridLines'
|
129
|
+
attributes << ['horizontalCentered', 1] if @hcenter
|
130
|
+
attributes << ['verticalCentered', 1] if @vcenter
|
131
|
+
attributes << ['headings', 1] if @print_headers
|
132
|
+
attributes << ['gridLines', 1] if @print_gridlines
|
132
133
|
writer.empty_tag('printOptions', attributes)
|
133
134
|
end
|
134
135
|
|
@@ -162,12 +163,12 @@ def write_odd_footer(writer) #:nodoc:
|
|
162
163
|
|
163
164
|
def margin_attributes # :nodoc:
|
164
165
|
[
|
165
|
-
'left', @margin_left,
|
166
|
-
'right', @margin_right,
|
167
|
-
'top', @margin_top,
|
168
|
-
'bottom', @margin_bottom,
|
169
|
-
'header', @margin_header,
|
170
|
-
'footer', @margin_footer
|
166
|
+
['left', @margin_left],
|
167
|
+
['right', @margin_right],
|
168
|
+
['top', @margin_top],
|
169
|
+
['bottom', @margin_bottom],
|
170
|
+
['header', @margin_header],
|
171
|
+
['footer', @margin_footer]
|
171
172
|
]
|
172
173
|
end
|
173
174
|
end
|
@@ -32,7 +32,7 @@ def test_start_end_tag
|
|
32
32
|
|
33
33
|
def test_attribute
|
34
34
|
assert_equal(
|
35
|
-
"<foo x=\"1>2\"/>", @obj.empty_tag("foo", ['x', '1>2'])
|
35
|
+
"<foo x=\"1>2\"/>", @obj.empty_tag("foo", [ ['x', '1>2'] ])
|
36
36
|
)
|
37
37
|
end
|
38
38
|
|
@@ -52,8 +52,8 @@ def test_data_element_with_empty_attr
|
|
52
52
|
|
53
53
|
def test_data_element
|
54
54
|
attributes = [
|
55
|
-
'name', '_xlnm.Print_Titles',
|
56
|
-
'localSheetId', 0
|
55
|
+
['name', '_xlnm.Print_Titles'],
|
56
|
+
['localSheetId', 0]
|
57
57
|
]
|
58
58
|
expected =
|
59
59
|
"<definedName name=\"_xlnm.Print_Titles\" localSheetId=\"0\">Sheet1!$1:$1</definedName>"
|
@@ -10,7 +10,7 @@ def setup
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_write_hyperlink_external
|
13
|
-
hyperlink = Writexlsx::Worksheet::Hyperlink.
|
13
|
+
hyperlink = Writexlsx::Worksheet::Hyperlink.factory('')
|
14
14
|
@worksheet.__send__('write_hyperlink_external', hyperlink, 0, 0, 1)
|
15
15
|
result = @worksheet.instance_variable_get(:@writer).string
|
16
16
|
expected = '<hyperlink ref="A1" r:id="rId1"/>'
|
@@ -18,7 +18,7 @@ def test_write_hyperlink_external
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def test_write_hyperlink_internal_sheet2
|
21
|
-
hyperlink = Writexlsx::Worksheet::Hyperlink.
|
21
|
+
hyperlink = Writexlsx::Worksheet::Hyperlink.factory('internal:Sheet2!A1', 'Sheet2!A1')
|
22
22
|
@worksheet.__send__('write_hyperlink_internal', hyperlink, 0, 0)
|
23
23
|
result = @worksheet.instance_variable_get(:@writer).string
|
24
24
|
expected = '<hyperlink ref="A1" location="Sheet2!A1" display="Sheet2!A1"/>'
|
@@ -26,7 +26,7 @@ def test_write_hyperlink_internal_sheet2
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def test_write_hyperlink_internal_quoted_sheet
|
29
|
-
hyperlink = Writexlsx::Worksheet::Hyperlink.
|
29
|
+
hyperlink = Writexlsx::Worksheet::Hyperlink.factory("internal:'Data Sheet'!D5", "'Data Sheet'!D5")
|
30
30
|
@worksheet.__send__('write_hyperlink_internal', hyperlink, 4, 0)
|
31
31
|
result = @worksheet.instance_variable_get(:@writer).string
|
32
32
|
expected = %q{<hyperlink ref="A5" location="'Data Sheet'!D5" display="'Data Sheet'!D5"/>}
|
@@ -34,7 +34,7 @@ def test_write_hyperlink_internal_quoted_sheet
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def test_write_hyperlink_internal_tooltip
|
37
|
-
hyperlink = Writexlsx::Worksheet::Hyperlink.
|
37
|
+
hyperlink = Writexlsx::Worksheet::Hyperlink.factory('internal:Sheet2!A1', 'Sheet2!A1')
|
38
38
|
hyperlink.tip = 'Screen Tip 1'
|
39
39
|
@worksheet.__send__('write_hyperlink_internal', hyperlink, 17, 0)
|
40
40
|
result = @worksheet.instance_variable_get(:@writer).string
|