write_xlsx 0.85.7 → 0.86.0

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