ss2json 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/CHANGELOG +5 -0
- data/Gemfile +4 -0
- data/README.md +83 -0
- data/Rakefile +1 -0
- data/bin/ss2json +7 -0
- data/doc/ss2json-1.png +0 -0
- data/doc/ss2json-2.png +0 -0
- data/lib/ss2json/cli.rb +60 -0
- data/lib/ss2json/options.rb +86 -0
- data/lib/ss2json/row_converter.rb +41 -0
- data/lib/ss2json/version.rb +3 -0
- data/lib/ss2json.rb +8 -0
- data/ss2json.gemspec +23 -0
- data/test/ss2json (1).ods +0 -0
- data/test/ss2json.ods +0 -0
- data/test/ss2json.xls +0 -0
- metadata +88 -0
data/.gitignore
ADDED
data/CHANGELOG
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
# ss2json
|
3
|
+
|
4
|
+
**ss2json** is a SpreadSheet To Json converter. It follow a few rules for generating nested hash.
|
5
|
+
|
6
|
+
For example, this document:
|
7
|
+
|
8
|
+
![Excel](https://github.com/guillermo/ss2json/raw/master/doc/ss2json-2.png "Title is optional")
|
9
|
+
|
10
|
+
We download as an OpenOffice document (ods), and run:
|
11
|
+
|
12
|
+
```ss2json -f document.ods```
|
13
|
+
|
14
|
+
Will converted in this:
|
15
|
+
|
16
|
+
```javscript
|
17
|
+
[
|
18
|
+
{
|
19
|
+
"id": 1,
|
20
|
+
"name": {
|
21
|
+
"first": "Guillermo",
|
22
|
+
"last": "Alvarez"
|
23
|
+
},
|
24
|
+
"child": [
|
25
|
+
{
|
26
|
+
"name": "pepe",
|
27
|
+
"age": 2
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"name": "Juanjo"
|
31
|
+
}
|
32
|
+
]
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"id": 2,
|
36
|
+
"name": {
|
37
|
+
"first": "Martin",
|
38
|
+
"last": "Luther"
|
39
|
+
},
|
40
|
+
"child": [
|
41
|
+
{
|
42
|
+
"name": "Jr"
|
43
|
+
}
|
44
|
+
]
|
45
|
+
},
|
46
|
+
{
|
47
|
+
"id": 3,
|
48
|
+
"name": {
|
49
|
+
"first": "Jesper"
|
50
|
+
}
|
51
|
+
}
|
52
|
+
]
|
53
|
+
```
|
54
|
+
|
55
|
+
## Install
|
56
|
+
|
57
|
+
gem install ss2json
|
58
|
+
|
59
|
+
## Usage
|
60
|
+
|
61
|
+
|
62
|
+
Run ```ss2json -h```
|
63
|
+
|
64
|
+
```sh
|
65
|
+
You need to at least specify a file
|
66
|
+
Usage: ss2json -f FILENAME [options]
|
67
|
+
|
68
|
+
-s, --sheet SHEET_NAME Use other that the first table
|
69
|
+
-r, --first-row ROW_NUMBER Set the default first row
|
70
|
+
-f, --file FILENAME Use the filename
|
71
|
+
-i, --ignore-value VALUE Ignore the fields with that value. Could be use several times
|
72
|
+
-b, --include-blank Generate a json with the values included in the ignore list
|
73
|
+
-c, --check-column NAME Only output objects wich his property NAME is not in IGNORED VALUES
|
74
|
+
-d, --disable-conversion Disable the conversion from floats to integers
|
75
|
+
|
76
|
+
-l, --list-sheets Return the list of sheets
|
77
|
+
|
78
|
+
-h, --help Show this help
|
79
|
+
```
|
80
|
+
|
81
|
+
## License
|
82
|
+
|
83
|
+
BSD
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/ss2json
ADDED
data/doc/ss2json-1.png
ADDED
Binary file
|
data/doc/ss2json-2.png
ADDED
Binary file
|
data/lib/ss2json/cli.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'roo'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
|
5
|
+
class Ss2Json
|
6
|
+
class Cli
|
7
|
+
attr_reader :content, :doc
|
8
|
+
|
9
|
+
def self.start
|
10
|
+
options = Ss2Json::Options.parse!
|
11
|
+
converter = new(options)
|
12
|
+
if options[:action] == :list
|
13
|
+
converter.doc.sheets.join("\n")
|
14
|
+
else
|
15
|
+
JSON.pretty_generate(converter.content)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(options)
|
20
|
+
@options = options
|
21
|
+
init_document
|
22
|
+
if options[:action] == :list
|
23
|
+
@doc.sheets.join("\n")
|
24
|
+
else
|
25
|
+
process_document
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def init_document
|
32
|
+
@doc = open
|
33
|
+
@doc.default_sheet = @options[:sheet] if @options[:sheet]
|
34
|
+
@doc.header_line = @options[:first_row] if @options[:first_row]
|
35
|
+
end
|
36
|
+
|
37
|
+
def process_document
|
38
|
+
@content = []
|
39
|
+
(@options[:first_row]+1).upto(@doc.last_row).each do |row_n|
|
40
|
+
row = @doc.find(row_n)[0]
|
41
|
+
object = RowConverter.new(row, @options[:converter])
|
42
|
+
if @options[:check_column]
|
43
|
+
next unless object[@options[:check_column]]
|
44
|
+
end
|
45
|
+
@content << object
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def open
|
51
|
+
kclass = case @options[:file][/\.(.*)$/,1]
|
52
|
+
when /xlsx/i then Excelx
|
53
|
+
when /ods/i then Openoffice
|
54
|
+
else
|
55
|
+
raise "Unknown format"
|
56
|
+
end
|
57
|
+
kclass.new(@options[:file])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
class Ss2Json
|
4
|
+
|
5
|
+
class Options < OptionParser
|
6
|
+
attr_reader :options
|
7
|
+
DEFAULT_OPTIONS = {
|
8
|
+
:first_row => 1,
|
9
|
+
:sheet => nil,
|
10
|
+
:file => nil,
|
11
|
+
:check_column => nil,
|
12
|
+
:converter => {
|
13
|
+
:show_null => false,
|
14
|
+
:dont_convert => false,
|
15
|
+
:ignored_values => []
|
16
|
+
}
|
17
|
+
|
18
|
+
}
|
19
|
+
|
20
|
+
def self.parse!
|
21
|
+
new.options
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@options = DEFAULT_OPTIONS
|
26
|
+
@help = nil
|
27
|
+
super do |opts|
|
28
|
+
@help = opts
|
29
|
+
|
30
|
+
opts.banner = "Usage: #{File.basename $0} -f FILENAME [options]"
|
31
|
+
opts.separator ""
|
32
|
+
opts.on("-s", "--sheet SHEET_NAME", "Use other that the first table") do |sheet|
|
33
|
+
@options[:sheet] = sheet
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("-r", "--first-row ROW_NUMBER", "Set the default first row") do |row|
|
37
|
+
die("Can't understand the row #{row}. Use a number") unless row =~ /\A\d*\z/
|
38
|
+
@options[:first_row] = row.to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on("-f", "--file FILENAME", "Use the filename") do |file|
|
42
|
+
File.file?(file) or die("Can't find the file #{file}.")
|
43
|
+
@options[:file] = file
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on("-i", "--ignore-value VALUE", "Ignore the fields with that value. Could be use several times") do |t|
|
47
|
+
@options[:converter][:ignored_values] << t
|
48
|
+
end
|
49
|
+
|
50
|
+
opts.on("-b", "--include-blank", "Generate a json with the values included in the ignore list") do |t|
|
51
|
+
@options[:converter][:show_null] = true
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.on("-c", "--check-column NAME", "Only output objects wich his property NAME is not in IGNORED VALUES") do |t|
|
55
|
+
@options[:check_column] = t
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on("-d", "--disable-conversion", "Disable the conversion from floats to integers") do
|
59
|
+
@options[:converter][:dont_convert] = true
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.separator ""
|
63
|
+
|
64
|
+
opts.on("-l", "--list-sheets", "Return the list of sheets") do |file|
|
65
|
+
@options[:action] = :list
|
66
|
+
end
|
67
|
+
|
68
|
+
opts.separator ""
|
69
|
+
|
70
|
+
opts.on_tail("-h","--help", "Show this help") do
|
71
|
+
puts opts
|
72
|
+
exit 0
|
73
|
+
end
|
74
|
+
end.parse!
|
75
|
+
|
76
|
+
die("You need to at least specify a file") if @options[:file].nil?
|
77
|
+
end
|
78
|
+
|
79
|
+
def die(msg)
|
80
|
+
$stderr.puts msg
|
81
|
+
$stderr.puts @help
|
82
|
+
exit -1
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'nested_hash'
|
2
|
+
|
3
|
+
class Ss2Json
|
4
|
+
class RowConverter < NestedHash
|
5
|
+
|
6
|
+
def initialize(hash, options={})
|
7
|
+
@options = options
|
8
|
+
super(hash)
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def is_valid_key?(key)
|
14
|
+
super && ! (key =~ /^i\./i)
|
15
|
+
end
|
16
|
+
|
17
|
+
def copy_invalid_keys?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
def sanitize_value(v)
|
22
|
+
return v if @options[:dont_convert]
|
23
|
+
end
|
24
|
+
|
25
|
+
def process(key,value)
|
26
|
+
super if valid_value?(value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid_value?(value)
|
30
|
+
!@options[:ignored_values].include?(value) &&
|
31
|
+
(@options[:show_null] || value )
|
32
|
+
end
|
33
|
+
|
34
|
+
def sanitize_value(v)
|
35
|
+
return v if @options[:dont_convert]
|
36
|
+
return v.to_i if v.is_a?(Float) && v % 1 == 0
|
37
|
+
v
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
data/lib/ss2json.rb
ADDED
data/ss2json.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "ss2json/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "ss2json"
|
7
|
+
s.version = Ss2json::VERSION
|
8
|
+
s.authors = ["Guillermo Álvarez"]
|
9
|
+
s.email = ["guillermo@cientifico.net"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{SpreadSheet to Json convert}
|
12
|
+
s.description = %q{Convert SpreadSheet documents to json following some conventions.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "ss2json"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_runtime_dependency "nested_hash"
|
22
|
+
s.add_runtime_dependency "roo"
|
23
|
+
end
|
Binary file
|
data/test/ss2json.ods
ADDED
Binary file
|
data/test/ss2json.xls
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ss2json
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Guillermo Álvarez
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-16 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nested_hash
|
16
|
+
requirement: &70291603211580 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70291603211580
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: roo
|
27
|
+
requirement: &70291603210920 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70291603210920
|
36
|
+
description: Convert SpreadSheet documents to json following some conventions.
|
37
|
+
email:
|
38
|
+
- guillermo@cientifico.net
|
39
|
+
executables:
|
40
|
+
- ss2json
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- CHANGELOG
|
46
|
+
- Gemfile
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- bin/ss2json
|
50
|
+
- doc/ss2json-1.png
|
51
|
+
- doc/ss2json-2.png
|
52
|
+
- lib/ss2json.rb
|
53
|
+
- lib/ss2json/cli.rb
|
54
|
+
- lib/ss2json/options.rb
|
55
|
+
- lib/ss2json/row_converter.rb
|
56
|
+
- lib/ss2json/version.rb
|
57
|
+
- ss2json.gemspec
|
58
|
+
- test/ss2json (1).ods
|
59
|
+
- test/ss2json.ods
|
60
|
+
- test/ss2json.xls
|
61
|
+
homepage: ''
|
62
|
+
licenses: []
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project: ss2json
|
81
|
+
rubygems_version: 1.8.16
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: SpreadSheet to Json convert
|
85
|
+
test_files:
|
86
|
+
- test/ss2json (1).ods
|
87
|
+
- test/ss2json.ods
|
88
|
+
- test/ss2json.xls
|