write_xlsx 0.72.2 → 0.72.3.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/{README.rdoc → Changes} +3 -94
  3. data/README.md +96 -0
  4. data/lib/write_xlsx/chart.rb +115 -259
  5. data/lib/write_xlsx/chart/axis.rb +4 -4
  6. data/lib/write_xlsx/chart/bar.rb +1 -1
  7. data/lib/write_xlsx/chart/column.rb +1 -1
  8. data/lib/write_xlsx/chart/pie.rb +3 -3
  9. data/lib/write_xlsx/chart/radar.rb +1 -1
  10. data/lib/write_xlsx/chart/scatter.rb +1 -1
  11. data/lib/write_xlsx/chart/series.rb +0 -37
  12. data/lib/write_xlsx/chartsheet.rb +25 -37
  13. data/lib/write_xlsx/col_name.rb +40 -0
  14. data/lib/write_xlsx/drawing.rb +95 -85
  15. data/lib/write_xlsx/format.rb +32 -32
  16. data/lib/write_xlsx/package/app.rb +18 -23
  17. data/lib/write_xlsx/package/button.rb +15 -12
  18. data/lib/write_xlsx/package/comments.rb +33 -30
  19. data/lib/write_xlsx/package/conditional_format.rb +18 -14
  20. data/lib/write_xlsx/package/content_types.rb +22 -17
  21. data/lib/write_xlsx/package/core.rb +19 -24
  22. data/lib/write_xlsx/package/relationships.rb +10 -13
  23. data/lib/write_xlsx/package/shared_strings.rb +8 -16
  24. data/lib/write_xlsx/package/styles.rb +59 -64
  25. data/lib/write_xlsx/package/table.rb +27 -37
  26. data/lib/write_xlsx/package/vml.rb +23 -21
  27. data/lib/write_xlsx/package/xml_writer_simple.rb +3 -6
  28. data/lib/write_xlsx/sheets.rb +4 -4
  29. data/lib/write_xlsx/sparkline.rb +22 -22
  30. data/lib/write_xlsx/utility.rb +61 -33
  31. data/lib/write_xlsx/version.rb +1 -1
  32. data/lib/write_xlsx/workbook.rb +46 -50
  33. data/lib/write_xlsx/worksheet.rb +149 -133
  34. data/lib/write_xlsx/worksheet/cell_data.rb +8 -6
  35. data/lib/write_xlsx/worksheet/data_validation.rb +14 -14
  36. data/lib/write_xlsx/worksheet/hyperlink.rb +97 -65
  37. data/lib/write_xlsx/worksheet/page_setup.rb +23 -22
  38. data/test/chart/test_write_a_latin.rb +3 -3
  39. data/test/regression/test_chart_font01.rb +1 -1
  40. data/test/regression/test_chart_font02.rb +1 -1
  41. data/test/regression/test_chart_font03.rb +1 -1
  42. data/test/regression/test_chart_font04.rb +1 -1
  43. data/test/regression/test_chart_font05.rb +1 -1
  44. data/test/regression/test_chart_font06.rb +1 -1
  45. data/test/test_xml_writer_simple.rb +3 -3
  46. data/test/worksheet/test_write_hyperlink.rb +4 -4
  47. data/test/worksheet/test_write_worksheet_attributes.rb +3 -3
  48. data/write_xlsx.gemspec +2 -1
  49. metadata +9 -8
  50. data/test/package/table/test_write_xml_declaration.rb +0 -20
@@ -57,17 +57,14 @@ def set_xml_writer(filename)
57
57
  # Assemble and writes the XML file.
58
58
  #
59
59
  def assemble_xml_file
60
- write_xml_declaration
61
- # Write the table element.
62
- @writer.tag_elements('table', write_table_attributes) do
63
- write_auto_filter
64
- write_table_columns
65
- write_table_style_info
60
+ write_xml_declaration do
61
+ # Write the table element.
62
+ @writer.tag_elements('table', write_table_attributes) do
63
+ write_auto_filter
64
+ write_table_columns
65
+ write_table_style_info
66
+ end
66
67
  end
67
-
68
- # Close the XML writer object and filehandle.
69
- @writer.crlf
70
- @writer.close
71
68
  end
72
69
 
73
70
  def add_the_table_columns
@@ -284,33 +281,26 @@ def set_the_autofilter_range
284
281
  @autofilter = @a_range if ptrue?(@param[:autofilter])
285
282
  end
286
283
 
