write_xlsx 0.85.11 → 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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/Changes +17 -0
  3. data/examples/colors.rb +47 -0
  4. data/examples/comments2.rb +1 -1
  5. data/examples/conditional_format.rb +60 -9
  6. data/examples/data_validate.rb +7 -7
  7. data/examples/panes.rb +1 -1
  8. data/examples/tab_colors.rb +1 -1
  9. data/lib/write_xlsx/format.rb +1 -1
  10. data/lib/write_xlsx/package/app.rb +12 -0
  11. data/lib/write_xlsx/package/comments.rb +4 -2
  12. data/lib/write_xlsx/package/conditional_format.rb +6 -0
  13. data/lib/write_xlsx/package/table.rb +17 -5
  14. data/lib/write_xlsx/package/xml_writer_simple.rb +3 -2
  15. data/lib/write_xlsx/version.rb +1 -1
  16. data/lib/write_xlsx/workbook.rb +12 -11
  17. data/lib/write_xlsx/worksheet.rb +20 -4
  18. data/lib/write_xlsx/worksheet/data_validation.rb +22 -10
  19. data/lib/write_xlsx/worksheet/hyperlink.rb +12 -8
  20. data/test/regression/images/red_208.png +0 -0
  21. data/test/regression/test_data_validation08.rb +24 -0
  22. data/test/regression/test_hyperlink22.rb +24 -0
  23. data/test/regression/test_hyperlink23.rb +24 -0
  24. data/test/regression/test_hyperlink24.rb +24 -0
  25. data/test/regression/test_image28.rb +27 -0
  26. data/test/regression/test_image29.rb +27 -0
  27. data/test/regression/test_image30.rb +27 -0
  28. data/test/regression/test_image31.rb +30 -0
  29. data/test/regression/test_image32.rb +28 -0
  30. data/test/regression/test_image33.rb +32 -0
  31. data/test/regression/test_properties02.rb +28 -0
  32. data/test/regression/xlsx_files/data_validation08.xlsx +0 -0
  33. data/test/regression/xlsx_files/hyperlink22.xlsx +0 -0
  34. data/test/regression/xlsx_files/hyperlink23.xlsx +0 -0
  35. data/test/regression/xlsx_files/hyperlink24.xlsx +0 -0
  36. data/test/regression/xlsx_files/image28.xlsx +0 -0
  37. data/test/regression/xlsx_files/image29.xlsx +0 -0
  38. data/test/regression/xlsx_files/image30.xlsx +0 -0
  39. data/test/regression/xlsx_files/image31.xlsx +0 -0
  40. data/test/regression/xlsx_files/image32.xlsx +0 -0
  41. data/test/regression/xlsx_files/image33.xlsx +0 -0
  42. data/test/regression/xlsx_files/properties02.xlsx +0 -0
  43. data/test/regression/xlsx_files/table18.xlsx +0 -0
  44. data/test/regression/xlsx_files/table19.xlsx +0 -0
  45. data/test/worksheet/test_cond_format_21.rb +90 -0
  46. data/test/worksheet/test_sparkline_12.rb +94 -0
  47. data/test/worksheet/test_write_data_validation_02.rb +14 -1
  48. metadata +56 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89f382bd2df994369316a0422365541984f53ec084c5d3bb1c5d5a03523757a9
4
- data.tar.gz: 363697c51b2250602fd5122aa3e9c7a6c71ec755a671e659f08f19c58b184792
3
+ metadata.gz: 794b9b3028ff50abeab1e2c85d951fdc38526887ef6e2d64c6125afe697b4f92
4
+ data.tar.gz: 0a460f71a4cb05d4f72d7ad77308dbcda504b06f0e56ceceb7d0a9a6e0c0514f
5
5
  SHA512:
