write_xlsx 0.72.2 → 0.72.3.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/{README.rdoc → Changes} +3 -94
  3. data/README.md +96 -0
  4. data/lib/write_xlsx/chart.rb +115 -259
  5. data/lib/write_xlsx/chart/axis.rb +4 -4
  6. data/lib/write_xlsx/chart/bar.rb +1 -1
  7. data/lib/write_xlsx/chart/column.rb +1 -1
  8. data/lib/write_xlsx/chart/pie.rb +3 -3
  9. data/lib/write_xlsx/chart/radar.rb +1 -1
  10. data/lib/write_xlsx/chart/scatter.rb +1 -1
  11. data/lib/write_xlsx/chart/series.rb +0 -37
  12. data/lib/write_xlsx/chartsheet.rb +25 -37
  13. data/lib/write_xlsx/col_name.rb +40 -0
  14. data/lib/write_xlsx/drawing.rb +95 -85
  15. data/lib/write_xlsx/format.rb +32 -32
  16. data/lib/write_xlsx/package/app.rb +18 -23
  17. data/lib/write_xlsx/package/button.rb +15 -12
  18. data/lib/write_xlsx/package/comments.rb +33 -30
  19. data/lib/write_xlsx/package/conditional_format.rb +18 -14
  20. data/lib/write_xlsx/package/content_types.rb +22 -17
  21. data/lib/write_xlsx/package/core.rb +19 -24
  22. data/lib/write_xlsx/package/relationships.rb +10 -13
  23. data/lib/write_xlsx/package/shared_strings.rb +8 -16
  24. data/lib/write_xlsx/package/styles.rb +59 -64
  25. data/lib/write_xlsx/package/table.rb +27 -37
  26. data/lib/write_xlsx/package/vml.rb +23 -21
  27. data/lib/write_xlsx/package/xml_writer_simple.rb +3 -6
  28. data/lib/write_xlsx/sheets.rb +4 -4
  29. data/lib/write_xlsx/sparkline.rb +22 -22
  30. data/lib/write_xlsx/utility.rb +61 -33
  31. data/lib/write_xlsx/version.rb +1 -1
  32. data/lib/write_xlsx/workbook.rb +46 -50
  33. data/lib/write_xlsx/worksheet.rb +149 -133
  34. data/lib/write_xlsx/worksheet/cell_data.rb +8 -6
  35. data/lib/write_xlsx/worksheet/data_validation.rb +14 -14
  36. data/lib/write_xlsx/worksheet/hyperlink.rb +97 -65
  37. data/lib/write_xlsx/worksheet/page_setup.rb +23 -22
  38. data/test/chart/test_write_a_latin.rb +3 -3
  39. data/test/regression/test_chart_font01.rb +1 -1
  40. data/test/regression/test_chart_font02.rb +1 -1
  41. data/test/regression/test_chart_font03.rb +1 -1
  42. data/test/regression/test_chart_font04.rb +1 -1
  43. data/test/regression/test_chart_font05.rb +1 -1
  44. data/test/regression/test_chart_font06.rb +1 -1
  45. data/test/test_xml_writer_simple.rb +3 -3
  46. data/test/worksheet/test_write_hyperlink.rb +4 -4
  47. data/test/worksheet/test_write_worksheet_attributes.rb +3 -3
  48. data/write_xlsx.gemspec +2 -1
  49. metadata +9 -8
  50. 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 = ['r', xl_rowcol_to_cell(row, col)]
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' << xf_index
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' << row_xf.get_xf_index
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' << col_xf.get_xf_index
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' << 's'
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' << 'str'
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' << @validate
132
- attributes << 'operator' << @criteria if @criteria != 'between'
131
+ attributes << ['type', @validate]
132
+ attributes << ['operator', @criteria] if @criteria != 'between'
133
133
 
134
134
  if @error_type
135
- attributes << 'errorStyle' << 'warning' if @error_type == 1
136
- attributes << 'errorStyle' << 'information' if @error_type == 2
135
+ attributes << ['errorStyle', 'warning'] if @error_type == 1
136
+ attributes << ['errorStyle', 'information'] if @error_type == 2
137
137
  end
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
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 initialize(url, str = nil)
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
- url = url.sub(/^internal:/, '')
17
- link_type = 2
18
- # Remove the URI scheme from external links.
13
+ InternalHyperlink.new(url, str)
19
14
  elsif url =~ /^external:/
