write_xlsx 0.75.0 → 0.76.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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/Changes +4 -0
  3. data/Gemfile +8 -2
  4. data/README.md +4 -2
  5. data/lib/write_xlsx/chart/axis.rb +69 -96
  6. data/lib/write_xlsx/chart/bar.rb +18 -21
  7. data/lib/write_xlsx/chart/caption.rb +1 -1
  8. data/lib/write_xlsx/chart/column.rb +1 -5
  9. data/lib/write_xlsx/chart/line.rb +2 -16
  10. data/lib/write_xlsx/chart/pie.rb +18 -40
  11. data/lib/write_xlsx/chart/radar.rb +2 -5
  12. data/lib/write_xlsx/chart/scatter.rb +24 -32
  13. data/lib/write_xlsx/chart/series.rb +218 -236
  14. data/lib/write_xlsx/chart/stock.rb +15 -27
  15. data/lib/write_xlsx/chart.rb +303 -392
  16. data/lib/write_xlsx/chartsheet.rb +22 -20
  17. data/lib/write_xlsx/colors.rb +9 -15
  18. data/lib/write_xlsx/drawing.rb +26 -28
  19. data/lib/write_xlsx/format.rb +15 -15
  20. data/lib/write_xlsx/package/comments.rb +1 -1
  21. data/lib/write_xlsx/package/conditional_format.rb +8 -8
  22. data/lib/write_xlsx/package/relationships.rb +4 -15
  23. data/lib/write_xlsx/package/styles.rb +9 -16
  24. data/lib/write_xlsx/shape.rb +1 -15
  25. data/lib/write_xlsx/sparkline.rb +1 -1
  26. data/lib/write_xlsx/utility.rb +69 -13
  27. data/lib/write_xlsx/version.rb +1 -1
  28. data/lib/write_xlsx/workbook.rb +19 -7
  29. data/lib/write_xlsx/worksheet/cell_data.rb +1 -1
  30. data/lib/write_xlsx/worksheet/hyperlink.rb +39 -37
  31. data/lib/write_xlsx/worksheet.rb +44 -72
  32. data/lib/write_xlsx/zip_file_utils.rb +99 -0
  33. data/test/chart/test_add_series.rb +5 -5
  34. data/test/chart/test_write_d_lbls.rb +1 -1
  35. data/test/chart/test_write_major_gridlines.rb +1 -1
  36. data/test/chart/test_write_marker.rb +1 -1
  37. data/test/chart/test_write_number_format.rb +1 -1
  38. data/test/helper.rb +7 -4
  39. data/test/regression/klt.csv +4 -0
  40. data/test/regression/test_chart_column07.rb +44 -0
  41. data/test/regression/test_chart_column08.rb +46 -0
  42. data/test/regression/test_chart_date01.rb +57 -0
  43. data/test/regression/test_chart_date02.rb +59 -0
  44. data/test/regression/test_chart_date03.rb +59 -0
  45. data/test/regression/test_chart_date04.rb +61 -0
  46. data/test/regression/test_chart_stock01.rb +1 -6
  47. data/test/regression/test_chart_title02.rb +44 -0
  48. data/test/regression/test_escapes01.rb +1 -1
  49. data/test/regression/test_escapes02.rb +1 -1
  50. data/test/regression/test_escapes03.rb +1 -1
  51. data/test/regression/test_escapes04.rb +1 -1
  52. data/test/regression/test_escapes05.rb +1 -1
  53. data/test/regression/test_escapes06.rb +1 -1
  54. data/test/regression/test_escapes07.rb +1 -1
  55. data/test/regression/test_escapes08.rb +1 -1
  56. data/test/regression/test_set_column09.rb +31 -0
  57. data/test/regression/test_shared_strings_encoding.rb +103 -0
  58. data/test/regression/xlsx_files/chart_column07.xlsx +0 -0
  59. data/test/regression/xlsx_files/chart_column08.xlsx +0 -0
  60. data/test/regression/xlsx_files/chart_date01.xlsx +0 -0
  61. data/test/regression/xlsx_files/chart_date02.xlsx +0 -0
  62. data/test/regression/xlsx_files/chart_date03.xlsx +0 -0
  63. data/test/regression/xlsx_files/chart_date04.xlsx +0 -0
  64. data/test/regression/xlsx_files/chart_title02.xlsx +0 -0
  65. data/test/regression/xlsx_files/set_column09.xlsx +0 -0
  66. data/test/regression/xlsx_files/shared_strings_encoding.xlsx +0 -0
  67. data/test/worksheet/test_write_hyperlink.rb +10 -15
  68. data/write_xlsx.gemspec +0 -3
  69. metadata +48 -39
  70. data/test/worksheet/test_set_column.rb +0 -25
