write_xlsx 0.85.7 → 0.86.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 (62) hide show
  1. checksums.yaml +5 -5
  2. data/Changes +29 -0
  3. data/README.md +1 -1
  4. data/examples/colors.rb +47 -0
  5. data/examples/comments2.rb +1 -1
  6. data/examples/conditional_format.rb +60 -9
  7. data/examples/data_validate.rb +7 -7
  8. data/examples/panes.rb +1 -1
  9. data/examples/tab_colors.rb +1 -1
  10. data/examples/update_range_format_with_params.rb +33 -0
  11. data/lib/write_xlsx/chart.rb +1 -1
  12. data/lib/write_xlsx/format.rb +4 -5
  13. data/lib/write_xlsx/package/app.rb +12 -0
  14. data/lib/write_xlsx/package/comments.rb +4 -2
  15. data/lib/write_xlsx/package/conditional_format.rb +8 -2
  16. data/lib/write_xlsx/package/shared_strings.rb +12 -10
  17. data/lib/write_xlsx/package/styles.rb +1 -1
  18. data/lib/write_xlsx/package/table.rb +17 -5
  19. data/lib/write_xlsx/package/xml_writer_simple.rb +9 -8
  20. data/lib/write_xlsx/utility.rb +4 -2
  21. data/lib/write_xlsx/version.rb +1 -1
  22. data/lib/write_xlsx/workbook.rb +17 -14
  23. data/lib/write_xlsx/worksheet.rb +117 -15
  24. data/lib/write_xlsx/worksheet/cell_data.rb +3 -1
  25. data/lib/write_xlsx/worksheet/data_validation.rb +23 -11
  26. data/lib/write_xlsx/worksheet/hyperlink.rb +14 -10
  27. data/test/regression/images/red_208.png +0 -0
  28. data/test/regression/test_data_validation08.rb +24 -0
  29. data/test/regression/test_hyperlink22.rb +24 -0
  30. data/test/regression/test_hyperlink23.rb +24 -0
  31. data/test/regression/test_hyperlink24.rb +24 -0
  32. data/test/regression/test_image28.rb +27 -0
  33. data/test/regression/test_image29.rb +27 -0
  34. data/test/regression/test_image30.rb +27 -0
  35. data/test/regression/test_image31.rb +30 -0
  36. data/test/regression/test_image32.rb +28 -0
  37. data/test/regression/test_image33.rb +32 -0
  38. data/test/regression/test_properties02.rb +28 -0
  39. data/test/regression/test_update_range_format_with_params.rb +42 -0
  40. data/test/regression/xlsx_files/data_validation08.xlsx +0 -0
  41. data/test/regression/xlsx_files/hyperlink22.xlsx +0 -0
  42. data/test/regression/xlsx_files/hyperlink23.xlsx +0 -0
  43. data/test/regression/xlsx_files/hyperlink24.xlsx +0 -0
  44. data/test/regression/xlsx_files/image28.xlsx +0 -0
  45. data/test/regression/xlsx_files/image29.xlsx +0 -0
  46. data/test/regression/xlsx_files/image30.xlsx +0 -0
  47. data/test/regression/xlsx_files/image31.xlsx +0 -0
  48. data/test/regression/xlsx_files/image32.xlsx +0 -0
  49. data/test/regression/xlsx_files/image33.xlsx +0 -0
  50. data/test/regression/xlsx_files/properties02.xlsx +0 -0
  51. data/test/regression/xlsx_files/table18.xlsx +0 -0
  52. data/test/regression/xlsx_files/table19.xlsx +0 -0
  53. data/test/regression/xlsx_files/update_range_format_with_params.xlsx +0 -0
  54. data/test/run_test.rb +9 -0
  55. data/test/test_xml_writer_simple.rb +3 -3
  56. data/test/worksheet/test_cond_format_21.rb +90 -0
  57. data/test/worksheet/test_format.rb +17 -0
  58. data/test/worksheet/test_sparkline_12.rb +94 -0
  59. data/test/worksheet/test_update_format_methods.rb +111 -0
  60. data/test/worksheet/test_write_data_validation_02.rb +14 -1
  61. data/write_xlsx.gemspec +1 -1
  62. metadata +69 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9321ad366de31af18f34ce1898368f6d754759b9
