Giter VIP home page Giter VIP logo

westonganger / spreadsheet_architect Goto Github PK

View Code? Open in Web Editor NEW
1.3K 25.0 44.0 1.14 MB

Spreadsheet Architect is a library that allows you to create XLSX, ODS, or CSV spreadsheets super easily from ActiveRecord relations, plain Ruby objects, or tabular data.

License: MIT License

Ruby 99.59% CSS 0.03% HTML 0.26% JavaScript 0.12%
spreadsheet xlsx ods csv export ruby activerecord rails excel excel-export

spreadsheet_architect's Introduction

Spreadsheet Architect

Gem Version CI Status RubyGems Downloads

Spreadsheet Architect is a library that allows you to create XLSX, ODS, or CSV spreadsheets super easily from ActiveRecord relations, plain Ruby objects, or tabular data.

Key Features:

  • Dead simple custom spreadsheets with custom data
  • Data Sources: Tabular Data from an Array, ActiveRecord relations, or array of plain Ruby object instances
  • Easily style and customize spreadsheets
  • Create multi sheet spreadsheets
  • Setting Class/Model or Project specific defaults
  • Simple to use ActionController renderers for Rails
  • Plain Ruby (without Rails) completely supported

Install

gem 'spreadsheet_architect'

General Usage

Tabular (Array) Data

The simplest and preferred usage is to simply create the data array yourself.

headers = ['Col 1','Col 2','Col 3']
data = [[1,2,3], [4,5,6], [7,8,9]]
SpreadsheetArchitect.to_xlsx(headers: headers, data: data)
SpreadsheetArchitect.to_ods(headers: headers, data: data)
SpreadsheetArchitect.to_csv(headers: headers, data: data)

Using this style will allow you to utilize any custom performance optimizations during your data generation process. This will come in handy when the spreadsheets get large and any loss in performance starts to matter.

Rails Relations or an Array of plain Ruby object instances

If you would like to add the methods to_xlsx, to_ods, to_csv, to_axlsx_package, to_rodf_spreadsheet to some class, you can simply include the SpreadsheetArchitect module to whichever classes you choose. For example:

class Post < ApplicationRecord
  include SpreadsheetArchitect
end

When using on an AR Relation or using the :instances option, SpreadsheetArchitect requires an instance method to be defined on the class to generate the data. By default it looks for the spreadsheet_columns method on the class. If you are using on an ActiveRecord model and that method is not defined, it would fallback to the models column_names method. If using the :data option this is completely ignored.

class Post
  include SpreadsheetArchitect

  def spreadsheet_columns
    ### Column format is: [Header, Cell Data / Method (if symbol) to Call on each Instance, (optional) Cell Type]
    [
      ['Title', :title],
      ['Content', content.strip],
      ['Author', (author.name if author)],
      ['Published?', (published ? 'Yes' : 'No')],
      :published_at, # uses the method name as header title Ex. 'Published At'
      ['# of Views', :number_of_views, :float],
      ['Rating', :rating],
      ['Category/Tags', "#{category.name} - #{tags.collect(&:name).join(', ')}"]
    ]
  end

end

Then use it on the class or ActiveRecord relations of the class

posts = Post.order(name: :asc).where(published: true)
posts.to_xlsx
posts.to_ods
posts.to_csv

# Plain Ruby Objects
posts_array = 10.times.map{|i| Post.new(number: i)}
Post.to_xlsx(instances: posts_array)
Post.to_ods(instances: posts_array)
Post.to_csv(instances: posts_array)

If you want to use a different method name then spreadsheet_columns you can pass a method name to the :spreadsheet_columns option.

Post.to_xlsx(instances: posts, spreadsheet_columns: :my_special_method)

Alternatively, you can pass a proc to the spreadsheet_columns option. For those purists that really dont want to define any extra spreadsheet_columns instance method on your model, this option can help you work with that methodology.

Post.to_xlsx(instances: posts, spreadsheet_columns: ->(instance){
  [
    ['Title', :title],
    ['Content', instance.content.strip],
    ['Author', (instance.author.name if instance.author)],
    ['Published?', (instance.published ? 'Yes' : 'No')],
    :published_at, # uses the method name as header title Ex. 'Published At'
    ['# of Views', :number_of_views, :float],
    ['Rating', :rating],
    ['Category/Tags', "#{instance.category.name} - #{instance.tags.collect(&:name).join(', ')}"],
    ['URL', :url, (val.start_with?("http") ? :hyperlink : :string)],
  ]
})

