writeexcel 0.4.0 → 0.4.1

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.
@@ -305,17 +305,20 @@ def convert_string(str)
305
305
  str.sub!(/"$/,'') # Remove trailing "
306
306
  str.gsub!(/""/,'"') # Substitute Excel's escaped double quote "" for "
307
307
 
308
- length = str.bytesize
308
+ # number of characters in str
309
+ length = ruby_18 { str.gsub(/[^\WA-Za-z_\d]/, ' ').length } ||
310
+ ruby_19 { str.length }
309
311
 
310
312
  # Handle utf8 strings
311
313
  if str.encoding == Encoding::UTF_8
312
- str = str.encode('UTF-16LE')
314
+ str = utf8_to_16le(str)
315
+ str.force_encoding('BINARY')
313
316
  encoding = 1
314
317
  end
315
318
 
316
319
  exit "String in formula has more than 255 chars\n" if length > 255
317
320
 
318
- [@ptg['ptgStr'], length, encoding].pack("CCC") + str.encode('BINARY')
321
+ [@ptg['ptgStr'], length, encoding].pack("CCC") + str
319
322
  end
320
323
 
321
324
  ###############################################################################
@@ -21,3 +21,22 @@ def convert_to_ascii_if_ascii(str)
21
21
  str
22
22
  end
23
23
  private :convert_to_ascii_if_ascii
24
+
25
+
26
+ def utf8_to_16be(utf8)
27
+ utf16be = NKF.nkf('-w16B0 -m0 -W', utf8)
28
+ utf16be.force_encoding('UTF-16BE')
29
+ end
30
+ private :utf8_to_16be
31
+
32
+ def utf8_to_16le(utf8)
33
+ utf16le = NKF.nkf('-w16L0 -m0 -W', utf8)
34
+ utf16le.force_encoding('UTF-16LE')
35
+ end
36
+ private :utf8_to_16le
37
+
38
+ def ascii_to_16be(ascii)
39
+ ascii.unpack("C*").pack("n*")
40
+ ascii.force_encoding('UTF-16BE')
41
+ end
42
+ private :ascii_to_16be
@@ -27,7 +27,7 @@ class OLEWriter #:nodoc:
27
27
 
28
28
  # Accept an IO or IO-like object or a filename (as a String)
29
29
  def initialize(arg)
30
- if arg.kind_of?(String)
30
+ if arg.respond_to?(:to_str)
31
31
  @io = File.open(arg, "w")
32
32
  else
33
33
  @io = arg
@@ -42,7 +42,7 @@ def getNthPps(no, data)
42
42
  end
43
43
 
44
44
  def _initParse(file)
45
- io = file.kind_of?(String) ? open(file, 'rb') : file
45
+ io = file.respond_to?(:to_str) ? open(file, 'rb') : file
46
46
  _getHeaderInfo(io)
47
47
  end
48
48
  private :_initParse
@@ -580,7 +580,7 @@ def save(sFile, bNoAs = nil, rh_info = nil)
580
580
 
581
581
  #1.Open File
582
582
  #1.1 sFile is Ref of scalar
583
- if sFile.kind_of?(String)
583
+ if sFile.respond_to?(:to_str)
584
584
  rh_info[:fileh] = open(sFile, "wb")
585
585
  else
586
586
  rh_info[:fileh] = sFile.binmode
@@ -956,9 +956,9 @@ def initialize(sNm, data = '')
956
956
  def set_file(sFile = '')
957
957
  if sFile.nil? or sFile == ''
958
958
  @pps_file = Tempfile.new('OLEStorageLitePPSFile')
959
- elsif sFile.kind_of?(IO) || sFile.kind_of?(StringIO)
959
+ elsif sFile.respond_to?(:write)
960
960
  @pps_file = sFile
961
- elsif sFile.kind_of?(String)
961
+ elsif sFile.respond_to?(:to_str)
962
962
  #File Name
963
963
  @pps_file = open(sFile, "r+")
964
964
  return nil unless @pps_file
@@ -14,19 +14,11 @@
14
14
  require 'digest/md5'
15
15
  require 'nkf'
16
16
  require 'writeexcel/biffwriter'
17
- require 'writeexcel/olewriter'
18
- require 'writeexcel/formula'
19
- require 'writeexcel/format'
20
17
  require 'writeexcel/worksheet'
21
18
  require 'writeexcel/chart'
22
- require 'writeexcel/charts/area'
23
- require 'writeexcel/charts/bar'
24
- require 'writeexcel/charts/column'
25
- require 'writeexcel/charts/external'
26
- require 'writeexcel/charts/line'
27
- require 'writeexcel/charts/pie'
28
- require 'writeexcel/charts/scatter'
29
- require 'writeexcel/charts/stock'
19
+ require 'writeexcel/format'
20
+ require 'writeexcel/formula'
21
+ require 'writeexcel/olewriter'
30
22
  require 'writeexcel/storage_lite'
31
23
  require 'writeexcel/compatibility'
32
24
 
@@ -112,11 +104,10 @@ def initialize(file, default_formats = {})
112
104
  }
113
105
  @str_array = []
114
106
  @str_block_sizes = []
115
- @extsst_offsets = []
107
+ @extsst_offsets = [] # array of [global_offset, local_offset]
116
108
  @extsst_buckets = 0
117
109
  @extsst_bucket_size = 0
118
110
 
119
- @ext_ref_count = 0
120
111
  @ext_refs = {}
121
112
 
122
113
  @mso_clusters = []
@@ -158,7 +149,7 @@ def initialize(file, default_formats = {})
158
149
  # Add the default format for hyperlinks
159
150
  @url_format = add_format(:color => 'blue', :underline => 1)
160
151
 
161
- if file.kind_of?(String) && file != ''
152
+ if file.respond_to?(:to_str) && file != ''
162
153
  @fh_out = open(file, "wb")