4
- data.tar.gz: 7ad3e41824e5e9443d211766fb285ca56550ff0b
2
+ SHA256:
3
+ metadata.gz: 794b9b3028ff50abeab1e2c85d951fdc38526887ef6e2d64c6125afe697b4f92
4
+ data.tar.gz: 0a460f71a4cb05d4f72d7ad77308dbcda504b06f0e56ceceb7d0a9a6e0c0514f
5
5
  SHA512:
6
- metadata.gz: 7aa745d393ba1664d8e59bcbf56c3eaf2430d4000dda9b4e929c6766bdf852ea1686af0fb0e30e7cec90fa94e49432ef0383aa871bec7c0ae45f13c4cc53f1ce
7
- data.tar.gz: f321d7ddd751e9a4e757b75c519859be73cee90966f31ad1089e15cd8f2ce97b2f03a0d6abc89931d68862facd442000b88fc2177e421c488ed31d91db370aef
6
+ metadata.gz: b51f580ca37d7586f3faa6bafebeb76f2b14129070a0e7e70fe9d648e75e504983ad2ad97976ba49b3a8bb5af598826f54aa982dd73a7044132f32044bac6469
7
+ data.tar.gz: 661206fe8a1eeb9878329559ee9bf5f2a8f12db9515fba264368fe2f9df8711bffe4bb2457a51fb993dcb7aa74ce1c1fcd9740b6b05c6666edebae9288e2e66c
data/Changes CHANGED
@@ -1,5 +1,34 @@
1
1
  Change history of write_xlsx rubygem.
2
2
 
3
+ 2020-11-01 v0.86.0
4
+ Fix for images with negative offsets.
5
+
6
+ Allow hyperlinks longer than 255 characters when the link and anchor
7
+ are each less than or equal to 255 characters.
8
+
9
+ Added hyperlink_base document property.
10
+
11
+ Added option to allow data validation input messages with the ‘any’
12
+ validate parameter.
13
+
14
+ Added "stop if true" feature to conditional formatting.
15
+
16
+ Added better support and documentation for html colours throughout
17
+ the module. The use of the Excel97 colour palette is supported for
18
+ backward compatibility but deprecated.
19
+
20
+ 2020-10-23 v0.85.11
21
+ Added Worksheet#update_range_format_with_params
22
+
23
+ 2020-10-23 v0.85.10
24
+ Fix frozen string litterals problems in Format#set_align
25
+
26
+ 2020-09-07 v0.85.9
27
+ apply pull-request #59 and #60
28
+
29
+ 2020-09-03 v0.85.8
30
+ apply pull-request #58 and #52
31
+
3
32
  2019-06-20 v0.85.7
4
33
  apply pull-request #26
5
34
 
data/README.md CHANGED
@@ -84,7 +84,7 @@ the first worksheet in an Excel XML spreadsheet called ruby.xlsx:
84
84
  ## Copyright
85
85
  Original Perl module was written by John McNamara(jmcnamara@cpan.org).
86
86
 
87
- Converted to ruby by Hideo NAKAMURA(cxn03651@msj.biglobe.ne.jp)
87
+ Converted to ruby by Hideo NAKAMURA(nakamrua.hideo@gmail.com)
88
88
  Copyright (c) 2012-2018 Hideo NAKAMURA.
89
89
 
90
90
  See LICENSE.txt for further details.
@@ -126,4 +126,51 @@
126
126
  end
127
127
  end
128
128
 
