spreadsheet 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/GUIDE.txt +209 -0
- data/History.txt +8 -0
- data/LICENSE.txt +619 -0
- data/Manifest.txt +46 -0
- data/README.txt +54 -0
- data/Rakefile +15 -0
- data/lib/parseexcel.rb +27 -0
- data/lib/parseexcel/parseexcel.rb +75 -0
- data/lib/parseexcel/parser.rb +11 -0
- data/lib/spreadsheet.rb +79 -0
- data/lib/spreadsheet/datatypes.rb +99 -0
- data/lib/spreadsheet/encodings.rb +49 -0
- data/lib/spreadsheet/excel.rb +75 -0
- data/lib/spreadsheet/excel/error.rb +26 -0
- data/lib/spreadsheet/excel/internals.rb +322 -0
- data/lib/spreadsheet/excel/internals/biff5.rb +17 -0
- data/lib/spreadsheet/excel/internals/biff8.rb +19 -0
- data/lib/spreadsheet/excel/offset.rb +37 -0
- data/lib/spreadsheet/excel/reader.rb +798 -0
- data/lib/spreadsheet/excel/reader/biff5.rb +22 -0
- data/lib/spreadsheet/excel/reader/biff8.rb +168 -0
- data/lib/spreadsheet/excel/row.rb +67 -0
- data/lib/spreadsheet/excel/sst_entry.rb +45 -0
- data/lib/spreadsheet/excel/workbook.rb +76 -0
- data/lib/spreadsheet/excel/worksheet.rb +85 -0
- data/lib/spreadsheet/excel/writer.rb +1 -0
- data/lib/spreadsheet/excel/writer/biff8.rb +66 -0
- data/lib/spreadsheet/excel/writer/format.rb +270 -0
- data/lib/spreadsheet/excel/writer/workbook.rb +586 -0
- data/lib/spreadsheet/excel/writer/worksheet.rb +556 -0
- data/lib/spreadsheet/font.rb +86 -0
- data/lib/spreadsheet/format.rb +172 -0
- data/lib/spreadsheet/formula.rb +9 -0
- data/lib/spreadsheet/row.rb +87 -0
- data/lib/spreadsheet/workbook.rb +120 -0
- data/lib/spreadsheet/worksheet.rb +215 -0
- data/lib/spreadsheet/writer.rb +29 -0
- data/test/data/test_copy.xls +0 -0
- data/test/data/test_version_excel5.xls +0 -0
- data/test/data/test_version_excel95.xls +0 -0
- data/test/data/test_version_excel97.xls +0 -0
- data/test/excel/row.rb +29 -0
- data/test/font.rb +163 -0
- data/test/integration.rb +1021 -0
- data/test/workbook.rb +21 -0
- data/test/worksheet.rb +62 -0
- metadata +113 -0
data/Manifest.txt
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
GUIDE.txt
|
2
|
+
History.txt
|
3
|
+
LICENSE.txt
|
4
|
+
Manifest.txt
|
5
|
+
README.txt
|
6
|
+
Rakefile
|
7
|
+
lib/parseexcel.rb
|
8
|
+
lib/parseexcel/parseexcel.rb
|
9
|
+
lib/parseexcel/parser.rb
|
10
|
+
lib/spreadsheet.rb
|
11
|
+
lib/spreadsheet/datatypes.rb
|
12
|
+
lib/spreadsheet/encodings.rb
|
13
|
+
lib/spreadsheet/excel.rb
|
14
|
+
lib/spreadsheet/excel/error.rb
|
15
|
+
lib/spreadsheet/excel/internals.rb
|
16
|
+
lib/spreadsheet/excel/internals/biff5.rb
|
17
|
+
lib/spreadsheet/excel/internals/biff8.rb
|
18
|
+
lib/spreadsheet/excel/offset.rb
|
19
|
+
lib/spreadsheet/excel/reader.rb
|
20
|
+
lib/spreadsheet/excel/reader/biff5.rb
|
21
|
+
lib/spreadsheet/excel/reader/biff8.rb
|
22
|
+
lib/spreadsheet/excel/row.rb
|
23
|
+
lib/spreadsheet/excel/sst_entry.rb
|
24
|
+
lib/spreadsheet/excel/workbook.rb
|
25
|
+
lib/spreadsheet/excel/worksheet.rb
|
26
|
+
lib/spreadsheet/excel/writer.rb
|
27
|
+
lib/spreadsheet/excel/writer/biff8.rb
|
28
|
+
lib/spreadsheet/excel/writer/format.rb
|
29
|
+
lib/spreadsheet/excel/writer/workbook.rb
|
30
|
+
lib/spreadsheet/excel/writer/worksheet.rb
|
31
|
+
lib/spreadsheet/font.rb
|
32
|
+
lib/spreadsheet/format.rb
|
33
|
+
lib/spreadsheet/formula.rb
|
34
|
+
lib/spreadsheet/row.rb
|
35
|
+
lib/spreadsheet/workbook.rb
|
36
|
+
lib/spreadsheet/worksheet.rb
|
37
|
+
lib/spreadsheet/writer.rb
|
38
|
+
test/data/test_copy.xls
|
39
|
+
test/data/test_version_excel5.xls
|
40
|
+
test/data/test_version_excel95.xls
|
41
|
+
test/data/test_version_excel97.xls
|
42
|
+
test/excel/row.rb
|
43
|
+
test/font.rb
|
44
|
+
test/integration.rb
|
45
|
+
test/workbook.rb
|
46
|
+
test/worksheet.rb
|
data/README.txt
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
= Spreadsheet
|
2
|
+
|
3
|
+
http://spreadsheet.rubyforge.org
|
4
|
+
|
5
|
+
== Description
|
6
|
+
|
7
|
+
The Spreadsheet Library is designed to read and write Spreadsheet Documents.
|
8
|
+
As of version 0.6.0, only Microsoft Excel compatible spreadsheets are
|
9
|
+
supported. Spreadsheet is a combination/complete rewrite of the
|
10
|
+
Spreadsheet::Excel Library by Daniel J. Berger and the ParseExcel Library by
|
11
|
+
Hannes Wyss. Spreadsheet can read, write and modify Spreadsheet Documents.
|
12
|
+
|
13
|
+
== What's new?
|
14
|
+
* Significantly improved memory-efficiency when reading large Excel Files
|
15
|
+
* Limited Spreadsheet modification support
|
16
|
+
* Improved handling of String Encodings
|
17
|
+
|
18
|
+
== Roadmap
|
19
|
+
0.7.0:: Improved Format support/Styles
|
20
|
+
0.7.1:: Document Modification: Formats/Styles
|
21
|
+
0.8.0:: Formula Support
|
22
|
+
0.8.1:: Document Modification: Formulas
|
23
|
+
0.9.0:: Write-Support: BIFF5
|
24
|
+
1.0.0:: Ruby 1.9 Support;
|
25
|
+
Remove backward compatibility code
|
26
|
+
|
27
|
+
== Dependencies
|
28
|
+
|
29
|
+
* ruby 1.8
|
30
|
+
* Iconv
|
31
|
+
* ruby-ole[http://code.google.com/p/ruby-ole/]
|
32
|
+
|
33
|
+
== Examples
|
34
|
+
|
35
|
+
Have a look at the GUIDE[link://files/GUIDE_txt.html].
|
36
|
+
|
37
|
+
== Authors
|
38
|
+
|
39
|
+
Original Code:
|
40
|
+
|
41
|
+
Spreadsheet::Excel:
|
42
|
+
Copyright (c) 2005 by Daniel J. Berger (djberg96@gmail.com)
|
43
|
+
|
44
|
+
ParseExcel:
|
45
|
+
Copyright (c) 2003 by Hannes Wyss (hannes.wyss@gmail.com)
|
46
|
+
|
47
|
+
New Code:
|
48
|
+
Copyright (c) 2008 by Hannes Wyss (hannes.wyss@gmail.com)
|
49
|
+
|
50
|
+
== License
|
51
|
+
|
52
|
+
This library is distributed under the GPL.
|
53
|
+
Please see the LICENSE[link://files/LICENSE_txt.html] file.
|
54
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/spreadsheet.rb'
|
6
|
+
|
7
|
+
ENV['RDOCOPT'] = '-c utf8'
|
8
|
+
|
9
|
+
Hoe.new('spreadsheet', Spreadsheet::VERSION) do |p|
|
10
|
+
# p.rubyforge_name = 'spreadsheetx' # if different than lowercase project name
|
11
|
+
p.developer('Hannes Wyss', 'hannes.wyss@gmail.com')
|
12
|
+
p.remote_rdoc_dir = ''
|
13
|
+
end
|
14
|
+
|
15
|
+
# vim: syntax=Ruby
|
data/lib/parseexcel.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
### Spreadsheet - A Library for reading and writing Spreadsheet Documents.
|
2
|
+
#
|
3
|
+
# Copyright (C) 2008 Hannes Wyss
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#
|
18
|
+
# Contact Information:
|
19
|
+
#
|
20
|
+
# E-Mail: hannes.wyss@gmail.com
|
21
|
+
# P-Mail: ywesee GmbH
|
22
|
+
# Hannes Wyss
|
23
|
+
# Winterthurerstrasse 52
|
24
|
+
# 8006 Zürich
|
25
|
+
### Switzerland
|
26
|
+
|
27
|
+
require 'parseexcel/parseexcel'
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spreadsheet'
|
2
|
+
|
3
|
+
warn <<-EOS
|
4
|
+
[DEPRECATED] By requiring 'parseexcel', 'parseexcel/parseexcel' and/or
|
5
|
+
'parseexcel/parser' you are loading a Compatibility layer which
|
6
|
+
provides a drop-in replacement for the ParseExcel library. This
|
7
|
+
code makes the reading of Spreadsheet documents less efficient and
|
8
|
+
will be removed in Spreadsheet version 1.0.0
|
9
|
+
EOS
|
10
|
+
|
11
|
+
module Spreadsheet
|
12
|
+
##
|
13
|
+
# The ParseExcel module is provided as a drop-in replacement for the
|
14
|
+
# ParseExcel library. This code is deprecated and will be removed in
|
15
|
+
# Spreadsheet version 1.0.0
|
16
|
+
module ParseExcel
|
17
|
+
def ParseExcel.parse path
|
18
|
+
Spreadsheet.open path
|
19
|
+
end
|
20
|
+
class Worksheet
|
21
|
+
class Cell
|
22
|
+
attr_accessor :value, :kind, :numeric, :code, :book,
|
23
|
+
:format, :rich, :encoding, :annotation
|
24
|
+
def initialize value, format, row, idx
|
25
|
+
@format = format
|
26
|
+
@idx = idx
|
27
|
+
@row = row
|
28
|
+
@value = value
|
29
|
+
@encoding = Spreadsheet.client_encoding
|
30
|
+
end
|
31
|
+
def date
|
32
|
+
@row.date @idx
|
33
|
+
end
|
34
|
+
def datetime
|
35
|
+
@row.datetime @idx
|
36
|
+
end
|
37
|
+
def to_i
|
38
|
+
@value.to_i
|
39
|
+
end
|
40
|
+
def to_f
|
41
|
+
@value.to_f
|
42
|
+
end
|
43
|
+
def to_s(target_encoding=nil)
|
44
|
+
if(target_encoding)
|
45
|
+
begin
|
46
|
+
Iconv.new(target_encoding, @encoding).iconv(@value)
|
47
|
+
rescue
|
48
|
+
Iconv.new(target_encoding, 'ascii').iconv(@value.to_s)
|
49
|
+
end
|
50
|
+
else
|
51
|
+
@value.to_s
|
52
|
+
end
|
53
|
+
end
|
54
|
+
def type
|
55
|
+
if @format && (@format.date? || @format.time?)
|
56
|
+
:date
|
57
|
+
elsif @value.is_a?(Numeric)
|
58
|
+
:numeric
|
59
|
+
else
|
60
|
+
:text
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
module Excel
|
67
|
+
class Reader # :nodoc: all
|
68
|
+
def set_cell worksheet, row, column, xf, value=nil
|
69
|
+
cells = @current_row_block[row] ||= Row.new(nil, row)
|
70
|
+
cells.formats[column] = xf = @workbook.format(xf)
|
71
|
+
cells[column] = ParseExcel::Worksheet::Cell.new(value, xf, cells, column)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/spreadsheet.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
### Spreadsheet - A Library for reading and writing Spreadsheet Documents.
|
2
|
+
#
|
3
|
+
# Copyright (C) 2008 Hannes Wyss
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#
|
18
|
+
# Contact Information:
|
19
|
+
#
|
20
|
+
# E-Mail: hannes.wyss@gmail.com
|
21
|
+
# P-Mail: ywesee GmbH
|
22
|
+
# Hannes Wyss
|
23
|
+
# Winterthurerstrasse 52
|
24
|
+
# 8006 Zürich
|
25
|
+
### Switzerland
|
26
|
+
|
27
|
+
require 'spreadsheet/excel/workbook'
|
28
|
+
require 'spreadsheet/excel/reader'
|
29
|
+
|
30
|
+
# = Synopsis
|
31
|
+
# The Spreadsheet Library is designed to read and write Spreadsheet Documents.
|
32
|
+
# As of version 0.6.0, only Microsoft Excel compatible spreadsheets are
|
33
|
+
# supported.
|
34
|
+
#
|
35
|
+
# == Example
|
36
|
+
# require 'spreadsheet'
|
37
|
+
#
|
38
|
+
# book = Spreadsheet.open '/path/to/an/excel-file.xls'
|
39
|
+
# sheet = book.worksheet 0
|
40
|
+
# sheet.each do |row| puts row[0] end
|
41
|
+
module Spreadsheet
|
42
|
+
|
43
|
+
##
|
44
|
+
# The version of Spreadsheet you are using.
|
45
|
+
VERSION = '0.6.0'
|
46
|
+
|
47
|
+
##
|
48
|
+
# Default client Encoding. Change this value if your application uses a
|
49
|
+
# different Encoding:
|
50
|
+
# Spreadsheet.client_encoding = 'ISO-LATIN-1//TRANSLIT//IGNORE'
|
51
|
+
@client_encoding = 'UTF8'
|
52
|
+
|
53
|
+
class << self
|
54
|
+
|
55
|
+
attr_accessor :client_encoding
|
56
|
+
|
57
|
+
##
|
58
|
+
# Parses a Spreadsheet Document and returns a Workbook object. At present,
|
59
|
+
# only Excel-Documents can be read.
|
60
|
+
def open io_or_path, mode="rb+", &block
|
61
|
+
if io_or_path.is_a? IO
|
62
|
+
Excel::Workbook.open(io_or_path)
|
63
|
+
elsif block
|
64
|
+
File.open(io_or_path, mode) do |fh|
|
65
|
+
block.call open(fh)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
open File.open(io_or_path, mode)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Returns a Writer object for the specified path. At present, only the
|
74
|
+
# Excel-Writer is available.
|
75
|
+
def writer io_or_path, type=Excel
|
76
|
+
Excel::Writer::Workbook.new io_or_path
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Spreadsheet
|
2
|
+
##
|
3
|
+
# This module defines convenience-methods for the definition of Spreadsheet
|
4
|
+
# attributes (boolean, colors and enumerations)
|
5
|
+
module Datatypes
|
6
|
+
def Datatypes.append_features mod
|
7
|
+
super
|
8
|
+
mod.module_eval do
|
9
|
+
class << self
|
10
|
+
##
|
11
|
+
# Valid colors for color attributes.
|
12
|
+
COLORS = [ :builtin_black, :builtin_white, :builtin_red, :builtin_green,
|
13
|
+
:builtin_blue, :builtin_yellow, :builtin_magenta, :builtin_cyan,
|
14
|
+
:text, :border, :pattern_bg, :dialog_bg, :chart_text, :chart_bg,
|
15
|
+
:chart_border, :tooltip_bg, :tooltip_text, :aqua,
|
16
|
+
:black, :blue, :cyan, :brown, :fuchsia, :gray, :grey, :green,
|
17
|
+
:lime, :magenta, :navy, :orange, :purple, :red, :silver, :white,
|
18
|
+
:yellow ]
|
19
|
+
##
|
20
|
+
# Define instance methods to read and write boolean attributes.
|
21
|
+
def boolean *args
|
22
|
+
args.each do |key|
|
23
|
+
define_method key do
|
24
|
+
!!instance_variable_get("@#{key}")
|
25
|
+
end
|
26
|
+
define_method "#{key}?" do
|
27
|
+
!!instance_variable_get("@#{key}")
|
28
|
+
end
|
29
|
+
define_method "#{key}!" do
|
30
|
+
instance_variable_set("@#{key}", true)
|
31
|
+
end
|
32
|
+
define_method "#{key}=" do |arg|
|
33
|
+
arg = false if arg == 0
|
34
|
+
instance_variable_set("@#{key}", !!arg)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
##
|
39
|
+
# Define instance methods to read and write color attributes.
|
40
|
+
# For valid colors see COLORS
|
41
|
+
def colors *args
|
42
|
+
args.each do |key|
|
43
|
+
attr_reader key
|
44
|
+
define_method "#{key}=" do |name|
|
45
|
+
name = name.to_s.downcase.to_sym
|
46
|
+
if COLORS.include?(name)
|
47
|
+
instance_variable_set "@#{key}", name
|
48
|
+
else
|
49
|
+
raise ArgumentError, "unknown color '#{name}'"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
##
|
55
|
+
# Define instance methods to read and write enumeration attributes.
|
56
|
+
# * The first argument designates the attribute name.
|
57
|
+
# * The second argument designates the default value.
|
58
|
+
# * All subsequent attributes are possible values.
|
59
|
+
# * If the last attribute is a Hash, each value in the Hash designates
|
60
|
+
# aliases for the corresponding key.
|
61
|
+
def enum key, *values
|
62
|
+
aliases = {}
|
63
|
+
if values.last.is_a? Hash
|
64
|
+
values.pop.each do |value, synonyms|
|
65
|
+
if synonyms.is_a? Array
|
66
|
+
synonyms.each do |synonym| aliases.store synonym, value end
|
67
|
+
else
|
68
|
+
aliases.store synonyms, value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
values.each do |value|
|
73
|
+
aliases.store value, value
|
74
|
+
end
|
75
|
+
define_method key do
|
76
|
+
instance_variable_get("@#{key}") || values.first
|
77
|
+
end
|
78
|
+
define_method "#{key}=" do |arg|
|
79
|
+
if arg
|
80
|
+
arg = aliases.fetch arg do
|
81
|
+
aliases.fetch arg.to_s.downcase.gsub(/[ \-]/, '_').to_sym, arg
|
82
|
+
end
|
83
|
+
if values.any? do |val| val === arg end
|
84
|
+
instance_variable_set("@#{key}", arg)
|
85
|
+
else
|
86
|
+
valid = values.collect do |val| val.inspect end.join ', '
|
87
|
+
raise ArgumentError,
|
88
|
+
"Invalid value '#{arg.inspect}' for #{key}. Valid values are: #{valid}"
|
89
|
+
end
|
90
|
+
else
|
91
|
+
instance_variable_set "@#{key}", values.first
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Spreadsheet
|
2
|
+
##
|
3
|
+
# Methods for Encoding-conversions. You should not need to use any of these.
|
4
|
+
module Encodings
|
5
|
+
if RUBY_VERSION >= '1.9'
|
6
|
+
def ascii string
|
7
|
+
string.encode 'ASCII//TRANSLIT//IGNORE'
|
8
|
+
end
|
9
|
+
def client string, internal='UTF-16LE'
|
10
|
+
string.encode Spreadsheet.client_encoding
|
11
|
+
end
|
12
|
+
def internal string, internal='UTF-16LE'
|
13
|
+
string.encode internal
|
14
|
+
end
|
15
|
+
else
|
16
|
+
require 'iconv'
|
17
|
+
@@utf8_utf16 = Iconv.new('UTF-16LE', 'UTF8')
|
18
|
+
@@utf16_ascii = Iconv.new('ASCII//TRANSLIT//IGNORE', 'UTF-16LE')
|
19
|
+
@@utf16_utf8 = Iconv.new('UTF8//TRANSLIT//IGNORE', 'UTF-16LE')
|
20
|
+
@@iconvs = {}
|
21
|
+
def ascii string
|
22
|
+
@@utf16_ascii.iconv string
|
23
|
+
rescue
|
24
|
+
string.gsub /[^\x20-\x7e]+/, ''
|
25
|
+
end
|
26
|
+
def client string, internal='UTF-16LE'
|
27
|
+
key = [Spreadsheet.client_encoding, internal]
|
28
|
+
iconv = @@iconvs[key] ||= Iconv.new(Spreadsheet.client_encoding, internal)
|
29
|
+
iconv.iconv string
|
30
|
+
end
|
31
|
+
def internal string, internal='UTF-16LE'
|
32
|
+
key = [internal, Spreadsheet.client_encoding]
|
33
|
+
iconv = @@iconvs[key] ||= Iconv.new(internal, Spreadsheet.client_encoding)
|
34
|
+
iconv.iconv string
|
35
|
+
end
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
warn "You don't have Iconv support compiled in your Ruby. Spreadsheet may not work as expected"
|
39
|
+
def ascii string
|
40
|
+
string.gsub /[^\x20-\x7e]+/, ''
|
41
|
+
end
|
42
|
+
def client string, internal='UTF-16LE'
|
43
|
+
string.delete "\0"
|
44
|
+
end
|
45
|
+
def internal string, internal='UTF-16LE'
|
46
|
+
string.split('').zip(Array.new(string.size, 0.chr)).join
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|