163
154
  @internal_fh = 1
164
155
  else
@@ -523,8 +514,7 @@ def check_sheetname(name, encoding = 0, chart = 0) #:nodoc:
523
514
 
524
515
  # Handle utf8 strings
525
516
  if name.encoding == Encoding::UTF_8
526
- name = NKF.nkf('-w16B0 -m0 -W', name)
527
- name.force_encoding('UTF-16BE')
517
+ name = utf8_to_16be(name)
528
518
  encoding = 1
529
519
  end
530
520
 
@@ -541,42 +531,33 @@ def check_sheetname(name, encoding = 0, chart = 0) #:nodoc:
541
531
  error = 0;
542
532
 
543
533
  if encd_a == 0 and encd_b == 0
544
- error = 1 if name_a.downcase == name_b.downcase
534
+ error = (name_a.downcase == name_b.downcase)
545
535
  elsif encd_a == 0 and encd_b == 1
546
- name_a = name_a.unpack("C*").pack("n*")
547
- error = 1 if name_a.downcase == name_b.downcase
536
+ name_a = ascii_to_16be(name_a)
537
+ error = (name_a.downcase == name_b.downcase)
548
538
  elsif encd_a == 1 and encd_b == 0
549
- name_b = name_b.unpack("C*").pack("n*")
550
- error = 1 if name_a.downcase == name_b.downcase
539
+ name_b = ascii_to_16be(name_b)
540
+ error = (name_a.downcase == name_b.downcase)
551
541
  elsif encd_a == 1 and encd_b == 1
552
- # # We can do a true case insensitive test with Perl 5.8 and utf8.
553
- # if ($] >= 5.008) {
554
- # $name_a = Encode::decode("UTF-16BE", $name_a);
555
- # $name_b = Encode::decode("UTF-16BE", $name_b);
556
- # $error = 1 if lc($name_a) eq lc($name_b);
557
- # }
558
- # else {
559
- # # We can't easily do a case insensitive test of the UTF16 names.
560
- # # As a special case we check if all of the high bytes are nulls and
561
- # # then do an ASCII style case insensitive test.
542
+ # TODO : not converted yet.
543
+
544
+ # We can't easily do a case insensitive test of the UTF16 names.
545
+ # As a special case we check if all of the high bytes are nulls and
546
+ # then do an ASCII style case insensitive test.
562
547
  #
563
- # # Strip out the high bytes (funkily).
564
- # my $hi_a = grep {ord} $name_a =~ /(.)./sg;
565
- # my $hi_b = grep {ord} $name_b =~ /(.)./sg;
548
+ # Strip out the high bytes (funkily).
549
+ # my $hi_a = grep {ord} $name_a =~ /(.)./sg;
550
+ # my $hi_b = grep {ord} $name_b =~ /(.)./sg;
566
551
  #
567
- # if ($hi_a or $hi_b) {
568
- # $error = 1 if $name_a eq $name_b;
569
- # }
570
- # else {
571
- # $error = 1 if lc($name_a) eq lc($name_b);
572
- # }
573
- # }
574
- # }
575
- # # If any of the cases failed we throw the error here.
552
+ # if ($hi_a or $hi_b) {
553
+ # $error = 1 if $name_a eq $name_b;
554
+ # }
555
+ # else {
556
+ # $error = 1 if lc($name_a) eq lc($name_b);
557
+ # }
576
558
  end
577
- if error != 0
578
- raise "Worksheet name '#{name}', with case ignored, " +
579
- "is already in use"
559
+ if error
560
+ raise "Worksheet name '#{name}', with case ignored, is already in use"
580
561
  end
581
562
  end
582
563
  [name, encoding]
@@ -593,7 +574,9 @@ def check_sheetname(name, encoding = 0, chart = 0) #:nodoc:
593
574
  #
594
575
  # See the "CELL FORMATTING" section for more details about Format properties and how to set them.
595
576
  #
596
- def add_format(formats = {})
577
+ def add_format(*args)
578
+ formats = {}
579
+ args.each { |arg| formats = formats.merge(arg) }
597
580
  format = Format.new(@xf_index, @default_formats.merge(formats))
598
581
  @xf_index += 1
599
582
  @formats.push format # Store format reference
@@ -1023,10 +1006,10 @@ def define_name(name, formula, encoding = 0)
1023
1006
  #
1024
1007
  def set_properties(params)
1025
1008
  # Ignore if no args were passed.
1026
- return -1 if !params.kind_of?(Hash) || params.empty?
1009
+ return -1 if !params.respond_to?(:to_hash) || params.empty?
1027
1010
 
1028
1011
  params.each do |k, v|
1029
- params[k] = convert_to_ascii_if_ascii(v) if v.kind_of?(String)
1012
+ params[k] = convert_to_ascii_if_ascii(v) if v.respond_to?(:to_str)
1030
1013
  end
1031
1014
  # List of valid input parameters.