@@ -35,25 +35,25 @@ module Writexlsx
35
35
 
36
36
  write_xml_declaration do
37
37
  # Write the root chartsheet element.
38
- write_chartsheet
39
- # Write the worksheet properties.
40
- write_sheet_pr
41
- # Write the sheet view properties.
42
- write_sheet_views
43
- # Write the sheetProtection element.
44
- write_sheet_protection
45
- # Write the printOptions element.
46
- write_print_options
47
- # Write the worksheet page_margins.
48
- write_page_margins
49
- # Write the worksheet page setup.
50
- write_page_setup
51
- # Write the headerFooter element.
52
- write_header_footer
53
- # Write the drawing element.
54
- write_drawings
55
- # Close the worksheet tag.
56
- @writer.end_tag('chartsheet')
38
+ write_chartsheet do
39
+ # Write the worksheet properties.
40
+ write_sheet_pr
41
+ # Write the sheet view properties.
42
+ write_sheet_views
43
+ # Write the sheetProtection element.
44
+ write_sheet_protection
45
+ # Write the printOptions element.
46
+ write_print_options
47
+ # Write the worksheet page_margins.
48
+ write_page_margins
49
+ # Write the worksheet page setup.
50
+ write_page_setup
51
+ # Write the headerFooter element.
52
+ write_header_footer
53
+ # Write the drawing element.
54
+ write_drawings
55
+ # Close the worksheet tag.
56
+ end
57
57
  end
58
58
  end
59
59
 
@@ -180,7 +180,9 @@ module Writexlsx
180
180
  ['xmlns:r', xmlns_r]
181
181
  ]
182
182
 
183
- @writer.start_tag('chartsheet', attributes)
183
+ @writer.tag_elements('chartsheet', attributes) do
184
+ yield
185
+ end
184
186
  end
185
187
 
186
188
  #
@@ -32,27 +32,21 @@ module Writexlsx
32
32
  # string into a number. Color range is 0..63 but we will restrict it
33
33
  # to 8..63 to comply with Gnumeric. Colors 0..7 are repeated in 8..15.
34
34
  #
35
- def get_color(color = nil) # :nodoc:
36
- if color.respond_to?(:to_int) && color.respond_to?(:+)
35
+ def color(color_code = nil) # :nodoc:
36
+ if color_code.respond_to?(:to_int) && color_code.respond_to?(:+)
37
37
  # the default color if arg is outside range,
38
- if color < 0 || 63 < color
38
+ if color_code < 0 || 63 < color_code
39
39
  0x7FFF
40
40
  # or an index < 8 mapped into the correct range,
41
- elsif color < 8
42
- (color + 8).to_i
41
+ elsif color_code < 8
42
+ (color_code + 8).to_i
43
43
  # or an integer in the valid range
44
44
  else
45
- color.to_i
46
- end
47
- elsif color.respond_to?(:to_sym)
48
- color = color.downcase.to_sym if color.respond_to?(:to_str)
49
- # or the color string converted to an integer,
50
- if COLORS.has_key?(color)
51
- COLORS[color]
52
- # or the default color if string is unrecognised,
53
- else
54
- 0x7FFF
45
+ color_code.to_i
55
46
  end