129
+
130
+ #
131
+ # Demonstrate the Html colors.
132
+ #
133
+
134
+ colors = {
135
+ '#000000' => 'black',
136
+ '#0000FF' => 'blue',
137
+ '#800000' => 'brown',
138
+ '#00FFFF' => 'cyan',
139
+ '#808080' => 'gray',
140
+ '#008000' => 'green',
141
+ '#00FF00' => 'lime',
142
+ '#FF00FF' => 'magenta',
143
+ '#000080' => 'navy',
144
+ '#FF6600' => 'orange',
145
+ '#FF00FF' => 'pink',
146
+ '#800080' => 'purple',
147
+ '#FF0000' => 'red',
148
+ '#C0C0C0' => 'silver',
149
+ '#FFFFFF' => 'white',
150
+ '#FFFF00' => 'yellow'
151
+ }
152
+
153
+ worksheet3 = workbook.add_worksheet('Html colors')
154
+
155
+ worksheet3.set_column(0, 3, 15)
156
+
157
+ worksheet3.write(0, 0, "Html", heading)
158
+ worksheet3.write(0, 1, "Name", heading)
159
+ worksheet3.write(0, 2, "Color", heading)
160
+
161
+ i = 1
162
+
163
+ colors.each do |html_color, color|
164
+ format = workbook.add_format(
165
+ :fg_color => html_color,
166
+ :pattern => 1,
167
+ :border => 1
168
+ )
169
+
170
+ worksheet3.write(i + 1, 1, html_color, center)
171
+ worksheet3.write(i + 1, 2, color, center)
172
+ worksheet3.write(i + 1, 3, '', format)
173
+ i += 1
174
+ end
175
+
129
176
  workbook.close
@@ -247,7 +247,7 @@
247
247
  comment = 'Hello.'
248
248
 
249
249
  worksheet6.write( 'C9', cell_text, text_wrap )
250
- worksheet6.write_comment( 'C9', comment, :color => 0x35 )
250
+ worksheet6.write_comment( 'C9', comment, :color => '#FF6600' )
251
251
 
252
252
 
253
253
  ###############################################################################
@@ -12,6 +12,7 @@
12
12
  worksheet6 = workbook.add_worksheet
13
13
  worksheet7 = workbook.add_worksheet
14
14
  worksheet8 = workbook.add_worksheet
15
+ worksheet9 = workbook.add_worksheet
15
16
 
16
17
  # Light red fill with dark red text.
17
18
  format1 = workbook.add_format(
@@ -25,6 +26,12 @@
25
26
  :color => '#006100'
26
27
  )
27
28
 
29
+ # Blue fill with dark blue text.
30
+ format3 = workbook.add_format(
31
+ :bg_color => '#C6CEFF',
32
+ :color => '#0000FF'
33
+ )
34
+
28
35
  # Some sample data to run the conditional formatting against.