287
- #
288
- # Write the XML declaration.
289
- #
290
- def write_xml_declaration
291
- @writer.xml_decl('UTF-8', 1)
292
- end
293
-
294
284
  def write_table_attributes
295
285
  schema = 'http://schemas.openxmlformats.org/'
296
286
  xmlns = "#{schema}spreadsheetml/2006/main"
297
287
 
298
288
  attributes = [
299
- 'xmlns', xmlns,
300
- 'id', @id,
301
- 'name', @name,
302
- 'displayName', @name,
303
- 'ref', @range
289
+ ['xmlns', xmlns],
290
+ ['id', @id],
291
+ ['name', @name],
292
+ ['displayName', @name],
293
+ ['ref', @range]
304
294
  ]
305
295
 
306
296
  unless ptrue?(@header_row_count)
307
- attributes << 'headerRowCount' << 0
297
+ attributes << ['headerRowCount', 0]
308
298
  end
309
299
 
310
300
  if ptrue?(@totals_row_shown)
311
- attributes << 'totalsRowCount' << 1
301
+ attributes << ['totalsRowCount', 1]
312
302
  else
313
- attributes << 'totalsRowShown' << 0
303
+ attributes << ['totalsRowShown', 0]
314
304
  end
315
305
  end
316
306
 
@@ -320,7 +310,7 @@ def write_table_attributes
320
310
  def write_auto_filter
321
311
  return unless ptrue?(@autofilter)
322
312
 
323
- attributes = ['ref', @autofilter]
313
+ attributes = [ ['ref', @autofilter] ]
324
314
 
325
315
  @writer.empty_tag('autoFilter', attributes)
326
316
  end
@@ -331,7 +321,7 @@ def write_auto_filter
331
321
  def write_table_columns
332
322
  count = @columns.size
333
323
 
334
- attributes = ['count', count]
324
+ attributes = [ ['count', count] ]
335
325
 
336
326
  @writer.tag_elements('tableColumns', attributes) do
337
327
  @columns.each {|col_data| write_table_column(col_data)}
@@ -343,18 +333,18 @@ def write_table_columns
343
333
  #
344
334
  def write_table_column(col_data)
345
335
  attributes = [
346
- 'id', col_data.id,
347
- 'name', col_data.name
336
+ ['id', col_data.id],
337
+ ['name', col_data.name]
348
338
  ]
349
339
 
350
340
  if ptrue?(col_data.total_string)
351
- attributes << :totalsRowLabel << col_data.total_string
341
+ attributes << [:totalsRowLabel, col_data.total_string]
352
342
  elsif ptrue?(col_data.total_function)
353
- attributes << :totalsRowFunction << col_data.total_function
343
+ attributes << [:totalsRowFunction, col_data.total_function]
354
344
  end
355
345
 
356
346
  if col_data.format
357
- attributes << :dataDxfId << col_data.format
347
+ attributes << [:dataDxfId, col_data.format]
358
348
  end
359
349
 
360
350
  if ptrue?(col_data.formula)
@@ -372,11 +362,11 @@ def write_table_column(col_data)
372
362
  #
373
363
  def write_table_style_info
374
364
  attributes = [
375
- 'name', @style,
376
- 'showFirstColumn', @show_first_col,
377
- 'showLastColumn', @show_last_col,
378
- 'showRowStripes', @show_row_stripes,
379
- 'showColumnStripes', @show_col_stripes
365
+ ['name', @style],
366
+ ['showFirstColumn', @show_first_col],
367
+ ['showLastColumn', @show_last_col],
368
+ ['showRowStripes', @show_row_stripes],
369
+ ['showColumnStripes', @show_col_stripes]
380
370
  ]
381
371
 
382
372
  @writer.empty_tag('tableStyleInfo', attributes)
@@ -72,9 +72,9 @@ def write_xml_namespace
72
72
  def xml_attributes
73
73
  schema = 'urn:schemas-microsoft-com:'
74
74
  [
75
- 'xmlns:v', "#{schema}vml",
76
- 'xmlns:o', "#{schema}office:office",
77
- 'xmlns:x', "#{schema}office:excel"
75
+ ['xmlns:v', "#{schema}vml"],
76
+ ['xmlns:o', "#{schema}office:office"],
77
+ ['xmlns:x', "#{schema}office:excel"]
78
78
  ]
79
79
  end
80
80
 
@@ -82,7 +82,9 @@ def xml_attributes
82
82
  # Write the <o:shapelayout> element.
83
83
  #