47
+ elsif color_code.respond_to?(:to_sym)
48
+ color_code = color_code.downcase.to_sym if color_code.respond_to?(:to_str)
49
+ COLORS[color_code] || 0x7FFF
56
50
  else
57
51
  0x7FFF
58
52
  end
@@ -81,7 +81,7 @@ module Writexlsx
81
81
  attributes << [:editAs, 'oneCell'] if type == 2
82
82
 
83
83
  # Add attribute for shapes.
84
- attributes << [:editAs, shape.edit_as] if shape && !shape.edit_as.nil?
84
+ attributes << [:editAs, shape.edit_as] if shape && shape.edit_as
85
85
 
86
86
  @writer.tag_elements('xdr:twoCellAnchor', attributes) do
87
87
  # Write the xdr:from element.
@@ -111,31 +111,29 @@ module Writexlsx
111
111
  # Write the <xdr:absoluteAnchor> element.
112
112
  #
113
113
  def write_absolute_anchor(index)
114
- @writer.start_tag('xdr:absoluteAnchor')
114
+ @writer.tag_elements('xdr:absoluteAnchor') do
115
+ # Different co-ordinates for horizonatal (= 0) and vertical (= 1).
116
+ if !ptrue?(@orientation)
115
117
 
116
- # Different co-ordinates for horizonatal (= 0) and vertical (= 1).
117
- if !ptrue?(@orientation)
118
+ # Write the xdr:pos element.
119
+ write_pos(0, 0)
118
120
 
119
- # Write the xdr:pos element.
120
- write_pos(0, 0)
121
-
122
- # Write the xdr:ext element.
123
- write_ext(9308969, 6078325)
124
- else
125
- # Write the xdr:pos element.
126
- write_pos(0, -47625)
127
-
128
- # Write the xdr:ext element.
129
- write_ext(6162675, 6124575)
130
- end
121
+ # Write the xdr:ext element.
122
+ write_ext(9308969, 6078325)
123
+ else
124
+ # Write the xdr:pos element.
125
+ write_pos(0, -47625)
131
126
 
132
- # Write the xdr:graphicFrame element.
133
- write_graphic_frame(index)
127
+ # Write the xdr:ext element.
128
+ write_ext(6162675, 6124575)
129
+ end
134
130
 
135
- # Write the xdr:clientData element.
136
- write_client_data
131
+ # Write the xdr:graphicFrame element.
132
+ write_graphic_frame(index)
137
133
 
138
- @writer.end_tag('xdr:absoluteAnchor')
134
+ # Write the xdr:clientData element.
135
+ write_client_data
136
+ end
139
137
  end
140
138
 
141
139
  #
@@ -246,7 +244,7 @@ module Writexlsx
246
244
  # Write the <xdr:nvGraphicFramePr> element.
247
245
  #
248
246
  def write_nv_graphic_frame_pr(index, name = nil)
249
- name = "Chart #{index}" if name.nil? || name.empty?
247
+ name = "Chart #{index}" unless ptrue?(name)
250
248
 
251
249
  @writer.tag_elements('xdr:nvGraphicFramePr') do
252
250
  # Write the xdr:cNvPr element.
@@ -400,7 +398,7 @@ module Writexlsx
400
398
  write_nv_cxn_sp_pr(index, shape)
401
399
 
402
400
  # Write the xdr:spPr element.
403
- write_xdr_sp_pr(index, col_absolute, row_absolute, width, height, shape)
401
+ write_xdr_sp_pr(col_absolute, row_absolute, width, height, shape)
404
402
  end
405
403
  else
406
404
  # Add attribute for shapes.
@@ -414,11 +412,11 @@ module Writexlsx
414
412
  write_nv_sp_pr(index, shape)
415
413
 
416
414
  # Write the xdr:spPr element.
417
- write_xdr_sp_pr(index, col_absolute, row_absolute, width, height, shape)
415
+ write_xdr_sp_pr(col_absolute, row_absolute, width, height, shape)
418
416
 
419
417
  # Write the xdr:txBody element.