1032
1015
  properties = {
@@ -1068,14 +1051,9 @@ def set_properties(params)
1068
1051
  property_sets = []
1069
1052
  strings.unshift("codepage")
1070
1053
  strings.push("created")
1071
- strings.each do |property|
1072
- if params.has_key?(property.to_sym) && !params[property.to_sym].nil?
1073
- property_sets.push(
1074
- [ properties[property.to_sym][0],
1075
- properties[property.to_sym][1],
1076
- params[property.to_sym] ]
1077
- )
1078
- end
1054
+ strings.each do |string|
1055
+ property = string.to_sym
1056
+ property_sets.push(property_set(properties, property, params)) if params[property]
1079
1057
  end
1080
1058
 
1081
1059
  # Pack the property sets.
@@ -1092,14 +1070,8 @@ def set_properties(params)
1092
1070
  # Create an array of property set values.
1093
1071
  property_sets = []
1094
1072
 
1095
- ["codepage", "category", "manager", "company"].each do |property|
1096
- if params.has_key?(property.to_sym) && !params[property.to_sym].nil?
1097
- property_sets.push(
1098
- [ properties[property.to_sym][0],
1099
- properties[property.to_sym][1],
1100
- params[property.to_sym] ]
1101
- )
1102
- end
1073
+ [:codepage, :category, :manager, :company].each do |property|
1074
+ property_sets.push(property_set(properties, property, params)) if params[property]
1103
1075
  end
1104
1076
 
1105
1077
  # Pack the property sets.
@@ -1109,6 +1081,11 @@ def set_properties(params)
1109
1081
  @add_doc_properties = 1
1110
1082
  end
1111
1083
 
1084
+ def property_set(properties, property, params)
1085
+ [ properties[property][0], properties[property][1], params[property] ]
1086
+ end
1087
+ private :property_set
1088
+
1112
1089
  ###############################################################################
1113
1090
  #
1114
1091
  # _get_property_set_codepage()
@@ -1183,7 +1160,7 @@ def store_workbook #:nodoc:
1183
1160
  # NOTE: If any records are added between here and EOF the
1184
1161
  # _calc_sheet_offsets() should be updated to include the new length.
1185
1162
  store_country
1186
- if @ext_ref_count != 0
1163
+ if @ext_refs.keys.size != 0
1187
1164
  store_supbook
1188
1165
  store_externsheet
1189
1166
  store_names
@@ -1196,7 +1173,7 @@ def store_workbook #:nodoc:
1196
1173
  store_eof
1197
1174
 
1198
1175
  # Store the workbook in an OLE container
1199
- store_OLE_file
1176
+ store_ole_filie
1200
1177
  end
1201
1178
  private :store_workbook
1202
1179
 
@@ -1226,12 +1203,12 @@ def localtime=(val) # :nodoc:
1226
1203
 
1227
1204
  ###############################################################################
1228
1205
  #
1229
- # _store_OLE_file()
1206
+ # _store_ole_filie()
1230
1207
  #
1231
1208
  # Store the workbook in an OLE container using the default handler or using
1232
1209
  # OLE::Storage_Lite if the workbook data is > ~ 7MB.
1233
1210
  #
1234
- def store_OLE_file #:nodoc:
1211
+ def store_ole_filie #:nodoc:
1235
1212
  maxsize = 7_087_104
1236
1213
  # maxsize = 1
1237
1214
 
@@ -1266,13 +1243,11 @@ def store_OLE_file #:nodoc:
1266
1243
  workbook.set_file # use tempfile
1267
1244
 
1268
1245
  while tmp = get_data
1269
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1270
1246
  workbook.append(tmp)
1271
1247
  end
1272
1248
 
1273
1249
  @worksheets.each do |worksheet|
1274
1250
  while tmp = worksheet.get_data
1275
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1276
1251
  workbook.append(tmp)
1277
1252
  end
1278
1253
  end
@@ -1304,7 +1279,7 @@ def store_OLE_file #:nodoc:
1304
1279
  return @fh_out.close if @internal_fh != 0
1305
1280
  end
1306
1281
  end
1307
- private :store_OLE_file
1282
+ private :store_ole_filie
1308
1283
 
1309
1284
  ###############################################################################
1310
1285
  #
@@ -1708,7 +1683,6 @@ def store_all_fonts #:nodoc:
1708
1683
 
1709
1684
  # Fonts are 0-indexed. According to the SDK there is no index 4,
1710
1685
  (0..3).each do
1711
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1712
1686
  append(font)
1713
1687
  end
1714
1688
 
@@ -1721,7 +1695,6 @@ def store_all_fonts #:nodoc:
1721
1695
  nil,
1722
1696
  :font_only => 1
1723
1697
  )
1724
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1725
1698
  append(tmp_format.get_font)
1726
1699
 
1727
1700
  # Index 6. Series names.
@@ -1729,7 +1702,6 @@ def store_all_fonts #:nodoc:
1729
1702
  nil,
1730
1703
  :font_only => 1
1731
1704
  )
1732
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1733
1705
  append(tmp_format.get_font)
1734
1706
 
1735
1707
  # Index 7. Title.
@@ -1738,7 +1710,6 @@ def store_all_fonts #:nodoc:
1738
1710
  :font_only => 1,
1739
1711
  :bold => 1
1740
1712
  )
1741
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1742
1713
  append(tmp_format.get_font)
1743
1714
 
1744
1715
  # Index 8. Axes.
@@ -1747,7 +1718,6 @@ def store_all_fonts #:nodoc:
1747
1718
  :font_only => 1,
1748
1719
  :bold => 1
1749
1720
  )
1750
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1751
1721
  append(tmp_format.get_font)
1752
1722
 
1753
1723
  # Index 9. Comments.
@@ -1757,7 +1727,6 @@ def store_all_fonts #:nodoc:
1757
1727
  :font => 'Tahoma',
1758
1728
  :size => 8
1759
1729
  )
1760
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1761
1730
  append(tmp_format.get_font)
1762
1731
 
1763
1732
  # Iterate through the XF objects and write a FONT record if it isn't the
@@ -1787,7 +1756,6 @@ def store_all_fonts #:nodoc:
1787
1756
  fmt.font_index = index
1788
1757
  index += 1
1789
1758
  font = fmt.get_font
1790
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1791
1759
  append(font)
1792
1760
  end
1793
1761
  end
@@ -1842,7 +1810,6 @@ def store_all_num_formats #:nodoc:
1842
1810
  def store_all_xfs #:nodoc:
1843
1811
  @formats.each do |format|
1844
1812
  xf = format.get_xf
1845
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
1846
1813
  append(xf)
1847
1814
  end
1848
1815
  end
@@ -2011,27 +1978,26 @@ def store_window1 #:nodoc:
2011
1978
  record = 0x003D # Record identifier
