write_xlsx 0.60.0 → 0.61.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 (43) hide show
  1. data/README.rdoc +11 -1
  2. data/examples/hide_row_col.rb +33 -0
  3. data/html/en/doc_en.html +7765 -0
  4. data/html/index.html +16 -0
  5. data/html/style.css +433 -0
  6. data/lib/write_xlsx/chart.rb +20 -0
  7. data/lib/write_xlsx/package/button.rb +132 -0
  8. data/lib/write_xlsx/package/comments.rb +97 -1
  9. data/lib/write_xlsx/package/shared_strings.rb +2 -2
  10. data/lib/write_xlsx/package/vml.rb +9 -419
  11. data/lib/write_xlsx/utility.rb +138 -0
  12. data/lib/write_xlsx/version.rb +1 -1
  13. data/lib/write_xlsx/workbook.rb +2 -2
  14. data/lib/write_xlsx/worksheet.rb +178 -115
  15. data/test/drawing/test_write_row.rb +1 -1
  16. data/test/perl_output/hide_row_col.xlsx +0 -0
  17. data/test/perl_output/merge4.xlsx +0 -0
  18. data/test/perl_output/merge6.xlsx +0 -0
  19. data/test/regression/{test_vml04.rb → disabled_test_vml04.rb} +0 -0
  20. data/test/regression/test_chart_size01.rb +41 -0
  21. data/test/regression/test_chart_size02.rb +41 -0
  22. data/test/regression/test_chart_size03.rb +39 -0
  23. data/test/regression/test_default_row01.rb +26 -0
  24. data/test/regression/test_default_row02.rb +28 -0
  25. data/test/regression/test_default_row03.rb +28 -0
  26. data/test/regression/test_default_row04.rb +31 -0
  27. data/test/regression/xlsx_files/chart_size01.xlsx +0 -0
  28. data/test/regression/xlsx_files/default_row01.xlsx +0 -0
  29. data/test/regression/xlsx_files/default_row02.xlsx +0 -0
  30. data/test/regression/xlsx_files/default_row03.xlsx +0 -0
  31. data/test/regression/xlsx_files/default_row04.xlsx +0 -0
  32. data/test/test_example_match.rb +22 -0
  33. data/test/worksheet/test_write_methods.rb +0 -7
  34. metadata +35 -22
  35. data/test/package/vml/test_write_anchor.rb +0 -14
  36. data/test/package/vml/test_write_column.rb +0 -14
  37. data/test/package/vml/test_write_fill.rb +0 -22
  38. data/test/package/vml/test_write_move_with_cells.rb +0 -14
  39. data/test/package/vml/test_write_row.rb +0 -14
  40. data/test/package/vml/test_write_shadow.rb +0 -14
  41. data/test/package/vml/test_write_size_with_cells.rb +0 -14
  42. data/test/package/vml/test_write_textbox.rb +0 -14
  43. data/test/worksheet/test_write_hyperlinks.rb +0 -27
@@ -14,8 +14,8 @@ module Writexlsx
14
14
  @count = {} # => count
15
15
  end
16
16
 
17
- def index(string)
18
- add(string)
17
+ def index(string, params = {})
18
+ add(string) unless params[:only_query]
19
19
  @strings.index(string)
20
20
  end
21
21
 
@@ -31,7 +31,7 @@ module Writexlsx
31
31
  worksheet.buttons_data.each do |button|
32
32
  # Write the v:shape element.
33
33
  vml_shape_id += 1
34
- write_button_shape(vml_shape_id, z_index, button)
34
+ button.write_shape(@writer, vml_shape_id, z_index)
35
35
  z_index += 1
36
36
  end
37
37
  end
@@ -41,7 +41,7 @@ module Writexlsx
41
41
  worksheet.comments_array.each do |comment|
42
42
  # Write the v:shape element.
43
43
  vml_shape_id += 1
44
- write_comment_shape(vml_shape_id, z_index, comment)
44
+ comment.write_shape(@writer, vml_shape_id, z_index)
45
45
  z_index += 1
46
46
  end
47
47
  end
@@ -52,22 +52,6 @@ module Writexlsx
52
52
 
53
53
  private
54
54
 
55
- #
56
- # Convert comment vertices from pixels to points.
57
- #
58
- def pixels_to_points(vertices)
59
- col_start, row_start, x1, y1,
60
- col_end, row_end, x2, y2,
61
- left, top, width, height = vertices.flatten
62
-
63
- left *= 0.75
64
- top *= 0.75
65
- width *= 0.75
66
- height *= 0.75
67
-
68
- [left, top, width, height]
69
- end
70
-
71
55
  #
