xls 0.1.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/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
|