84
84
  def write_shapelayout(data_id)
85
- attributes = ['v:ext', 'edit']
85
+ attributes = [
86
+ ['v:ext', 'edit']
87
+ ]
86
88
 
87
89
  @writer.tag_elements('o:shapelayout', attributes) do
88
90
  # Write the o:idmap element.
@@ -95,8 +97,8 @@ def write_shapelayout(data_id)
95
97
  #
96
98
  def write_idmap(data_id)
97
99
  attributes = [
98
- 'v:ext', 'edit',
99
- 'data', data_id
100
+ ['v:ext', 'edit'],
101
+ ['data', data_id]
100
102
  ]
101
103
 
102
104
  @writer.empty_tag('o:idmap', attributes)
@@ -107,10 +109,10 @@ def write_idmap(data_id)
107
109
  #
108
110
  def write_comment_shapetype
109
111
  attributes = [
110
- 'id', '_x0000_t202',
111
- 'coordsize', '21600,21600',
112
- 'o:spt', 202,
113
- 'path', 'm,l,21600r21600,l21600,xe'
112
+ ['id', '_x0000_t202'],
113
+ ['coordsize', '21600,21600'],
114
+ ['o:spt', 202],
115
+ ['path', 'm,l,21600r21600,l21600,xe']
114
116
  ]
115
117
 
116
118
  @writer.tag_elements('v:shapetype', attributes) do
@@ -126,10 +128,10 @@ def write_comment_shapetype
126
128
  #
127
129
  def write_button_shapetype
128
130
  attributes = [
129
- 'id', '_x0000_t201',
130
- 'coordsize', '21600,21600',
131
- 'o:spt', 201,
132
- 'path', 'm,l,21600r21600,l21600,xe'
131
+ ['id', '_x0000_t201'],
132
+ ['coordsize', '21600,21600'],
133
+ ['o:spt', 201],
134
+ ['path', 'm,l,21600r21600,l21600,xe']
133
135
  ]
134
136
 
135
137
  @writer.tag_elements('v:shapetype', attributes) do
@@ -147,11 +149,11 @@ def write_button_shapetype
147
149
  #
148
150
  def write_button_path
149
151
  attributes = [
150
- 'shadowok', 'f',
151
- 'o:extrusionok', 'f',
152
- 'strokeok', 'f',
153
- 'fillok', 'f',
154
- 'o:connecttype', 'rect'
152
+ ['shadowok', 'f'],
153
+ ['o:extrusionok', 'f'],
154
+ ['strokeok', 'f'],
155
+ ['fillok', 'f'],
156
+ ['o:connecttype', 'rect']
155
157
  ]
156
158
  @writer.empty_tag('v:path', attributes)
157
159
  end
@@ -161,8 +163,8 @@ def write_button_path
161
163
  #
162
164
  def write_shapetype_lock
163
165
  attributes = [
164
- 'v:ext', 'edit',
165
- 'shapetype', 't'
166
+ ['v:ext', 'edit'],
167
+ ['shapetype', 't']
166
168
  ]
167
169
  @writer.empty_tag('o:lock', attributes)
168
170
  end
