writeexcel 0.3.5 → 0.4.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 (122) hide show
  1. data/.gitattributes +1 -0
  2. data/README.rdoc +12 -6
  3. data/VERSION +1 -1
  4. data/charts/chartex.rb +316 -315
  5. data/charts/demo1.rb +1 -0
  6. data/charts/demo2.rb +1 -0
  7. data/charts/demo3.rb +117 -116
  8. data/charts/demo4.rb +119 -118
  9. data/charts/demo5.rb +48 -47
  10. data/examples/a_simple.rb +1 -0
  11. data/examples/autofilter.rb +1 -0
  12. data/examples/bigfile.rb +30 -29
  13. data/examples/chart_area.rb +121 -120
  14. data/examples/chart_bar.rb +120 -119
  15. data/examples/chart_column.rb +120 -119
  16. data/examples/chart_line.rb +120 -119
  17. data/examples/chart_pie.rb +108 -107
  18. data/examples/chart_scatter.rb +121 -120
  19. data/examples/chart_stock.rb +148 -147
  20. data/examples/chess.rb +1 -0
  21. data/examples/colors.rb +1 -0
  22. data/examples/comments1.rb +1 -0
  23. data/examples/comments2.rb +3 -2
  24. data/examples/copyformat.rb +1 -0
  25. data/examples/data_validate.rb +1 -0
  26. data/examples/date_time.rb +1 -0
  27. data/examples/defined_name.rb +1 -0
  28. data/examples/demo.rb +1 -0
  29. data/examples/diag_border.rb +1 -0
  30. data/examples/formats.rb +1 -0
  31. data/examples/formula_result.rb +1 -0
  32. data/examples/header.rb +1 -0
  33. data/examples/hide_sheet.rb +1 -0
  34. data/examples/hyperlink.rb +1 -0
  35. data/examples/images.rb +1 -0
  36. data/examples/indent.rb +1 -0
  37. data/examples/merge1.rb +1 -0
  38. data/examples/merge2.rb +1 -0
  39. data/examples/merge3.rb +1 -0
  40. data/examples/merge4.rb +1 -0
  41. data/examples/merge5.rb +1 -0
  42. data/examples/merge6.rb +67 -66
  43. data/examples/outline.rb +1 -0
  44. data/examples/outline_collapsed.rb +1 -0
  45. data/examples/panes.rb +1 -0
  46. data/examples/properties.rb +1 -0
  47. data/examples/properties_jp.rb +1 -0
  48. data/examples/protection.rb +1 -0
  49. data/examples/regions.rb +1 -0
  50. data/examples/repeat.rb +1 -0
  51. data/examples/right_to_left.rb +1 -0
  52. data/examples/row_wrap.rb +1 -0
  53. data/examples/stats.rb +1 -0
  54. data/examples/stocks.rb +1 -0
  55. data/examples/tab_colors.rb +1 -0
  56. data/examples/write_arrays.rb +1 -0
  57. data/lib/writeexcel.rb +6 -1
  58. data/lib/writeexcel/biffwriter.rb +21 -20
  59. data/lib/writeexcel/chart.rb +25 -12
  60. data/lib/writeexcel/charts/area.rb +153 -152
  61. data/lib/writeexcel/charts/bar.rb +178 -177
  62. data/lib/writeexcel/charts/column.rb +157 -156
  63. data/lib/writeexcel/charts/external.rb +62 -61
  64. data/lib/writeexcel/charts/line.rb +153 -152
  65. data/lib/writeexcel/charts/pie.rb +170 -169
  66. data/lib/writeexcel/charts/scatter.rb +4 -3
  67. data/lib/writeexcel/charts/stock.rb +212 -211
  68. data/lib/writeexcel/compatibility.rb +320 -0
  69. data/lib/writeexcel/excelformulaparser.rb +587 -586
  70. data/lib/writeexcel/format.rb +12 -13
  71. data/lib/writeexcel/formula.rb +30 -28
  72. data/lib/writeexcel/helper.rb +23 -0
  73. data/lib/writeexcel/olewriter.rb +5 -16
  74. data/lib/writeexcel/properties.rb +43 -54
  75. data/lib/writeexcel/storage_lite.rb +981 -968
  76. data/lib/writeexcel/workbook.rb +94 -73
  77. data/lib/writeexcel/worksheet.rb +230 -210
  78. data/test/helper.rb +19 -0
  79. data/test/test_00_IEEE_double.rb +1 -0
  80. data/test/test_01_add_worksheet.rb +1 -0
  81. data/test/test_02_merge_formats.rb +3 -5
  82. data/test/test_04_dimensions.rb +3 -5
  83. data/test/test_05_rows.rb +6 -6
  84. data/test/test_06_extsst.rb +8 -8
  85. data/test/test_11_date_time.rb +3 -5
  86. data/test/test_12_date_only.rb +3 -5
  87. data/test/test_13_date_seconds.rb +4 -6
  88. data/test/test_21_escher.rb +3 -5
  89. data/test/test_22_mso_drawing_group.rb +20 -22
  90. data/test/test_23_note.rb +5 -7
  91. data/test/test_24_txo.rb +3 -5
  92. data/test/test_25_position_object.rb +84 -79
  93. data/test/test_26_autofilter.rb +3 -13
  94. data/test/test_27_autofilter.rb +3 -13
  95. data/test/test_28_autofilter.rb +3 -13
  96. data/test/test_29_process_jpg.rb +5 -0
  97. data/test/test_30_validation_dval.rb +3 -5
  98. data/test/test_31_validation_dv_strings.rb +3 -5
  99. data/test/test_32_validation_dv_formula.rb +3 -5
  100. data/test/test_40_property_types.rb +10 -9
  101. data/test/test_41_properties.rb +1 -0
  102. data/test/test_42_set_properties.rb +14 -15
  103. data/test/test_50_name_stored.rb +299 -302
  104. data/test/test_51_name_print_area.rb +357 -360
  105. data/test/test_52_name_print_titles.rb +454 -457
  106. data/test/test_53_autofilter.rb +203 -206
  107. data/test/test_60_chart_generic.rb +5 -0
  108. data/test/test_61_chart_subclasses.rb +95 -94
  109. data/test/test_62_chart_formats.rb +272 -267
  110. data/test/test_63_chart_area_formats.rb +649 -644
  111. data/test/test_biff.rb +12 -38
  112. data/test/test_compatibility.rb +627 -0
  113. data/test/test_example_match.rb +3 -18
  114. data/test/test_format.rb +46 -105
  115. data/test/test_formula.rb +1 -0
  116. data/test/test_ole.rb +3 -4
  117. data/test/test_storage_lite.rb +125 -146
  118. data/test/test_workbook.rb +2 -23
  119. data/test/test_worksheet.rb +4 -5
  120. data/utils/add_magic_comment.rb +80 -0
  121. data/writeexcel.gemspec +8 -2
  122. metadata +10 -4
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  ###############################################################################
2
3
  #