Sending & Saving Spreadsheets

Method 1: Save to a file manually

file_data = SpreadsheetArchitect.to_xlsx(headers: headers, data: data)

File.open('path/to/file.xlsx', 'w+b') do |f|
  f.write file_data
end

Method 2: Send Data via Rails Controller

class PostsController < ActionController::Base
  respond_to :html, :xlsx, :ods, :csv

  def index
    @posts = Post.order(published_at: :asc)

    render xlsx: @posts
  end

  # Using respond_with
  def index
    @posts = Post.order(published_at: :asc)

    respond_with @posts
  end

  # OR Using respond_with with custom options
  def index
    @posts = Post.order(published_at: :asc)

    if ['xlsx','ods','csv'].include?(request.format)
      respond_with @posts.to_xlsx(row_style: {bold: true}), filename: 'Posts'
    else
      respond_with @posts
    end
  end

  # OR Using responders
  def index
    @posts = Post.order(published_at: :asc)

    respond_to do |format|
      format.html
      format.xlsx { render xlsx: @posts }
      format.ods { render ods: @posts }
      format.csv{ render csv: @posts }
    end
  end

  # OR Using responders with custom options
  def index
    @posts = Post.order(published_at: :asc)

    respond_to do |format|
      format.html
      format.xlsx { render xlsx: @posts.to_xlsx(headers: false) }
      format.ods { render ods: Post.to_ods(instances: @posts) }
      format.csv{ render csv: @posts.to_csv(headers: false), filename: 'articles' }
    end
  end
end

Multi Sheet Spreadsheets

XLSX

axlsx_package = SpreadsheetArchitect.to_axlsx_package({headers: headers, data: data})
axlsx_package = SpreadsheetArchitect.to_axlsx_package({headers: headers, data: data}, axlsx_package)

File.open('path/to/multi_sheet_file.xlsx', 'w+b') do |f|
  f.write axlsx_package.to_stream.read
end

ODS

ods_spreadsheet = SpreadsheetArchitect.to_rodf_spreadsheet({headers: headers, data: data})
ods_spreadsheet = SpreadsheetArchitect.to_rodf_spreadsheet({headers: headers, data: data}, ods_spreadsheet)

File.open('path/to/multi_sheet_file.ods', 'w+b') do |f|
  f.write ods_spreadsheet.bytes
end

Methods

to_xlsx(options={})

Option Default Notes
data
2D Array
Cannot be used with the :instances option.

Tabular data for the non-header row cells.
instances
Array
Cannot be used with the :data option.

Array of class/model instances to be used as row data. Cannot be used with :data option
spreadsheet_columns
Proc/Symbol/String
Use this option to override or define the spreadsheet columns. Normally, if this option is not specified and are using the instances option/ActiveRecord relation, it uses the classes custom spreadsheet_columns method or any custom defaults defined.
If neither of those and is an ActiveRecord model, then it will falls back to the models self.column_names
Cannot be used with the :data option.

If a Proc value is passed it will be evaluated on the instance object.