72
56
  # Write the <xml> element. This is the root element of VML.
73
57
  #
@@ -91,9 +75,7 @@ module Writexlsx
91
75
  # Write the <o:shapelayout> element.
92
76
  #
93
77
  def write_shapelayout(data_id)
94
- ext = 'edit'
95
-
96
- attributes = ['v:ext', ext]
78
+ attributes = ['v:ext', 'edit']
97
79
 
98
80
  @writer.tag_elements('o:shapelayout', attributes) do
99
81
  # Write the o:idmap element.
@@ -105,10 +87,8 @@ module Writexlsx
105
87
  # Write the <o:idmap> element.
106
88
  #
107
89
  def write_idmap(data_id)
108
- ext = 'edit'
109
-
110
90
  attributes = [
111
- 'v:ext', ext,
91
+ 'v:ext', 'edit',
112
92
  'data', data_id
113
93
  ]
114
94
 
@@ -139,11 +119,11 @@ module Writexlsx
139
119
  #
140
120
  def write_button_shapetype
141
121
  attributes = [
142
- 'id', '_x0000_t201',
143
- 'coordsize', '21600,21600',
144
- 'o:spt', 201,
145
- 'path', 'm,l,21600r21600,l21600,xe'
146
- ]
122
+ 'id', '_x0000_t201',
123
+ 'coordsize', '21600,21600',
124
+ 'o:spt', 201,
125
+ 'path', 'm,l,21600r21600,l21600,xe'
126
+ ]
147
127
 
148
128
  @writer.tag_elements('v:shapetype', attributes) do
149
129
  # Write the v:stroke element.
@@ -155,29 +135,6 @@ module Writexlsx
155
135
  end
156
136
  end
157
137
 
158
- #
159
- # Write the <v:stroke> element.
160
- #
161
- def write_stroke
162
- joinstyle = 'miter'
163
-
164
- attributes = ['joinstyle', joinstyle]
165
-
166
- @writer.empty_tag('v:stroke', attributes)
167
- end
168
-
169
- #
170
- # Write the <v:path> element.
171
- #
172
- def write_comment_path(gradientshapeok, connecttype)
173
- attributes = []
174
-
175
- attributes << 'gradientshapeok' << 't' if gradientshapeok
176
- attributes << 'o:connecttype' << connecttype
177
-
178
- @writer.empty_tag('v:path', attributes)
179
- end
180
-
181
138
  #
182
139
  # Write the <v:path> element.
183
140
  #
@@ -202,373 +159,6 @@ module Writexlsx
202
159
  ]
203
160
  @writer.empty_tag('o:lock', attributes)
204
161
  end