3
4
  # Workbook - A writer class for Excel Workbooks.
@@ -10,6 +11,8 @@
10
11
  # original written in Perl by John McNamara
11
12
  # converted to Ruby by Hideo Nakamura, cxn03651@msj.biglobe.ne.jp
12
13
  #
14
+ require 'digest/md5'
15
+ require 'nkf'
13
16
  require 'writeexcel/biffwriter'
14
17
  require 'writeexcel/olewriter'
15
18
  require 'writeexcel/formula'
@@ -24,15 +27,17 @@
24
27
  require 'writeexcel/charts/pie'
25
28
  require 'writeexcel/charts/scatter'
26
29
  require 'writeexcel/charts/stock'
27
- require 'writeexcel/properties'
28
- require 'digest/md5'
29
30
  require 'writeexcel/storage_lite'
31
+ require 'writeexcel/compatibility'
30
32
 
31
33
  class Workbook < BIFFWriter
34
+ require 'writeexcel/properties'
35
+ require 'writeexcel/helper'
36
+ private :convert_to_ascii_if_ascii
37
+
32
38
  BOF = 11 # :nodoc:
33
39
  EOF = 4 # :nodoc:
34
40
  SheetName = "Sheet" # :nodoc:
35
- NonAscii = /[^!"#\$%&'\(\)\*\+,\-\.\/\:\;<=>\?@0-9A-Za-z_\[\\\]^` ~\0\n]/ # :nodoc:
36
41
 
37
42
  #
38
43
  # file is a filename (as string) or io object where to out spreadsheet data.
@@ -208,7 +213,8 @@ def close
208
213
  return if @fileclosed # Prevent close() from being called twice.
209
214
 
210
215
  @fileclosed = true
211
- return store_workbook
216
+ store_workbook
217
+ cleanup
212
218
  end
213
219
 
214
220
  # get array of Worksheet objects
@@ -489,11 +495,13 @@ def check_sheetname(name, encoding = 0, chart = 0) #:nodoc:
489
495
  end
490
496
  end
491
497
 
498
+ name = convert_to_ascii_if_ascii(name)
499
+
492
500
  # Check that sheetname is <= 31 (1 or 2 byte chars). Excel limit.
493
- raise "Sheetname $name must be <= 31 chars" if name.length > limit
501
+ raise "Sheetname $name must be <= 31 chars" if name.bytesize > limit
494
502
 
495
503
  # Check that Unicode sheetname has an even number of bytes
496
- if encoding == 1 && (name.length % 2 != 0)
504
+ if encoding == 1 && (name.bytesize % 2 != 0)
497
505
  raise "Odd number of bytes in Unicode worksheet name: #{name}"
498
506
  end
499
507
 
@@ -514,8 +522,9 @@ def check_sheetname(name, encoding = 0, chart = 0) #:nodoc:
514
522
  end
515
523
 
516
524
  # Handle utf8 strings
517
- if name =~ NonAscii
525
+ if name.encoding == Encoding::UTF_8
518
526
  name = NKF.nkf('-w16B0 -m0 -W', name)
527
+ name.force_encoding('UTF-16BE')
519
528
  encoding = 1
520
529
  end
521
530
 
@@ -750,7 +759,7 @@ def set_custom_color(index = nil, red = nil, green = nil, blue = nil)
750
759
  # Set the RGB value
751
760
  @palette[index] = [red, green, blue, 0]
752
761
 
753
- return index + 8
762
+ index + 8
754
763
  end
755
764
 
756
765
  ###############################################################################
@@ -818,7 +827,7 @@ def set_palette_xl97 #:nodoc:
818
827
  [0x33, 0x33, 0x99, 0x00], # 62
819
828
  [0x33, 0x33, 0x33, 0x00] # 63
820
829
  ]