If a Symbol or String value is passed then it will search the instance for a method name that matches and call it.
headers
Array / 2D Array
Data for the header row cells. If using on a class/relation, this defaults to the ones provided via spreadsheet_columns. Pass false to skip the header row.
sheet_name
String
Sheet1
header_style
Hash
{background_color: "AAAAAA", color: "FFFFFF", align: :center, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false} See all available style options here
row_style
Hash
{background_color: nil, color: "000000", align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false, format_code: nil} Styles for non-header rows. See all available style options here
column_styles
Array
See the kitchen sink example for usage
range_styles
Array
See the kitchen sink example for usage
conditional_row_styles
Array
See the kitchen sink example for usage. The if/unless proc will called with the following args: row_index, row_data
merges
Array
Merge cells. See the kitchen sink example for usage. Warning merges cannot overlap eachother, if you attempt to do so Excel will claim your spreadsheet is corrupt and refuse to open your spreadsheet.
borders
Array
See the kitchen sink example for usage
column_types
Array
Valid types for XLSX are :string, :integer, :float, :date, :time, :boolean, :hyperlink, nil = auto determine. You may also pass a Proc which evaluates to any of the valid types, for example ->(cell_val){ cell_val.start_with?('http') ? :hyperlink : :string }
column_widths
Array
Sometimes you may want explicit column widths. Use nil if you want a column to autofit again.
freeze_headers
Boolean
Make all header rows frozen/fixed so they do not scroll.
freeze
Hash
Make all specified row and/or column frozen/fixed so they do not scroll. See example usage
skip_defaults
Boolean
false Removes defaults and default styles. Particularily useful for heavily customized spreadsheets where the default styles get in the way.
escape_formulas
Boolean or Array
true Pass a single boolean to apply to all cells, or an array of booleans to control column-by-column. Advisable to be set true when involved with untrusted user input. See an example of the underlying functionality. NOTE: Header row cells are not escaped.
use_zero_based_row_index
Boolean
false Allows you to use zero-based row indexes when defining range_styles, merges, etc. Recommended to set this option for the whole project rather than per call. The original reason it was designed to be 1-based is because spreadsheet row numbers actually start with 1.

to_axlsx_spreadsheet(options={}, axlsx_package_to_join=nil)

Same options as to_xlsx

to_ods(options={})

Option Default Notes
data
2D Array
Cannot be used with the :instances option.

Tabular data for the non-header row cells.
instances
Array
Cannot be used with the :data option.

Array of class/model instances to be used as row data. Cannot be used with :data option
spreadsheet_columns
Proc/Symbol/String
Use this option to override or define the spreadsheet columns. Normally, if this option is not specified and are using the instances option/ActiveRecord relation, it uses the classes custom spreadsheet_columns method or any custom defaults defined.
If neither of those and is an ActiveRecord model, then it will falls back to the models self.column_names
Cannot be used with the :data option.

If a Proc value is passed it will be evaluated on the instance object.

If a Symbol or String value is passed then it will search the instance for a method name that matches and call it.
headers
Array / 2D Array
Data for the header row cells. If using on a class/relation, this defaults to the ones provided via spreadsheet_columns. Pass false to skip the header row.
sheet_name
String
Sheet1
header_style
Hash
{background_color: "AAAAAA", color: "FFFFFF", align: :center, font_size: 10, bold: true} Note: Currently ODS only supports these options
row_style
Hash
{background_color: nil, color: "000000", align: :left, font_size: 10, bold: false} Styles for non-header rows. Currently ODS only supports these options
column_types
Array
Valid types for ODS are :string, :float, :date, :time, :boolean, :hyperlink, nil = auto determine. Due to RODF Issue #19, :date/:time will be converted to :string. You may also pass a Proc which evaluates to any of the valid types, for example ->(cell_val){ cell_val.start_with?('http') ? :hyperlink : :string }
skip_defaults
Boolean
false Skip defaults and default styles. Particularly useful for heavily customized spreadsheets where the default styles get in the way.

to_rodf_spreadsheet(options={}, spreadsheet_to_join=nil)

Same options as to_ods

to_csv(options={})

Option Default Notes
data
2D Array
Cannot be used with the :instances option.

Tabular data for the non-header row cells.
instances
Array
Cannot be used with the :data option.

Array of class/model instances to be used as row data. Cannot be used with :data option
spreadsheet_columns
Proc/Symbol/String
Use this option to override or define the spreadsheet columns. Normally, if this option is not specified and are using the instances option/ActiveRecord relation, it uses the classes custom spreadsheet_columns method or any custom defaults defined.
If neither of those and is an ActiveRecord model, then it will falls back to the models self.column_names
Cannot be used with the :data option.

If a Proc value is passed it will be evaluated on the instance object.

If a Symbol or String value is passed then it will search the instance for a method name that matches and call it.
headers
Array / 2D Array
Data for the header row cells. If using on a class/relation, this defaults to the ones provided via spreadsheet_columns. Pass false to skip the header row.

Change class-wide default method options