205
-
206
- #
207
- # Write the <o:lock> element.
208
- #
209
- def write_rotation_lock
210
- attributes = [
211
- 'v:ext', 'edit',
212
- 'rotation', 't'
213
- ]
214
- @writer.empty_tag('o:lock', attributes)
215
- end
216
-
217
- #
218
- # Write the <v:shape> element.
219
- #
220
- def write_comment_shape(id, z_index, comment)
221
- type = '#_x0000_t202'
222
- insetmode = 'auto'
223
- visibility = 'hidden'
224
-
225
- # Set the shape index.
226
- id = '_x0000_s' + id.to_s
227
-
228
- left, top, width, height = pixels_to_points(comment.vertices)
229
-
230
- # Set the visibility.
231
- visibility = 'visible' if comment.visible != 0 && !comment.visible.nil?
232
-
233
- left_str = float_to_str(left)
234
- top_str = float_to_str(top)
235
- width_str = float_to_str(width)
236
- height_str = float_to_str(height)
237
- z_index_str = float_to_str(z_index)
238
-
239
- style =
240
- 'position:absolute;' +
241
- 'margin-left:' +
242
- left_str + 'pt;' +
243
- 'margin-top:' +
244
- top_str + 'pt;' +
245
- 'width:' +
246
- width_str + 'pt;' +
247
- 'height:' +
248
- height_str + 'pt;' +
249
- 'z-index:' +
250
- z_index_str + ';' +
251
- 'visibility:' +
252
- visibility
253
-
254
-
255
- attributes = [
256
- 'id', id,
257
- 'type', type,
258
- 'style', style,
259
- 'fillcolor', comment.color,
260
- 'o:insetmode', insetmode
261
- ]
262
-
263
- @writer.tag_elements('v:shape', attributes) do
264
- # Write the v:fill element.
265
- write_comment_fill
266
- # Write the v:shadow element.
267
- write_shadow
268
- # Write the v:path element.
269
- write_comment_path(nil, 'none')
270
- # Write the v:textbox element.
271
- write_comment_textbox
272
- # Write the x:ClientData element.
273
- write_comment_client_data(comment)
274
- end
275
- end
276
-
277
- #
278
- # Write the <v:shape> element.
279
- #
280
- def write_button_shape(id, z_index, button)
281
- type = '#_x0000_t201'
282
-
283
- # Set the shape index.
284
- id = "_x0000_s#{id}"
285
-
286
- left, top, width, height = pixels_to_points(button[:_vertices])
287
-
288
- left_str = float_to_str(left)
289
- top_str = float_to_str(top)
290
- width_str = float_to_str(width)
291
- height_str = float_to_str(height)
292
- z_index_str = float_to_str(z_index)
293
-
294
- style =
295
- 'position:absolute;' +
296
- 'margin-left:' +
297
- left_str + 'pt;' +
298
- 'margin-top:' +
299
- top_str + 'pt;' +
300
- 'width:' +
301
- width_str + 'pt;' +
302
- 'height:' +
303
- height_str + 'pt;' +
304
- 'z-index:' +
305
- z_index_str + ';' +
306
- 'mso-wrap-style:tight'
307
-
308
- attributes = [
309
- 'id', id,
310
- 'type', type,
311
- 'style', style,
312
- 'o:button', 't',
313
- 'fillcolor', 'buttonFace [67]',
314
- 'strokecolor', 'windowText [64]',
315
- 'o:insetmode', 'auto'
316
- ]
317
-
318
- @writer.tag_elements('v:shape', attributes) do
319
- # Write the v:fill element.
320
- write_button_fill
321
- # Write the o:lock element.
322
- write_rotation_lock
323
- # Write the v:textbox element.
324
- write_button_textbox(button[:_font])
325
- # Write the x:ClientData element.
326
- write_button_client_data(button)
327
- end
328
- end
329
-
330
- def float_to_str(float)
331
- return '' unless float
332
- if float == float.to_i
333
- float.to_i.to_s
334
- else
335
- float.to_s
336
- end
337
- end
338
-
339
- #
340
- # Write the <v:fill> element.
341
- #
342
- def write_comment_fill
343
- color_2 = '#ffffe1'
344
- attributes = ['color2', color_2]
345
-
346
- @writer.empty_tag('v:fill', attributes)
347
- end
348
-
349
- #
350
- # Write the <v:fill> element.
351
- #
352
- def write_button_fill
353
- color_2 = 'buttonFace [67]'
354
- detectmouseclick = 't'
355
-
356
- attributes = [
357
- 'color2', color_2,
358
- 'o:detectmouseclick', detectmouseclick
359
- ]
360
-
361
- @writer.empty_tag('v:fill', attributes)
362
- end
363
-
364
- #
365
- # Write the <v:shadow> element.
366
- #
367
- def write_shadow
368
- on = 't'
369
- color = 'black'
370
- obscured = 't'
371
-
372
- attributes = [
373
- 'on', on,
374
- 'color', color,
375
- 'obscured', obscured
376
- ]
377
-
378
- @writer.empty_tag('v:shadow', attributes)
379
- end
380
-
381
- #
382
- # Write the <v:textbox> element.
383
- #
384
- def write_comment_textbox
385
- style = 'mso-direction-alt:auto'
386
-
387
- attributes = ['style', style]
388
-
389
- @writer.tag_elements('v:textbox', attributes) do
390
- # Write the div element.
391
- write_div('left')
392
- end
393
- end
394
-
395
- #
396
- # Write the <v:textbox> element.
397
- #
398
- def write_button_textbox(font)
399
- style = 'mso-direction-alt:auto'
400
-
401
- attributes = ['style', style, 'o:singleclick', 'f']
402
-
403
- @writer.tag_elements('v:textbox', attributes) do
404
- # Write the div element.
405
- write_div('center', font)
406
- end
407
- end
408
-
409
- #
410
- # Write the <div> element.
411
- #
412
- def write_div(align, font = nil)
413
- style = "text-align:#{align}"
414
- attributes = ['style', style]
415
-
416
- @writer.tag_elements('div', attributes) do
417
- if font
418
- # Write the font element.
419
- write_font(font)
420
- end
421
- end
422
- end
423
-
424
- #
425
- # Write the <font> element.
426
- #
427
- def write_font(font)
428
- caption = font[:_caption]
429
- face = 'Calibri'
430
- size = 220
431
- color = '#000000'
432
-
433
- attributes = [
434
- 'face', face,
435
- 'size', size,
436
- 'color', color
437
- ]
438
- @writer.data_element('font', caption, attributes)
439
- end
440
-
441
- #
442
- # Write the <x:ClientData> element.
443
- #
444
- def write_comment_client_data(comment)
445
- object_type = 'Note'
446
-
447
- attributes = ['ObjectType', object_type]
448
-
449
- @writer.tag_elements('x:ClientData', attributes) do
450
- # Write the x:MoveWithCells element.
451
- write_move_with_cells
452
- # Write the x:SizeWithCells element.
453
- write_size_with_cells
454
- # Write the x:Anchor element.
455
- write_anchor(comment.vertices)
456
- # Write the x:AutoFill element.
457
- write_auto_fill
458
- # Write the x:Row element.
459
- write_row(comment.row)
460
- # Write the x:Column element.
461
- write_column(comment.col)
462
- # Write the x:Visible element.
463
- write_visible if comment.visible != 0 && !comment.visible.nil?
464
- end
465
- end
466
-
467
- #
468
- # Write the <x:ClientData> element.
469
- #
470
- def write_button_client_data(button)
471
- object_type = 'Button'
472
-
473
- attributes = ['ObjectType', object_type]
474
-
475
- @writer.tag_elements('x:ClientData', attributes) do
476
- # Write the x:Anchor element.
477
- write_anchor(button[:_vertices])
478
- # Write the x:PrintObject element.
479
- write_print_object
480
- # Write the x:AutoFill element.
481
- write_auto_fill
482
- # Write the x:FmlaMacro element.
483
- write_fmla_macro(button[:_macro])
484
- # Write the x:TextHAlign element.
485
- write_text_halign
486
- # Write the x:TextVAlign element.
487
- write_text_valign
488
- end
489
- end
490
-
491
- #
492
- # Write the <x:MoveWithCells> element.
493
- #
494
- def write_move_with_cells
495
- @writer.empty_tag('x:MoveWithCells')
496
- end
497
-
498
- #
499
- # Write the <x:SizeWithCells> element.
500
- #
501
- def write_size_with_cells
502
- @writer.empty_tag('x:SizeWithCells')
503
- end
504
-
505
- #
506
- # Write the <x:Visible> element.
507
- #
508
- def write_visible
509
- @writer.empty_tag('x:Visible')
510
- end
511
-
512
- #
513
- # Write the <x:Anchor> element.
514
- #
515
- def write_anchor(vertices)
516
- col_start, row_start, x1, y1, col_end, row_end, x2, y2 = vertices
517
- data = [col_start, x1, row_start, y1, col_end, x2, row_end, y2].join(', ')
518
-
519
- @writer.data_element('x:Anchor', data)
520
- end
521
-
522
- #
523
- # Write the <x:AutoFill> element.
524
- #
525
- def write_auto_fill
526
- data = 'False'
527
-
528
- @writer.data_element('x:AutoFill', data)
529
- end
530
-
531
- #
532
- # Write the <x:Row> element.
533
- #
534
- def write_row(data)
535
- @writer.data_element('x:Row', data)
536
- end
537
-
538
- #
539
- # Write the <x:Column> element.
540
- #
541
- def write_column(data)
542
- @writer.data_element('x:Column', data)
543
- end
544
-
545
- #
546
- # Write the <x:PrintObject> element.
547
- #
548
- def write_print_object
549
- @writer.data_element('x:PrintObject', 'False')
550
- end
551
-
552
- #
553
- # Write the <x:TextHAlign> element.
554
- #
555
- def write_text_halign
556
- @writer.data_element('x:TextHAlign', 'Center')
557
- end
558
-
559
- #
560
- # Write the <x:TextVAlign> element.
561
- #
562
- def write_text_valign
563
- @writer.data_element('x:TextVAlign', 'Center')
564
- end
565
-
566
- #
567
- # Write the <x:FmlaMacro> element.
568
- #
569
- def write_fmla_macro(data)
570
- @writer.data_element('x:FmlaMacro', data)
571
- end
572
162
  end