2012
1979
  length = 0x0012 # Number of bytes to follow
2013
1980
 
2014
- xWn = 0x0000 # Horizontal position of window
2015
- yWn = 0x0000 # Vertical position of window
2016
- dxWn = 0x355C # Width of window
2017
- dyWn = 0x30ED # Height of window
1981
+ x_pos = 0x0000 # Horizontal position of window
1982
+ y_pos = 0x0000 # Vertical position of window
1983
+ dx_win = 0x355C # Width of window
1984
+ dy_win = 0x30ED # Height of window
2018
1985
 
2019
1986
  grbit = 0x0038 # Option flags
2020
1987
  ctabsel = @selected # Number of workbook tabs selected
2021
- wTabRatio = 0x0258 # Tab to scrollbar ratio
1988
+ tab_ratio = 0x0258 # Tab to scrollbar ratio
2022
1989
 
2023
- itabFirst = @sinfo[:firstsheet] # 1st displayed worksheet
2024
- itabCur = @sinfo[:activesheet] # Active worksheet
1990
+ tab_cur = @sinfo[:activesheet] # Active worksheet
1991
+ tab_first = @sinfo[:firstsheet] # 1st displayed worksheet
2025
1992
 
2026
1993
  header = [record, length].pack("vv")
2027
1994
  data = [
2028
- xWn, yWn, dxWn, dyWn,
1995
+ x_pos, y_pos, dx_win, dy_win,
2029
1996
  grbit,
2030
- itabCur, itabFirst,
2031
- ctabsel, wTabRatio
1997
+ tab_cur, tab_first,
1998
+ ctabsel, tab_ratio
2032
1999
  ].pack("vvvvvvvvv")
2033
2000
 
2034
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2035
2001
  append(header, data)
2036
2002
  end
2037
2003
  private :store_window1
@@ -2064,7 +2030,6 @@ def store_boundsheet(sheetname, offset, type, hidden, encoding) #:nodoc:
2064
2030
  header = [record, length].pack("vv")
2065
2031
  data = [offset, grbit, cch, encoding].pack("VvCC")
2066
2032
 
2067
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2068
2033
  append(header, data, sheetname)
2069
2034
  end
2070
2035
  private :store_boundsheet
@@ -2088,7 +2053,6 @@ def store_style(type, xf_index) #:nodoc:
2088
2053
  header = [record, length].pack("vv")
2089
2054
  data = [xf_index, type, level].pack("vCC")
2090
2055
 
2091
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2092
2056
  append(header, data)
2093
2057
  end
2094
2058
  private :store_style
@@ -2103,7 +2067,7 @@ def store_style(type, xf_index) #:nodoc:
2103
2067
  # Writes Excel FORMAT record for non "built-in" numerical formats.
2104
2068
  #
2105
2069
  def store_num_format(format, ifmt, encoding) #:nodoc:
2106
- format = format.to_s unless format.kind_of?(String)
2070
+ format = format.to_s unless format.respond_to?(:to_str)
2107
2071
  record = 0x041E # Record identifier
2108
2072
  # length # Number of bytes to follow
2109
2073
  # Char length of format string
@@ -2113,8 +2077,7 @@ def store_num_format(format, ifmt, encoding) #:nodoc:
2113
2077
 
2114
2078
  # Handle utf8 strings
2115
2079
  if format.encoding == Encoding::UTF_8
2116
- format = NKF.nkf('-w16B0 -m0 -W', format)
2117
- format.force_encoding('UTF-16BE')
2080
+ format = utf8_to_16be(format)
2118
2081
  encoding = 1
2119
2082
  end
2120
2083
 
@@ -2138,7 +2101,6 @@ def store_num_format(format, ifmt, encoding) #:nodoc:
2138
2101
  header = [record, length].pack("vv")
2139
2102
  data = [ifmt, cch, encoding].pack("vvC")
2140
2103
 
2141
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2142
2104
  append(header, data, format)
2143
2105
  end
2144
2106
  private :store_num_format
@@ -2158,7 +2120,6 @@ def store_1904 #:nodoc:
2158
2120
  header = [record, length].pack("vv")
2159
2121
  data = [f1904].pack("v")
2160
2122
 
2161
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2162
2123
  append(header, data)
2163
2124
  end
2164
2125
  private :store_1904
@@ -2174,13 +2135,12 @@ def store_supbook #:nodoc:
2174
2135
  record = 0x01AE # Record identifier
2175
2136
  length = 0x0004 # Number of bytes to follow
2176
2137
 
2177
- ctabs = @worksheets.size # Number of worksheets
2178
- stVirtPath = 0x0401 # Encoded workbook filename
2138
+ tabs = @worksheets.size # Number of worksheets
2139
+ virt_path = 0x0401 # Encoded workbook filename
2179
2140
 
2180
2141
  header = [record, length].pack("vv")
2181
- data = [ctabs, stVirtPath].pack("vv")
2142
+ data = [tabs, virt_path].pack("vv")
2182
2143
 
2183
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2184
2144
  append(header, data)
2185
2145
  end
2186
2146
  private :store_supbook
@@ -2197,8 +2157,7 @@ def store_externsheet # :nodoc:
2197
2157
  record = 0x0017 # Record identifier
2198
2158
 
2199
2159
  # Get the external refs
2200
- ext_refs = @ext_refs
2201
- ext = ext_refs.keys.sort
2160
+ ext = @ext_refs.keys.sort
2202
2161
 
2203
2162
  # Change the external refs from stringified "1:1" to [1, 1]
2204
2163
  ext.map! {|e| e.split(/:/).map! {|v| v.to_i} }
@@ -2214,7 +2173,6 @@ def store_externsheet # :nodoc:
2214
2173
  data = [cxti].pack("v") + rgxti
2215
2174
  header = [record, data.bytesize].pack("vv")
2216
2175
 
