ported xlsx over

This commit is contained in:
Andy Meneely
2020-10-02 13:44:42 -04:00
parent ca96a0e857
commit 9b0602a50c
14 changed files with 344 additions and 48 deletions
+1 -38
View File
@@ -8,30 +8,6 @@ require_relative '../import/data_frame'
module Squib
# DSL method. See http://squib.readthedocs.io
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 = Squib::DataFrame.new
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
# DSL method. See http://squib.readthedocs.io
def csv(opts = {})
# TODO refactor all this out to separate methods, and its own class
@@ -102,20 +78,7 @@ module Squib
end
module_function :check_duplicate_csv_headers
# @api private
def explode_quantities(data, qty)
return data unless data.col? qty.to_s.strip
qtys = data[qty]
new_data = Squib::DataFrame.new
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
+1 -1
View File
@@ -12,7 +12,7 @@ module Squib::Args::ArgLoader
load!(args, expand_by: deck.size, layout: deck.layout, dpi: deck.dpi)
end
# Main class invoked by the client (i.e. api/ methods)
# Main class invoked by the client (i.e. dsl/ methods)
def load!(args, expand_by: 1, layout: {}, dpi: 300)
@dpi = dpi
args[:layout] = prep_layout_args(args[:layout], expand_by: expand_by)
+28 -6
View File
@@ -1,16 +1,24 @@
require_relative 'arg_loader'
module Squib::Args
module_function def extract_import(opts)
# note how we don't use ArgLoader here because it's way more complex than
# what we need here. Don't need layouts or singleton expansion, so...
# ...let's just do it ourselves.
Import.parameters.each { |p, value| opts[p] = value unless opts.key? p }
return Import.new.load! opts
end
class Import
include ArgLoader
def self.parameters
{ strip: true,
explode: 'qty'
explode: 'qty',
file: nil,
sheet: 0
}
end
attr_accessor *(self.parameters.keys)
def self.expanding_parameters
[] # none of them
end
@@ -19,13 +27,27 @@ module Squib::Args
[] # none of them
end
def load!(opts)
@strip = validate_strip opts[:strip]
@explode = validate_explode opts[:explode]
@file = validate_file opts[:file]
@sheet = opts[:sheet]
return self
end
def validate_strip(arg)
raise 'Strip must be true or false' unless arg == true || arg == false
arg
end
def validate_explode(arg)
arg
arg.to_s
end
def validate_file(arg)
raise 'file argument not provided.' if arg.nil?
raise "File #{File.expand_path(arg)} does not exist!" unless File.exists?(arg)
File.expand_path(arg)
end
def strip?
+1 -3
View File
@@ -13,9 +13,7 @@ module Squib::Args
end
def self.parameters
{ file: nil,
sheet: 0,
}
{ file: nil }
end
def self.expanding_parameters
+1
View File
@@ -131,5 +131,6 @@ module Squib
require_relative 'dsl/text'
require_relative 'dsl/triangle'
require_relative 'dsl/units'
require_relative 'dsl/xlsx'
end
end
+41
View File
@@ -0,0 +1,41 @@
require_relative '../args/input_file'
require_relative '../args/import'
require_relative '../import/xlsx_importer'
require_relative '../errors_warnings/warn_unexpected_params'
module Squib
# DSL method. See http://squib.readthedocs.io
def xlsx(opts = {}, &block)
DSL::Xlsx.new(__callee__).run(opts, &block)
end
module_function :xlsx
class Deck
# DSL method. See http://squib.readthedocs.io
def xlsx(opts = {}, &block)
DSL::Xlsx.new(__callee__).run(opts, &block)
end
end
module DSL
class Xlsx
include WarnUnexpectedParams
attr_reader :dsl_method, :block
def initialize(dsl_method)
@dsl_method = dsl_method
end
def self.accepted_params
%i( file sheet strip explode )
end
def run(opts,&block)
warn_if_unexpected opts
import_args = Args.extract_import opts
importer = Squib::Import::XlsxImporter.new
importer.import_to_dataframe(import_args, &block)
end
end
end
end
+18
View File
@@ -0,0 +1,18 @@
module Squib
module Import
module QuantityExploder
def explode_quantities(data, qty)
return data unless data.col? qty.to_s.strip
qtys = data[qty]
new_data = Squib::DataFrame.new
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
end
end
end
+27
View File
@@ -0,0 +1,27 @@
require_relative 'quantity_exploder'
module Squib::Import
class XlsxImporter
include Squib::Import::QuantityExploder
def import_to_dataframe(import, &block)
s = Roo::Excelx.new(import.file)
s.default_sheet = s.sheets[import.sheet]
data = Squib::DataFrame.new
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 = block.yield(header, cell) unless block.nil?
data[header] << cell
end# row
end# col
explode_quantities(data, import.explode)
end
end
end