ss2json 0.3.2 → 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +29 -2
- data/Rakefile +12 -4
- data/balance.xlsx +0 -0
- data/bin/ss2json +38 -3
- data/lib/ss2json-commands/cat.rb +71 -0
- data/lib/ss2json-commands/compress.rb +67 -0
- data/lib/ss2json-commands/constants.rb +132 -0
- data/lib/ss2json-commands/humanize.rb +72 -0
- data/lib/ss2json-commands/ls.rb +71 -0
- data/lib/ss2json-commands/merge.rb +87 -0
- data/lib/ss2json-commands/to_array.rb +128 -0
- data/lib/ss2json-commands/to_hash.rb +137 -0
- data/lib/ss2json/command.rb +22 -0
- data/lib/ss2json/converter.rb +95 -0
- data/lib/ss2json/row_converter.rb +1 -2
- data/lib/ss2json/version.rb +2 -2
- data/ss2json.gemspec +13 -2
- data/test/catss.fixture +9 -0
- data/test/catss2.fixture +7 -0
- data/test/cli_test.rb +61 -0
- data/test/integration_test.rb +90 -0
- data/test/row_converter_test.rb +0 -12
- data/test/ss2json.xls +0 -0
- metadata +65 -27
- data/bin/merge_jsons +0 -32
- data/lib/ss2json.rb +0 -8
- data/lib/ss2json/cli.rb +0 -120
- data/lib/ss2json/options.rb +0 -146
data/bin/merge_jsons
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
unless (ARGV.size >= 1 && ARGV.all?{|f| File.file?(f)})
|
4
|
-
$stderr.puts "Usage: #{File.basename($0)} file1.json file2.json ..."
|
5
|
-
$stderr.puts <<-EOF
|
6
|
-
\nmerge_jsons will receive several files as an arguments and will generate
|
7
|
-
and write to the stdout the a json hash with the name of the filename
|
8
|
-
(without the extension) as a key, and the content of the file as a value
|
9
|
-
for each file passed.
|
10
|
-
EOF
|
11
|
-
exit -1
|
12
|
-
end
|
13
|
-
|
14
|
-
require 'rubygems'
|
15
|
-
require 'json'
|
16
|
-
|
17
|
-
global_hash = {}
|
18
|
-
|
19
|
-
ARGV.each do |file|
|
20
|
-
begin
|
21
|
-
json = JSON.parse(File.read(file))
|
22
|
-
rescue => e
|
23
|
-
$stderr.puts "Could not parse or read the file #{file}"
|
24
|
-
exit -1
|
25
|
-
end
|
26
|
-
|
27
|
-
key = File.basename(file).split(".").first
|
28
|
-
global_hash[key] = json
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
puts JSON.pretty_generate(global_hash)
|
data/lib/ss2json.rb
DELETED
data/lib/ss2json/cli.rb
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
require 'roo'
|
2
|
-
require 'json'
|
3
|
-
|
4
|
-
|
5
|
-
class Ss2Json
|
6
|
-
class Cli
|
7
|
-
attr_reader :content, :doc
|
8
|
-
|
9
|
-
# Parse the options from ARGV, initialize the conversion, and return the string with the output
|
10
|
-
def self.start
|
11
|
-
options = Ss2Json::Options.parse!
|
12
|
-
converter = new(options)
|
13
|
-
case options[:action]
|
14
|
-
when :list
|
15
|
-
converter.doc.sheets.join("\n")
|
16
|
-
else
|
17
|
-
JSON.pretty_generate(converter.content)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# Create a new converter the options are:
|
22
|
-
#
|
23
|
-
# * **:file** Input file.
|
24
|
-
# * **:sheet** Name of the sheet to use.
|
25
|
-
# * **:first_row** Where the title of the columns is.
|
26
|
-
# * **:check_column** Output only the results with a value present on the specific field.
|
27
|
-
# * **:orientation** The data orientation (:horizontal/:vertical).
|
28
|
-
# * **:key_column** Column of the keys for vertical mode.
|
29
|
-
# * **:value_column** Column of the values.
|
30
|
-
# * **:action** Could
|
31
|
-
# * *:convert* Do the normal conversion.
|
32
|
-
# * *:list* Will list the sheets.
|
33
|
-
# * **:converter**: Options passed to the converter: Ss2Json::RowConverter
|
34
|
-
def initialize(options)
|
35
|
-
@options = options
|
36
|
-
init_document
|
37
|
-
if options[:action] == :list
|
38
|
-
@doc.sheets.join("\n")
|
39
|
-
else
|
40
|
-
if options[:orientation] == :horizontal
|
41
|
-
@options[:first_row] += 1
|
42
|
-
process_horizontal
|
43
|
-
elsif options[:orientation] == :vertical
|
44
|
-
process_vertical
|
45
|
-
else
|
46
|
-
raise "Orientation #{options[:orientation]} not recognized"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
protected
|
52
|
-
|
53
|
-
def init_document
|
54
|
-
@doc = open
|
55
|
-
begin
|
56
|
-
@doc.default_sheet = @options[:sheet] if @options[:sheet]
|
57
|
-
rescue RangeError => e
|
58
|
-
raise if @doc.sheets.include?(@options[:sheet])
|
59
|
-
raise "\nThe sheet #{@options[:sheet]} did not exists. The available sheets are:\n" + @doc.sheets.map{|s| "\t* #{s}\n"}.join("")
|
60
|
-
end
|
61
|
-
@doc.header_line = @options[:first_row] if @options[:first_row]
|
62
|
-
end
|
63
|
-
|
64
|
-
def process_horizontal
|
65
|
-
if @options[:hash_key]
|
66
|
-
@content = {}
|
67
|
-
each_hash_row do |hash|
|
68
|
-
if value = hash.get(@options[:hash_key])
|
69
|
-
hash.delete(@options[:hash_key]) unless @options[:dont_remove_key]
|
70
|
-
@content[value] = hash
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
else
|
75
|
-
@content = []
|
76
|
-
each_hash_row do |hash|
|
77
|
-
@options[:hash_key]
|
78
|
-
@content << hash
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def each_row
|
84
|
-
(@options[:first_row]).upto(@doc.last_row).each do |row_n|
|
85
|
-
yield row_n
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def each_hash_row
|
90
|
-
each_row do |row|
|
91
|
-
row = @doc.find(row)[0]
|
92
|
-
object = RowConverter.new(row,@options[:converter])
|
93
|
-
next if @options[:check_column] && object[@options[:check_column]].nil?
|
94
|
-
yield object
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def process_vertical
|
99
|
-
hash = {}
|
100
|
-
each_row do |row|
|
101
|
-
key = @doc.cell(row, @options[:key_column])
|
102
|
-
value = @doc.cell(row, @options[:value_column])
|
103
|
-
hash[key] = value
|
104
|
-
end
|
105
|
-
@content = RowConverter.new(hash, @options[:converter])
|
106
|
-
end
|
107
|
-
|
108
|
-
|
109
|
-
def open
|
110
|
-
kclass = case @options[:file][/\.(.*)$/,1]
|
111
|
-
when /xlsx$/i then Excelx
|
112
|
-
when /xls$/i then Excel
|
113
|
-
when /ods$/i then Openoffice
|
114
|
-
else
|
115
|
-
raise "Unknown format"
|
116
|
-
end
|
117
|
-
kclass.new(@options[:file])
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
data/lib/ss2json/options.rb
DELETED
@@ -1,146 +0,0 @@
|
|
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
|
-
:action => :convert,
|
13
|
-
:orientation => :horizontal,
|
14
|
-
:key_column => 1,
|
15
|
-
:value_column => 2,
|
16
|
-
:converter => {
|
17
|
-
:show_null => false,
|
18
|
-
:dont_convert => false,
|
19
|
-
:ignored_values => [],
|
20
|
-
:downcase_first_letter => true,
|
21
|
-
:key_pattern => nil
|
22
|
-
}
|
23
|
-
|
24
|
-
}
|
25
|
-
|
26
|
-
def self.parse!
|
27
|
-
new.options
|
28
|
-
end
|
29
|
-
|
30
|
-
def initialize
|
31
|
-
@options = DEFAULT_OPTIONS
|
32
|
-
@help = nil
|
33
|
-
super do |opts|
|
34
|
-
@help = opts
|
35
|
-
|
36
|
-
opts.banner = "Usage: #{File.basename $0} -f FILENAME [options]"
|
37
|
-
|
38
|
-
opts.separator "\nMode options:"
|
39
|
-
|
40
|
-
opts.on("-h", "--horizontal", "Normal processing mode (DEFAULT). Can be ommited") do
|
41
|
-
@options[:orientation] = :horizontal
|
42
|
-
end
|
43
|
-
|
44
|
-
opts.on("-v", "--vertical", "Process the spreadhsheet on vertical") do
|
45
|
-
@options[:orientation] = :vertical
|
46
|
-
end
|
47
|
-
|
48
|
-
opts.on("-l", "--list-sheets", "Return the list of sheets") do |file|
|
49
|
-
@options[:action] = :list
|
50
|
-
end
|
51
|
-
|
52
|
-
opts.separator "Common options:"
|
53
|
-
|
54
|
-
opts.on("-f", "--file FILENAME", "Use the filename") do |file|
|
55
|
-
File.file?(file) or die("Can't find the file #{file}.")
|
56
|
-
@options[:file] = File.expand_path(file)
|
57
|
-
end
|
58
|
-
|
59
|
-
opts.on("-s", "--sheet SHEET_NAME", "Use other that the first table") do |sheet|
|
60
|
-
@options[:sheet] = sheet
|
61
|
-
end
|
62
|
-
|
63
|
-
opts.separator "\nHorizontal and Vertical mode options:"
|
64
|
-
|
65
|
-
opts.on("-r", "--first-row ROW_NUMBER", "Set the first row") do |row|
|
66
|
-
die("Can't understand the row #{row}. Use a number") unless row =~ /\A\d*\z/
|
67
|
-
@options[:first_row] = row.to_i
|
68
|
-
end
|
69
|
-
|
70
|
-
opts.separator "\nHorizontal mode options:"
|
71
|
-
|
72
|
-
opts.on("-u", "--use-key KEY", "Generate a hash instead of an array using KEY as the hash index key") do |key|
|
73
|
-
@options[:hash_key] = key
|
74
|
-
end
|
75
|
-
|
76
|
-
opts.on("--dont-remove-key", "Don't remove key from the hash") do
|
77
|
-
@options[:dont_remove_key] = true
|
78
|
-
end
|
79
|
-
|
80
|
-
opts.separator "\nVertical mode options:"
|
81
|
-
|
82
|
-
opts.on("-k", "--key-column COLUMN_NUMBER", "Column where the keys are (Default to 1)") do |column|
|
83
|
-
die("Can't understand the column #{column}. Use a number") unless column =~ /\A\d*\z/
|
84
|
-
@options[:key_column] = column.to_i
|
85
|
-
end
|
86
|
-
|
87
|
-
opts.on("-a", "--value-column COLUMN_NUMBER", "Column where the values are (Default to 2)") do |column|
|
88
|
-
die("Can't understand the column #{column}. Use a number") unless column =~ /\A\d*\z/
|
89
|
-
@options[:value_column] = column.to_i
|
90
|
-
end
|
91
|
-
|
92
|
-
opts.separator "\nData options:"
|
93
|
-
|
94
|
-
opts.on("-i", "--ignore-value VALUE", "Ignore the fields with that value. Could be use several times") do |t|
|
95
|
-
@options[:converter][:ignored_values] << t
|
96
|
-
end
|
97
|
-
|
98
|
-
opts.on("-b", "--include-blank", "Generate a json with the values included in the ignore list") do |t|
|
99
|
-
@options[:converter][:show_null] = true
|
100
|
-
end
|
101
|
-
|
102
|
-
opts.on("-d", "--disable-conversion", "Disable the conversion from floats to integers") do
|
103
|
-
@options[:converter][:dont_convert] = true
|
104
|
-
end
|
105
|
-
|
106
|
-
opts.on("-l", "--disable-first-letter", "Will disable the downcase of the first letter of the key") do
|
107
|
-
@options[:converter][:downcase_first_letter] = false
|
108
|
-
end
|
109
|
-
|
110
|
-
opts.on("--key-pattern PATTERN", "keys must match against PATTERN defaults to '\\A[\\.\\w]+\\z'") do |pattern|
|
111
|
-
@options[:converter][:key_pattern] = pattern
|
112
|
-
end
|
113
|
-
|
114
|
-
opts.separator "\nFilter options:"
|
115
|
-
|
116
|
-
opts.on("-c", "--check-column NAME", "Only output objects wich his property NAME is not in IGNORED VALUES") do |t|
|
117
|
-
@options[:check_column] = t
|
118
|
-
end
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
opts.separator "\n"
|
123
|
-
|
124
|
-
opts.on_tail("-h","--help", "Show this help") do
|
125
|
-
puts opts
|
126
|
-
exit 0
|
127
|
-
end
|
128
|
-
|
129
|
-
opts.on_tail("--version", "Show the version") do
|
130
|
-
puts "#{File.basename($0)} Version: #{Ss2Json::VERSION}"
|
131
|
-
exit 0
|
132
|
-
end
|
133
|
-
|
134
|
-
end.parse!
|
135
|
-
|
136
|
-
die("You need to at least specify a file") if @options[:file].nil?
|
137
|
-
end
|
138
|
-
|
139
|
-
def die(msg)
|
140
|
-
$stderr.puts msg
|
141
|
-
$stderr.puts @help
|
142
|
-
exit -1
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
end
|