class Post < ApplicationRecord
  include SpreadsheetArchitect

  def spreadsheet_columns
    [:name, :content]
  end

  SPREADSHEET_OPTIONS = {
    headers: [
      ['My Post Report'],
      self.column_names.map{|x| x.titleize}
    ],
     spreadsheet_columns: :spreadsheet_columns,
    header_style: {background_color: 'AAAAAA', color: 'FFFFFF', align: :center, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
    row_style: {background_color: nil, color: '000000', align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
    sheet_name: self.name,
    column_styles: [],
    range_styles: [],
    conditional_row_styles: [],
    merges: [],
    borders: [],
    column_types: [],
  }
end

Change project-wide default method options

# config/initializers/spreadsheet_architect.rb

SpreadsheetArchitect.default_options = {
  headers: true,
  spreadsheet_columns: :spreadsheet_columns,
  header_style: {background_color: 'AAAAAA', color: 'FFFFFF', align: :center, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
  row_style: {background_color: nil, color: '000000', align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
  sheet_name: 'My Project Export',
  column_styles: [],
  range_styles: [],
  conditional_row_styles: [],
  merges: [],
  borders: [],
  column_types: [],
  use_zero_based_row_index: false,
}

Kitchen Sink Examples with Styling for XLSX and ODS

See test "kitchen sink" for XLSX and ODS

Axlsx Style Reference

I have compiled a list of all available style options for axlsx here: docs/axlsx_style_reference.md

Tips for Reducing Memory Usage

  • Use the :data option instead of active record relations
  • Utilize the light_record gem

Testing / Validating your Spreadsheets

A wise word of advice, when testing your spreadsheets I recommend to use Excel instead of LibreOffice. This is because I have seen through testing, that where LibreOffice seems to just let most incorrect things just slide on through, Excel will not even open the spreadsheet as apparently it is much more strict about the spreadsheet validations. This will help you better identify any incorrect styling or customization issues.

Contributing

We use the appraisal gem for testing multiple versions of axlsx. Please use the following steps to test using appraisal.

  1. bundle exec appraisal install
  2. bundle exec appraisal rake test

At this time the spreadsheets generated by the test suite are manually inspected. After running the tests, the test output can be viewed in tmp/

Credits

Created & Maintained by Weston Ganger - @westonganger

spreadsheet_architect's People

Contributors

abuhtoyarov avatar bradleypriest avatar hybridindie avatar jelaniwoods avatar livedo avatar petergoldstein avatar rayfaddis avatar samsinite avatar westonganger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spreadsheet_architect's Issues

I'm running out of memory ....

Happy 2022!

My sidekiq workers are running out of memory because I did not anticipate the size of the data arrays I'm using and the number of sheets being generated.

In using the to_xlsx method. I am passing the full data array which can be extremely large. What is being returned is a large object which I am writing to an external file.

I'm NOT sure that I can do what I want to do ...

  1. init the spreadsheet, styles headers etc.
  2. pass one data row at a time into to_xlsx
  3. update the external file goto 2 until no more data -- yes I said GOTO :)
  4. close the external file.

If I can do something like that, then it should significantly reduce the amount of process memory needed to generate the xlsx file.

I'm not very hopefully. I will take a look at the internals of axlsx to see if there is anything there that might help.

Any suggestions?

[Feature Request] I'd like to be able to highlight a different cell in each row

Imagine a table like this:

foo | bar | baz
---------------
red | clear | clear
clear | red | clear
red | clear | clear

Where those are the assigned background colors for the individual cells within each row. The idea is to be able to call out a cell where data needs to be adjusted, but which cell is dependent on the data making up that row. Is there some way (passing a block, perhaps) that this could be made to happen? All the documentation about the various background color styling options seem to apply only to individual rows or all rows.

Axlsx deprecation warning

Hi, great gem but I recently faced warnings such as

/Users/loschcode/.rvm/gems/ruby-2.5.1/gems/axlsx-2.0.1/lib/axlsx/util/validators.rb:96: warning: constant ::Fixnum is deprecated

Which seem to be related to your own dependencies. How do you get rid of it ? Is there already a plan to fix that warning ?

Time cell in ODS file

Hi, first of all thank you for your work on Spreadsheet Architect, you make life easier for thousands of developers.

I am using the 2.0.2 version of the gem and I have an issue while trying to create a ODS file with a Time in a cell.
Here is my code :

SpreadsheetArchitect.to_ods(data: [[Time.now]], header: false)

When i open with LibreOffice the produced file the cell value is 0 (displayed 30/12/1899) and the format is set to date.

Am I missing something ?

Thanks for your help

Improve test suite automation

It would be a huge improvement to the test suite if the tests validated the xml/txt contents of the spreadsheets automatically instead of requiring a manual look at the test spreadsheets.

I would love any PR's or contributions that could help improve our tests. Some test examples to get started could be found within the axlsx and rodf repos.

ODS column type(s) ineffective

When creating spreadsheet with AR model objects:

SpreadsheetArchitect.to_ods(
						instances: ar_objects_collection,
						spreadsheet_columns: Proc.new{|instance|
							[
								['Total', :total_amount, :currency],
							]},
					)

the column_type argument (here :currency) seems to have no effect. The same happens if column_types array is given separately. In both cases the column values are formatted as Default.

Gem version checked is 3.2.1, Rails version if 5.0, Ruby version is 2.3.7

Add ability to pass :instances option to SpreadsheetArchitect class methods

We should have the ability to create sheets from an array of instances of assorted class instances which all have the spreadsheet_columns instance method. Example:

@assorted_objects = BlogPost.all.to_a + OtherBlogPost.all.to_a
SpreadsheetArchitect.to_xlsx(instances: @assorted_objects, headers: my_headers)

Some Requirements:

  • If :headers is provided (recommended) use those headers, Else use the headers provided by the first instance in the array.
  • This :instances option would not be compatible with the :data option and would raise error if both are used at once.

This would remove the need for the following Per-Ruby model syntax which feels kinda awkward anyways. Example:
NonActiveRecordItem.to_xlsx(instances: item_array)

As an added bonus include SpreadsheetArchitect would no longer be required in the per-ruby classes. Only the spreadsheet_columns instance method is required to be defined or it will raise an exception.

I plan to release this in v3.0.0 along with some other improvements.

Add option to remove all default styles

It would be good to have an option to remove all default styling. Then all headers and rows styles can be implemented in a heavily customized way without overriding the general / project wide defaults.

SpreadsheetArchitect.to_xlsx(remove_default_styles: true)

Empty Relation

There's a problem in module SpreadsheetArchitect

line 38 ( Helpers#get_options )
array = options[:spreadsheet_columns] || options[:data].first.spreadsheet_columns
raises
undefined method 'spreadsheet_columns' for nil:NilClass
if the controller returns no records at all.

I think that should at least raise a specific error in a guard clause
raise SpreadsheetArchitect::NoDataError if options[:data].none?

Add ability to pass an alternative method name as a symbol to the :spreadsheet_columns option

The :spreadsheet_columns option should support the ability to specify an alternative method name instead of spreadsheet_columns on the model. Ex.

class Post < ActiveRecord::Base
  def other_spreadsheet_columns
    [
      ['Title', :title],
      ['Content', instance.content.strip],
      ['Author', (instance.author.name if instance.author)],
  ]
  end
end

Post.all.to_xlsx(spreadsheet_columns: :other_spreadsheet_columns)

If this is needed in the meantime, this can be accomplished using current the Proc syntax. Ex.

Post.all.to_xlsx(spreadsheet_columns: Proc.new{|instance| instance.other_spreadsheet_columns})

Keep the header row from scrolling

It is not obvious to me switch style to use in the header style has to cause the header ro to be fixed non-scrolling. I thought maybe it was locked but that did not work; nor did it keep a user from changing the content of a cell in the header row.

Does spreadsheet_architect support this capability?

In stack overflow this question is asked of axlsx with the following answer:

`
Axlsx::Package.new do |p|
p.workbook.add_worksheet(:name => 'DATA') do |sheet|
sheet.add_row(%w{key col1 col2 col3 col4 col5})
#Fix first line and column
sheet.sheet_view.pane do |pane|
pane.top_left_cell = "B2"
pane.state = :frozen_split
pane.y_split = 1
pane.x_split = 1
pane.active_pane = :bottom_right
end

    10.times{
      sheet.add_row(%w{1 2 3 4 5 6})
    }
  end    

  puts "Write %s" % XLSX_temp
  p.serialize(XLSX_temp)

end
`
Assuming this works, what is the equivalent SSA api?``

More complex example in spreadsheet collection

Hi,

I use your gem for the first time and I try to use it to export in xlsx with specific needs but I could not find the right syntax :

  def self.spreadsheet_columns
    [
      [ "Date", "I18n.l(created_at.to_date, format: :long)" ],
      [ I18n.t('payments.csv.id'), :id ],
      [ I18n.t('payments.csv.login'), :payer_login ],
      [ I18n.t('payments.csv.email'), :payer_email ],
      [ I18n.t('payments.csv.firstname'), :payer_first_name ],
      [ I18n.t('payments.csv.lastname'), :payer_last_name ],
      [ I18n.t('payments.csv.type'), "type.slice(0, type.index('Payment'))" ],
      [ I18n.t('payments.csv.amount'), "#{amount} #{currency.symbol}" ],
      [ I18n.t('payments.csv.reward'), 'reward.present? ? (reward.amount - reward.description) : I18n.t("payments.csv.no_rewards")' ],
      [ I18n.t('payments.csv.address'), 'try(:payer_location).try(:address_complete) || "-"' ]
    ]
  end

I have go just 2 errors on these lines :

      [ I18n.t('payments.csv.amount'), "#{amount} #{currency.symbol}" ],
      [ I18n.t('payments.csv.reward'), 'reward.present? ? (reward.amount - reward.description) : I18n.t("payments.csv.no_rewards")' ],

Is there a way to do this with your gem?

Argument column_widths does not seem to work

I'm using your library to export XLSX, CSV and ODS. The code is as such

      def data
        SpreadsheetArchitect.to_xlsx(arguments)
      end

      def arguments
        {
          sheet_name: spreadsheet.name,
          column_widths: spreadsheet.column_widths,
          headers: spreadsheet.headers,
          data: spreadsheet.data
        }
      end

We have column_widths with let's say [10, 10] and headers with ['Set 1', 'Set 2'] which should set the size of each column to 10 and work clean.

It does not work, for some reason my columns end up being all in different sizes, as you can see in the screenshot. Am I missing something with the column_widths option or is it bug ?

Here's a screenshot with real data I tried to export a XLSX.

screenshot 2018-08-13 14 26 55

Invalid hash syntax

After including the gem into Gemfile I started receiving syntax errors:

/Users/john/.rvm/gems/ruby-2.1.5@railsapp/gems/bundler-1.11.2/lib/bundler/runtime.rb:77:in `require': /Users/john/.rvm/gems/ruby-2.1.5@railsapp/gems/spreadsheet_architect-1.4.5/lib/spreadsheet_architect.rb:215: syntax error, unexpected ':', expecting keyword_end (SyntaxError)
            property :text, 'font-weight': :bold
                                          ^
/Users/john/.rvm/gems/ruby-2.1.5@railsapp/gems/spreadsheet_architect-1.4.5/lib/spreadsheet_architect.rb:218: syntax error, unexpected ':', expecting keyword_end
            property :text, 'align': options[:header_style][:align]
                                    ^
/Users/john/.rvm/gems/ruby-2.1.5@railsapp/gems/spreadsheet_architect-1.4.5/lib/spreadsheet_architect.rb:221: syntax error, unexpected ':', expecting keyword_end
            property :text, 'font-size': options[:header_style][:size]
                                        ^
/Users/john/.rvm/gems/ruby-2.1.5@railsapp/gems/spreadsheet_architect-1.4.5/lib/spreadsheet_architect.rb:224: syntax error, unexpected ':', expecting keyword_end
...       property :text, 'color': "##{options[:header_style][:...
...                               ^
/Users/john/.rvm/gems/ruby-2.1.5@railsapp/gems/spreadsheet_architect-1.4.5/lib/spreadsheet_architect.rb:231: syntax error, unexpected ':', expecting keyword_end
            property :text, 'font-weight': :bold
                                          ^
/Users/john/.rvm/gems/ruby-2.1.5@railsapp/gems/spreadsheet_architect-1.4.5/lib/spreadsheet_architect.rb:234: syntax error, unexpected ':', expecting keyword_end
            property :text, 'align': options[:row_style][:align]
                                    ^
/Users/john/.rvm/gems/ruby-2.1.5@railsapp/gems/spreadsheet_architect-1.4.5/lib/spreadsheet_architect.rb:237: syntax error, unexpected ':', expecting keyword_end
            property :text, 'font-size': options[:row_style][:size]
                                        ^
/Users/john/.rvm/gems/ruby-2.1.5@railsapp/gems/spreadsheet_architect-1.4.5/lib/spreadsheet_architect.rb:240: syntax error, unexpected ':', expecting keyword_end
            property :text, 'color': "##{options[:row_style][:color]}"




Add multi-threaded support

On very large datasets spreadsheet generation can be slower. I think it may be a good idea to add an option parallel which defaults to false and can be set to true when having performance issues.

I think it should be off by default because parallel execution sometimes makes things behave slightly differently (ie screws up better_errors or whatever) and the user should be aware they are using this option.

To implement this we can use Parallel.map from the Parallel gem.

Add support for :active_pane to XLSX :freeze option

PR Wanted

For now the :freeze option is limited to the top and/or left portions of the spreadsheet (active_pane: :bottom_right).

Currently I am unable to come up with a working implementation that allows to specify alternative :active_pane.

All available Axlsx options for :active_pane are:

  • :bottom_right - Default mode, currently locked to this mode of freeze
  • :bottom_left
  • :top_left
  • :top_right

See the following to get started.

### Currently not working
#if options[:freeze][:active_pane]
# Axlsx.validate_pane_type(options[:freeze][:active_pane])
# pane.active_pane = options[:freeze][:active_pane]
#else
# pane.active_pane = :bottom_right
#end

Support caxlsx gem

A new gem caxlsx (Community Axlsx) has been released, Spreadsheet Architect should support this.

Add support for Proc/lambda on column_types

It would be good to support Proc/lambda for column types

This could be supported as

.to_xlsx(
  column_types: [
    :string, 
    ->(cell_val){ cell_val.start_with?("http") ? :hyperlink : :string }, 
    :float,
  ]
)

We dont need to do anything additional for spreadsheet_columns because its already instance evaluated so you can already do things like

.to_xlsx(
  spreadsheet_columns: ->(){
    [
      "Foo", :foo, :string
      "Bar", :bar, (bar.start_with?("http") ? :hyperlink : :string)
      "Baz", :baz, :float
    ]
  }
)

Time formatting problem

Hi. First of all, thank you for providing us with such a framework for our developers.

When I used it, I found a problem. The pattern I used was: SpreadsheetArchitect.to_xlsx(data: data, headers: headers),

When the data in the first row of the data data I passed in the data format has empty or empty characters, all the time in the current column will be wrong.

Seems to take only the first item of the collection for complex treatment

Hi Weston,

I update your gem recently and test it. I run into a strange problem when I use a more complex method (4 last lines from spreadhsheet_columns).
It seems to iterate always with the first item and always repeat it :

  def spreadsheet_columns
    [
      [ "Date", I18n.l(created_at.to_date, format: :long) ],
      [ I18n.t('payments.csv.id'), :id ],
      [ I18n.t('payments.csv.login'), :payer_login ],
      [ I18n.t('payments.csv.email'), :payer_email ],
      [ I18n.t('payments.csv.firstname'), :payer_first_name ],
      [ I18n.t('payments.csv.lastname'), :payer_last_name ],
      [ I18n.t('payments.csv.type'), (type.slice(0, type.index('Payment'))) ],
      [ I18n.t('payments.csv.amount'), ("#{amount} #{currency.symbol}") ],
      [ I18n.t('payments.csv.reward'), (reward.present? ? "#{reward.amount} - #{reward.description}" : I18n.t("payments.csv.no_rewards")) ],
      [ I18n.t('payments.csv.address'), (try(:payer_location).try(:address_complete) || "-") ]
    ]
  end 

The same problem happens with csv and xlsx

Thanks for your helps
Luc Donnet

Number and Date formats

First of all: Nice gem, makes generating spreadsheets easy with only a few lines of code. Thanks.

I've got some issues with formatting though:

in .xlsx and .ods:
when outputting a localized date (e.g 31.1.2010) the cell value is preceded with a single quote ('). So I cannot work with any date functions of LibreOffice on that value.
if I do not localize the value, I get the integer representation. I admit, I can just format that column as date manually in LibreOffice, but most users will not see that little workaround.

in .ods only:
when outputting an integer, it is as well preceded with a " ' ", so the cell is a text value. When outputting a float, the cell uses a dot as the decimal sign, which leads to the problem, that the value is interpreted as text in (german) LibreOffice.
Note: both integer and float work in .xlsx spreadsheets.

ps:
spreadsheet_architect 1.2.0
axlsx 2.1.0.pre

Unable to use my own spreadsheet_column method

For some reason, I'm trying to use my own spreadsheet_column method, like that :
@dossiers_xlsx = @dossiers.to_xlsx(spreadsheet_columns: :information_list_export)
But got this error :

NoMethodError (undefined method `each_with_index' for :information_list_export:Symbol)

The only way I made it work was by doing a Class method :

def self.information_list_export
    column contents here
end

Then :
@dossiers_xlsx = @dossiers.to_xlsx(spreadsheet_columns: Dossier.information_list_export)
But it doesn't work like I need, the self method doesn't allow me to do what I want.
Am I missing something ? I'm actually on a project with the 2.0.0 version of spreadsheet-architect.
(Have to say it works perfectly when I don't overwrite the spreadsheet_column method, but here I need to)
If anyone can help me, thanks a lot !

ArgumentError using .to_ods method

Hello, first of all thank you for this amazing gem, I will refer to it for every single project. Each time there is a need of "big export", and manual CSV writer methods become a technical debt after some iterations.

I opened an issue because I can use .to_csv and .to_xlsx without any problem, but .to_ods bring me this error:

"ArgumentError: wrong number of arguments (given 1, expected 0)"
"from ....rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/spreadsheet_architect-1.4.6/lib/spreadsheet_architect.rb:206:in to_rodf_spreadsheet'" "from .....rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/spreadsheet_architect-1.4.6/lib/spreadsheet_architect.rb:266:in to_ods'
from (irb):1"

I tried every steps from ruby console, watched the miniTest for .to_ods method from the gem, but I cannot get out the ArgumentError. My ruby version is 2.3.1.
Thanks for your help, and congratz for this gem ๐Ÿ‘

Add conditional_row_styles option

It would be helpful to add an option for conditional_row_styles which is an array of style hashes which have an if/unless that utilizes a lambda or model method name as symbol

cool concept

Great idea to make these functions all available in a single package.

I just tried to use this but got a few errors.

here is what I used:

f = [["Record ID", :record_id],
["Protocol #", :protocol_id],
["PI", :pi_name],
["Title", :title],
["Current Enrollment/Target Enrollment", :ce_te],
["Current Enrollment", :ce],
["Target Enrollment", :te],
["IRB", :irb],
["Status", :status],
["IRB Termination date", :irb_termination_date],
["Date of Last Continuing Review IRB Approval", :date_last_irb_approval],
["Date Contiuing Review (expires)", :date_review_expires],
["Date of Most Recently Approved Protocol", :date_last_appr_prot],
["Version Number of Most Recently Approved Protocol", :version_last_apprv_prot],
["Date of Last DSMC Review", :date_last_dsmc_review],
["Date of Last Monitoring Visit", :date_last_monitoring_visit],
["Type of Last Monitoring Visit", :type_last_monitoring_visit],
["CMP/Complexity", :cmp_complexity],
["Next IMV", :next_imv],
["Comments", :comments]]

Org::Org1::IntramuralStudyOversightAndStatuses1.to_xlsx(sheet_name: 'test', spreadsheet_columns: f)

NoMethodError: undefined method each_with_index' for #<Org::Org1::IntramuralStudyOversightAndStatuses1:0x007f5e88678340> from /home/mark/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activemodel-4.2.6/lib/active_model/attribute_methods.rb:433:inmethod_missing'

I tried this using to_csv and got the same undefined method `each_with_index'.

Any ideas?

This gem is actually what I am looking for right now. Kudos!

-mark

Issue following rodf gem upgrade

The rodf gem has been updated recently to version 1.0.0.

Spreadsheet Architect has a runtime dependency to this gem, but seems incompatible with the latest version of rodf.

The following message is thrown after gems update and environment loading : LoadError: cannot load such file -- odf/spreadsheet

For the moment, the workaround we have implemented is just a fix in our Gemfile :

gem "rodf", "~> 0.3.7"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.