6
- metadata.gz: c719aa61decdc25064a72704d015d8a1eea48b3a94ccb7ccaf01e99456a6521c5c4fc5a5ee738a721c1e06c4632c737cf47d14afd3830a164162a789acc6e452
7
- data.tar.gz: 96f55161f36511ef22708a377ea647f21f4ae76c978039b0c85c32c5db55ac0330f3e4c7a0e1f030d60c3d00c0c96f6c3f045bbfd240a2e2031c8ced2b2c2945
6
+ metadata.gz: b51f580ca37d7586f3faa6bafebeb76f2b14129070a0e7e70fe9d648e75e504983ad2ad97976ba49b3a8bb5af598826f54aa982dd73a7044132f32044bac6469
7
+ data.tar.gz: 661206fe8a1eeb9878329559ee9bf5f2a8f12db9515fba264368fe2f9df8711bffe4bb2457a51fb993dcb7aa74ce1c1fcd9740b6b05c6666edebae9288e2e66c
data/Changes CHANGED
@@ -1,5 +1,22 @@
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
+
3
20
  2020-10-23 v0.85.11
4
21
  Added Worksheet#update_range_format_with_params
5
22
 
@@ -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
@@ -582,7 +582,7 @@ def set_border_color(color)
582
582
  def set_rotation(rotation)
583
583
  if rotation == 270
584
584
  rotation = 255
585
- elsif rotation >= -90 || rotation <= 90
585
+ elsif rotation >= -90 && rotation <= 90
586
586
  rotation = -rotation + 90 if rotation < 0
587
587
  else
588
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
@@ -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,
@@ -10,7 +10,7 @@ class Table
10
10
 
11
11
  class ColumnData
12
12
  attr_reader :id
13
- attr_accessor :name, :format, :formula
13
+ attr_accessor :name, :format, :formula, :name_format
14
14
  attr_accessor :total_string, :total_function
15
15
 
16
16
  def initialize(id, param = {})
@@ -20,6 +20,7 @@ def initialize(id, param = {})
20
20
  @total_function = ''
21
21
  @formula = ''
22
22
  @format = nil
23
+ @name_format = nil
23
24
  @user_data = param[id-1] if param
24
25
  end
25
26
  end
@@ -93,10 +94,14 @@ def overrite_the_defaults_with_any_use_defined_values(col_id, col_data, col_num)
93
94
  if user_data[:header] && !user_data[:header].empty?
94
95
  col_data.name = user_data[:header]
95
96
  end
97
+
98
+ # Get the header format if defined.
99
+ col_data.name_format = user_data[:header_format]
100
+
96
101
  # Handle the column formula.
97
102
  handle_the_column_formula(
98
- col_data, col_num, user_data[:formula], user_data[:format]
99
- )
103
+ col_data, col_num, user_data[:formula], user_data[:format]
104
+ )
100
105
 
101
106
  # Handle the function for the total row.
102
107
  if user_data[:total_function]
@@ -123,7 +128,9 @@ def overrite_the_defaults_with_any_use_defined_values(col_id, col_data, col_num)
123
128
 
124
129
  def write_the_column_headers_to_the_worksheet(col_num, col_data)
125
130
  if @param[:header_row] != 0
126
- @worksheet.write_string(@row1, col_num, col_data.name)
131
+ @worksheet.write_string(
132
+ @row1, col_num, col_data.name, col_data.name_format
133
+ )
127
134
  end
128
135
  end
129
136
 
@@ -268,7 +275,12 @@ def set_the_table_style
268
275
  end
269
276
 
270
277
  def set_the_table_name
271
- @name = @param[:name] if @param[:name]
278
+ if @param[:name]
279
+ name = @param[:name]
280
+
281
+ raise "Name '#{name} in add_table cannot contain spaces" if name =~ /\s/
282
+ @name = @param[:name]
283
+ end
272
284
  end
273
285
 
274
286
  def set_the_table_and_autofilter_ranges
@@ -118,13 +118,14 @@ def key_vals(attribute)
118
118
  end
119
119
 
120
120
  def escape_attributes(str = '')