29
36
  data = [
30
37
  [ 34, 72, 38, 30, 75, 48, 75, 66, 84, 86 ],
@@ -219,18 +226,19 @@
219
226
  #
220
227
  caption = 'Examples of color scales and data bars. Default colors.'
221
228
 
222
- data = 1 .. 12
229
+ # Use different sample data for examples 7 and 8
230
+ data7 = 1 .. 12
223
231
 
224
232
  worksheet7.write('A1', caption)
225
233
 
226
234
  worksheet7.write('B2', "2 Color Scale")
227
- worksheet7.write_col('B3', data)
235
+ worksheet7.write_col('B3', data7)
228
236
 
229
237
  worksheet7.write('D2', "3 Color Scale")
230
- worksheet7.write_col('D3', data)
238
+ worksheet7.write_col('D3', data7)
231
239
 
232
240
  worksheet7.write('F2', "Data Bars")
233
- worksheet7.write_col('F3', data)
241
+ worksheet7.write_col('F3', data7)
234
242
 
235
243
 
236
244
  worksheet7.conditional_formatting('B3:B14',
@@ -258,18 +266,16 @@
258
266
  #
259
267
  caption = 'Examples of color scales and data bars. Modified colors.'
260
268
 
261
- data = 1 .. 12
262
-
263
269
  worksheet8.write('A1', caption)
264
270
 
265
271
  worksheet8.write('B2', "2 Color Scale")
266
- worksheet8.write_col('B3', data)
272
+ worksheet8.write_col('B3', data7)
267
273
 
268
274
  worksheet8.write('D2', "3 Color Scale")
269
- worksheet8.write_col('D3', data)
275
+ worksheet8.write_col('D3', data7)
270
276
 
271
277
  worksheet8.write('F2', "Data Bars")
272
- worksheet8.write_col('F3', data)
278
+ worksheet8.write_col('F3', data7)
273
279
 
274
280
 
275
281
  worksheet8.conditional_formatting('B3:B14',
@@ -296,4 +302,49 @@
296
302
  }
297
303
  )
298
304
 
305
+ ###############################################################################
306
+ #
307
+ # Example 9
308
+ #
309
+ caption = 'Cells with values >= 100 are always in blue. ' +
310
+ 'Otherwise, cells with values >= 50 are in light red ' +
311
+ 'and values < 50 are in light green.'
312
+
313
+ # Write the data.
314
+ worksheet9.write('A1', caption)
315
+ worksheet9.write_col('B3', data)
316
+
317
+ # Write a conditional format over a range.
318
+ # Use stopIfTrue to prevent previous formats from being used
319
+ # if the conditions of this format are met.
320
+ worksheet9.conditional_formatting('B3:K12',
321
+ {
322
+ :type => 'cell',
323
+ :criteria => '>=',
324
+ :value => 100,
325
+ :format => format3,
326
+ :stop_if_true => 1
327
+ }
328
+ )
329
+
330
+ # Write another conditional format over the same range.
331
+ worksheet9.conditional_formatting('B3:K12',
332
+ {
333
+ :type => 'cell',
334
+ :criteria => '>=',
335
+ :value => 50,
336
+ :format => format1
337
+ }
338
+ )
339
+
340
+ # Write another conditional format over the same range.
341
+ worksheet9.conditional_formatting('B3:K12',
342
+ {
343
+ :type => 'cell',
344
+ :criteria => '<',
345
+ :value => 50,
346
+ :format => format2
347
+ }
348
+ )
349
+
299
350
  workbook.close
@@ -19,13 +19,13 @@
19
19
 
20
20
  # Add a format for the header cells.
21
21
  header_format = workbook.add_format(
22
- :border => 1,
23
- :bg_color => 43,
24
- :bold => 1,
25
- :text_wrap => 1,
26
- :valign => 'vcenter',
27
- :indent => 1
28
- )
22
+ :border => 1,
23
+ :bg_color => '#C6EFCE',
24
+ :bold => 1,
25
+ :text_wrap => 1,
26
+ :valign => 'vcenter',
27
+ :indent => 1
28
+ )
29
29
 
30
30
  # Set up layout of the worksheet.
31
31
  worksheet.set_column('A:A', 68)
@@ -39,7 +39,7 @@
39
39
  header = workbook.add_format(
40
40
  :align => 'center',
41
41
  :valign => 'vcenter',
42
- :fg_color => 0x2A
42
+ :fg_color => '#C3FFC0'
43
43
  )
44
44
 
45
45
  center = workbook.add_format(:align => 'center')
@@ -20,6 +20,6 @@
20
20
  # Worksheet1 will have the default tab colour.
21
21
  worksheet2.tab_color = 'red'
22
22
  worksheet3.tab_color = 'green'
23
- worksheet4.tab_color = 0x35 # Orange
23
+ worksheet4.tab_color = '#FF6600' # Orange
24
24
 
25
25
  workbook.close
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #######################################################################
5
+ #
6
+ # A simple example of how to use the write_xlsx gem to
7
+ # update format of the range of cells.
8
+ #
9
+
10
+ require 'write_xlsx'
11
+
12
+ workbook = WriteXLSX.new('update_range_format_with_params.xlsx')
13
+ worksheet = workbook.add_worksheet
14
+
15
+ common_format = workbook.add_format(align: 'center', border: 1)
16
+
17
+ table_contents = [
18
+ ['Table', 'Header', 'Contents'],
19
+ ['table', 'body', 'contents'],
20
+ ['table', 'body', 'contents'],
21
+ ['table', 'body', 'contents']
22
+ ]
23
+
24
+ worksheet.write_col(0, 0, table_contents, common_format)
25
+ worksheet.update_range_format_with_params(
26
+ 0, 0, 0, 2,
27
+ bold: 1, top: 2, bottom: 2, bg_color: 31
28
+ )
29
+ worksheet.update_range_format_with_params(0, 0, 3, 0, left: 2)
30
+ worksheet.update_range_format_with_params(0, 2, 3, 2, right: 2)
31
+ worksheet.update_range_format_with_params(3, 0, 3, 2, bottom: 2)
32
+
33
+ workbook.close
@@ -2631,7 +2631,7 @@ def write_custom_error_base(tag, values, data)
2631
2631
  end