573
163
  end
574
164
  end
@@ -357,5 +357,143 @@ module Writexlsx
357
357
  @dim_colmin = col if !@dim_colmin || (col < @dim_colmin)
358
358
  @dim_colmax = col if !@dim_colmax || (col > @dim_colmax)
359
359
  end
360
+
361
+ def float_to_str(float)
362
+ return '' unless float
363
+ if float == float.to_i
364
+ float.to_i.to_s
365
+ else
366
+ float.to_s
367
+ end
368
+ end
369
+
370
+ #
371
+ # Convert vertices from pixels to points.
372
+ #
373
+ def pixels_to_points(vertices)
374
+ col_start, row_start, x1, y1,
375
+ col_end, row_end, x2, y2,
376
+ left, top, width, height = vertices.flatten
377
+
378
+ left *= 0.75
379
+ top *= 0.75
380
+ width *= 0.75
381
+ height *= 0.75
382
+
383
+ [left, top, width, height]
384
+ end
385
+
386
+ def v_shape_attributes_base(id, z_index)
387
+ [
388
+ 'id', "_x0000_s#{id}",
389
+ 'type', type,
390
+ 'style', (v_shape_style_base(z_index, vertices) + style_addition).join,
391
+ ]
392
+ end
393
+
394
+ def v_shape_style_base(z_index, vertices)
395
+ left, top, width, height = pixels_to_points(vertices)
396
+
397
+ left_str = float_to_str(left)
398
+ top_str = float_to_str(top)
399
+ width_str = float_to_str(width)
400
+ height_str = float_to_str(height)
401
+ z_index_str = float_to_str(z_index)
402
+
403
+ shape_style_base(left_str, top_str, width_str, height_str, z_index_str)
404
+ end
405
+
406
+ def shape_style_base(left_str, top_str, width_str, height_str, z_index_str)
407
+ [
408
+ 'position:absolute;',
409
+ 'margin-left:',
410
+ left_str, 'pt;',
411
+ 'margin-top:',
412
+ top_str, 'pt;',
413
+ 'width:',
414
+ width_str, 'pt;',
415
+ 'height:',
416
+ height_str, 'pt;',
417
+ 'z-index:',
418
+ z_index_str, ';'
419
+ ]
420
+ end
421
+
422
+ #
423
+ # Write the <v:fill> element.
424
+ #
425
+ def write_fill
426
+ @writer.empty_tag('v:fill', fill_attributes)
427
+ end
428
+
429
+ #
430
+ # Write the <v:path> element.
431
+ #
432
+ def write_comment_path(gradientshapeok, connecttype)
433
+ attributes = []
434
+
435
+ attributes << 'gradientshapeok' << 't' if gradientshapeok
436
+ attributes << 'o:connecttype' << connecttype
437
+
438
+ @writer.empty_tag('v:path', attributes)
439
+ end
440
+
441
+ #
442
+ # Write the <x:Anchor> element.
443
+ #
444
+ def write_anchor
445
+ col_start, row_start, x1, y1, col_end, row_end, x2, y2 = vertices
446
+ data = [col_start, x1, row_start, y1, col_end, x2, row_end, y2].join(', ')
447
+
448
+ @writer.data_element('x:Anchor', data)
449
+ end
450
+
451
+ #
452
+ # Write the <x:AutoFill> element.
453
+ #
454
+ def write_auto_fill
455
+ @writer.data_element('x:AutoFill', 'False')
456
+ end
457
+
458
+ #
459
+ # Write the <div> element.
460
+ #
461
+ def write_div(align, font = nil)
462
+ style = "text-align:#{align}"
463
+ attributes = ['style', style]
464
+
465
+ @writer.tag_elements('div', attributes) do
466
+ if font
467
+ # Write the font element.
468
+ write_font(font)
469
+ end
470
+ end
471
+ end
472
+
473
+ #
474
+ # Write the <font> element.
475
+ #
476
+ def write_font(font)
477
+ caption = font[:_caption]
478
+ face = 'Calibri'
479
+ size = 220
480
+ color = '#000000'
481
+
482
+ attributes = [
483
+ 'face', face,
484
+ 'size', size,
485
+ 'color', color
486
+ ]
487
+ @writer.data_element('font', caption, attributes)
488
+ end
489
+
490
+ #
491
+ # Write the <v:stroke> element.
492
+ #
493
+ def write_stroke
494
+ attributes = ['joinstyle', 'miter']
495
+
496
+ @writer.empty_tag('v:stroke', attributes)
497
+ end
360
498
  end
361
499
  end
@@ -1,5 +1,5 @@
1
1
  require 'write_xlsx/workbook'
2
2
 
3
3
  class WriteXLSX < Writexlsx::Workbook
4
- VERSION = "0.60.0"
4
+ VERSION = "0.61.0"
5
5
  end
@@ -870,8 +870,8 @@ module Writexlsx
870
870
  # Add a string to the shared string table, if it isn't already there, and
871
871
  # return the string index.
872
872
  #
873
- def shared_string_index(str) #:nodoc:
874
- @shared_strings.index(str)
873
+ def shared_string_index(str, params = {}) #:nodoc:
874
+ @shared_strings.index(str, params)
875
875
  end
876
876
 
877
877
  def str_unique