2217
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2218
2176
  append(header, data)
2219
2177
  end
2220
2178
 
@@ -2267,7 +2225,6 @@ def store_name(name, encoding, sheet_index, formula) # :nodoc:
2267
2225
 
2268
2226
  header = [record, data.bytesize].pack("vv")
2269
2227
 
2270
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2271
2228
  append(header, data)
2272
2229
  end
2273
2230
 
@@ -2292,16 +2249,16 @@ def store_name_short(index, type, ext_ref, rowmin, rowmax, colmin, colmax, hidde
2292
2249
  length = 0x001b # Number of bytes to follow
2293
2250
 
2294
2251
  grbit = 0x0020 # Option flags
2295
- chKey = 0x00 # Keyboard shortcut
2252
+ chkey = 0x00 # Keyboard shortcut
2296
2253
  cch = 0x01 # Length of text name
2297
2254
  cce = 0x000b # Length of text definition
2298
2255
  unknown01 = 0x0000 #
2299
2256
  ixals = index + 1 # Sheet index
2300
2257
  unknown02 = 0x00 #
2301
- cchCustMenu = 0x00 # Length of cust menu text
2302
- cchDescription = 0x00 # Length of description text
2303
- cchHelptopic = 0x00 # Length of help topic text
2304
- cchStatustext = 0x00 # Length of status bar text
2258
+ cch_cust_menu = 0x00 # Length of cust menu text
2259
+ cch_description = 0x00 # Length of description text
2260
+ cch_helptopic = 0x00 # Length of help topic text
2261
+ cch_statustext = 0x00 # Length of status bar text
2305
2262
  rgch = type # Built-in name type
2306
2263
  unknown03 = 0x3b #
2307
2264
 
@@ -2309,16 +2266,16 @@ def store_name_short(index, type, ext_ref, rowmin, rowmax, colmin, colmax, hidde
2309
2266
 
2310
2267
  header = [record, length].pack("vv")
2311
2268
  data = [grbit].pack("v")
2312
- data += [chKey].pack("C")
2269
+ data += [chkey].pack("C")
2313
2270
  data += [cch].pack("C")
2314
2271
  data += [cce].pack("v")
2315
2272
  data += [unknown01].pack("v")
2316
2273
  data += [ixals].pack("v")
2317
2274
  data += [unknown02].pack("C")
2318
- data += [cchCustMenu].pack("C")
2319
- data += [cchDescription].pack("C")
2320
- data += [cchHelptopic].pack("C")
2321
- data += [cchStatustext].pack("C")
2275
+ data += [cch_cust_menu].pack("C")
2276
+ data += [cch_description].pack("C")
2277
+ data += [cch_helptopic].pack("C")
2278
+ data += [cch_statustext].pack("C")
2322
2279
  data += [rgch].pack("C")
2323
2280
  data += [unknown03].pack("C")
2324
2281
  data += [ext_ref].pack("v")
@@ -2328,7 +2285,6 @@ def store_name_short(index, type, ext_ref, rowmin, rowmax, colmin, colmax, hidde
2328
2285
  data += [colmin].pack("v")
2329
2286
  data += [colmax].pack("v")
2330
2287
 
2331
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2332
2288
  append(header, data)
2333
2289
  end
2334
2290
  private :store_name_short
@@ -2355,16 +2311,16 @@ def store_name_long(index, type, ext_ref, rowmin, rowmax, colmin, colmax)
2355
2311
  length = 0x002a # Number of bytes to follow
2356
2312
 
2357
2313
  grbit = 0x0020 # Option flags
2358
- chKey = 0x00 # Keyboard shortcut
2314
+ chkey = 0x00 # Keyboard shortcut
2359
2315
  cch = 0x01 # Length of text name
2360
2316
  cce = 0x001a # Length of text definition
2361
2317
  unknown01 = 0x0000 #
2362
2318
  ixals = index + 1 # Sheet index
2363
2319
  unknown02 = 0x00 #
2364
- cchCustMenu = 0x00 # Length of cust menu text
2365
- cchDescription = 0x00 # Length of description text
2366
- cchHelptopic = 0x00 # Length of help topic text
2367
- cchStatustext = 0x00 # Length of status bar text
2320
+ cch_cust_menu = 0x00 # Length of cust menu text
2321
+ cch_description = 0x00 # Length of description text
2322
+ cch_helptopic = 0x00 # Length of help topic text
2323
+ cch_statustext = 0x00 # Length of status bar text
2368
2324
  rgch = type # Built-in name type
2369
2325
 
2370
2326
  unknown03 = 0x29
@@ -2373,16 +2329,16 @@ def store_name_long(index, type, ext_ref, rowmin, rowmax, colmin, colmax)
2373
2329
 
2374
2330
  header = [record, length].pack("vv")
2375
2331
  data = [grbit].pack("v")
2376
- data += [chKey].pack("C")
2332
+ data += [chkey].pack("C")
2377
2333
  data += [cch].pack("C")
2378
2334
  data += [cce].pack("v")
2379
2335
  data += [unknown01].pack("v")
2380
2336
  data += [ixals].pack("v")
2381
2337
  data += [unknown02].pack("C")
2382
- data += [cchCustMenu].pack("C")
2383
- data += [cchDescription].pack("C")
2384
- data += [cchHelptopic].pack("C")
2385
- data += [cchStatustext].pack("C")
2338
+ data += [cch_cust_menu].pack("C")
2339
+ data += [cch_description].pack("C")
2340
+ data += [cch_helptopic].pack("C")
2341
+ data += [cch_statustext].pack("C")
2386
2342
  data += [rgch].pack("C")
2387
2343
 
2388
2344
  # Column definition
@@ -2405,7 +2361,6 @@ def store_name_long(index, type, ext_ref, rowmin, rowmax, colmin, colmax)
2405
2361
  # End of data
2406
2362
  data += [0x10].pack("C")
2407
2363
 
2408
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2409
2364
  append(header, data)
2410
2365
  end
2411
2366
  private :store_name_long
@@ -2429,7 +2384,6 @@ def store_palette #:nodoc:
2429
2384
 
2430
2385
  header = [record, length, ccv].pack("vvv")
2431
2386
 
2432
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2433
2387
  append(header, data)
2434
2388
  end
2435
2389
  private :store_palette
@@ -2445,11 +2399,7 @@ def store_codepage #:nodoc:
2445
2399
  length = 0x0002 # Number of bytes to follow
2446
2400
  cv = @codepage # The code page
2447
2401
 
2448
- header = [record, length].pack("vv")
2449
- data = [cv].pack("v")
2450
-
2451
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2452
- append(header, data)
2402
+ store_common(record, length, cv)
2453
2403
  end
2454
2404
  private :store_codepage
2455
2405
 
@@ -2465,10 +2415,7 @@ def store_country #:nodoc:
2465
2415
  country_default = @country
2466
2416
  country_win_ini = @country
2467
2417
 
2468
- header = [record, length].pack("vv")
2469
- data = [country_default, country_win_ini].pack("vv")
2470
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2471
- append(header, data)
2418
+ store_common(record, length, country_default, country_win_ini)
2472
2419
  end
2473
2420
  private :store_country
2474
2421
 
@@ -2483,19 +2430,17 @@ def store_hideobj #:nodoc:
2483
2430
  length = 0x0002 # Number of bytes to follow
2484
2431
  hide = @hideobj # Option to hide objects
2485
2432
 
2486
- header = [record, length].pack("vv")
2487
- data = [hide].pack("v")
2488
-
2489
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2490
- append(header, data)
2433
+ store_common(record, length, hide)
2491
2434
  end
2492
2435
  private :store_hideobj
2493
2436
 
2494
- ###############################################################################
2495
- ###############################################################################
2496
- ###############################################################################
2497
-
2437
+ def store_common(record, length, *data)
2438
+ header = [record, length].pack("vv")
2439
+ add_data = [*data].pack("v*")
2498
2440
 
2441
+ append(header, add_data)
2442
+ end
2443
+ private :store_common
2499
2444
 
2500
2445
  ###############################################################################
2501
2446
  #
@@ -2506,7 +2451,6 @@ def store_hideobj #:nodoc:
2506
2451
  #
2507
2452
  def calculate_extern_sizes # :nodoc:
2508
2453
  ext_refs = @parser.get_ext_sheets
2509
- ext_ref_count = ext_refs.keys.size
2510
2454
  length = 0
2511
2455
  index = 0
2512
2456
 
@@ -2514,10 +2458,7 @@ def calculate_extern_sizes # :nodoc:
2514
2458
  index = 0
2515
2459
  key = "#{index}:#{index}"
2516
2460
 
2517
- unless ext_refs.has_key?(key)
2518
- ext_refs[key] = ext_ref_count
2519
- ext_ref_count += 1
2520
- end
2461
+ add_ext_refs(ext_refs, key) unless ext_refs.has_key?(key)
2521
2462
  end
2522
2463
 
2523
2464
  @defined_names.each do |defined_name|
@@ -2528,34 +2469,23 @@ def calculate_extern_sizes # :nodoc:
2528
2469
 
2529
2470
  rowmin = worksheet.title_rowmin
2530
2471
  colmin = worksheet.title_colmin
2531
- filter = worksheet.filter_count
2532
2472
  key = "#{index}:#{index}"
2533
2473
  index += 1
2534
2474
 
2535
2475
  # Add area NAME records
2536
2476
  #
2537
- if !worksheet.print_rowmin.nil?
2538
- if ext_refs[key].nil?
2539
- ext_refs[key] = ext_ref_count
2540
- ext_ref_count += 1
2541
- end
2477
+ if worksheet.print_rowmin
2478
+ add_ext_refs(ext_refs, key) unless ext_refs[key]
2542
2479
  length += 31
2543
2480
  end
2544
2481
 
2545
2482
  # Add title NAME records
2546
2483
  #
2547
2484
  if rowmin and colmin
2548
- if ext_refs[key].nil?
2549
- ext_refs[key] = ext_ref_count
2550
- ext_ref_count += 1
2551
- end
2552
-
2485
+ add_ext_refs(ext_refs, key) unless ext_refs[key]
2553
2486
  length += 46
2554
2487
  elsif rowmin or colmin
2555
- if ext_refs[key].nil?
2556
- ext_refs[key] = ext_ref_count
2557
- ext_ref_count += 1
2558
- end
2488
+ add_ext_refs(ext_refs, key) unless ext_refs[key]
2559
2489
  length += 31
2560
2490
  else
2561
2491
  # TODO, may need this later.
@@ -2563,17 +2493,14 @@ def calculate_extern_sizes # :nodoc:
2563
2493
 
2564
2494
  # Add Autofilter NAME records
2565
2495
  #
2566
- if filter != 0
2567
- if ext_refs[key].nil?
2568
- ext_refs[key] = ext_ref_count
2569
- ext_ref_count += 1
2570
- end
2496
+ unless worksheet.filter_count == 0
2497
+ add_ext_refs(ext_refs, key) unless ext_refs[key]
2571
2498
  length += 31
2572
2499
  end
2573
2500
  end
2574
2501
 
2575
2502
  # Update the ref counts.
2576
- @ext_ref_count = ext_ref_count
2503
+ ext_ref_count = ext_refs.keys.size
2577
2504
  @ext_refs = ext_refs
2578
2505
 
2579
2506
  # If there are no external refs then we don't write, SUPBOOK, EXTERNSHEET
@@ -2590,6 +2517,11 @@ def calculate_extern_sizes # :nodoc:
2590
2517
  length
2591
2518
  end
2592
2519
 
2520
+ def add_ext_refs(ext_refs, key)
2521
+ ext_refs[key] = ext_refs.keys.size
2522
+ end
2523
+ private :add_ext_refs
2524
+
2593
2525
  ###############################################################################
2594
2526
  #
2595
2527
  # _calculate_shared_string_sizes()
@@ -2635,10 +2567,7 @@ def calculate_shared_string_sizes #:nodoc:
2635
2567
  continue = 0
2636
2568
 
2637
2569
  strings.each do |string|
2638
-
2639
2570
  string_length = string.bytesize
2640
- encoding = string.unpack("xx C")[0]
2641
- split_string = 0
2642
2571
 
2643
2572
  # Block length is the total length of the strings that will be
2644
2573
  # written out in a single SST or CONTINUE block.
@@ -2651,44 +2580,14 @@ def calculate_shared_string_sizes #:nodoc:
2651
2580
  next
2652
2581
  end
2653
2582
 
2654
-
2655
2583
  # Deal with the cases where the next string to be written will exceed
2656
2584
  # the CONTINUE boundary. If the string is very long it may need to be
2657
2585
  # written in more than one CONTINUE record.
2658
- #
2586
+ encoding = string.unpack("xx C")[0]
2587
+ split_string = 0
2659
2588
  while block_length >= continue_limit
2660
-
2661
- # We need to avoid the case where a string is continued in the first
2662
- # n bytes that contain the string header information.
2663
- #
2664
- header_length = 3 # Min string + header size -1
2665
- space_remaining = continue_limit -written -continue
2666
-
2667
-
2668
- # Unicode data should only be split on char (2 byte) boundaries.
2669
- # Therefore, in some cases we need to reduce the amount of available
2670
- # space by 1 byte to ensure the correct alignment.
2671
- align = 0
2672
-
2673
- # Only applies to Unicode strings
2674
- if encoding == 1
2675
- # Min string + header size -1
2676
- header_length = 4
2677
-
2678
- if space_remaining > header_length
2679
- # String contains 3 byte header => split on odd boundary
2680
- if split_string == 0 and space_remaining % 2 != 1
2681
- space_remaining -= 1
2682
- align = 1
2683
- # Split section without header => split on even boundary
2684
- elsif split_string != 0 and space_remaining % 2 == 1
2685
- space_remaining -= 1
2686
- align = 1
2687
- end
2688
-
2689
- split_string = 1
2690
- end
2691
- end
2589
+ header_length, space_remaining, align, split_string =
2590
+ _split_string_setup(encoding, split_string, continue_limit, written, continue)
2692
2591
 
2693
2592
  if space_remaining > header_length
2694
2593
  # Write as much as possible of the string in the current block
@@ -2750,6 +2649,38 @@ def calculate_shared_string_sizes #:nodoc:
2750
2649
  end
2751
2650
  private :calculate_shared_string_sizes
2752
2651
 
2652
+ def _split_string_setup(encoding, split_string, continue_limit, written, continue)
2653
+ # We need to avoid the case where a string is continued in the first
2654
+ # n bytes that contain the string header information.
2655
+ header_length = 3 # Min string + header size -1
2656
+ space_remaining = continue_limit - written - continue
2657
+
2658
+ # Unicode data should only be split on char (2 byte) boundaries.
2659
+ # Therefore, in some cases we need to reduce the amount of available
2660
+ # space by 1 byte to ensure the correct alignment.
2661
+ align = 0
2662
+
2663
+ # Only applies to Unicode strings
2664
+ if encoding == 1
2665
+ # Min string + header size -1
2666
+ header_length = 4
2667
+ if space_remaining > header_length
2668
+ # String contains 3 byte header => split on odd boundary
2669
+ if split_string == 0 and space_remaining % 2 != 1
2670
+ space_remaining -= 1
2671
+ align = 1
2672
+ # Split section without header => split on even boundary
2673
+ elsif split_string != 0 and space_remaining % 2 == 1
2674
+ space_remaining -= 1
2675
+ align = 1
2676
+ end
2677
+ split_string = 1
2678
+ end
2679
+ end
2680
+ [header_length, space_remaining, align, split_string]
2681
+ end
2682
+ private :_split_string_setup
2683
+
2753
2684
  ###############################################################################
2754
2685
  #
2755
2686
  # _store_shared_strings()
@@ -2797,7 +2728,6 @@ def store_shared_strings #:nodoc:
2797
2728
  # Write the SST block header information
2798
2729
  header = [record, length].pack("vv")
2799
2730
  data = [@sinfo[:str_total], @sinfo[:str_unique]].pack("VV")
2800
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2801
2731
  append(header, data)
2802
2732
 
2803
2733
  # Iterate through the strings and write them out
@@ -2805,15 +2735,11 @@ def store_shared_strings #:nodoc:
2805
2735
  strings.each do |string|
2806
2736
 
2807
2737
  string_length = string.bytesize
2808
- encoding = string.unpack("xx C")[0]
2809
- split_string = 0
2810
- bucket_string = 0 # Used to track EXTSST bucket offsets.
2811
2738
 
2812
2739
  # Check if the string is at the start of a EXTSST bucket.
2813
2740
  extsst_str_num += 1
2814
- if extsst_str_num % @extsst_bucket_size == 0
2815
- bucket_string = 1
2816
- end
2741
+ # Used to track EXTSST bucket offsets.
2742
+ bucket_string = (extsst_str_num % @extsst_bucket_size == 0)
2817
2743
 
2818
2744
  # Block length is the total length of the strings that will be
2819
2745
  # written out in a single SST or CONTINUE block.
@@ -2824,15 +2750,11 @@ def store_shared_strings #:nodoc:
2824
2750
  if block_length < continue_limit
2825
2751
 
2826
2752
  # Store location of EXTSST bucket string.
2827
- if bucket_string != 0
2828
- global_offset = @datasize
2829
- local_offset = @datasize - sst_block_start
2830
-
2831
- @extsst_offsets.push([global_offset, local_offset])
2832
- bucket_string = 0
2753
+ if bucket_string
2754
+ @extsst_offsets.push([@datasize, @datasize - sst_block_start])
2755
+ bucket_string = false
2833
2756
  end
2834
2757
 
2835
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2836
2758
  append(string)
2837
2759
  written += string_length
2838
2760
  next
@@ -2841,58 +2763,24 @@ def store_shared_strings #:nodoc:
2841
2763
  # Deal with the cases where the next string to be written will exceed
2842
2764
  # the CONTINUE boundary. If the string is very long it may need to be
2843
2765
  # written in more than one CONTINUE record.
2844
- #
2766
+ encoding = string.unpack("xx C")[0]
2767
+ split_string = 0
2845
2768
  while block_length >= continue_limit
2846
-
2847
- # We need to avoid the case where a string is continued in the first
2848
- # n bytes that contain the string header information.
2849
- #
2850
- header_length = 3 # Min string + header size -1
2851
- space_remaining = continue_limit -written -continue
2852
-
2853
-
2854
- # Unicode data should only be split on char (2 byte) boundaries.
2855
- # Therefore, in some cases we need to reduce the amount of available
2856
- # space by 1 byte to ensure the correct alignment.
2857
- align = 0
2858
-
2859
- # Only applies to Unicode strings
2860
- if encoding == 1
2861
- # Min string + header size -1
2862
- header_length = 4
2863
-
2864
- if space_remaining > header_length
2865
- # String contains 3 byte header => split on odd boundary
2866
- if split_string == 0 and space_remaining % 2 != 1
2867
- space_remaining -= 1
2868
- align = 1
2869
- # Split section without header => split on even boundary
2870
- elsif split_string != 0 and space_remaining % 2 == 1
2871
- space_remaining -= 1
2872
- align = 1
2873
- end
2874
-
2875
- split_string = 1
2876
- end
2877
- end
2769
+ header_length, space_remaining, align, split_string =
2770
+ _split_string_setup(encoding, split_string, continue_limit, written, continue)
2878
2771
 
2879
2772
  if space_remaining > header_length
2880
2773
  # Write as much as possible of the string in the current block
2881
2774
  tmp = string[0, space_remaining]
2882
2775
 
2883
2776
  # Store location of EXTSST bucket string.
2884
- if bucket_string != 0
2885
- global_offset = @datasize
2886
- local_offset = @datasize - sst_block_start
2887
-
2888
- @extsst_offsets.push([global_offset, local_offset])
2889
- bucket_string = 0
2777
+ if bucket_string
2778
+ @extsst_offsets.push([@datasize, @datasize - sst_block_start])
2779
+ bucket_string = false
2890
2780
  end
2891
2781
 
2892
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2893
2782
  append(tmp)
2894
2783
 
2895
-
2896
2784
  # The remainder will be written in the next block(s)
2897
2785
  string = string[space_remaining .. string.length-1]
2898
2786
 
@@ -2924,7 +2812,6 @@ def store_shared_strings #:nodoc:
2924
2812
  header = [record, length].pack("vv")
2925
2813
  header += [encoding].pack("C") if continue != 0
2926
2814
 
2927
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2928
2815
  append(header)
2929
2816
  end
2930
2817
 
@@ -2935,15 +2822,10 @@ def store_shared_strings #:nodoc:
2935
2822
  if block_length < continue_limit
2936
2823
 
2937
2824
  # Store location of EXTSST bucket string.
2938
- if bucket_string != 0
2939
- global_offset = @datasize
2940
- local_offset = @datasize - sst_block_start
2941
-
2942
- @extsst_offsets.push([global_offset, local_offset])
2943
-
2944
- bucket_string = 0
2825
+ if bucket_string
2826
+ @extsst_offsets.push([@datasize, @datasize - sst_block_start])
2827
+ bucket_string = false
2945
2828
  end
2946
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
2947
2829
  append(string)
2948
2830
 
2949
2831
  written = block_length
@@ -3002,7 +2884,6 @@ def store_extsst #:nodoc:
3002
2884
  data += [offset[0], offset[1], 0].pack('Vvv')
3003
2885
  end
3004
2886
 
3005
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
3006
2887
  append(header, data)
3007
2888
  end
3008
2889
  private :store_extsst
@@ -3068,7 +2949,6 @@ def add_mso_drawing_group_continue(data) #:nodoc:
3068
2949
 
3069
2950
  # Case 1 above. Just return the data as it is.
3070
2951
  if data.bytesize <= limit
3071
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
3072
2952
  append(data)
3073
2953
  return
3074
2954
  end
@@ -3077,7 +2957,6 @@ def add_mso_drawing_group_continue(data) #:nodoc:
3077
2957
  tmp = data.dup
3078
2958
  tmp[0, limit + 4] = ""
3079
2959
  tmp[2, 2] = [limit].pack('v')
3080
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
3081
2960
  append(tmp)
3082
2961
 
3083
2962
  # Add MSODRAWINGGROUP and CONTINUE blocks for Case 3 above.
@@ -3093,13 +2972,11 @@ def add_mso_drawing_group_continue(data) #:nodoc:
3093
2972
 
3094
2973
  tmp = data.dup
3095
2974
  tmp[0, limit] = ''
3096
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
3097
2975
  append(header, tmp)
3098
2976
  end
3099
2977
 
3100
2978
  # Last CONTINUE block for remaining data. Case 2 and 3 above.
3101
2979
  header = [continue, data.bytesize].pack("vv")
3102
- print "#{__FILE__}(#{__LINE__}) \n" if defined?($debug)
3103
2980
  append(header, data)
3104
2981
 
3105
2982
  # Turn the base class _add_continue() method back on.