ss2json 0.3.2 → 1.0.0.pre
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 +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
|