writeexcel 0.4.0 → 0.4.1

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