lib/squib/api/data.rb in squib-0.8.0 vs lib/squib/api/data.rb in squib-0.9.0

- old
+ new

@@ -1,131 +1,131 @@ -require 'roo' -require 'csv' -require 'squib/args/input_file' -require 'squib/args/import' - -module Squib - - # Pulls Excel data from `.xlsx` files into a column-based hash - # - # Pulls the data into a Hash of arrays based on the columns. First row is assumed to be the header row. - # See the example `samples/excel.rb` in the [source repository](https://github.com/andymeneely/squib/tree/master/samples) - # - # @example - # # Excel file looks like this: - # # | h1 | h2 | - # # ------------ - # # | 1 | 2 | - # # | 3 | 4 | - # data = xlsx file: 'data.xlsx', sheet: 0 - # => {'h1' => [1,3], 'h2' => [2,4]} - # - # @option opts file [String] the file to open. Must end in `.xlsx`. Opens relative to the current directory. - # @option opts sheet [Integer] (0) The zero-based index of the sheet from which to read. - # @option opts strip [Boolean] (true) When true, strips leading and trailing whitespace on values and headers - # @option opts explode [String] ('qty') Quantity explosion will be applied to the column this name. See README for example. - # @return [Hash] a hash of arrays based on columns in the spreadsheet - # @api public - def xlsx(opts = {}) - input = Args::InputFile.new(file: 'deck.xlsx').load!(opts) - import = Args::Import.new.load!(opts) - s = Roo::Excelx.new(input.file[0]) - s.default_sheet = s.sheets[input.sheet[0]] - data = {} - s.first_column.upto(s.last_column) do |col| - header = s.cell(s.first_row,col).to_s - header.strip! if import.strip? - data[header] = [] - (s.first_row + 1).upto(s.last_row) do |row| - cell = s.cell(row,col) - # Roo hack for avoiding unnecessary .0's on whole integers (https://github.com/roo-rb/roo/issues/139) - cell = s.excelx_value(row,col) if s.excelx_type(row,col) == [:numeric_or_formula, 'General'] - cell.strip! if cell.respond_to?(:strip) && import.strip? - cell = yield(header, cell) if block_given? - data[header] << cell - end#row - end#col - explode_quantities(data, import.explode) - end#xlsx - module_function :xlsx - - # Pulls CSV data from `.csv` files into a column-based hash - # - # Pulls the data into a Hash of arrays based on the columns. First row is assumed to be the header row. - # See the example `samples/csv.rb` in the [source repository](https://github.com/andymeneely/squib/tree/master/samples) - # - # @example - # # File data.csv looks like this (without the comment symbols) - # # h1,h2 - # # 1,2 - # # 3,4 - # data = csv file: 'data.csv' - # => {'h1' => [1,3], 'h2' => [2,4]} - # - # Parsing uses Ruby's CSV, with options `{headers: true, converters: :numeric}` - # http://www.ruby-doc.org/stdlib-2.0/libdoc/csv/rdoc/CSV.html - # - # @option opts file [String] the CSV-formatted file to open. Opens relative to the current directory. - # @option opts strip [Boolean] (true) When true, strips leading and trailing whitespace on values and headers - # @option opts explode [String] ('qty') Quantity explosion will be applied to the column this name. See README for example. - # @return [Hash] a hash of arrays based on columns in the table - # @api public - def csv(opts = {}) - file = Args::InputFile.new(file: 'deck.csv').load!(opts).file[0] - import = Args::Import.new.load!(opts) - table = CSV.read(file, headers: true, converters: :numeric) - check_duplicate_csv_headers(table) - hash = Hash.new - table.headers.each do |header| - new_header = header.to_s - new_header = new_header.strip if import.strip? - hash[new_header] ||= table[header] - end - if import.strip? - new_hash = Hash.new - hash.each do |header, col| - new_hash[header] = col.map { |str| str = str.strip if str.respond_to?(:strip); str } - end - hash = new_hash - end - return explode_quantities(hash, import.explode) - end - module_function :csv - - # Check if the given CSV table has duplicate columns, and throw a warning - # @api private - def check_duplicate_csv_headers(table) - if table.headers.size != table.headers.uniq.size - dups = table.headers.select{|e| table.headers.count(e) > 1 } - Squib.logger.warn "CSV duplicated the following column keys: #{dups.join(',')}" - end - end - module_function :check_duplicate_csv_headers - - def explode_quantities(data, qty) - return data unless data.key? qty.to_s.strip - qtys = data[qty] - new_data = {} - data.each do |col, arr| - new_data[col] = [] - qtys.each_with_index do |qty, index| - qty.to_i.times { new_data[col] << arr[index] } - end - end - return new_data - end - module_function :explode_quantities - - class Deck - - # Convenience call on deck goes to the module function - def xlsx(opts = {}) - Squib.xlsx(opts) - end - - # Convenience call on deck goes to the module function - def csv(opts = {}) - Squib.csv(opts) - end - - end -end +require 'roo' +require 'csv' +require 'squib/args/input_file' +require 'squib/args/import' + +module Squib + + # Pulls Excel data from `.xlsx` files into a column-based hash + # + # Pulls the data into a Hash of arrays based on the columns. First row is assumed to be the header row. + # See the example `samples/excel.rb` in the [source repository](https://github.com/andymeneely/squib/tree/master/samples) + # + # @example + # # Excel file looks like this: + # # | h1 | h2 | + # # ------------ + # # | 1 | 2 | + # # | 3 | 4 | + # data = xlsx file: 'data.xlsx', sheet: 0 + # => {'h1' => [1,3], 'h2' => [2,4]} + # + # @option opts file [String] the file to open. Must end in `.xlsx`. Opens relative to the current directory. + # @option opts sheet [Integer] (0) The zero-based index of the sheet from which to read. + # @option opts strip [Boolean] (true) When true, strips leading and trailing whitespace on values and headers + # @option opts explode [String] ('qty') Quantity explosion will be applied to the column this name. See README for example. + # @return [Hash] a hash of arrays based on columns in the spreadsheet + # @api public + def xlsx(opts = {}) + input = Args::InputFile.new(file: 'deck.xlsx').load!(opts) + import = Args::Import.new.load!(opts) + s = Roo::Excelx.new(input.file[0]) + s.default_sheet = s.sheets[input.sheet[0]] + data = {} + s.first_column.upto(s.last_column) do |col| + header = s.cell(s.first_row,col).to_s + header.strip! if import.strip? + data[header] = [] + (s.first_row + 1).upto(s.last_row) do |row| + cell = s.cell(row,col) + # Roo hack for avoiding unnecessary .0's on whole integers (https://github.com/roo-rb/roo/issues/139) + cell = s.excelx_value(row,col) if s.excelx_type(row,col) == [:numeric_or_formula, 'General'] + cell.strip! if cell.respond_to?(:strip) && import.strip? + cell = yield(header, cell) if block_given? + data[header] << cell + end#row + end#col + explode_quantities(data, import.explode) + end#xlsx + module_function :xlsx + + # Pulls CSV data from `.csv` files into a column-based hash + # + # Pulls the data into a Hash of arrays based on the columns. First row is assumed to be the header row. + # See the example `samples/csv.rb` in the [source repository](https://github.com/andymeneely/squib/tree/master/samples) + # + # @example + # # File data.csv looks like this (without the comment symbols) + # # h1,h2 + # # 1,2 + # # 3,4 + # data = csv file: 'data.csv' + # => {'h1' => [1,3], 'h2' => [2,4]} + # + # Parsing uses Ruby's CSV, with options `{headers: true, converters: :numeric}` + # http://www.ruby-doc.org/stdlib-2.0/libdoc/csv/rdoc/CSV.html + # + # @option opts file [String] the CSV-formatted file to open. Opens relative to the current directory. + # @option opts strip [Boolean] (true) When true, strips leading and trailing whitespace on values and headers + # @option opts explode [String] ('qty') Quantity explosion will be applied to the column this name. See README for example. + # @return [Hash] a hash of arrays based on columns in the table + # @api public + def csv(opts = {}) + file = Args::InputFile.new(file: 'deck.csv').load!(opts).file[0] + import = Args::Import.new.load!(opts) + table = CSV.read(file, headers: true, converters: :numeric) + check_duplicate_csv_headers(table) + hash = Hash.new + table.headers.each do |header| + new_header = header.to_s + new_header = new_header.strip if import.strip? + hash[new_header] ||= table[header] + end + if import.strip? + new_hash = Hash.new + hash.each do |header, col| + new_hash[header] = col.map { |str| str = str.strip if str.respond_to?(:strip); str } + end + hash = new_hash + end + return explode_quantities(hash, import.explode) + end + module_function :csv + + # Check if the given CSV table has duplicate columns, and throw a warning + # @api private + def check_duplicate_csv_headers(table) + if table.headers.size != table.headers.uniq.size + dups = table.headers.select{|e| table.headers.count(e) > 1 } + Squib.logger.warn "CSV duplicated the following column keys: #{dups.join(',')}" + end + end + module_function :check_duplicate_csv_headers + + def explode_quantities(data, qty) + return data unless data.key? qty.to_s.strip + qtys = data[qty] + new_data = {} + data.each do |col, arr| + new_data[col] = [] + qtys.each_with_index do |qty, index| + qty.to_i.times { new_data[col] << arr[index] } + end + end + return new_data + end + module_function :explode_quantities + + class Deck + + # Convenience call on deck goes to the module function + def xlsx(opts = {}) + Squib.xlsx(opts) + end + + # Convenience call on deck goes to the module function + def csv(opts = {}) + Squib.csv(opts) + end + + end +end