Created
January 7, 2022 15:12
-
-
Save TheRealNeil/0af0ed82dfa21048410a3f834743c630 to your computer and use it in GitHub Desktop.
Module providing generic xlsx (Excel/OpenOffice) import/export functionality
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This module provides generic XLSX import/export capabilities. | |
# For more details check the gems; | |
# Exporting: 'caxlsx', https://github.com/caxlsx/caxlsx.git | |
# Importing: 'xsv', https://github.com/martijn/xsv | |
# | |
module ExcelIntegration | |
def self.included(base) | |
base.send :include, InstanceMethods | |
base.extend ClassMethods | |
end | |
module InstanceMethods | |
# These instance methods will be included when the module is included | |
# | |
# def foo | |
# 'foo' | |
# end | |
# | |
end | |
module ClassMethods | |
# The base class will be extended with these methods when the module is included | |
# | |
# def bar | |
# 'bar' | |
# end | |
# | |
def export_to_excel(filepath="#{table_name}_#{Date.today.to_s}.xlsx", table_style='TableStyleMedium2') | |
Axlsx::Package.new do |p| | |
# Create a worksheet with the same name as the DB table | |
p.workbook.add_worksheet(:name => table_name.humanize) do |sheet| | |
# Define formatting for each DB attribute type | |
styles = {} | |
styles[:boolean] = sheet.styles.add_style format_code: '@' | |
styles[:date] = sheet.styles.add_style format_code: 'yyyy-mm-dd' | |
styles[:integer] = sheet.styles.add_style num_fmt: 1 | |
styles[:string] = sheet.styles.add_style format_code: '@' | |
# Add a header row using the DB table column names | |
sheet.add_row attribute_names | |
# Add a data row for each record in the table | |
all.each do |record| | |
sheet.add_row record.attributes.values | |
end | |
# Apply the formatting for each column type (Excluding the Header row) | |
columns_hash.each_with_index do |(_name, column),index| | |
# p "#{index}: #{_name} => #{column.type}" | |
sheet.col_style index, styles[column.type], row_offset: 1 | |
end | |
# Add an excel table referencing our data | |
sheet.add_table("A1:#{('A'..'Z').to_a[attribute_names.size - 1]}#{all.size + 1}", name: table_name, style_info: { name: table_style, show_row_stripes: true }) | |
end | |
p.serialize(filepath) | |
end | |
end | |
# import_from_excel(filepath, attr_allowed) | |
# | |
# Deletes all existing records in the database by truncating the table and then imports data from | |
# the specified excel file (filepath). By default, all excel columns with headings matching table column | |
# names will be imported. You can override this by passing an array to the 'attr_allowed' parameter. | |
def import_from_excel(filepath="#{table_name}_#{Date.today.to_s}.xlsx",attr_allowed=attribute_names) | |
# Delete existing records | |
ActiveRecord::Base.connection.truncate(table_name) | |
# Create new records from excel | |
workbook = Xsv::Workbook.open(filepath) | |
sheet = workbook.sheets_by_name(table_name.humanize).first | |
# Parse headers and switch to hash mode | |
sheet.parse_headers! | |
sheet.each_row do |row| | |
create(row.select { | k,_| attr_allowed.include? k }) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment