write_xlsx 0.85.11 → 0.86.0

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