xls 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -0
- data/bin/xls +35 -0
- data/lib/xls.rb +7 -0
- data/lib/xls/columnizer.rb +77 -0
- data/lib/xls/version.rb +3 -0
- data/test/columnizer_test.rb +54 -0
- data/test/test_helper.rb +18 -0
- metadata +167 -0
data/README.md
ADDED
data/bin/xls
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), '..', 'lib'))
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'xls'
|
6
|
+
require 'commander/import'
|
7
|
+
|
8
|
+
program :name, 'XLS'
|
9
|
+
program :version, Xls::VERSION
|
10
|
+
program :description, 'A command line utility for working with data in Excel.'
|
11
|
+
|
12
|
+
|
13
|
+
################################################################################
|
14
|
+
# Processing
|
15
|
+
################################################################################
|
16
|
+
|
17
|
+
command :columnize do |c|
|
18
|
+
c.syntax = 'xls columnize FILE'
|
19
|
+
c.description = 'Converts a worksheet formatted as table into 2-column rows using header/value.'
|
20
|
+
c.option('--output FILE', 'The path to the output file.')
|
21
|
+
c.option('--fixed-columns COLUMNS', 'The columns that should stay fixed.')
|
22
|
+
c.when_called do|args, options|
|
23
|
+
# Open input file.
|
24
|
+
abort("Input file required") if args.length == 0
|
25
|
+
workbook = Spreadsheet.open(args.first)
|
26
|
+
|
27
|
+
# Run columnizer.
|
28
|
+
columnizer = Xls::Columnizer.new()
|
29
|
+
columnizer.fixed_columns = options.fixed_columns.to_s.split(",")
|
30
|
+
columnizer.execute(workbook)
|
31
|
+
|
32
|
+
# Write output.
|
33
|
+
workbook.write(options.output || $stdout)
|
34
|
+
end
|
35
|
+
end
|
data/lib/xls.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
class Xls
|
2
|
+
class Columnizer
|
3
|
+
############################################################################
|
4
|
+
#
|
5
|
+
# Constructor
|
6
|
+
#
|
7
|
+
############################################################################
|
8
|
+
|
9
|
+
def initialize(options={})
|
10
|
+
self.fixed_columns = options[:fixed_columns] || []
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
############################################################################
|
15
|
+
#
|
16
|
+
# Attributes
|
17
|
+
#
|
18
|
+
############################################################################
|
19
|
+
|
20
|
+
# A list of names of the columns that should stay fixed.
|
21
|
+
attr_accessor :fixed_columns
|
22
|
+
|
23
|
+
|
24
|
+
############################################################################
|
25
|
+
#
|
26
|
+
# Methods
|
27
|
+
#
|
28
|
+
############################################################################
|
29
|
+
|
30
|
+
# Converts the columns on the worksheets of the input workbook from
|
31
|
+
# n-column tables to 2-column tables.
|
32
|
+
#
|
33
|
+
# @param [Workbook] input The input workbook.
|
34
|
+
#
|
35
|
+
# @return [Workbook] The columnized workbook.
|
36
|
+
def process(input)
|
37
|
+
output = Spreadsheet::Workbook.new()
|
38
|
+
|
39
|
+
(0...input.sheet_count).each do |input_sheet_index|
|
40
|
+
input_sheet = input.worksheet(input_sheet_index)
|
41
|
+
output_sheet = output.create_worksheet()
|
42
|
+
output_index = 1
|
43
|
+
|
44
|
+
# Process headers.
|
45
|
+
input_headers = input_sheet.row(0).map { |cell| cell.to_s }
|
46
|
+
output_sheet.row(0).replace(fixed_columns.clone.concat(['KEY', 'VALUE']))
|
47
|
+
|
48
|
+
# Process data.
|
49
|
+
column_range = (0...input_headers.length)
|
50
|
+
input_sheet.each(1) do |input_row|
|
51
|
+
# Determine fixed column values.
|
52
|
+
fixed_column_values = fixed_columns.map { '' }
|
53
|
+
column_range.each do |index|
|
54
|
+
fixed_column_index = fixed_columns.index(input_headers[index])
|
55
|
+
fixed_column_values[fixed_column_index] = input_row[index] unless fixed_column_index.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
# Write key/value data.
|
59
|
+
column_range.each do |index|
|
60
|
+
next if fixed_columns.index(input_headers[index])
|
61
|
+
output_row = output_sheet.row(output_index)
|
62
|
+
output_row.replace(fixed_column_values)
|
63
|
+
|
64
|
+
# Write header and data.
|
65
|
+
output_row.push(input_headers[index])
|
66
|
+
output_row.push(input_row[index])
|
67
|
+
|
68
|
+
output_index = output_index + 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
return output
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/xls/version.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestColumnizer < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@columnizer = Xls::Columnizer.new
|
6
|
+
end
|
7
|
+
|
8
|
+
######################################
|
9
|
+
# Execute
|
10
|
+
######################################
|
11
|
+
|
12
|
+
def test_columnize
|
13
|
+
input = Spreadsheet.open('fixtures/columnizer/basic.xls')
|
14
|
+
output = @columnizer.process(input)
|
15
|
+
assert_worksheet [
|
16
|
+
['KEY', 'VALUE'],
|
17
|
+
['col1', 'a'],
|
18
|
+
['col2', 'b'],
|
19
|
+
['col3', 'c'],
|
20
|
+
['col4', 'd'],
|
21
|
+
['col5', 'e'],
|
22
|
+
['col6', 'f'],
|
23
|
+
['col1', 'g'],
|
24
|
+
['col2', 'h'],
|
25
|
+
['col3', 'i'],
|
26
|
+
['col4', 'j'],
|
27
|
+
['col5', 'k'],
|
28
|
+
['col6', 'l']
|
29
|
+
],
|
30
|
+
output.worksheet(0)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_columnize_with_fixed_columns
|
34
|
+
input = Spreadsheet.open('fixtures/columnizer/fixed_columns.xls')
|
35
|
+
@columnizer.fixed_columns = ['fix1', 'fix2']
|
36
|
+
output = @columnizer.process(input)
|
37
|
+
assert_worksheet [
|
38
|
+
['fix1', 'fix2', 'KEY', 'VALUE'],
|
39
|
+
['AA', 'BB', 'col1', 'a'],
|
40
|
+
['AA', 'BB', 'col2', 'b'],
|
41
|
+
['AA', 'BB', 'col3', 'c'],
|
42
|
+
['AA', 'BB', 'col4', 'd'],
|
43
|
+
['AA', 'BB', 'col5', 'e'],
|
44
|
+
['AA', 'BB', 'col6', 'f'],
|
45
|
+
['CC', 'DD', 'col1', 'g'],
|
46
|
+
['CC', 'DD', 'col2', 'h'],
|
47
|
+
['CC', 'DD', 'col3', 'i'],
|
48
|
+
['CC', 'DD', 'col4', 'j'],
|
49
|
+
['CC', 'DD', 'col5', 'k'],
|
50
|
+
['CC', 'DD', 'col6', 'l']
|
51
|
+
],
|
52
|
+
output.worksheet(0)
|
53
|
+
end
|
54
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'mocha'
|
4
|
+
require 'unindentable'
|
5
|
+
require 'xls'
|
6
|
+
|
7
|
+
class MiniTest::Unit::TestCase
|
8
|
+
def assert_worksheet exp, worksheet, msg = nil
|
9
|
+
act = []
|
10
|
+
worksheet.each do |row|
|
11
|
+
act << row.map {|cell| cell.to_s.strip }
|
12
|
+
end
|
13
|
+
exp = exp.map {|row| row.map {|cell| '%-10s' % cell.to_s}.join('').strip}.join("\n")
|
14
|
+
act = act.map {|row| row.map {|cell| '%-10s' % cell.to_s}.join('').strip}.join("\n")
|
15
|
+
assert_equal(exp, act, msg)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xls
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ben Johnson
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: commander
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 4.1.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 4.1.3
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: ruby-progressbar
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.0.2
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.0.2
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: spreadsheet
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.7.6
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.7.6
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.9.2.2
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.9.2.2
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: minitest
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 3.5.0
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 3.5.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: mocha
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 0.12.5
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.12.5
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: unindentable
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.1.0
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.1.0
|
126
|
+
description:
|
127
|
+
email:
|
128
|
+
- benbjohnson@yahoo.com
|
129
|
+
executables:
|
130
|
+
- xls
|
131
|
+
extensions: []
|
132
|
+
extra_rdoc_files: []
|
133
|
+
files:
|
134
|
+
- lib/xls/columnizer.rb
|
135
|
+
- lib/xls/version.rb
|
136
|
+
- lib/xls.rb
|
137
|
+
- README.md
|
138
|
+
- test/columnizer_test.rb
|
139
|
+
- test/test_helper.rb
|
140
|
+
- bin/xls
|
141
|
+
homepage: http://github.com/benbjohnson/xls
|
142
|
+
licenses: []
|
143
|
+
post_install_message:
|
144
|
+
rdoc_options: []
|
145
|
+
require_paths:
|
146
|
+
- lib
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
none: false
|
149
|
+
requirements:
|
150
|
+
- - ! '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
155
|
+
requirements:
|
156
|
+
- - ! '>='
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
requirements: []
|
160
|
+
rubyforge_project:
|
161
|
+
rubygems_version: 1.8.24
|
162
|
+
signing_key:
|
163
|
+
specification_version: 3
|
164
|
+
summary: A command line utilty for working with data in Excel.
|
165
|
+
test_files:
|
166
|
+
- test/columnizer_test.rb
|
167
|
+
- test/test_helper.rb
|