420
418
  if shape.text != 0
421
- write_txBody(col_absolute, row_absolute, width, height, shape)
419
+ write_tx_body(shape)
422
420
  end
423
421
  end
424
422
  end
@@ -585,7 +583,7 @@ module Writexlsx
585
583
  #
586
584
  # Write the <xdr:spPr> element for shapes.
587
585
  #
588
- def write_xdr_sp_pr(index, col_absolute, row_absolute, width, height, shape)
586
+ def write_xdr_sp_pr(col_absolute, row_absolute, width, height, shape)
589
587
  attributes = [ ['bwMode', 'auto'] ]
590
588
 
591
589
  @writer.tag_elements('xdr:spPr', attributes) do
@@ -748,7 +746,7 @@ module Writexlsx
748
746
  #
749
747
  # Write the <xdr:txBody> element.
750
748
  #
751
- def write_txBody(col_absolute, row_absolute, width, height, shape)
749
+ def write_tx_body(shape)
752
750
  attributes = [
753
751
  [:vertOverflow, "clip"],
754
752
  [:wrap, "square"],
@@ -797,7 +795,7 @@ module Writexlsx
797
795
  @writer.tag_elements('a:rPr', attributes) do
798
796
  color = shape.format[:color]
799
797
  if color
800
- color = shape.get_palette_color(color)
798
+ color = shape.palette_color(color)
801
799
  color = color.sub(/^FF/, '') # Remove leading FF from rgb for shape color.
802
800
  else
803
801
  color = '000000'
@@ -464,8 +464,8 @@ module Writexlsx
464
464
  end
465
465
  end
466
466
 
467
- def get_color(color)
468
- Format.get_color(color)
467
+ def color(color_code)
468
+ Format.color(color_code)
469
469
  end
470
470
 
471
471
  #
@@ -473,31 +473,31 @@ module Writexlsx
473
473
  # string into a number. Color range is 0..63 but we will restrict it
474
474
  # to 8..63 to comply with Gnumeric. Colors 0..7 are repeated in 8..15.
475
475
  #
476
- def self.get_color(color)
476
+ def self.color(color_code)
477
477
 
478
478
  colors = Colors::COLORS
479
479
 
480
- if color.respond_to?(:to_str)
480
+ if color_code.respond_to?(:to_str)
481
481
  # Return RGB style colors for processing later.
482
- return color if color =~ /^#[0-9A-F]{6}$/i
482
+ return color_code if color_code =~ /^#[0-9A-F]{6}$/i
483
483
 
484
484
  # Return the default color if undef,
485
- return 0x00 unless color
485
+ return 0x00 unless color_code
486
486
 
487
487
  # or the color string converted to an integer,
488
- return colors[color.downcase.to_sym] if colors[color.downcase.to_sym]
488
+ return colors[color_code.downcase.to_sym] if colors[color_code.downcase.to_sym]
489
489
 
490
490
  # or the default color if string is unrecognised,
491
- return 0x00 if color =~ /\D/
491
+ return 0x00 if color_code =~ /\D/
492
492
  else
493
493
  # or an index < 8 mapped into the correct range,
494
- return color + 8 if color < 8
494
+ return color_code + 8 if color_code < 8
495
495
 
496
496
  # or the default color if arg is outside range,
497
- return 0x00 if color > 63
497
+ return 0x00 if color_code > 63
498
498
 
499
499
  # or an integer in the valid range
500
- return color
500
+ return color_code
501
501
  end
502
502
  end
503
503
 
@@ -647,9 +647,9 @@ module Writexlsx
647
647
  # Check that the attribute exists
648
648
  # ........
649
649
  if method =~ /set\w+color$/ # for "set_property_color" methods
650
- value = get_color(args[0])
650
+ value = color(args[0])
651
651
  else # for "set_xxx" methods
652
- value = args[0].nil? ? 1 : args[0]
652
+ value = args[0] || 1
653
653
  end
654
654
 
655
655
  instance_variable_set(attribute, value)
@@ -750,7 +750,7 @@ module Writexlsx
750
750
  elsif ptrue?(@color_indexed)
751
751
  write_color(writer, 'indexed', @color_indexed)
752
752
  elsif ptrue?(@color)
753
- color = worksheet.get_palette_color(@color)
753
+ color = worksheet.palette_color(@color)
754
754
  write_color(writer, 'rgb', color)
755
755
  elsif !ptrue?(dxf_format)
756
756
  write_color(writer, 'theme', 1)
@@ -771,7 +771,7 @@ module Writexlsx
771
771
  if ptrue?(theme)
772
772
  write_color(writer, 'theme', theme)
773
773
  elsif ptrue?(@color)
774
- color = worksheet.get_palette_color(@color)
774
+ color = worksheet.palette_color(@color)
775
775
  write_color(writer, 'rgb', color)
776
776
  else
777
777
  write_color(writer, 'theme', 1)
@@ -47,7 +47,7 @@ module Writexlsx
47
47
  end
48
48
 
49
49
  def backgrount_color(color)
50
- color_id = Format.get_color(color)
50
+ color_id = Format.color(color)
51
51
 
52
52
  if color_id == 0
53
53
  @color = '#ffffe1'
@@ -247,8 +247,8 @@ module Writexlsx
247
247
  @param[:min_color] ||= '#FF7128'
248
248
  @param[:max_color] ||= '#FFEF9C'
249
249
 
250
- @param[:max_color] = get_palette_color( @param[:max_color] )
251
- @param[:min_color] = get_palette_color( @param[:min_color] )
250
+ @param[:max_color] = palette_color( @param[:max_color] )
251
+ @param[:min_color] = palette_color( @param[:min_color] )
252
252
  when '3_color_scale'
253
253
  @param[:type] = 'colorScale'
254
254
 
@@ -265,9 +265,9 @@ module Writexlsx
265
265
  @param[:mid_color] ||= '#FFEB84'
266
266
  @param[:max_color] ||= '#63BE7B'
267
267
 
268
- @param[:max_color] = get_palette_color(@param[:max_color])
269
- @param[:mid_color] = get_palette_color(@param[:mid_color])
270
- @param[:min_color] = get_palette_color(@param[:min_color])
268
+ @param[:max_color] = palette_color(@param[:max_color])
269
+ @param[:mid_color] = palette_color(@param[:mid_color])
270
+ @param[:min_color] = palette_color(@param[:min_color])
271
271
  when 'dataBar'
272
272
  # Color scales don't use any additional formatting.
273
273
  @param[:format] = nil
@@ -278,12 +278,12 @@ module Writexlsx
278
278
  @param[:max_value] ||= 0
279
279
  @param[:bar_color] ||= '#638EC6'
280
280
 
281
- @param[:bar_color] = get_palette_color(@param[:bar_color])
281
+ @param[:bar_color] = palette_color(@param[:bar_color])
282
282
  end
283
283
  end
284
284
 
285
- def get_palette_color(index)
286
- @worksheet.get_palette_color(index)
285
+ def palette_color(index)
286
+ @worksheet.palette_color(index)
287
287
  end
288
288
 
289
289
  def range_start_cell_for_conditional_formatting(*args) # :nodoc:
@@ -32,20 +32,14 @@ module Writexlsx
32
32
  # Add container relationship to XLSX .rels xml files.
33
33
  #
34
34
  def add_document_relationship(type, target)
35
- type = Document_schema + type
36
- target = target
37
-
38
- @rels.push([type, target])
35
+ @rels.push([Document_schema + type, target])
39
36
  end
40
37
 
41
38
  #
42
39
  # Add container relationship to XLSX .rels xml files.
43
40
  #
44
41
  def add_package_relationship(type, target)
45
- type = Package_schema + type
46
- target = target
47
-
48
- @rels.push([type, target])
42
+ @rels.push([Package_schema + type, target])
49
43
  end
50
44
 
51
45
  #
@@ -53,19 +47,14 @@ module Writexlsx
53
47
  #
54
48
  def add_ms_package_relationship(type, target)
55
49
  schema = 'http://schemas.microsoft.com/office/2006/relationships'
56
- type = schema + type
57
-
58
- @rels.push([type, target])
50
+ @rels.push([schema + type, target])
59
51
  end
60
52
 
61
53
  #
62
54
  # Add worksheet relationship to sheet.rels xml files.
63
55
  #
64
56
  def add_worksheet_relationship(type, target, target_mode = nil)
65
- type = Document_schema + type
66
- target = target
67
-
68
- @rels.push([type, target, target_mode])
57
+ @rels.push([Document_schema + type, target, target_mode])
69
58
  end
70
59
 
71
60
  private
@@ -59,19 +59,12 @@ module Writexlsx
59
59
  # Convert from an Excel internal colour index to a XML style #RRGGBB index
60
60
  # based on the default or user defined values in the Workbook palette.
61
61
  #
62
- def get_palette_color(index)
63
- palette = @palette
64
-
65
- # Handle colours in #XXXXXX RGB format.
66
- return "FF#{$1.upcase}" if index =~ /^#([0-9A-F]{6})$/i
67
-
68
- # Adjust the colour index.
69
- index -= 8
70
-
71
- # Palette is passed in from the Workbook class.
72
- rgb = @palette[index]
73
-
74
- sprintf("FF%02X%02X%02X", *rgb[0, 3])
62
+ def palette_color(index)
63
+ if index =~ /^#([0-9A-F]{6})$/i
64
+ "FF#{$1.upcase}"
65
+ else
66
+ "FF#{super(index)}"
67
+ end
75
68
  end
76
69
 
77
70
  #
@@ -261,12 +254,12 @@ module Writexlsx
261
254
 
262
255
  @writer.tag_elements('patternFill', attributes) do
263
256
  if fg_color && fg_color != 0
264
- fg_color = get_palette_color(fg_color)
257
+ fg_color = palette_color(fg_color)
265
258
  @writer.empty_tag('fgColor', [ ['rgb', fg_color] ])
266
259
  end
267
260
 
268
261
  if bg_color && bg_color != 0
269
- bg_color = get_palette_color(bg_color)
262
+ bg_color = palette_color(bg_color)
270
263
  @writer.empty_tag('bgColor', [ ['rgb', bg_color] ])
271
264
  else
272
265
  @writer.empty_tag('bgColor', [ ['indexed', 64] ]) if !dxf_format
@@ -364,7 +357,7 @@ module Writexlsx
364
357
 
365
358
  @writer.tag_elements(type, attributes) do
366
359
  if color != 0
367
- color = get_palette_color(color)
360
+ color = palette_color(color)
368
361
  @writer.empty_tag('color', [ ['rgb', color] ])
369
362
  else
370
363
  @writer.empty_tag('color', [ ['auto', 1] ])
@@ -11,6 +11,7 @@ module Writexlsx
11
11
  # Converted to ruby by Hideo NAKAMURA, cxn03651@msj.biglobe.ne.jp
12
12
  #
13
13
  class Shape
14
+ include Writexlsx::Utility
14
15
 
15
16
  attr_reader :edit_as, :type, :drawing
16
17
  attr_reader :tx_box, :fill, :line, :format
@@ -145,21 +146,6 @@ module Writexlsx
145
146
  @adjustments = *args
146
147
  end
147
148
 
148
- #
149
- # Convert from an Excel internal colour index to a XML style #RRGGBB index
150
- # based on the default or user defined values in the Workbook palette.
151
- # Note: This version doesn't add an alpha channel.
152
- #
153
- def get_palette_color(index)
154
- # Adjust the colour index.
155
- idx = index - 8
156
-
157
- # Palette is passed in from the Workbook class.
158
- rgb = @palette[idx]
159
-
160
- sprintf("%02X%02X%02X", *rgb)
161
- end
162
-
163
149
  #
164
150
  # Calculate the vertices that define the position of a shape object within
165
151
  # the worksheet in EMUs. Save the vertices with the object.
@@ -100,7 +100,7 @@ module Writexlsx
100
100
 
101
101
  # Override the style colours with user defined colors.
102
102
  [:series_color, :negative_color, :markers_color, :first_color, :last_color, :high_color, :low_color].each do |user_color|
103
- set_spark_color(user_color, ptrue?(param[user_color]) ? ws.get_palette_color(param[user_color]) : nil)
103
+ set_spark_color(user_color, ptrue?(param[user_color]) ? ws.palette_color(param[user_color]) : nil)
104
104
  end
105
105
  end
106
106
 
@@ -344,6 +344,29 @@ module Writexlsx
344
344
  end
345
345
  end
346
346
 
347
+ #
348
+ # Convert user defined layout properties to the format required internally.
349
+ #
350
+ def layout_properties(args, is_text = false)
351
+ return unless ptrue?(args)
352
+
353
+ properties = is_text ? [:x, :y] : [:x, :y, :width, :height]
354
+
355
+ # Check for valid properties.
356
+ allowable = Hash.new
357
+ allowable[properties.size] = nil
358
+
359
+ # Set the layout properties
360
+ layout = Hash.new
361
+ properties.each do |property|
362
+ value = args[property]
363
+ # Convert to the format used by Excel for easier testing.
364
+ layout[property] = sprintf("%.17g", value)
365
+ end
366
+
367
+ layout
368
+ end
369
+
347
370
  #
348
371
  # Convert vertices from pixels to points.
349
372
  #
@@ -488,9 +511,28 @@ module Writexlsx
488
511
  # Convert user defined line properties to the structure required internally.
489
512
  #
490
513
  def line_properties(line) # :nodoc:
491
- return { :_defined => 0 } unless line
514
+ line_fill_properties(line) do
515
+ value_or_raise(dash_types, line[:dash_type], 'dash type')
516
+ end
517
+ end
518
+
519
+ #
520
+ # Convert user defined fill properties to the structure required internally.
521
+ #
522
+ def fill_properties(fill) # :nodoc:
523
+ line_fill_properties(fill)
524
+ end
492
525
 
493
- dash_types = {
526
+ def line_fill_properties(params)
527
+ return { :_defined => 0 } unless params
528
+ ret = params.dup
529
+ ret[:dash_type] = yield if block_given? && ret[:dash_type]
530
+ ret[:_defined] = 1
531
+ ret
532
+ end
533
+
534
+ def dash_types
535
+ {
494
536
  :solid => 'solid',
495
537
  :round_dot => 'sysDot',
496
538
  :square_dot => 'sysDash',
@@ -503,22 +545,36 @@ module Writexlsx
503
545
  :system_dash_dot => 'sysDashDot',
504
546
  :system_dash_dot_dot => 'sysDashDotDot'
505
547
  }
506
-
507
- # Check the dash type.
508
- dash_type = line[:dash_type]
509
-
510
- if dash_type
511
- line[:dash_type] = value_or_raise(dash_types, dash_type, 'dash type')
512
- end
513
-
514
- line[:_defined] = 1
515
-
516
- line
517
548
  end
518
549
 
519
550
  def value_or_raise(hash, key, msg)
520
551
  raise "Unknown #{msg} '#{key}'" unless hash[key.to_sym]
521
552
  hash[key.to_sym]
522
553
  end
554
+
555
+ def palette_color(index)
556
+ # Adjust the colour index.
557
+ idx = index - 8
558
+
559
+ rgb = @palette[idx]
560
+ sprintf("%02X%02X%02X", *rgb)
561
+ end
562
+ end
563
+
564
+ module WriteDPtPoint
565
+ #
566
+ # Write an individual <c:dPt> element. Override the parent method to add
567
+ # markers.
568
+ #
569
+ def write_d_pt_point(index, point)
570
+ @writer.tag_elements('c:dPt') do
571
+ # Write the c:idx element.
572
+ write_idx(index)
573
+ @writer.tag_elements('c:marker') do
574
+ # Write the c:spPr element.
575
+ write_sp_pr(point)
576
+ end
577
+ end
578
+ end
523
579
  end
524
580
  end
@@ -1,5 +1,5 @@
1
1
  require 'write_xlsx/workbook'
2
2
 
3
3
  class WriteXLSX < Writexlsx::Workbook
4
- VERSION = "0.75.0"
4
+ VERSION = "0.76.0"
5
5
  end
@@ -9,10 +9,11 @@ require 'write_xlsx/format'
9
9
  require 'write_xlsx/shape'
10
10
  require 'write_xlsx/utility'
11
11
  require 'write_xlsx/chart'
12
+ ruby_18 { require 'write_xlsx/zip_file_utils' }
13
+ ruby_19 { require 'zip' }
12
14
  require 'tmpdir'
13
15
  require 'tempfile'
14
16
  require 'digest/md5'
15
- require 'zip'
16
17
 
17
18
  module Writexlsx
18
19
 
@@ -873,7 +874,7 @@ module Writexlsx
873
874
  #
874
875
  def set_custom_color(index, red = 0, green = 0, blue = 0)
875
876
  # Match a HTML #xxyyzz style parameter
876
- if !red.nil? && red =~ /^#(\w\w)(\w\w)(\w\w)/
877
+ if red =~ /^#(\w\w)(\w\w)(\w\w)/
877
878
  red = $1.hex
878
879
  green = $2.hex
879
880
  blue = $3.hex
@@ -1164,7 +1165,7 @@ module Writexlsx
1164
1165
  end
1165
1166
 
1166
1167
  def write_defined_names #:nodoc:
1167
- return if @defined_names.nil? || @defined_names.empty?
1168
+ return unless ptrue?(@defined_names)
1168
1169
  @writer.tag_elements('definedNames') do
1169
1170
  @defined_names.each { |defined_name| write_defined_name(defined_name) }
1170
1171
  end
@@ -1232,10 +1233,13 @@ module Writexlsx
1232
1233
  packager = nil
1233
1234
 
1234
1235
  # Store the xlsx component files with the temp dir name removed.
1235
- # See https://github.com/randym/axlsx
1236
- Zip::OutputStream.open(@filename) do |zip|
1237
- write_parts(zip)
1238
- end
1236
+ ruby_19 do
1237
+ # See https://github.com/randym/axlsx
1238
+ Zip::OutputStream.open(@filename) do |zip|
1239
+ write_parts(zip)
1240
+ end
1241
+ end ||
1242
+ ruby_18 { ZipFileUtils.zip("#{@tempdir}", @filename) }
1239
1243
 
1240
1244
  IO.copy_stream(@filename, @fileobj) if @fileobj
1241
1245
  Writexlsx::Utility.delete_files(@tempdir)
@@ -1563,6 +1567,14 @@ module Writexlsx
1563
1567
  # Skip if we couldn't parse the formula.
1564
1568
  next unless sheetname
1565
1569
 
1570
+ # Handle non-contiguous ranges: (Sheet1!$A$1:$A$2,Sheet1!$A$4:$A$5).
1571
+ # We don't try to parse the ranges. We just return an empty list.
1572
+ if sheetname =~ /^\([^,]+,/
1573
+ chart.formula_data[id] = []
1574
+ seen_ranges[range] = []
1575
+ next
1576
+ end
1577
+
1566
1578
  # Raise if the name is unknown since it indicates a user error in
1567
1579
  # a chart series formula.
1568
1580
  unless worksheets[sheetname]
@@ -117,7 +117,7 @@ module Writexlsx
117
117
  end
118
118
 
119
119
  class BlankCellData < CellData # :nodoc:
120
- def initialize(worksheet, row, col, index, xf)
120
+ def initialize(worksheet, row, col, xf)
121
121
  @worksheet = worksheet
122
122
  @row, @col, @xf = row, col, xf
123
123
  end