121
- return str if !(str.to_s =~ /["&<>]/)
121
+ return str if !(str.to_s =~ /["&<>\n]/)
122
122
 
123
123
  str.
124
124
  gsub(/&/, "&amp;").
125
125
  gsub(/"/, "&quot;").
126
126
  gsub(/</, "&lt;").
127
- gsub(/>/, "&gt;")
127
+ gsub(/>/, "&gt;").
128
+ gsub(/\n/, "&#xA;")
128
129
  end
129
130
 
130
131
  def escape_data(str = '')
@@ -1 +1 @@
1
- WriteXLSX_VERSION = "0.85.11"
1
+ WriteXLSX_VERSION = "0.86.0"
@@ -786,17 +786,18 @@ def set_properties(params)
786
786
 
787
787
  # List of valid input parameters.
788
788
  valid = {
789
- :title => 1,
790
- :subject => 1,
791
- :author => 1,
792
- :keywords => 1,
793
- :comments => 1,
794
- :last_author => 1,
795
- :created => 1,
796
- :category => 1,
797
- :manager => 1,
798
- :company => 1,
799
- :status => 1
789
+ :title => 1,
790
+ :subject => 1,
791
+ :author => 1,
792
+ :keywords => 1,
793
+ :comments => 1,
794
+ :last_author => 1,
795
+ :created => 1,
796
+ :category => 1,
797
+ :manager => 1,
798
+ :company => 1,
799
+ :status => 1,
800
+ :hyperlink_base => 1
800
801
  }
801
802
 
802
803
  # Check for valid input parameters.
@@ -296,6 +296,7 @@ class Worksheet
296
296
  attr_reader :comments, :comments_author # :nodoc:
297
297
  attr_accessor :dxf_priority # :nodoc:
298
298
  attr_reader :vba_codename # :nodoc:
299
+ attr_writer :excel_version
299
300
 
300
301
  def initialize(workbook, index, name) #:nodoc:
301
302
  @writer = Package::XMLWriterSimple.new
@@ -4288,7 +4289,7 @@ def conditional_formatting(*args)
4288
4289
  # :header
4289
4290
  # :formula
4290
4291
  # :total_string
4291
- # :total_function
4292
+ # :
4292
4293
  # :format
4293
4294
  #
4294
4295
  # The column data must be specified as an array of hash. For example to
@@ -4916,9 +4917,8 @@ def insert_button(*args)
4916
4917
  # :custom
4917
4918
  #
4918
4919
  # +:any+ is used to specify that the type of data is unrestricted.
4919
- # This is the same as not applying a data validation. It is only
4920
- # provided for completeness and isn't used very often in the
4921
- # context of WriteXLSX.
4920
+ # This is usefl to display an input message without restricting the data
4921
+ # that can be entered.
4922
4922
  #
4923
4923
  # +:integer+ restricts the cell to integer values. Excel refers to this
4924
4924
  # as 'whole number'.
@@ -5802,6 +5802,22 @@ def get_range_data(row_start, col_start, row_end, col_end) # :nodoc:
5802
5802
  # width # Width of object frame.
5803
5803
  # height # Height of object frame.
5804
5804
  def position_object_pixels(col_start, row_start, x1, y1, width, height) #:nodoc:
5805
+ # Adjust start column for negative offsets.
5806
+ while x1 < 0 && col_start > 0
5807
+ x1 += size_col(col_start - 1)
5808
+ col_start -= 1
5809
+ end
5810
+
5811
+ # Adjust start row for negative offsets.
5812
+ while y1 < 0 && row_start > 0
5813
+ y1 += size_row(row_start - 1)
5814
+ row_start -= 1
5815
+ end
5816
+
5817
+ # Ensure that the image isn't shifted off the page at top left.
5818
+ x1 = 0 if x1 < 0
5819
+ y1 = 0 if y1 < 0
5820
+
5805
5821
  # Calculate the absolute x offset of the top-left vertex.
5806
5822
  if @col_size_changed
5807
5823
  x_abs = (0 .. col_start-1).inject(0) {|sum, col| sum += size_col(col)}