ss2json 0.0.1
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/.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
|
+

|
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
|