spreadsheetx 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/VERSION +1 -1
- data/lib/spreadsheetx.rb +2 -2
- data/lib/spreadsheetx/workbook.rb +9 -4
- data/lib/spreadsheetx/worksheet.rb +47 -24
- data/spec/spreadsheetx_spec.rb +38 -1
- data/spreadsheetx.gemspec +5 -2
- metadata +22 -11
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -3,10 +3,11 @@ GEM
|
|
3
3
|
specs:
|
4
4
|
diff-lcs (1.1.2)
|
5
5
|
git (1.2.5)
|
6
|
-
jeweler (1.6.
|
6
|
+
jeweler (1.6.4)
|
7
7
|
bundler (~> 1.0)
|
8
8
|
git (>= 1.2.5)
|
9
9
|
rake
|
10
|
+
libxml-ruby (2.0.9)
|
10
11
|
rake (0.9.2)
|
11
12
|
rcov (0.9.9)
|
12
13
|
rspec (2.3.0)
|
@@ -25,6 +26,7 @@ PLATFORMS
|
|
25
26
|
DEPENDENCIES
|
26
27
|
bundler (~> 1.0.0)
|
27
28
|
jeweler (~> 1.6.2)
|
29
|
+
libxml-ruby (~> 2.0.9)
|
28
30
|
rcov
|
29
31
|
rspec (~> 2.3.0)
|
30
32
|
zipruby (~> 0.3.6)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/spreadsheetx.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# zipruby is nice as it can modify an existing zip file, perfect for our usecase
|
2
2
|
require 'zipruby'
|
3
|
-
# we use this because it
|
4
|
-
require '
|
3
|
+
# we use this because it is WAY faster than rexml
|
4
|
+
require 'xml'
|
5
5
|
# for copying files
|
6
6
|
require 'fileutils'
|
7
7
|
#
|
@@ -19,10 +19,15 @@ module SpreadsheetX
|
|
19
19
|
|
20
20
|
#parse the XML and build the worksheets
|
21
21
|
@worksheets = []
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
# parse the XML and hold the doc
|
23
|
+
xml_doc = XML::Document.string(file_contents)
|
24
|
+
# set the default namespace
|
25
|
+
xml_doc.root.namespaces.default_prefix = 'spreadsheetml'
|
26
|
+
|
27
|
+
xml_doc.find('spreadsheetml:sheets/spreadsheetml:sheet').each do |node|
|
28
|
+
sheet_id = node['sheetId'].to_i
|
29
|
+
r_id = node['id'].gsub('rId','').to_i
|
30
|
+
name = node['name'].to_s
|
26
31
|
@worksheets.push SpreadsheetX::Worksheet.new(archive, sheet_id, r_id, name)
|
27
32
|
end
|
28
33
|
|
@@ -18,8 +18,10 @@ module SpreadsheetX
|
|
18
18
|
|
19
19
|
# read contents of this file
|
20
20
|
file_contents = f.read
|
21
|
-
#parse the XML and hold the doc
|
22
|
-
@xml_doc =
|
21
|
+
# parse the XML and hold the doc
|
22
|
+
@xml_doc = XML::Document.string(file_contents)
|
23
|
+
# set the default namespace
|
24
|
+
@xml_doc.root.namespaces.default_prefix = 'spreadsheetml'
|
23
25
|
|
24
26
|
end
|
25
27
|
|
@@ -30,35 +32,55 @@ module SpreadsheetX
|
|
30
32
|
|
31
33
|
cell_id = SpreadsheetX::Worksheet.cell_id(col_number, row_number)
|
32
34
|
|
33
|
-
|
35
|
+
row = @xml_doc.find_first("spreadsheetml:sheetData/spreadsheetml:row[@r=#{row_number}]")
|
36
|
+
|
34
37
|
# was this row found
|
35
|
-
|
38
|
+
unless row
|
36
39
|
# build a new row
|
37
|
-
row =
|
38
|
-
|
39
|
-
#
|
40
|
-
|
40
|
+
row = XML::Node.new('row')
|
41
|
+
row['r'] = row_number.to_s
|
42
|
+
# add it to the other rows
|
43
|
+
@xml_doc.find_first('spreadsheetml:sheetData') << row
|
41
44
|
end
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
cell =
|
46
|
+
cell = row.find_first("spreadsheetml:c[@r='#{cell_id}']")
|
47
|
+
# was this row found
|
48
|
+
unless cell
|
49
|
+
# build a new cell
|
50
|
+
cell = XML::Node.new('c')
|
51
|
+
cell['r'] = cell_id
|
52
|
+
# add it to the other rows
|
53
|
+
row << cell
|
49
54
|
end
|
50
55
|
|
51
|
-
#
|
52
|
-
cell.delete_element('*')
|
53
|
-
|
54
|
-
# now we put the value in the cell
|
56
|
+
# create the node which represents the value in the cell
|
55
57
|
if val.kind_of? String
|
56
|
-
|
57
|
-
|
58
|
+
|
59
|
+
# put the strings inline to make life easier
|
60
|
+
cell['t'] = 'inlineStr'
|
61
|
+
|
62
|
+
# the string node looke like <is><t>string</t></is>
|
63
|
+
is = XML::Node.new('is')
|
64
|
+
t = XML::Node.new('t')
|
65
|
+
t.content = val
|
66
|
+
|
67
|
+
cell_value = ( is << t )
|
68
|
+
|
58
69
|
else
|
59
|
-
|
60
|
-
|
70
|
+
|
71
|
+
# incase this was an inline string, clear out this attribute
|
72
|
+
cell['t'] = ''
|
73
|
+
|
74
|
+
cell_value = XML::Node.new('v')
|
75
|
+
cell_value.content = val.to_s
|
76
|
+
|
61
77
|
end
|
78
|
+
|
79
|
+
# first clear out any existing values (nodes)
|
80
|
+
cell.find('*').each{|n| n.remove! }
|
81
|
+
|
82
|
+
# now we put the value in the cell
|
83
|
+
cell << cell_value
|
62
84
|
|
63
85
|
end
|
64
86
|
|
@@ -66,8 +88,8 @@ module SpreadsheetX
|
|
66
88
|
# NOTE: this is the count of those rows, not the length of the document
|
67
89
|
def row_count
|
68
90
|
count = 0
|
69
|
-
|
70
|
-
count
|
91
|
+
# target the sheetData rows
|
92
|
+
@xml_doc.find('spreadsheetml:sheetData/spreadsheetml:row').count
|
71
93
|
end
|
72
94
|
|
73
95
|
# returns the xml representation of this worksheet
|
@@ -77,6 +99,7 @@ module SpreadsheetX
|
|
77
99
|
|
78
100
|
# turns a cell address into its excel name, 1,1 = A1 2,3 = C2 etc.
|
79
101
|
def self.cell_id(col_number, row_number)
|
102
|
+
raise 'There is no row 0, start at 1 instead' if row_number < 1
|
80
103
|
letter = 'A'
|
81
104
|
# some day, speed this up
|
82
105
|
(col_number.to_i-1).times{letter = letter.succ}
|
data/spec/spreadsheetx_spec.rb
CHANGED
@@ -50,7 +50,6 @@ describe "Spreadsheetx" do
|
|
50
50
|
SpreadsheetX::Worksheet.cell_id(26, 4).should == 'Z4'
|
51
51
|
SpreadsheetX::Worksheet.cell_id(820, 496).should == 'AEN496'
|
52
52
|
|
53
|
-
|
54
53
|
end
|
55
54
|
|
56
55
|
it "allows cell values to be updated" do
|
@@ -81,5 +80,43 @@ describe "Spreadsheetx" do
|
|
81
80
|
workbook.save(new_xlsx_file)
|
82
81
|
|
83
82
|
end
|
83
|
+
|
84
|
+
it "handles large numbers of rows and cols" do
|
85
|
+
|
86
|
+
# a valid xlsx file used for testing
|
87
|
+
empty_xlsx_file = "#{File.dirname(__FILE__)}/../templates/spec.xlsx"
|
88
|
+
workbook = SpreadsheetX.open(empty_xlsx_file)
|
89
|
+
|
90
|
+
500.times do |row|
|
91
|
+
6.times do |col|
|
92
|
+
random_string = (0...30).map{65.+(rand(25)).chr}.join
|
93
|
+
# ump the row because there is no row 0
|
94
|
+
workbook.worksheets.last.update_cell(col, (row+1), random_string)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
new_xlsx_file = "#{File.dirname(__FILE__)}/../templates/spec_large_data.xlsx"
|
99
|
+
workbook.save(new_xlsx_file)
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
it "handles various types of content" do
|
104
|
+
|
105
|
+
# a valid xlsx file used for testing
|
106
|
+
empty_xlsx_file = "#{File.dirname(__FILE__)}/../templates/spec.xlsx"
|
107
|
+
workbook = SpreadsheetX.open(empty_xlsx_file)
|
108
|
+
|
109
|
+
workbook.worksheets.last.update_cell(9, 9, Time.now)
|
110
|
+
workbook.worksheets.last.update_cell(9, 10, 'A string')
|
111
|
+
workbook.worksheets.last.update_cell(9, 11, 10.3)
|
112
|
+
workbook.worksheets.last.update_cell(9, 12, 53)
|
113
|
+
workbook.worksheets.last.update_cell(9, 13, nil)
|
114
|
+
|
115
|
+
new_xlsx_file = "#{File.dirname(__FILE__)}/../templates/spec_various_content.xlsx"
|
116
|
+
workbook.save(new_xlsx_file)
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
|
84
121
|
|
85
122
|
end
|
data/spreadsheetx.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{spreadsheetx}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Craig Ulliott"]
|
12
|
-
s.date = %q{2011-07-
|
12
|
+
s.date = %q{2011-07-09}
|
13
13
|
s.description = %q{Using an existing xlsx file as a template, it allows you to modify cell values and add rows and columns. Facilitating a templateized approach to creating a new xlsx spreadsheet}
|
14
14
|
s.email = %q{craigulliott@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -44,12 +44,14 @@ Gem::Specification.new do |s|
|
|
44
44
|
|
45
45
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
46
46
|
s.add_runtime_dependency(%q<zipruby>, ["~> 0.3.6"])
|
47
|
+
s.add_runtime_dependency(%q<libxml-ruby>, ["~> 2.0.9"])
|
47
48
|
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
48
49
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
49
50
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
|
50
51
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
51
52
|
else
|
52
53
|
s.add_dependency(%q<zipruby>, ["~> 0.3.6"])
|
54
|
+
s.add_dependency(%q<libxml-ruby>, ["~> 2.0.9"])
|
53
55
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
54
56
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
55
57
|
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
@@ -57,6 +59,7 @@ Gem::Specification.new do |s|
|
|
57
59
|
end
|
58
60
|
else
|
59
61
|
s.add_dependency(%q<zipruby>, ["~> 0.3.6"])
|
62
|
+
s.add_dependency(%q<libxml-ruby>, ["~> 2.0.9"])
|
60
63
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
61
64
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
62
65
|
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: spreadsheetx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Craig Ulliott
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-07-
|
13
|
+
date: 2011-07-09 00:00:00 -05:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -25,8 +25,19 @@ dependencies:
|
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: *id001
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: libxml-ruby
|
29
29
|
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.0.9
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: rspec
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
30
41
|
none: false
|
31
42
|
requirements:
|
32
43
|
- - ~>
|
@@ -34,10 +45,10 @@ dependencies:
|
|
34
45
|
version: 2.3.0
|
35
46
|
type: :development
|
36
47
|
prerelease: false
|
37
|
-
version_requirements: *
|
48
|
+
version_requirements: *id003
|
38
49
|
- !ruby/object:Gem::Dependency
|
39
50
|
name: bundler
|
40
|
-
requirement: &
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
41
52
|
none: false
|
42
53
|
requirements:
|
43
54
|
- - ~>
|
@@ -45,10 +56,10 @@ dependencies:
|
|
45
56
|
version: 1.0.0
|
46
57
|
type: :development
|
47
58
|
prerelease: false
|
48
|
-
version_requirements: *
|
59
|
+
version_requirements: *id004
|
49
60
|
- !ruby/object:Gem::Dependency
|
50
61
|
name: jeweler
|
51
|
-
requirement: &
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
52
63
|
none: false
|
53
64
|
requirements:
|
54
65
|
- - ~>
|
@@ -56,10 +67,10 @@ dependencies:
|
|
56
67
|
version: 1.6.2
|
57
68
|
type: :development
|
58
69
|
prerelease: false
|
59
|
-
version_requirements: *
|
70
|
+
version_requirements: *id005
|
60
71
|
- !ruby/object:Gem::Dependency
|
61
72
|
name: rcov
|
62
|
-
requirement: &
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
63
74
|
none: false
|
64
75
|
requirements:
|
65
76
|
- - ">="
|
@@ -67,7 +78,7 @@ dependencies:
|
|
67
78
|
version: "0"
|
68
79
|
type: :development
|
69
80
|
prerelease: false
|
70
|
-
version_requirements: *
|
81
|
+
version_requirements: *id006
|
71
82
|
description: Using an existing xlsx file as a template, it allows you to modify cell values and add rows and columns. Facilitating a templateized approach to creating a new xlsx spreadsheet
|
72
83
|
email: craigulliott@gmail.com
|
73
84
|
executables: []
|
@@ -107,7 +118,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
118
|
requirements:
|
108
119
|
- - ">="
|
109
120
|
- !ruby/object:Gem::Version
|
110
|
-
hash: -
|
121
|
+
hash: -772800674702882304
|
111
122
|
segments:
|
112
123
|
- 0
|
113
124
|
version: "0"
|