@@ -110,12 +110,9 @@ def key_val(key, val)
110
110
  %Q{ #{key}="#{val}"}
111
111
  end
112
112
 
113
- def key_vals(attr)
114
- array = []
115
- (0 .. attr.size-1).step(2) do |i|
116
- array << key_val(attr[i], escape_attributes(attr[i+1]))
117
- end
118
- array.join('')
113
+ def key_vals(attribute)
114
+ attribute.
115
+ inject('') { |str, attr| str + key_val(attr.first, escape_attributes(attr.last)) }
119
116
  end
120
117
 
121
118
  def escape_attributes(str = '')
@@ -215,14 +215,14 @@ def write_sheet_files(dir, sheet, index)
215
215
 
216
216
  def write_sheet(writer, sheet, sheet_id) #:nodoc:
217
217
  attributes = [
218
- 'name', sheet.name,
219
- 'sheetId', sheet_id
218
+ ['name', sheet.name],
219
+ ['sheetId', sheet_id]
220
220
  ]
221
221
 
222
222
  if sheet.hidden?
223
- attributes << 'state' << 'hidden'
223
+ attributes << ['state', 'hidden']
224
224
  end
225
- attributes += r_id_attributes(sheet_id)
225
+ attributes << r_id_attributes(sheet_id)
226
226
  writer.empty_tag_encoded('sheet', attributes)
227
227
  end
228
228
  end
@@ -113,27 +113,27 @@ def group_attributes
113
113
  cust_min = cust_max_min(@min) if @min
114
114
 
115
115
  a = []
116
- a << 'manualMax' << @max if @max && @max != 'group'
117
- a << 'manualMin' << @min if @min && @min != 'group'
116
+ a << ['manualMax', @max] if @max && @max != 'group'
117
+ a << ['manualMin', @min] if @min && @min != 'group'
118
118
 
119
119
  # Ignore the default type attribute (line).
120
- a << 'type' << @type if @type != 'line'
121
-
122
- a << 'lineWeight' << @weight if @weight
123
- a << 'dateAxis' << 1 if @date_axis
124
- a << 'displayEmptyCellsAs' << @empty if ptrue?(@empty)
125
-
126
- a << 'markers' << 1 if @markers
127
- a << 'high' << 1 if @high
128
- a << 'low' << 1 if @low
129
- a << 'first' << 1 if @first
130
- a << 'last' << 1 if @last
131
- a << 'negative' << 1 if @negative
132
- a << 'displayXAxis' << 1 if @axis
133
- a << 'displayHidden' << 1 if @hidden
134
- a << 'minAxisType' << cust_min if cust_min
135
- a << 'maxAxisType' << cust_max if cust_max
136
- a << 'rightToLeft' << 1 if @reverse
120
+ a << ['type', @type] if @type != 'line'
121
+
122
+ a << ['lineWeight', @weight] if @weight
123
+ a << ['dateAxis', 1] if @date_axis
124
+ a << ['displayEmptyCellsAs', @empty] if ptrue?(@empty)
125
+
126
+ a << ['markers', 1] if @markers
127
+ a << ['high', 1] if @high
128
+ a << ['low', 1] if @low
129
+ a << ['first', 1] if @first
130
+ a << ['last', 1] if @last
131
+ a << ['negative', 1] if @negative
132
+ a << ['displayXAxis', 1] if @axis
133
+ a << ['displayHidden', 1] if @hidden
134
+ a << ['minAxisType', cust_min] if cust_min
135
+ a << ['maxAxisType', cust_max] if cust_max
136
+ a << ['rightToLeft', 1] if @reverse
137
137
  a
138
138
  end
139
139
 
@@ -272,9 +272,9 @@ def write_sparklines # :nodoc:
272
272
  def write_spark_color(element, color) # :nodoc:
273
273
  attr = []
274
274
 
275
- attr << 'rgb' << color[:_rgb] if color[:_rgb]
276
- attr << 'theme' << color[:_theme] if color[:_theme]
277
- attr << 'tint' << color[:_tint] if color[:_tint]
275
+ attr << ['rgb', color[:_rgb]] if color[:_rgb]
276
+ attr << ['theme', color[:_theme]] if color[:_theme]
277
+ attr << ['tint', color[:_tint]] if color[:_tint]
278
278
 
279
279
  @writer.empty_tag(element, attr)
280
280
  end
@@ -1,4 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
+ require 'write_xlsx/col_name'
3
+
2
4
  module Writexlsx
3
5
  module Utility
4
6
  ROW_MAX = 1048576 # :nodoc:
@@ -50,25 +52,7 @@ def xl_cell_to_rowcol(cell)
50
52
  end
51
53
 
52
54
  def xl_col_to_name(col, col_absolute)
53
- # Change from 0-indexed to 1 indexed.
54
- col += 1
55
- col_str = ''
56
-
57
- while col > 0
58
- # Set remainder from 1 .. 26
59
- remainder = col % 26
60
- remainder = 26 if remainder == 0
61
-
62
- # Convert the remainder to a character. C-ishly.
63
- col_letter = ("A".ord + remainder - 1).chr
64
-
65
- # Accumulate the column letters, right to left.
66
- col_str = col_letter + col_str
67
-
68
- # Get the next order of magnitude.
69
- col = (col - 1) / 26
70
- end
71
-
55
+ col_str = ColName.instance.col_str(col)
72
56
  "#{absolute_char(col_absolute)}#{col_str}"
73
57
  end
74
58
 
@@ -285,11 +269,11 @@ def substitute_cellref(cell, *args) #:nodoc:
285
269
 
286
270
  def underline_attributes(underline)
287
271
  if underline == 2
288
- ['val', 'double']
272
+ [['val', 'double']]
289
273
  elsif underline == 33
290
- ['val', 'singleAccounting']
274
+ [['val', 'singleAccounting']]
291
275
  elsif underline == 34
292
- ['val', 'doubleAccounting']
276
+ [['val', 'doubleAccounting']]
293
277
  else
294
278
  [] # Default to single underline.
295
279
  end
@@ -299,7 +283,7 @@ def underline_attributes(underline)
299
283
  # Write the <color> element.
300
284
  #
301
285
  def write_color(writer, name, value) #:nodoc:
302
- attributes = [name, value]
286
+ attributes = [[name, value]]
303
287
 
304
288
  writer.empty_tag('color', attributes)
305
289
  end
@@ -378,9 +362,9 @@ def pixels_to_points(vertices)
378
362
 
379
363
  def v_shape_attributes_base(id, z_index)
380
364
  [
381
- 'id', "_x0000_s#{id}",
382
- 'type', type,
383
- 'style', (v_shape_style_base(z_index, vertices) + style_addition).join,
365
+ ['id', "_x0000_s#{id}"],
366
+ ['type', type],
367
+ ['style', (v_shape_style_base(z_index, vertices) + style_addition).join]
384
368
  ]
385
369
  end
386
370
 
@@ -425,8 +409,8 @@ def write_fill
425
409
  def write_comment_path(gradientshapeok, connecttype)
426
410
  attributes = []
427
411
 
428
- attributes << 'gradientshapeok' << 't' if gradientshapeok
429
- attributes << 'o:connecttype' << connecttype
412
+ attributes << ['gradientshapeok', 't'] if gradientshapeok
413
+ attributes << ['o:connecttype', connecttype]
430
414
 
431
415
  @writer.empty_tag('v:path', attributes)
432
416
  end
@@ -453,7 +437,7 @@ def write_auto_fill
453
437
  #
454
438
  def write_div(align, font = nil)
455
439
  style = "text-align:#{align}"
456
- attributes = ['style', style]
440
+ attributes = [['style', style]]
457
441
 
458
442
  @writer.tag_elements('div', attributes) do
459
443
  if font
@@ -473,9 +457,9 @@ def write_font(font)
473
457
  color = '#000000'
474
458
 
475
459
  attributes = [
476
- 'face', face,
477
- 'size', size,
478
- 'color', color
460
+ ['face', face],
461
+ ['size', size],
462
+ ['color', color]
479
463
  ]
480
464
  @writer.data_element('font', caption, attributes)
481
465
  end
@@ -484,7 +468,7 @@ def write_font(font)
484
468
  # Write the <v:stroke> element.
485
469
  #
486
470
  def write_stroke
487
- attributes = ['joinstyle', 'miter']
471
+ attributes = [['joinstyle', 'miter']]
488
472
 
489
473
  @writer.empty_tag('v:stroke', attributes)
490
474
  end
@@ -492,5 +476,49 @@ def write_stroke
492
476
  def r_id_attributes(id)
493
477
  ['r:id', "rId#{id}"]
494
478
  end
479
+
480
+ def write_xml_declaration
481
+ @writer.xml_decl
482
+ yield
483
+ @writer.crlf
484
+ @writer.close
485
+ end
486
+
487
+ #
488
+ # Convert user defined line properties to the structure required internally.
489
+ #
490
+ def line_properties(line) # :nodoc:
491
+ return { :_defined => 0 } unless line
492
+
493
+ dash_types = {
494
+ :solid => 'solid',
495
+ :round_dot => 'sysDot',
496
+ :square_dot => 'sysDash',
497
+ :dash => 'dash',
498
+ :dash_dot => 'dashDot',
499
+ :long_dash => 'lgDash',
500
+ :long_dash_dot => 'lgDashDot',
501
+ :long_dash_dot_dot => 'lgDashDotDot',
502
+ :dot => 'dot',
503
+ :system_dash_dot => 'sysDashDot',
504
+ :system_dash_dot_dot => 'sysDashDotDot'
505
+ }
506
+
507
+ # Check the dash type.
508
+ dash_type = line[:dash_type]
509
+
510
+ if dash_type
511
+ line[:dash_type] = value_or_raise(dash_types, dash_type, 'dash type')
512
+ end
513
+
514
+ line[:_defined] = 1
515
+
516
+ line
517
+ end
518
+
519
+ def value_or_raise(hash, key, msg)
520
+ raise "Unknown #{msg} '#{key}'" unless hash[key.to_sym]
521
+ hash[key.to_sym]
522
+ end
495
523
  end
496
524
  end