2632
2632
 
2633
2633
  def write_num_ref_or_lit(values, data)
2634
- if values =~ /^=/ # '=Sheet1!$A$1:$A$5'
2634
+ if values.to_s =~ /^=/ # '=Sheet1!$A$1:$A$5'
2635
2635
  write_num_ref(values, data, 'num')
2636
2636
  else # [1, 2, 3]
2637
2637
  write_num_lit(values)
@@ -287,11 +287,10 @@ def set_format_properties(*properties) # :nodoc:
287
287
 
288
288
  # Create a sub to set the property.
289
289
  if value.respond_to?(:to_str) || !value.respond_to?(:+)
290
- s = "set_#{key}('#{value}')"
290
+ send("set_#{key}", value.to_s)
291
291
  else
292
- s = "set_#{key}(#{value})"
292
+ send("set_#{key}", value)
293
293
  end
294
- eval s
295
294
  end
296
295
  end
297
296
  end
@@ -507,7 +506,7 @@ def self.color(color_code)
507
506
  def set_align(location)
508
507
  return unless location # No default
509
508
 
510
- location.downcase!
509
+ location = location.downcase
511
510
 
512
511
  set_text_h_align(1) if location == 'left'
513
512
  set_text_h_align(2) if location == 'centre'
@@ -583,7 +582,7 @@ def set_border_color(color)
583
582
  def set_rotation(rotation)
584
583
  if rotation == 270
585
584
  rotation = 255
586
- elsif rotation >= -90 || rotation <= 90
585
+ elsif rotation >= -90 && rotation <= 90
587
586
  rotation = -rotation + 90 if rotation < 0
588
587
  else
589
588
  raise "Rotation #{rotation} outside range: -90 <= angle <= 90"
@@ -32,6 +32,7 @@ def assemble_xml_file
32
32
  write_company
33
33
  write_links_up_to_date
34
34
  write_shared_doc
35
+ write_hyperlink_base
35
36
  write_hyperlinks_changed
36
37
  write_app_version
37
38
  end
@@ -220,6 +221,17 @@ def write_shared_doc
220
221
  @writer.data_element('SharedDoc', data)
221
222
  end
222
223
 
224
+ #
225
+ # Write the <HyperlinkBase> element.
226
+ #
227
+ def write_hyperlink_base
228
+ data = @properties[:hyperlink_base]
229
+
230
+ return unless data
231
+
232
+ @writer.data_element('HyperlinkBase', data)
233
+ end
234
+
223
235
  #
224
236
  # Write the <HyperlinksChanged> element.
225
237
  #
@@ -41,11 +41,13 @@ def initialize(workbook, worksheet, row, col, string, options = {})
41
41
  def backgrount_color(color)
42
42
  color_id = Format.color(color)
43
43
 
44
- if color_id == 0
44
+ if color_id.to_s =~ /^#[0-9A-F]{6}/i
45
+ @color = color_id.to_s
46
+ elsif color_id == 0
45
47
  @color = '#ffffe1'
46
48
  else
47
49
  rgb = @workbook.palette[color_id - 8]
48
- @color = "##{rgb_color(rgb)} [#{color_id}]\n"
50
+ @color = "##{rgb_color(rgb)} [#{color_id}]"
49
51
  end
50
52
  end
51
53
 
@@ -71,6 +71,7 @@ def attributes
71
71
  attr << ['type' , type]
72
72
  attr << ['dxfId', format] if format
73
73
  attr << ['priority', priority]
74
+ attr << ['stopIfTrue', 1] if stop_if_true
74
75
  attr
75
76
  end
76
77
 