20
- url = url.sub(/^external:/, '')
21
- link_type = 3
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
- # Copy string for use in hyperlink elements.
37
- url_str = str.dup
38
-
39
- # External links to URLs and to other Excel workbooks have slightly
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
- # Ordinary URL style external links don't have a "location" string.
59
- url_str = nil
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
- # Treat as a default external link now that the data has been modified.
77
- link_type = 1
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 = 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 += r_id_attributes(id)
59
+ attributes = [ ['ref', ref] ]
60
+ attributes << r_id_attributes(id)
95
61
 
96
- attributes << 'location' << url_str if url_str
97
- attributes << 'display' << display if display
98
- attributes << 'tooltip' << tip if tip
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 = ['ref', ref, 'location', url]
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
- attributes << 'tooltip' << tip if tip
108
- attributes << 'display' << str
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' << @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
- attributes << 'portrait'
106
- else
107
- attributes << 'landscape'
108
- end
109
- attributes << 'useFirstPageNumber' << @page_start if ptrue?(@page_start)
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' << 1 if @hcenter
129
- attributes << 'verticalCentered' << 1 if @vcenter
130
- attributes << 'headings' << 1 if @print_headers
131
- attributes << 'gridLines' << 1 if @print_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
@@ -12,9 +12,9 @@ def test_write_a_latin
12
12
 
13
13
  result = @chart.__send__('write_a_latin',
14
14
  [
15
- 'typeface', 'Arial',
16
- 'pitchFamily', 34,
17
- 'charset', 0
15
+ ['typeface', 'Arial'],
16
+ ['pitchFamily', 34],
17
+ ['charset', 0]
18
18
  ]
19
19
  )
20
20
  assert_equal(expected, result)
@@ -10,7 +10,7 @@ def teardown
10
10
  File.delete(@xlsx) if File.exist?(@xlsx)
11
11
  end
12
12
 
13
- def test_chart_area01
13
+ def test_chart_font01
14
14
  @xlsx = 'chart_font01.xlsx'
15
15
  workbook = WriteXLSX.new(@xlsx)
16
16
  worksheet = workbook.add_worksheet
@@ -10,7 +10,7 @@ def teardown
10
10
  File.delete(@xlsx) if File.exist?(@xlsx)
11
11
  end
12
12
 
13
- def test_chart_area02
13
+ def test_chart_font02
14
14
  @xlsx = 'chart_font02.xlsx'
15
15
  workbook = WriteXLSX.new(@xlsx)
16
16
  worksheet = workbook.add_worksheet
@@ -10,7 +10,7 @@ def teardown
10
10
  File.delete(@xlsx) if File.exist?(@xlsx)
11
11
  end
12
12
 
13
- def test_chart_area03
13
+ def test_chart_font03
14
14
  @xlsx = 'chart_font03.xlsx'
15
15
  workbook = WriteXLSX.new(@xlsx)
16
16
  worksheet = workbook.add_worksheet
@@ -10,7 +10,7 @@ def teardown
10
10
  File.delete(@xlsx) if File.exist?(@xlsx)
11
11
  end
12
12
 
13
- def test_chart_area04
13
+ def test_chart_font04
14
14
  @xlsx = 'chart_font04.xlsx'
15
15
  workbook = WriteXLSX.new(@xlsx)
16
16
  worksheet = workbook.add_worksheet
@@ -10,7 +10,7 @@ def teardown
10
10
  File.delete(@xlsx) if File.exist?(@xlsx)
11
11
  end
12
12
 
13
- def test_chart_area05
13
+ def test_chart_font05
14
14
  @xlsx = 'chart_font05.xlsx'
15
15
  workbook = WriteXLSX.new(@xlsx)
16
16
  worksheet = workbook.add_worksheet
@@ -10,7 +10,7 @@ def teardown
10
10
  File.delete(@xlsx) if File.exist?(@xlsx)
11
11
  end
12
12
 
13
- def test_chart_area06
13
+ def test_chart_font06
14
14
  @xlsx = 'chart_font06.xlsx'
15
15
  workbook = WriteXLSX.new(@xlsx)
16
16
  worksheet = workbook.add_worksheet
@@ -32,7 +32,7 @@ def test_start_end_tag
32
32
 
33
33
  def test_attribute
34
34
  assert_equal(
35
- "<foo x=\"1&gt;2\"/>", @obj.empty_tag("foo", ['x', '1>2'])
35
+ "<foo x=\"1&gt;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.new('')
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.new('internal:Sheet2!A1', 'Sheet2!A1')
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.new("internal:'Data Sheet'!D5", "'Data Sheet'!D5")
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.new('internal:Sheet2!A1', 'Sheet2!A1')
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