821
- return 0
830
+ 0
822
831
  end
823
832
  private :set_palette_xl97
824
833
 
@@ -956,7 +965,7 @@ def define_name(name, formula, encoding = 0)
956
965
  }
957
966
  )
958
967
 
959
- index = @defined_names.length
968
+ index = @defined_names.size
960
969
 
961
970
  parser.set_ext_name(name, index)
962
971
  end
@@ -1016,6 +1025,9 @@ def set_properties(params)
1016
1025
  # Ignore if no args were passed.
1017
1026
  return -1 if !params.kind_of?(Hash) || params.empty?
1018
1027
 
1028
+ params.each do |k, v|
1029
+ params[k] = convert_to_ascii_if_ascii(v) if v.kind_of?(String)
1030
+ end
1019
1031
  # List of valid input parameters.
1020
1032
  properties = {
1021
1033
  :codepage => [0x0001, 'VT_I2' ],
@@ -1112,7 +1124,7 @@ def get_property_set_codepage(params, strings) #:nodoc:
1112
1124
  else
1113
1125
  strings.each do |string|
1114
1126
  next unless params.has_key?(string.to_sym)
1115
- return 0xFDE9 if params[string.to_sym] =~ NonAscii
1127
+ return 0xFDE9 if params[string.to_sym].encoding == Encoding::UTF_8
1116
1128
  end
1117
1129
  return 0x04E4; # Default codepage, Latin 1.
1118
1130
  end
@@ -1248,8 +1260,6 @@ def store_OLE_file #:nodoc:
1248
1260
 
1249
1261
  return ole.close
1250
1262
  else
1251
- # Write the OLE file using ruby-ole if data > 7MB
1252
-
1253
1263
  # Create the Workbook stream.
1254
1264
  stream = 'Workbook'.unpack('C*').pack('v*')
1255
1265
  workbook = OLEStorageLitePPSFile.new(stream)
@@ -1327,7 +1337,7 @@ def calc_sheet_offsets #:nodoc:
1327
1337
  offset += mso_size
1328
1338
 
1329
1339
  @worksheets.each do |sheet|
1330
- offset += _bof + sheet.name.length
1340
+ offset += _bof + sheet.name.bytesize
1331
1341
  end
1332
1342
 
1333
1343
  offset += _eof
@@ -1483,7 +1493,7 @@ def process_images #:nodoc:
1483
1493
  # Slurp the file into a string and do some size calcs.
1484
1494
  # my $data = do {local $/; <$fh>};
1485
1495
  data = fh.read
1486
- size = data.length
1496
+ size = data.bytesize
1487
1497
  checksum1 = image_checksum(data, image_id)
1488
1498
  checksum2 = checksum1
1489
1499
  ref_count = 1
@@ -1594,7 +1604,7 @@ def process_png(data) #:nodoc:
1594
1604
  width = data[16, 4].unpack("N")[0]
1595
1605
  height = data[20, 4].unpack("N")[0]
1596
1606
 
1597
- return [type, width, height]
1607
+ [type, width, height]
1598
1608
  end
1599
1609
  private :process_png
1600
1610
 
@@ -1610,7 +1620,7 @@ def process_bmp(data, filename) #:nodoc:
1610
1620
  type = 7 # Excel Blip type (MSOBLIPTYPE).
1611
1621
 
1612
1622
  # Check that the file is big enough to be a bitmap.
1613
- if data.length <= 0x36
1623
+ if data.bytesize <= 0x36
1614
1624
  raise "#{filename} doesn't contain enough data."
1615
1625
  end
1616
1626
 
@@ -1643,7 +1653,7 @@ def process_bmp(data, filename) #:nodoc:
1643
1653
  raise "#{filename}: compression not supported in bitmap image."
1644
1654
  end
1645
1655
 
1646
- return [type, width, height]
1656
+ [type, width, height]
1647
1657
  end
1648
1658
  private :process_bmp
1649
1659
 
@@ -1657,7 +1667,7 @@ def process_jpg(data, filename) # :nodoc:
1657
1667
  type = 5 # Excel Blip type (MSOBLIPTYPE).
1658
1668
 
1659
1669
  offset = 2;
1660
- data_length = data.length
1670
+ data_length = data.bytesize
1661
1671
 
1662
1672
  # Search through the image data to find the 0xFFC0 marker. The height and
1663
1673
  # width are contained in the data for that sub element.
@@ -1675,7 +1685,7 @@ def process_jpg(data, filename) # :nodoc:
1675
1685
  break
1676
1686
  end
1677
1687
 
1678
- offset = offset + length + 2
1688
+ offset += length + 2
1679
1689
  break if marker == 0xFFDA
1680
1690
  end
1681
1691
 
@@ -1762,21 +1772,21 @@ def store_all_fonts #:nodoc:
1762
1772
  # Fonts that are marked as '_font_only' are always stored. These are used
1763
1773
  # mainly for charts and may not have an associated XF record.
1764
1774
 
1765
- @formats.each do |format|
1766
- key = format.get_font_key
1767
- if format.font_only == 0 and !fonts[key].nil?
1775
+ @formats.each do |fmt|
1776
+ key = fmt.get_font_key
1777
+ if fmt.font_only == 0 and !fonts[key].nil?
1768
1778
  # FONT has already been used
1769
- format.font_index = fonts[key]
1779
+ fmt.font_index = fonts[key]
1770
1780
  else
1771
1781
  # Add a new FONT record
1772
1782
 
1773
- if format.font_only == 0
1783
+ if fmt.font_only == 0
1774
1784
  fonts[key] = index
1775
1785
  end
1776
1786
 
1777
- format.font_index = index
1787
+ fmt.font_index = index
1778
1788
  index += 1
1779
- font = format.get_font
1789
+ font = fmt.get_font
1780
1790
  print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1781
1791
  append(font)
1782
1792
  end
@@ -2038,10 +2048,10 @@ def store_window1 #:nodoc:
2038
2048
  # Writes Excel BIFF BOUNDSHEET record.
2039
2049
  #
2040
2050
  def store_boundsheet(sheetname, offset, type, hidden, encoding) #:nodoc:
2041
- record = 0x0085 # Record identifier
2042
- length = 0x08 + sheetname.length # Number of bytes to follow
2051
+ record = 0x0085 # Record identifier
2052
+ length = 0x08 + sheetname.bytesize # Number of bytes to follow
2043
2053
 
2044
- cch = sheetname.length # Length of sheet name
2054
+ cch = sheetname.bytesize # Length of sheet name
2045
2055
 
2046
2056
  grbit = type | hidden
2047
2057
 
@@ -2097,11 +2107,14 @@ def store_num_format(format, ifmt, encoding) #:nodoc:
2097
2107
  record = 0x041E # Record identifier
2098
2108
  # length # Number of bytes to follow
2099
2109
  # Char length of format string
2100
- cch = format.length
2110
+ cch = format.bytesize
2111
+
2112
+ format = convert_to_ascii_if_ascii(format)
2101
2113
 
2102
2114
  # Handle utf8 strings
2103
- if format =~ NonAscii
2115
+ if format.encoding == Encoding::UTF_8
2104
2116
  format = NKF.nkf('-w16B0 -m0 -W', format)
2117
+ format.force_encoding('UTF-16BE')
2105
2118
  encoding = 1
2106
2119
  end
2107
2120
 
@@ -2112,14 +2125,15 @@ def store_num_format(format, ifmt, encoding) #:nodoc:
2112
2125
  format = format.unpack('n*').pack('v*')
2113
2126
  end
2114
2127
 
2128
+ =begin
2115
2129
  # Special case to handle Euro symbol, 0x80, in non-Unicode strings.
2116
2130
  if encoding == 0 and format =~ /\x80/
2117
2131
  format = format.unpack('C*').pack('v*')
2118
2132
  format.gsub!(/\x80\x00/, "\xAC\x20")
2119
2133
  encoding = 1
2120
2134
  end
2121
-
2122
- length = 0x05 + format.length
2135
+ =end
2136
+ length = 0x05 + format.bytesize
2123
2137
 
2124
2138
  header = [record, length].pack("vv")
2125
2139
  data = [ifmt, cch, encoding].pack("vvC")
@@ -2187,18 +2201,18 @@ def store_externsheet # :nodoc:
2187
2201
  ext = ext_refs.keys.sort
2188
2202
 
2189
2203
  # Change the external refs from stringified "1:1" to [1, 1]
2190
- ext.map! {|e| e.split(/:/).map! {|e| e.to_i} }
2204
+ ext.map! {|e| e.split(/:/).map! {|v| v.to_i} }
2191
2205
 
2192
2206
  cxti = ext.size # Number of Excel XTI structures
2193
2207
  rgxti = '' # Array of XTI structures
2194
2208
 
2195
2209
  # Write the XTI structs
2196
2210
  ext.each do |e|
2197
- rgxti = rgxti + [0, e[0], e[1]].pack("vvv")
2211
+ rgxti += [0, e[0], e[1]].pack("vvv")
2198
2212
  end
2199
2213
 
2200
2214
  data = [cxti].pack("v") + rgxti
2201
- header = [record, data.length].pack("vv")
2215
+ header = [record, data.bytesize].pack("vv")
2202
2216
 
2203
2217
  print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2204
2218
  append(header, data)
@@ -2212,10 +2226,12 @@ def store_externsheet # :nodoc:
2212
2226
  # and _store_name_long().
2213
2227
  #
2214
2228
  def store_name(name, encoding, sheet_index, formula) # :nodoc:
2229
+ formula = convert_to_ascii_if_ascii(formula)
2230
+
2215
2231
  record = 0x0018 # Record identifier
2216
2232
 
2217
- text_length = name.length
2218
- formula_length = formula.length
2233
+ text_length = name.bytesize
2234
+ formula_length = formula.bytesize
2219
2235
 
2220
2236
  # UTF-16 string length is in characters not bytes.
2221
2237
  text_length /= 2 if encoding != 0
@@ -2230,9 +2246,9 @@ def store_name(name, encoding, sheet_index, formula) # :nodoc:
2230
2246
 
2231
2247
  # Set grbit built-in flag and the hidden flag for autofilters.
2232
2248
  if text_length == 1
2233
- grbit = 0x0020 if name[0] == 0x06 # Print area
2234
- grbit = 0x0020 if name[0] == 0x07 # Print titles
2235
- grbit = 0x0021 if name[0] == 0x0D # Autofilter
2249
+ grbit = 0x0020 if name.ord == 0x06 # Print area
2250
+ grbit = 0x0020 if name.ord == 0x07 # Print titles
2251
+ grbit = 0x0021 if name.ord == 0x0D # Autofilter
2236
2252
  end
2237
2253
 
2238
2254
  data = [grbit].pack("v")
@@ -2249,7 +2265,7 @@ def store_name(name, encoding, sheet_index, formula) # :nodoc:
2249
2265
  data += name
2250
2266
  data += formula
2251
2267
 
2252
- header = [record, data.length].pack("vv")
2268
+ header = [record, data.bytesize].pack("vv")
2253
2269
 
2254
2270
  print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2255
2271
  append(header, data)
@@ -2280,7 +2296,7 @@ def store_name_short(index, type, ext_ref, rowmin, rowmax, colmin, colmax, hidde
2280
2296
  cch = 0x01 # Length of text name
2281
2297
  cce = 0x000b # Length of text definition
2282
2298
  unknown01 = 0x0000 #
2283
- ixals = index +1 # Sheet index
2299
+ ixals = index + 1 # Sheet index
2284
2300
  unknown02 = 0x00 #
2285
2301
  cchCustMenu = 0x00 # Length of cust menu text
2286
2302
  cchDescription = 0x00 # Length of description text
@@ -2343,7 +2359,7 @@ def store_name_long(index, type, ext_ref, rowmin, rowmax, colmin, colmax)
2343
2359
  cch = 0x01 # Length of text name
2344
2360
  cce = 0x001a # Length of text definition
2345
2361
  unknown01 = 0x0000 #
2346
- ixals = index +1 # Sheet index
2362
+ ixals = index + 1 # Sheet index
2347
2363
  unknown02 = 0x00 #
2348
2364
  cchCustMenu = 0x00 # Length of cust menu text
2349
2365
  cchDescription = 0x00 # Length of description text
@@ -2408,7 +2424,7 @@ def store_palette #:nodoc:
2408
2424
 
2409
2425
  # Pack the RGB data
2410
2426
  @palette.each do |p|
2411
- data = data + p.pack('CCCC')
2427
+ data += p.pack('CCCC')
2412
2428
  end
2413
2429
 
2414
2430
  header = [record, length, ccv].pack("vvv")
@@ -2505,7 +2521,7 @@ def calculate_extern_sizes # :nodoc:
2505
2521
  end
2506
2522
 
2507
2523
  @defined_names.each do |defined_name|
2508
- length += 19 + defined_name[:name].length + defined_name[:formula].length
2524
+ length += 19 + defined_name[:name].bytesize + defined_name[:formula].bytesize
2509
2525
  end
2510
2526
 
2511
2527
  @worksheets.each do |worksheet|
@@ -2571,7 +2587,7 @@ def calculate_extern_sizes # :nodoc:
2571
2587
  # The EXTERNSHEET record is 6 bytes + 6 bytes for each external ref
2572
2588
  length += 6 * (1 + ext_ref_count)
2573
2589
 
2574
- return length
2590
+ length
2575
2591
  end
2576
2592
 
2577
2593
  ###############################################################################
@@ -2620,7 +2636,7 @@ def calculate_shared_string_sizes #:nodoc:
2620
2636
 
2621
2637
  strings.each do |string|
2622
2638
 
2623
- string_length = string.length
2639
+ string_length = string.bytesize
2624
2640
  encoding = string.unpack("xx C")[0]
2625
2641
  split_string = 0
2626
2642
 
@@ -2730,7 +2746,7 @@ def calculate_shared_string_sizes #:nodoc:
2730
2746
  length += 4 + block_sizes.shift # CONTINUEs
2731
2747
  end
2732
2748
 
2733
- return length
2749
+ length
2734
2750
  end
2735
2751
  private :calculate_shared_string_sizes
2736
2752
 
@@ -2788,7 +2804,7 @@ def store_shared_strings #:nodoc:
2788
2804
  return if strings.empty?
2789
2805
  strings.each do |string|
2790
2806
 
2791
- string_length = string.length
2807
+ string_length = string.bytesize
2792
2808
  encoding = string.unpack("xx C")[0]
2793
2809
  split_string = 0
2794
2810
  bucket_string = 0 # Used to track EXTSST bucket offsets.
@@ -2906,7 +2922,7 @@ def store_shared_strings #:nodoc:
2906
2922
  length = block_sizes.shift
2907
2923
 
2908
2924
  header = [record, length].pack("vv")
2909
- header = header + [encoding].pack("C") if continue != 0
2925
+ header += [encoding].pack("C") if continue != 0
2910
2926
 
2911
2927
  print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2912
2928
  append(header)
@@ -2963,7 +2979,7 @@ def calculate_extsst_size #:nodoc:
2963
2979
  @extsst_buckets = buckets
2964
2980
  @extsst_bucket_size = bucket_size
2965
2981
 
2966
- return 6 + 8 * buckets
2982
+ 6 + 8 * buckets
2967
2983
  end
2968
2984
 
2969
2985
  ###############################################################################
@@ -2983,7 +2999,7 @@ def store_extsst #:nodoc:
2983
2999
  data = [bucket_size].pack('v')
2984
3000
 
2985
3001
  offsets.each do |offset|
2986
- data = data + [offset[0], offset[1], 0].pack('Vvv')
3002
+ data += [offset[0], offset[1], 0].pack('Vvv')
2987
3003
  end
2988
3004
 
2989
3005
  print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
@@ -3009,20 +3025,20 @@ def add_mso_drawing_group #:nodoc:
3009
3025
  length = 0x0000 # Number of bytes to follow
3010
3026
 
3011
3027
  data = store_mso_dgg_container
3012
- data = data + store_mso_dgg(*@mso_clusters)
3013
- data = data + store_mso_bstore_container
3028
+ data += store_mso_dgg(*@mso_clusters)
3029
+ data += store_mso_bstore_container
3014
3030
  @images_data.each do |image|
3015
- data = data + store_mso_images(*image)
3031
+ data += store_mso_images(*image)
3016
3032
  end
3017
- data = data + store_mso_opt
3018
- data = data + store_mso_split_menu_colors
3033
+ data += store_mso_opt
3034
+ data += store_mso_split_menu_colors
3019
3035
 
3020
- length = data.length
3036
+ length = data.bytesize
3021
3037
  header = [record, length].pack("vv")
3022
3038
 
3023
3039
  add_mso_drawing_group_continue(header + data)
3024
3040
 
3025
- return header + data # For testing only.
3041
+ header + data # For testing only.
3026
3042
  end
3027
3043
  private :add_mso_drawing_group
3028
3044
 
@@ -3051,7 +3067,7 @@ def add_mso_drawing_group_continue(data) #:nodoc:
3051
3067
  @ignore_continue = 1
3052
3068
 
3053
3069
  # Case 1 above. Just return the data as it is.
3054
- if data.length <= limit
3070
+ if data.bytesize <= limit
3055
3071
  print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
3056
3072
  append(data)
3057
3073
  return
@@ -3065,7 +3081,7 @@ def add_mso_drawing_group_continue(data) #:nodoc:
3065
3081
  append(tmp)
3066
3082
 
3067
3083
  # Add MSODRAWINGGROUP and CONTINUE blocks for Case 3 above.
3068
- while data.length > limit
3084
+ while data.bytesize > limit
3069
3085
  if block_count == 1
3070
3086
  # Add extra MSODRAWINGGROUP block header.
3071
3087
  header = [mso_group, limit].pack("vv")
@@ -3082,7 +3098,7 @@ def add_mso_drawing_group_continue(data) #:nodoc:
3082
3098
  end
3083
3099
 
3084
3100
  # Last CONTINUE block for remaining data. Case 2 and 3 above.
3085
- header = [continue, data.length].pack("vv")
3101
+ header = [continue, data.bytesize].pack("vv")
3086
3102
  print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
3087
3103
  append(header, data)
3088
3104
 
@@ -3104,7 +3120,7 @@ def store_mso_dgg_container #:nodoc:
3104
3120
  data = ''
3105
3121
  length = @mso_size -12 # -4 (biff header) -8 (for this).
3106
3122
 
3107
- return add_mso_generic(type, version, instance, data, length)
3123
+ add_mso_generic(type, version, instance, data, length)
3108
3124
  end
3109
3125
  private :store_mso_dgg_container
3110
3126
 
@@ -3133,10 +3149,10 @@ def store_mso_dgg(max_spid, num_clusters, shapes_saved, drawings_saved, clusters
3133
3149
  drawing_id = aref[0]
3134
3150
  shape_ids_used = aref[1]
3135
3151
 
3136
- data = data + [drawing_id, shape_ids_used].pack("VV")
3152
+ data += [drawing_id, shape_ids_used].pack("VV")
3137
3153
  end
3138
3154
 
3139
- return add_mso_generic(type, version, instance, data, length)
3155
+ add_mso_generic(type, version, instance, data, length)
3140
3156
  end
3141
3157
  private :store_mso_dgg
3142
3158
 
@@ -3155,7 +3171,7 @@ def store_mso_bstore_container #:nodoc:
3155
3171
  data = ''
3156
3172
  length = @images_size +8 *instance
3157
3173
 
3158
- return add_mso_generic(type, version, instance, data, length)
3174
+ add_mso_generic(type, version, instance, data, length)
3159
3175
  end
3160
3176
  private :store_mso_bstore_container
3161
3177
 
@@ -3187,7 +3203,7 @@ def store_mso_images(ref_count, image_type, image, size, checksum1, checksum2)
3187
3203
  checksum2
3188
3204
  )
3189
3205
 
3190
- return blip_store_entry + blip
3206
+ blip_store_entry + blip
3191
3207
  end
3192
3208
  private :store_mso_images
3193
3209
 
@@ -3218,7 +3234,7 @@ def store_mso_blip_store_entry(ref_count, image_type, size, checksum1) #:n
3218
3234
  [0x00].pack('C') + # Unused
3219
3235
  [0x00].pack('C') # Unused
3220
3236
 
3221
- return add_mso_generic(type, version, instance, data, length)
3237
+ add_mso_generic(type, version, instance, data, length)
3222
3238
  end
3223
3239
  private :store_mso_blip_store_entry
3224
3240
 
@@ -3250,7 +3266,7 @@ def store_mso_blip(image_type, image_data, size, checksum1, checksum2) #:n
3250
3266
  [0xFF].pack('C') + # Tag
3251
3267
  image_data # Image
3252
3268
 
3253
- return add_mso_generic(type, version, instance, data, length)
3269
+ add_mso_generic(type, version, instance, data, length)
3254
3270
  end
3255
3271
  private :store_mso_blip
3256
3272
 
@@ -3269,7 +3285,7 @@ def store_mso_opt #:nodoc:
3269
3285
 
3270
3286
  data = ['BF0008000800810109000008C0014000'+'0008'].pack("H*")
3271
3287
 
3272
- return add_mso_generic(type, version, instance, data, length)
3288
+ add_mso_generic(type, version, instance, data, length)
3273
3289
  end
3274
3290
  private :store_mso_opt
3275
3291
 
@@ -3288,7 +3304,12 @@ def store_mso_split_menu_colors #:nodoc:
3288
3304
 
3289
3305
  data = ['0D0000080C00000817000008F7000010'].pack("H*")
3290
3306
 
3291
- return add_mso_generic(type, version, instance, data, length)
3307
+ add_mso_generic(type, version, instance, data, length)
3292
3308
  end
3293
3309
  private :store_mso_split_menu_colors
3310
+
3311
+ def cleanup
3312
+ super
3313
+ sheets.each { |sheet| sheet.cleanup }
3314
+ end
3294
3315
  end