@@ -86,6 +87,10 @@ def priority
86
87
  @param[:priority]
87
88
  end
88
89
 
90
+ def stop_if_true
91
+ @param[:stop_if_true]
92
+ end
93
+
89
94
  def criteria
90
95
  @param[:criteria]
91
96
  end
@@ -306,7 +311,7 @@ def range_start_cell_for_conditional_formatting(*args) # :nodoc:
306
311
 
307
312
  def row_col_param_for_conditional_formatting(*args)
308
313
  # Check for a cell reference in A1 notation and substitute row and column
309
- if args[0] =~ /^\D/
314
+ if args[0].to_s =~ /^\D/
310
315
  # Check for a user defined multiple range like B3:K6,B8:K11.
311
316
  user_range = args[0].sub(/^=/, '').gsub(/\s*,\s*/, ' ').gsub(/\$/, '') if args[0] =~ /,/
312
317
  end
@@ -383,7 +388,7 @@ def check_conditional_formatting_parameters(param) # :nodoc:
383
388
  end
384
389
 
385
390
  def convert_date_time_if_required(val)
386
- if val =~ /T/
391
+ if val.to_s =~ /T/
387
392
  date_time = convert_date_time(val)
388
393
  raise "Invalid date/time value '#{val}' in conditional_formatting()" unless date_time
389
394
  date_time
@@ -401,6 +406,7 @@ def valid_parameter_for_conditional_formatting
401
406
  :value,
402
407
  :minimum,
403
408
  :maximum,
409
+ :stop_if_true,
404
410
  :min_type,
405
411
  :mid_type,
406
412
  :max_type,
@@ -1,4 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
2
3
  require 'write_xlsx/package/xml_writer_simple'
3
4
  require 'write_xlsx/utility'
4
5
 
@@ -8,11 +9,13 @@ class SharedStrings
8
9
 
9
10
  include Writexlsx::Utility
10
11
 
12
+ PRESERVE_SPACE_ATTRIBUTES = ['xml:space', 'preserve'].freeze
13
+
11
14
  def initialize
12
15
  @writer = Package::XMLWriterSimple.new
13
16
  @strings = [] # string table
14
17
  @strings_index = {} # string table index
15
- @count = {} # count
18
+ @count = 0 # count
16
19
  end
17
20
 
18
21
  def index(string, params = {})
@@ -21,18 +24,18 @@ def index(string, params = {})
21
24
  end
22
25
 
23
26
  def add(string)
24
- str = string.dup
25
- if @count[str]
26
- @count[str] += 1
27
- else
27
+ unless @strings_index[string]
28
+ # Only first time the string will be append to list
29
+ # next time we only check and not #dup it
30
+ str = string.dup.freeze
28
31
  @strings << str
29
32
  @strings_index[str] = @strings.size - 1
30
- @count[str] = 1
31
33
  end
34
+ @count += 1
32
35
  end
33
36
 
34
37
  def string(index)
35
- @strings[index].dup
38
+ @strings[index]
36
39
  end
37
40
 
38
41
  def empty?
@@ -79,7 +82,6 @@ def write_sst_strings
79
82
  # Write the <si> element.
80
83
  #
81
84
  def write_si(string)
82
- string = string.dup
83
85
  attributes = []
84
86
 
85
87
  # Excel escapes control characters with _xHHHH_ and also escapes any
@@ -102,7 +104,7 @@ def write_si(string)
102
104
  end
103
105
 
104
106
  # Add attribute to preserve leading or trailing whitespace.
105
- attributes << ['xml:space', 'preserve'] if string =~ /\A\s|\s\Z/
107
+ attributes << PRESERVE_SPACE_ATTRIBUTES if string =~ /\A\s|\s\Z/
106
108
 
107
109
  # Write any rich strings without further tags.
108
110
  if string =~ %r{^<r>} && string =~ %r{</r>$}
@@ -122,7 +124,7 @@ def add_c2_c3(string)
122
124
  end
123
125
 
124
126
  def total_count
125
- @count.values.inject(0) { |sum, count| sum += count }
127
+ @count
126
128
  end
127
129
 
128
130
  def unique_count