spreadsheet_architect 1.4.8 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|