spreadsheet_architect 1.4.8 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -2
- data/README.md +117 -98
- data/Rakefile +8 -1
- data/lib/generators/spreadsheet_architect/add_project_defaults_generator.rb +12 -3
- data/lib/spreadsheet_architect.rb +19 -330
- data/lib/spreadsheet_architect/action_controller_renderers.rb +9 -19
- data/lib/spreadsheet_architect/class_methods/csv.rb +22 -0
- data/lib/spreadsheet_architect/class_methods/ods.rb +61 -0
- data/lib/spreadsheet_architect/class_methods/xlsx.rb +162 -0
- data/lib/spreadsheet_architect/exceptions.rb +47 -0
- data/lib/spreadsheet_architect/{set_mime_types.rb → mime_types.rb} +0 -2
- data/lib/spreadsheet_architect/monkey_patches/axlsx_column_width.rb +23 -0
- data/lib/spreadsheet_architect/utils.rb +223 -0
- data/lib/spreadsheet_architect/utils/xlsx.rb +126 -0
- data/lib/spreadsheet_architect/version.rb +1 -1
- data/test/rails_app/Gemfile +17 -0
- data/test/rails_app/Gemfile.lock +176 -0
- data/test/rails_app/README.md +24 -0
- data/test/rails_app/Rakefile +6 -0
- data/test/rails_app/app/assets/config/manifest.js +3 -0
- data/test/rails_app/app/assets/javascripts/application.js +16 -0
- data/test/rails_app/app/assets/javascripts/cable.js +13 -0
- data/test/rails_app/app/assets/stylesheets/application.css +15 -0
- data/test/rails_app/app/channels/application_cable/channel.rb +4 -0
- data/test/rails_app/app/channels/application_cable/connection.rb +4 -0
- data/test/rails_app/app/controllers/application_controller.rb +3 -0
- data/test/rails_app/app/controllers/spreadsheets_controller.rb +74 -0
- data/test/rails_app/app/helpers/application_helper.rb +2 -0
- data/test/rails_app/app/jobs/application_job.rb +2 -0
- data/test/rails_app/app/mailers/application_mailer.rb +4 -0
- data/test/rails_app/app/models/active_model_object.rb +14 -0
- data/test/rails_app/app/models/application_record.rb +3 -0
- data/test/rails_app/app/models/bad_plain_ruby_object.rb +3 -0
- data/test/rails_app/app/models/custom_post.rb +15 -0
- data/test/rails_app/app/models/plain_ruby_object.rb +19 -0
- data/test/rails_app/app/models/post.rb +3 -0
- data/test/rails_app/app/views/layouts/application.html.erb +14 -0
- data/test/rails_app/app/views/layouts/mailer.html.erb +13 -0
- data/test/rails_app/app/views/layouts/mailer.text.erb +1 -0
- data/test/rails_app/bin/bundle +3 -0
- data/test/rails_app/bin/rails +9 -0
- data/test/rails_app/bin/rake +9 -0
- data/test/rails_app/bin/setup +34 -0
- data/test/rails_app/bin/spring +16 -0
- data/test/rails_app/bin/update +29 -0
- data/test/rails_app/config.ru +5 -0
- data/test/rails_app/config/application.rb +15 -0
- data/test/rails_app/config/boot.rb +3 -0
- data/test/rails_app/config/cable.yml +9 -0
- data/test/rails_app/config/database.yml +16 -0
- data/test/rails_app/config/environment.rb +5 -0
- data/test/rails_app/config/environments/development.rb +54 -0
- data/test/rails_app/config/environments/production.rb +86 -0
- data/test/rails_app/config/environments/test.rb +42 -0
- data/test/rails_app/config/initializers/application_controller_renderer.rb +6 -0
- data/test/rails_app/config/initializers/assets.rb +11 -0
- data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails_app/config/initializers/cookies_serializer.rb +5 -0
- data/test/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/rails_app/config/initializers/inflections.rb +16 -0
- data/test/rails_app/config/initializers/mime_types.rb +4 -0
- data/test/rails_app/config/initializers/new_framework_defaults.rb +24 -0
- data/test/rails_app/config/initializers/session_store.rb +3 -0
- data/test/rails_app/config/initializers/wrap_parameters.rb +14 -0
- data/test/rails_app/config/locales/en.yml +23 -0
- data/test/rails_app/config/routes.rb +7 -0
- data/test/rails_app/config/secrets.yml +22 -0
- data/test/{spreadsheet_architect.sqlite3.db → rails_app/db/development.sqlite3} +0 -0
- data/test/rails_app/db/migrate/20170103234524_add_posts.rb +10 -0
- data/test/rails_app/db/schema.rb +23 -0
- data/test/rails_app/db/seeds.rb +7 -0
- data/test/rails_app/db/test.sqlite3 +0 -0
- data/test/rails_app/log/development.log +1195 -0
- data/test/rails_app/log/test.log +52766 -0
- data/test/rails_app/public/404.html +67 -0
- data/test/rails_app/public/422.html +67 -0
- data/test/rails_app/public/500.html +66 -0
- data/test/rails_app/public/apple-touch-icon-precomposed.png +0 -0
- data/test/rails_app/public/apple-touch-icon.png +0 -0
- data/test/rails_app/public/favicon.ico +0 -0
- data/test/rails_app/public/robots.txt +5 -0
- data/test/rails_app/test/controllers/spreadsheets_controller_test.rb +46 -0
- data/test/rails_app/test/models/active_model_object_test.rb +54 -0
- data/test/rails_app/test/models/bad_plain_ruby_object_test.rb +30 -0
- data/test/rails_app/test/models/csv_test.rb +60 -0
- data/test/rails_app/test/models/custom_post_test.rb +47 -0
- data/test/rails_app/test/models/ods_test.rb +68 -0
- data/test/rails_app/test/models/plain_ruby_object_test.rb +54 -0
- data/test/rails_app/test/models/post_test.rb +47 -0
- data/test/rails_app/test/models/spreadsheet_architect_utils_test.rb +68 -0
- data/test/rails_app/test/models/xlsx_test.rb +99 -0
- data/test/rails_app/test/test_helper.rb +21 -0
- data/test/rails_app/tmp/active_model_object/csv.csv +21 -0
- data/test/rails_app/tmp/active_model_object/ods.ods +0 -0
- data/test/rails_app/tmp/active_model_object/xlsx.xlsx +0 -0
- data/test/rails_app/tmp/controller_tests/alt_xlsx.xlsx +0 -0
- data/test/rails_app/tmp/controller_tests/csv.csv +1 -0
- data/test/rails_app/tmp/controller_tests/ods.ods +0 -0
- data/test/rails_app/tmp/controller_tests/xlsx.xlsx +0 -0
- data/test/rails_app/tmp/custom_posts/csv.csv +1 -0
- data/test/rails_app/tmp/custom_posts/empty.xlsx +0 -0
- data/test/rails_app/tmp/custom_posts/ods.ods +0 -0
- data/test/rails_app/tmp/custom_posts/xlsx.xlsx +0 -0
- data/test/rails_app/tmp/empty_model.csv +1 -0
- data/test/rails_app/tmp/empty_model.xlsx +0 -0
- data/test/rails_app/tmp/empty_sa.csv +0 -0
- data/test/rails_app/tmp/empty_sa.xlsx +0 -0
- data/test/rails_app/tmp/extreme.xlsx +0 -0
- data/test/rails_app/tmp/model.csv +1 -0
- data/test/rails_app/tmp/model.xlsx +0 -0
- data/test/rails_app/tmp/ods/empty_model.ods +0 -0
- data/test/rails_app/tmp/ods/empty_sa.ods +0 -0
- data/test/rails_app/tmp/ods/model.ods +0 -0
- data/test/rails_app/tmp/ods/model_options.ods +0 -0
- data/test/rails_app/tmp/ods/sa.ods +0 -0
- data/test/rails_app/tmp/options.csv +1 -0
- data/test/rails_app/tmp/plain_ruby_object/csv.csv +4 -0
- data/test/rails_app/tmp/plain_ruby_object/ods.ods +0 -0
- data/test/rails_app/tmp/plain_ruby_object/xlsx.xlsx +0 -0
- data/test/rails_app/tmp/posts/csv.csv +1 -0
- data/test/rails_app/tmp/posts/empty.xlsx +0 -0
- data/test/rails_app/tmp/posts/ods.ods +0 -0
- data/test/rails_app/tmp/posts/xlsx.xlsx +0 -0
- data/test/rails_app/tmp/sa.csv +4 -0
- data/test/rails_app/tmp/sa.xlsx +0 -0
- metadata +255 -21
- data/lib/spreadsheet_architect/axlsx_column_width_patch.rb +0 -13
- data/test/database.yml +0 -3
- data/test/helper.rb +0 -52
- data/test/tc_spreadsheet_architect.rb +0 -84
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d4000e6f14557a9a68ad0c48c9b0af57e537f50
|
4
|
+
data.tar.gz: 8d38d5252918e37378b38d98fac0ec73a85cd396
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15cf33b58be7549574d0945fdadd9446bf0be3fb986577767de14147f53e8b3e71c893ce9fa603fce66237cf706ebf2e85c96dd3332462d638715d972ee635ee
|
7
|
+
data.tar.gz: 3181178d0ec7a662af3c23cbcaea731607d54de5c1a9c43af45acdb9060e6cc9afdb26f8a14d96e2ebdd491423dfdcd9991f139962ea1254728a2ef6c7c07b6f
|
data/CHANGELOG.md
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
---------
|
3
3
|
|
4
|
+
- **January.28.2017**: 2.0.0
|
5
|
+
- Add to xlsx: `merges`, `column_styles`, `range_styles`, `borders`, `column_widths` multi-row headers, date/time default format_code
|
6
|
+
- Add `column_types` option for xlsx and ods
|
7
|
+
- Add ability to make multi-sheet spreadsheets in XLSX & ODS
|
8
|
+
- Adds `axlsx_styler` gem dependency
|
9
|
+
- Add Examples
|
10
|
+
- Add Axlsx Style Reference
|
11
|
+
- Refractor into smaller files
|
4
12
|
- **December.6.2016**: 1.4.8
|
5
13
|
- Lock `rodf` gem to v0.3.7 for last v1 version of this gem
|
6
14
|
- **November.7.2016**: 1.4.7
|
7
15
|
- Fix method arguments for `to_rodf_spreadsheet` method
|
8
|
-
- **May.
|
9
|
-
- Fix ruby
|
16
|
+
- **May.16.2016**: 1.4.6
|
17
|
+
- Fix hash syntax for support of ruby v2.1 and below
|
10
18
|
- **May.4.2016**: 1.4.5
|
11
19
|
- Bug fixes
|
12
20
|
- **May.3.2016**: 1.4.4
|
data/README.md
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
# Spreadsheet Architect
|
2
|
-
<a href=
|
2
|
+
<a href='https://www.patreon.com/bePatron?u=4956947' target='_blank'><img height='32' style='border:0px;height:32px;' src='https://miraclesfor.me/wp-content/plugins/patron-button-and-widgets-by-codebard/images/patreon-medium-button.png' border='0' alt='Become a Patron' /></a>
|
3
|
+
<a href='https://ko-fi.com/A5071NK' target='_blank'><img height='32' style='border:0px;height:32px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=a' border='0' alt='Buy Me a Coffee' /></a>
|
3
4
|
|
4
5
|
Spreadsheet Architect is a library that allows you to create XLSX, ODS, or CSV spreadsheets easily from ActiveRecord relations, Plain Ruby classes, or predefined data.
|
5
6
|
|
6
7
|
Key Features:
|
7
8
|
|
8
|
-
- Can generate headers & columns from ActiveRecord column_names
|
9
|
-
-
|
10
|
-
-
|
11
|
-
- Easily style
|
12
|
-
-
|
13
|
-
-
|
9
|
+
- Can generate headers & columns from ActiveRecord column_names or a Class/Model's `spreadsheet_columns` method
|
10
|
+
- Dead simple custom spreadsheets with custom data
|
11
|
+
- Data Sources: ActiveRecord relations, array of Ruby Objects, or 2D Array Data
|
12
|
+
- Easily style and customize spreadsheets
|
13
|
+
- Create multi sheet spreadsheets
|
14
|
+
- Setting Class/Model or Project specific defaults
|
15
|
+
- Simple to use ActionController renderers for Rails
|
16
|
+
- Plain Ruby (without Rails) supported
|
14
17
|
|
15
18
|
Spreadsheet Architect adds the following methods:
|
16
19
|
```ruby
|
@@ -30,20 +33,15 @@ data = [[1,2,3], [4,5,6], [7,8,9]]
|
|
30
33
|
SpreadsheetArchitect.to_xlsx(data: data, headers: headers)
|
31
34
|
SpreadsheetArchitect.to_ods(data: data, headers: headers)
|
32
35
|
SpreadsheetArchitect.to_csv(data: data, header: false)
|
33
|
-
|
34
|
-
# These return a ruby object that can be further manipulated
|
35
|
-
# These methods may also be used on models/classes
|
36
|
-
SpreadsheetArchitect.to_axlsx('package', {data: data, headers: headers})
|
37
|
-
SpreadsheetArchitect.to_axlsx('sheet', {data: data, headers: headers})
|
38
|
-
SpreadsheetArchitect.to_rodf_spreadsheet(data: data, headers: headers)
|
39
36
|
```
|
40
37
|
|
41
38
|
# Install
|
42
39
|
```ruby
|
43
|
-
|
40
|
+
# Gemfile
|
41
|
+
gem 'spreadsheet_architect'
|
44
42
|
```
|
45
43
|
|
46
|
-
# Class/Model Setup
|
44
|
+
# Basic Class/Model Setup
|
47
45
|
|
48
46
|
### Model
|
49
47
|
```ruby
|
@@ -57,14 +55,14 @@ class Post < ActiveRecord::Base #activerecord not required
|
|
57
55
|
#optional for activerecord classes, defaults to the models column_names
|
58
56
|
def spreadsheet_columns
|
59
57
|
|
60
|
-
#[[Label, Method/Statement to Call on each Instance, Cell Type(optional)]....]
|
58
|
+
#[[Label, Method/Statement, Type(optional) to Call on each Instance, Cell Type(optional)]....]
|
61
59
|
[
|
62
60
|
['Title', :title],
|
63
61
|
['Content', content],
|
64
|
-
['Author', (author.name
|
62
|
+
['Author', (author.name if author)],
|
65
63
|
['Published?', (published ? 'Yes' : 'No')],
|
66
64
|
['Published At', :published_at],
|
67
|
-
['# of Views', :number_of_views],
|
65
|
+
['# of Views', :number_of_views, :float],
|
68
66
|
['Rating', :rating],
|
69
67
|
['Category/Tags', "#{category.name} - #{tags.collect(&:name).join(', ')}"]
|
70
68
|
]
|
@@ -73,11 +71,13 @@ class Post < ActiveRecord::Base #activerecord not required
|
|
73
71
|
[:title, :content, :published]
|
74
72
|
|
75
73
|
# OR a Combination of Both ex. "Title", "Content", "Author Name", "Published"
|
76
|
-
[:title, :content, ['Author Name',(author.name rescue nil)], :published]
|
74
|
+
[:title, :content, ['Author Name',(author.name rescue nil)], ['# of Views', :number_of_views, :float], :published]
|
77
75
|
end
|
78
76
|
end
|
79
77
|
```
|
80
78
|
|
79
|
+
Note: Do not define your labels inside this method if you are going to be using custom headers in the model or project defaults.
|
80
|
+
|
81
81
|
# Usage
|
82
82
|
|
83
83
|
### Method 1: Controller (for Rails)
|
@@ -123,7 +123,7 @@ class PostsController < ActionController::Base
|
|
123
123
|
respond_to do |format|
|
124
124
|
format.html
|
125
125
|
format.xlsx { render xlsx: @posts.to_xlsx(headers: false) }
|
126
|
-
format.ods { render ods: Post.
|
126
|
+
format.ods { render ods: Post.to_ods(instances: @posts) }
|
127
127
|
format.csv{ render csv: @posts.to_csv(headers: false), file_name: 'articles' }
|
128
128
|
end
|
129
129
|
end
|
@@ -132,88 +132,102 @@ end
|
|
132
132
|
|
133
133
|
### Method 2: Save to a file manually
|
134
134
|
```ruby
|
135
|
-
# Ex. with ActiveRecord
|
136
|
-
File.open('path/to/file.xlsx') do |f|
|
135
|
+
# Ex. with ActiveRecord relation
|
136
|
+
File.open('path/to/file.xlsx', 'w+b') do |f|
|
137
137
|
f.write{ Post.order(published_at: :asc).to_xlsx }
|
138
138
|
end
|
139
|
-
File.open('path/to/file.ods') do |f|
|
139
|
+
File.open('path/to/file.ods', 'w+b) do |f|
|
140
140
|
f.write{ Post.order(published_at: :asc).to_ods }
|
141
141
|
end
|
142
|
-
File.open('path/to/file.csv') do |f|
|
142
|
+
File.open('path/to/file.csv', 'w+b') do |f|
|
143
143
|
f.write{ Post.order(published_at: :asc).to_csv }
|
144
144
|
end
|
145
145
|
|
146
146
|
# Ex. with plain ruby class
|
147
|
-
File.open('path/to/file.xlsx') do |f|
|
147
|
+
File.open('path/to/file.xlsx', 'w+b') do |f|
|
148
148
|
f.write{ Post.to_xlsx(instances: posts_array) }
|
149
149
|
end
|
150
150
|
|
151
151
|
# Ex. One time Usage
|
152
|
-
File.open('path/to/file.xlsx') do |f|
|
152
|
+
File.open('path/to/file.xlsx', 'w+b') do |f|
|
153
153
|
headers = ['Col 1','Col 2','Col 3']
|
154
154
|
data = [[1,2,3], [4,5,6], [7,8,9]]
|
155
155
|
f.write{ SpreadsheetArchitect::to_xlsx(data: data, headers: headers) }
|
156
156
|
end
|
157
157
|
```
|
158
|
+
<br>
|
158
159
|
|
159
|
-
#
|
160
|
+
# Methods & Options
|
160
161
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|**
|
167
|
-
|**
|
168
|
-
|**
|
169
|
-
|**
|
170
|
-
|**
|
162
|
+
|
163
|
+
## SomeClass.to_xlsx
|
164
|
+
|
165
|
+
|Option|Default|Notes|
|
166
|
+
|---|---|---|
|
167
|
+
|**spreadsheet_columns**<br>*Array*| This defaults to your models custom `spreadsheet_columns` method or any custom defaults defined.<br>If none of those then falls back to `self.column_names` for ActiveRecord models. | Use this option to override the model instances `spreadsheet_columns` method|
|
168
|
+
|**instances**<br>*Array*| |**Required only for Non-ActiveRecord classes** Array of class/model instances.|
|
169
|
+
|**headers**<br>*2D Array*|This defaults to your models custom spreadsheet_columns method or `self.column_names.collect(&:titleize)`|Pass `false` to skip the header row.|
|
170
|
+
|**sheet_name**<br>*String*|The class name||
|
171
|
+
|**header_style**<br>*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](https://github.com/westonganger/spreadsheet_architect/blob/master/docs/axlsx_styles_reference.md)|
|
172
|
+
|**row_style**<br>*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](https://github.com/westonganger/spreadsheet_architect/blob/master/docs/axlsx_styles_reference.md)|
|
173
|
+
|**column_styles**<br>*Array*||[See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/examples/complex_xlsx_styling.rb)|
|
174
|
+
|**range_styles**<br>*Array*||[See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/examples/complex_xlsx_styling.rb)|
|
175
|
+
|**merges**<br>*Array*||Merge cells. [See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/examples/complex_xlsx_styling.rb)|
|
176
|
+
|**borders**<br>*Array*||[See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/examples/complex_xlsx_styling.rb)|
|
177
|
+
|**column_widths**<br>*Array*||Sometimes you may want explicit column widths. Use nil if you want a column to autofit again.|
|
171
178
|
|
172
179
|
<br>
|
173
|
-
|
174
|
-
|Option|
|
175
|
-
|
176
|
-
|**spreadsheet_columns
|
177
|
-
|**instances
|
178
|
-
|**headers
|
179
|
-
|**sheet_name
|
180
|
-
|**header_style
|
181
|
-
|**row_style
|
180
|
+
## SomeClass.to_ods
|
181
|
+
|Option|Default|Notes|
|
182
|
+
|---|---|---|
|
183
|
+
|**spreadsheet_columns**<br>*Array*| This defaults to your models custom `spreadsheet_columns` method or any custom defaults defined.<br>If none of those then falls back to `self.column_names` for ActiveRecord models. | Use this option to override the model instances `spreadsheet_columns` method|
|
184
|
+
|**instances**<br>*Array*| |**Required only for Non-ActiveRecord models** Array of class/model instances.|
|
185
|
+
|**headers**<br>*2D Array*|`self.column_names.collect(&:titleize)`|Pass `false` to skip the header row.|
|
186
|
+
|**sheet_name**<br>*String*|The class name||
|
187
|
+
|**header_style**<br>*Hash*|`{background_color: "AAAAAA", color: "FFFFFF", align: :center, font_size: 10, bold: true}`|Note: Currently ODS only supports these options (values can be changed though)|
|
188
|
+
|**row_style**<br>*Hash*|`{background_color: nil, color: "000000", align: :left, font_size: 10, bold: false}`|Styles for non-header rows. Currently ODS only supports these options|
|
182
189
|
|
183
190
|
<br>
|
184
|
-
|
185
|
-
|Option|
|
186
|
-
|
187
|
-
|**spreadsheet_columns
|
188
|
-
|**instances
|
189
|
-
|**headers
|
191
|
+
## SomeClass.to_csv
|
192
|
+
|Option|Default|Notes|
|
193
|
+
|---|---|---|
|
194
|
+
|**spreadsheet_columns**<br>*Array*| This defaults to your models custom `spreadsheet_columns` method or any custom defaults defined.<br>If none of those then falls back to `self.column_names` for ActiveRecord models. | Use this to option override the model instances `spreadsheet_columns` method|
|
195
|
+
|**instances**<br>*Array*| |**Required only for Non-ActiveRecord classes** Array of class/model instances.|
|
196
|
+
|**headers**<br>*2D Array*|`self.column_names.collect(&:titleize)`| Data for the header rows cells. Pass `false` to skip the header row.|
|
190
197
|
|
191
198
|
<br>
|
192
|
-
|
193
|
-
|Option|
|
194
|
-
|
195
|
-
|**data
|
196
|
-
|**headers
|
197
|
-
|**sheet_name
|
198
|
-
|**header_style
|
199
|
-
|**row_style
|
199
|
+
## SpreadsheetArchitect.to_xlsx
|
200
|
+
|Option|Default|Notes|
|
201
|
+
|---|---|---|
|
202
|
+
|**data**<br>*Array*| |Data for the non-header row cells. |
|
203
|
+
|**headers**<br>*2D Array*|`false`|Data for the header row cells. Pass `false` to skip the header row.|
|
204
|
+
|**sheet_name**<br>*String*|`Sheet1`||
|
205
|
+
|**header_style**<br>*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](https://github.com/westonganger/spreadsheet_architect/blob/master/docs/axlsx_styles_reference.md)|
|
206
|
+
|**row_style**<br>*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](https://github.com/westonganger/spreadsheet_architect/blob/master/docs/axlsx_styles_reference.md)|
|
207
|
+
|**column_styles**<br>*Array*||[See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/examples/complex_xlsx_styling.rb)|
|
208
|
+
|**range_styles**<br>*Array*||[See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/examples/complex_xlsx_styling.rb)|
|
209
|
+
|**merges**<br>*Array*||Merge cells. [See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/examples/complex_xlsx_styling.rb)|
|
210
|
+
|**borders**<br>*Array*||[See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/examples/complex_xlsx_styling.rb)|
|
211
|
+
|**column_types**<br>*Array*||Valid types for XLSX are :string, :integer, :float, :date, :time, :boolean, nil = auto determine|
|
212
|
+
|**column_widths**<br>*Array*||Sometimes you may want explicit column widths. Use nil if you want a column to autofit again.|
|
200
213
|
|
201
214
|
<br>
|
202
|
-
|
203
|
-
|Option|
|
204
|
-
|
205
|
-
|**data
|
206
|
-
|**headers
|
207
|
-
|**sheet_name
|
208
|
-
|**header_style
|
209
|
-
|**row_style
|
215
|
+
## SpreadsheetArchitect.to_ods
|
216
|
+
|Option|Default|Notes|
|
217
|
+
|---|---|---|
|
218
|
+
|**data**<br>*2D Array*| |Data for the non-header row cells.|
|
219
|
+
|**headers**<br>*2D Array*|`false`|Data for the header rows cells. Pass `false` to skip the header row.|
|
220
|
+
|**sheet_name**<br>*String*|`Sheet1`||
|
221
|
+
|**header_style**<br>*Hash*|`{background_color: "AAAAAA", color: "FFFFFF", align: :center, font_size: 10, bold: true}`|Note: Currently ODS only supports these options|
|
222
|
+
|**row_style**<br>*Hash*|`{background_color: nil, color: "000000", align: :left, font_size: 10, bold: false}`|Styles for non-header rows. Currently ODS only supports these options|
|
223
|
+
|**column_types**<br>*Array*||Valid types for ODS are :string, :float, :date, :percent, :currency, nil = auto determine|
|
210
224
|
|
211
225
|
<br>
|
212
|
-
|
213
|
-
|Option|
|
214
|
-
|
215
|
-
|**data
|
216
|
-
|**headers
|
226
|
+
## SpreadsheetArchitect.to_csv
|
227
|
+
|Option|Default|Notes|
|
228
|
+
|---|---|---|
|
229
|
+
|**data**<br>*2D Array*| |Data for the non-header row cells.|
|
230
|
+
|**headers**<br>*2D Array*|`false`|Data for the header rows cells. Pass `false` to skip the header row.|
|
217
231
|
|
218
232
|
|
219
233
|
# Change model default method options
|
@@ -226,10 +240,18 @@ class Post
|
|
226
240
|
end
|
227
241
|
|
228
242
|
SPREADSHEET_OPTIONS = {
|
229
|
-
headers:
|
243
|
+
headers: [
|
244
|
+
['My Post Report'],
|
245
|
+
self.column_names.map{|x| x.titleize}
|
246
|
+
],
|
230
247
|
header_style: {background_color: 'AAAAAA', color: 'FFFFFF', align: :center, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
|
231
|
-
row_style: {background_color: nil, color: '
|
232
|
-
sheet_name: self.name
|
248
|
+
row_style: {background_color: nil, color: '000000', align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
|
249
|
+
sheet_name: self.name,
|
250
|
+
column_styles: [],
|
251
|
+
range_styles: [],
|
252
|
+
merges: [],
|
253
|
+
borders: [],
|
254
|
+
column_types: []
|
233
255
|
}
|
234
256
|
end
|
235
257
|
```
|
@@ -238,38 +260,35 @@ end
|
|
238
260
|
```ruby
|
239
261
|
# config/initializers/spreadsheet_architect.rb
|
240
262
|
|
241
|
-
SpreadsheetArchitect.
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
263
|
+
SpreadsheetArchitect.default_options = {
|
264
|
+
headers: true,
|
265
|
+
header_style: {background_color: 'AAAAAA', color: 'FFFFFF', align: :center, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
|
266
|
+
row_style: {background_color: nil, color: 'FFFFFF', align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
|
267
|
+
sheet_name: 'My Project Export',
|
268
|
+
column_styles: [],
|
269
|
+
range_styles: [],
|
270
|
+
merges: [],
|
271
|
+
borders: [],
|
272
|
+
column_types: []
|
273
|
+
}
|
249
274
|
```
|
250
275
|
|
251
|
-
#
|
276
|
+
# Complex XLSX Example with Styling
|
277
|
+
See this example: (https://github.com/westonganger/spreadsheet_architect/blob/master/examples/complex_xlsx_styling.rb)
|
252
278
|
|
253
|
-
Unfortunately so far I have only been successful in applying the format_code to all numbers in the entire spreadsheet.
|
254
279
|
|
255
|
-
|
256
|
-
|
257
|
-
Product.to_xlsx(headers: headers, data: data, number_format_code: "$#,##0.00")
|
258
|
-
```
|
280
|
+
# Multi Sheet XLSX or ODS spreadsheets
|
281
|
+
See this example: (https://github.com/westonganger/spreadsheet_architect/blob/master/examples/multi_sheet_spreadsheets.rb)
|
259
282
|
|
260
|
-
# TODO
|
261
283
|
|
262
|
-
|
284
|
+
# Axlsx Style Reference
|
285
|
+
I have compiled a list of all available style options for `axlsx` here: (https://github.com/westonganger/spreadsheet_architect/blob/master/docs/axlsx_styles_reference.md)
|
263
286
|
|
264
|
-
- More ODS style options
|
265
|
-
- Apply format codes to only certain columns (xlsx) - this is supposed to be possible with axlsx_styler
|
266
|
-
- Add Columns styles (xlsx & ods)
|
267
|
-
- Create multiple sheets (xlsx & ods)
|
268
287
|
|
269
288
|
# Credits
|
270
289
|
Created by Weston Ganger - @westonganger
|
271
290
|
|
272
291
|
Heavily influenced by the dead gem `acts_as_xlsx` by @randym but adapted to work for more spreadsheet types and plain ruby models.
|
273
292
|
|
274
|
-
|
275
|
-
<a href=
|
293
|
+
<a href='https://www.patreon.com/bePatron?u=4956947' target='_blank'><img height='32' style='border:0px;height:32px;' src='https://miraclesfor.me/wp-content/plugins/patron-button-and-widgets-by-codebard/images/patreon-medium-button.png' border='0' alt='Become a Patron' /></a>
|
294
|
+
<a href='https://ko-fi.com/A5071NK' target='_blank'><img height='32' style='border:0px;height:32px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=a' border='0' alt='Buy Me a Coffee' /></a>
|
data/Rakefile
CHANGED
@@ -5,9 +5,16 @@ task :test do
|
|
5
5
|
require 'rake/testtask'
|
6
6
|
Rake::TestTask.new do |t|
|
7
7
|
t.libs << 'test'
|
8
|
-
t.test_files = FileList['test
|
8
|
+
t.test_files = FileList['test/**/*_test.rb']
|
9
9
|
t.verbose = true
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
task default: :test
|
14
|
+
|
15
|
+
task :console do
|
16
|
+
require 'spreadsheet_architect'
|
17
|
+
|
18
|
+
require 'irb'
|
19
|
+
binding.irb
|
20
|
+
end
|
@@ -1,10 +1,19 @@
|
|
1
1
|
require 'rails/generators'
|
2
2
|
|
3
3
|
module SpreadsheetArchitect
|
4
|
-
class
|
4
|
+
class AddDefaultOptionsGenerator < Rails::Generators::Base
|
5
5
|
|
6
|
-
def
|
7
|
-
create_file "config/initializers/spreadsheet_architect.rb",
|
6
|
+
def add_default_options
|
7
|
+
create_file "config/initializers/spreadsheet_architect.rb", <<eos
|
8
|
+
SpreadsheetArchitect.default_options = {
|
9
|
+
headers: true,
|
10
|
+
header_style: {background_color: "AAAAAA", color: "FFFFFF", align: :center, bold: false, font_name: 'Arial', font_size: 10, italic: false, underline: false},
|
11
|
+
row_style: {background_color: nil, color: "000000", align: :left, bold: false, font_name: 'Arial', font_size: 10, italic: false, underline: false},
|
12
|
+
column_styles: [],
|
13
|
+
range_styles: [],
|
14
|
+
borders: []
|
15
|
+
}
|
16
|
+
eos
|
8
17
|
end
|
9
18
|
|
10
19
|
end
|
@@ -1,343 +1,32 @@
|
|
1
|
-
require 'spreadsheet_architect/
|
1
|
+
require 'spreadsheet_architect/mime_types'
|
2
2
|
require 'spreadsheet_architect/action_controller_renderers'
|
3
|
-
require 'axlsx'
|
4
|
-
require 'spreadsheet_architect/axlsx_column_width_patch'
|
5
|
-
require 'odf/spreadsheet'
|
6
|
-
require 'csv'
|
7
3
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
class NoDataError < StandardError
|
14
|
-
def initialize
|
15
|
-
super("Missing data option or data is empty")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class NoInstancesError < StandardError
|
20
|
-
def initialize
|
21
|
-
super("Missing instances option or relation is empty.")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
class SpreadsheetColumnsNotDefined < StandardError
|
26
|
-
def initialize(klass=nil)
|
27
|
-
super("The spreadsheet_columns option is not defined on #{klass.name}")
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
module Helpers
|
32
|
-
def self.str_humanize(str, capitalize = true)
|
33
|
-
str = str.sub(/\A_+/, '').gsub(/[_\.]/,' ').sub(' rescue nil','')
|
34
|
-
if capitalize
|
35
|
-
str = str.gsub(/(\A|\ )\w/){|x| x.upcase}
|
36
|
-
end
|
37
|
-
return str
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.get_type(value, type=nil, last_run=false)
|
41
|
-
return type if !type.blank?
|
42
|
-
if value.is_a?(Numeric)
|
43
|
-
if [:float, :decimal].include?(type)
|
44
|
-
type = :float
|
45
|
-
else
|
46
|
-
type = :integer
|
47
|
-
end
|
48
|
-
elsif !last_run && value.is_a?(Symbol)
|
49
|
-
type = :symbol
|
50
|
-
else
|
51
|
-
type = :string
|
52
|
-
end
|
53
|
-
return type
|
54
|
-
end
|
55
|
-
|
56
|
-
def self.get_cell_data(options={}, klass)
|
57
|
-
if klass.name == 'SpreadsheetArchitect'
|
58
|
-
if !options[:data] || options[:data].empty?
|
59
|
-
raise SpreadsheetArchitect::NoDataError
|
60
|
-
end
|
61
|
-
|
62
|
-
if options[:headers] && !options[:headers].empty?
|
63
|
-
headers = options[:headers]
|
64
|
-
else
|
65
|
-
headers = false
|
66
|
-
end
|
67
|
-
|
68
|
-
data = options[:data]
|
69
|
-
|
70
|
-
types = []
|
71
|
-
data.first.each do |x|
|
72
|
-
types.push self.get_type(x, nil)
|
73
|
-
end
|
74
|
-
else
|
75
|
-
has_custom_columns = options[:spreadsheet_columns] || klass.instance_methods.include?(:spreadsheet_columns)
|
76
|
-
|
77
|
-
if !options[:instances] && defined?(ActiveRecord) && klass.ancestors.include?(ActiveRecord::Base)
|
78
|
-
options[:instances] = klass.where(nil).to_a # triggers the relation call, not sure how this works but it does
|
79
|
-
end
|
80
|
-
|
81
|
-
if !options[:instances] || options[:instances].empty?
|
82
|
-
raise SpreadsheetArchitect::NoInstancesError
|
83
|
-
end
|
84
|
-
|
85
|
-
if has_custom_columns
|
86
|
-
headers = []
|
87
|
-
columns = []
|
88
|
-
types = []
|
89
|
-
array = options[:spreadsheet_columns] || options[:instances].first.spreadsheet_columns
|
90
|
-
array.each do |x|
|
91
|
-
if x.is_a?(Array)
|
92
|
-
headers.push x[0].to_s
|
93
|
-
columns.push x[1]
|
94
|
-
#types.push self.get_type(x[1], x[2])
|
95
|
-
types.push self.get_type(x[1], nil)
|
96
|
-
else
|
97
|
-
headers.push str_humanize(x.to_s)
|
98
|
-
columns.push x
|
99
|
-
types.push self.get_type(x, nil)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
elsif !has_custom_columns && defined?(ActiveRecord) && klass.ancestors.include?(ActiveRecord::Base)
|
103
|
-
ignored_columns = ["id","created_at","updated_at","deleted_at"]
|
104
|
-
the_column_names = (klass.column_names - ignored_columns)
|
105
|
-
headers = the_column_names.map{|x| str_humanize(x)}
|
106
|
-
columns = the_column_names.map{|x| x.to_sym}
|
107
|
-
types = klass.columns.keep_if{|x| !ignored_columns.include?(x.name)}.collect(&:type)
|
108
|
-
types.map!{|type| self.get_type(nil, type)}
|
109
|
-
else
|
110
|
-
raise SpreadsheetArchitect::SpreadsheetColumnsNotDefined, klass
|
111
|
-
end
|
112
|
-
|
113
|
-
if options[:headers].nil?
|
114
|
-
options[:headers] = klass::SPREADSHEET_OPTIONS[:headers] if defined?(klass::SPREADSHEET_OPTIONS)
|
115
|
-
options[:headers] = SpreadsheetArchitect::SPREADSHEET_OPTIONS[:headers] if options[:headers].nil?
|
116
|
-
end
|
117
|
-
if options[:headers].nil? || options[:headers] == false
|
118
|
-
headers = false
|
119
|
-
end
|
120
|
-
|
121
|
-
data = []
|
122
|
-
options[:instances].each do |instance|
|
123
|
-
if has_custom_columns && !options[:spreadsheet_columns]
|
124
|
-
row_data = []
|
125
|
-
instance.spreadsheet_columns.each do |x|
|
126
|
-
if x.is_a?(Array)
|
127
|
-
row_data.push(x[1].is_a?(Symbol) ? instance.instance_eval(x[1].to_s) : x[1])
|
128
|
-
else
|
129
|
-
row_data.push(x.is_a?(Symbol) ? instance.instance_eval(x.to_s) : x)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
data.push row_data
|
133
|
-
else
|
134
|
-
data.push columns.map{|col| col.is_a?(Symbol) ? instance.instance_eval(col.to_s) : col}
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
# Fixes missing types from symbol methods
|
139
|
-
if has_custom_columns || options[:spreadsheet_columns]
|
140
|
-
data.first.each_with_index do |x,i|
|
141
|
-
if types[i] == :symbol
|
142
|
-
types[i] = self.get_type(x, nil, true)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
return options.merge(headers: headers, data: data, types: types)
|
149
|
-
end
|
150
|
-
|
151
|
-
def self.get_options(options={}, klass)
|
152
|
-
if options[:headers]
|
153
|
-
if defined?(klass::SPREADSHEET_OPTIONS)
|
154
|
-
header_style = SpreadsheetArchitect::SPREADSHEET_OPTIONS[:header_style].merge(klass::SPREADSHEET_OPTIONS[:header_style] || {})
|
155
|
-
else
|
156
|
-
header_style = SpreadsheetArchitect::SPREADSHEET_OPTIONS[:header_style]
|
157
|
-
end
|
158
|
-
|
159
|
-
if options[:header_style]
|
160
|
-
header_style.merge!(options[:header_style])
|
161
|
-
elsif options[:header_style] == false
|
162
|
-
header_style = false
|
163
|
-
end
|
164
|
-
else
|
165
|
-
header_style = false
|
166
|
-
end
|
167
|
-
|
168
|
-
if options[:row_style] == false
|
169
|
-
row_style = false
|
170
|
-
else
|
171
|
-
if defined?(klass::SPREADSHEET_OPTIONS)
|
172
|
-
row_style = SpreadsheetArchitect::SPREADSHEET_OPTIONS[:row_style].merge(klass::SPREADSHEET_OPTIONS[:row_style] || {})
|
173
|
-
else
|
174
|
-
row_style = SpreadsheetArchitect::SPREADSHEET_OPTIONS[:row_style]
|
175
|
-
end
|
176
|
-
|
177
|
-
if options[:row_style]
|
178
|
-
row_style.merge!(options[:row_style])
|
179
|
-
end
|
180
|
-
end
|
4
|
+
require 'spreadsheet_architect/exceptions'
|
5
|
+
require 'spreadsheet_architect/utils'
|
6
|
+
require 'spreadsheet_architect/utils/xlsx'
|
181
7
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
sheet_name = options[:sheet_name] || SpreadsheetArchitect::SPREADSHEET_OPTIONS[:sheet_name] || klass.name
|
186
|
-
end
|
187
|
-
|
188
|
-
return {headers: options[:headers], header_style: header_style, row_style: row_style, types: options[:types], sheet_name: sheet_name, data: options[:data]}
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
module ClassMethods
|
193
|
-
def to_csv(opts={})
|
194
|
-
opts = SpreadsheetArchitect::Helpers.get_cell_data(opts, self)
|
195
|
-
options = SpreadsheetArchitect::Helpers.get_options(opts, self)
|
196
|
-
|
197
|
-
CSV.generate do |csv|
|
198
|
-
csv << options[:headers] if options[:headers]
|
199
|
-
|
200
|
-
options[:data].each do |row_data|
|
201
|
-
csv << row_data
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def to_rodf_spreadsheet(opts={})
|
207
|
-
opts = SpreadsheetArchitect::Helpers.get_cell_data(opts, self)
|
208
|
-
options = SpreadsheetArchitect::Helpers.get_options(opts, self)
|
209
|
-
|
210
|
-
spreadsheet = ODF::Spreadsheet.new
|
211
|
-
|
212
|
-
spreadsheet.office_style :header_style, family: :cell do
|
213
|
-
if options[:header_style]
|
214
|
-
unless opts[:header_style] && opts[:header_style][:bold] == false #uses opts, temporary
|
215
|
-
property :text, 'font-weight' => :bold
|
216
|
-
end
|
217
|
-
if options[:header_style][:align]
|
218
|
-
property :text, align: options[:header_style][:align]
|
219
|
-
end
|
220
|
-
if options[:header_style][:size]
|
221
|
-
property :text, 'font-size' => options[:header_style][:size]
|
222
|
-
end
|
223
|
-
if options[:header_style][:color] && opts[:header_style] && opts[:header_style][:color] #temporary
|
224
|
-
property :text, color: "##{options[:header_style][:color]}"
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
spreadsheet.office_style :row_style, family: :cell do
|
229
|
-
if options[:row_style]
|
230
|
-
if options[:row_style][:bold]
|
231
|
-
property :text, 'font-weight' => :bold
|
232
|
-
end
|
233
|
-
if options[:row_style][:align]
|
234
|
-
property :text, align: options[:row_style][:align]
|
235
|
-
end
|
236
|
-
if options[:row_style][:size]
|
237
|
-
property :text, 'font-size' => options[:row_style][:size]
|
238
|
-
end
|
239
|
-
if opts[:row_style] && opts[:row_style][:color] #uses opts, temporary
|
240
|
-
property :text, color: "##{options[:row_style][:color]}"
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
spreadsheet.table options[:sheet_name] do
|
246
|
-
if options[:headers]
|
247
|
-
row do
|
248
|
-
options[:headers].each do |header|
|
249
|
-
cell header, style: :header_style
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
options[:data].each do |row_data|
|
254
|
-
row do
|
255
|
-
row_data.each_with_index do |y,i|
|
256
|
-
cell y, style: :row_style, type: options[:types][i]
|
257
|
-
end
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
return spreadsheet
|
263
|
-
end
|
264
|
-
|
265
|
-
def to_ods(opts={})
|
266
|
-
return to_rodf_spreadsheet(opts).bytes
|
267
|
-
end
|
268
|
-
|
269
|
-
def to_axlsx(which='sheet', opts={})
|
270
|
-
opts = SpreadsheetArchitect::Helpers.get_cell_data(opts, self)
|
271
|
-
options = SpreadsheetArchitect::Helpers.get_options(opts, self)
|
272
|
-
|
273
|
-
header_style = {}
|
274
|
-
if options[:header_style]
|
275
|
-
header_style[:fg_color] = options[:header_style].delete(:color)
|
276
|
-
header_style[:bg_color] = options[:header_style].delete(:background_color)
|
277
|
-
if header_style[:align]
|
278
|
-
header_style[:alignment] = {}
|
279
|
-
header_style[:alignment][:horizontal] = options[:header_style].delete(:align)
|
280
|
-
end
|
281
|
-
header_style[:b] = options[:header_style].delete(:bold)
|
282
|
-
header_style[:sz] = options[:header_style].delete(:font_size)
|
283
|
-
header_style[:i] = options[:header_style].delete(:italic)
|
284
|
-
if options[:header_style][:underline]
|
285
|
-
header_style[:u] = options[:header_style].delete(:underline)
|
286
|
-
end
|
287
|
-
header_style.delete_if{|x| x.nil?}
|
288
|
-
end
|
289
|
-
|
290
|
-
row_style = {}
|
291
|
-
if options[:row_style]
|
292
|
-
row_style[:fg_color] = options[:row_style].delete(:color)
|
293
|
-
row_style[:bg_color] = options[:row_style].delete(:background_color)
|
294
|
-
if row_style[:align]
|
295
|
-
row_style[:alignment] = {}
|
296
|
-
row_style[:alignment][:horizontal] = options[:row_style][:align]
|
297
|
-
end
|
298
|
-
row_style[:b] = options[:row_style].delete(:bold)
|
299
|
-
row_style[:sz] = options[:row_style].delete(:font_size)
|
300
|
-
row_style[:i] = options[:row_style].delete(:italic)
|
301
|
-
if options[:row_style][:underline]
|
302
|
-
row_style[:u] = options[:row_style].delete(:underline)
|
303
|
-
end
|
304
|
-
row_style.delete_if{|x| x.nil?}
|
305
|
-
end
|
306
|
-
|
307
|
-
package = Axlsx::Package.new
|
308
|
-
|
309
|
-
return package if options[:data].empty?
|
310
|
-
|
311
|
-
the_sheet = package.workbook.add_worksheet(name: options[:sheet_name]) do |sheet|
|
312
|
-
if options[:headers]
|
313
|
-
sheet.add_row options[:headers], style: package.workbook.styles.add_style(header_style)
|
314
|
-
end
|
315
|
-
|
316
|
-
options[:data].each do |row_data|
|
317
|
-
row_style.merge!(format_code: opts[:row_style][:number_format_code]) if opts[:row_style] && opts[:row_style][:number_format_code]
|
318
|
-
sheet.add_row row_data, style: package.workbook.styles.add_style(row_style), types: options[:types]
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
if which.to_sym == :sheet
|
323
|
-
return the_sheet
|
324
|
-
else
|
325
|
-
return package
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
def to_xlsx(opts={})
|
330
|
-
return to_axlsx('package', opts).to_stream.read
|
331
|
-
end
|
8
|
+
require 'spreadsheet_architect/class_methods/csv'
|
9
|
+
require 'spreadsheet_architect/class_methods/ods'
|
10
|
+
require 'spreadsheet_architect/class_methods/xlsx'
|
332
11
|
|
12
|
+
module SpreadsheetArchitect
|
13
|
+
def self.included(base)
|
14
|
+
base.send(:extend, ClassMethods)
|
333
15
|
end
|
334
16
|
|
335
17
|
extend SpreadsheetArchitect::ClassMethods
|
336
18
|
|
337
|
-
|
19
|
+
@default_options = {
|
338
20
|
headers: true,
|
339
|
-
#sheet_name: self.name,
|
340
21
|
header_style: {background_color: "AAAAAA", color: "FFFFFF", align: :center, bold: false, font_name: 'Arial', font_size: 10, italic: false, underline: false},
|
341
22
|
row_style: {background_color: nil, color: "000000", align: :left, bold: false, font_name: 'Arial', font_size: 10, italic: false, underline: false}
|
342
23
|
}
|
24
|
+
|
25
|
+
def self.default_options=(val)
|
26
|
+
@default_options = val
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.default_options
|
30
|
+
@default_options
|
31
|
+
end
|
343
32
|
end
|