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.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -2
  3. data/README.md +117 -98
  4. data/Rakefile +8 -1
  5. data/lib/generators/spreadsheet_architect/add_project_defaults_generator.rb +12 -3
  6. data/lib/spreadsheet_architect.rb +19 -330
  7. data/lib/spreadsheet_architect/action_controller_renderers.rb +9 -19
  8. data/lib/spreadsheet_architect/class_methods/csv.rb +22 -0
  9. data/lib/spreadsheet_architect/class_methods/ods.rb +61 -0
  10. data/lib/spreadsheet_architect/class_methods/xlsx.rb +162 -0
  11. data/lib/spreadsheet_architect/exceptions.rb +47 -0
  12. data/lib/spreadsheet_architect/{set_mime_types.rb → mime_types.rb} +0 -2
  13. data/lib/spreadsheet_architect/monkey_patches/axlsx_column_width.rb +23 -0
  14. data/lib/spreadsheet_architect/utils.rb +223 -0
  15. data/lib/spreadsheet_architect/utils/xlsx.rb +126 -0
  16. data/lib/spreadsheet_architect/version.rb +1 -1
  17. data/test/rails_app/Gemfile +17 -0
  18. data/test/rails_app/Gemfile.lock +176 -0
  19. data/test/rails_app/README.md +24 -0
  20. data/test/rails_app/Rakefile +6 -0
  21. data/test/rails_app/app/assets/config/manifest.js +3 -0
  22. data/test/rails_app/app/assets/javascripts/application.js +16 -0
  23. data/test/rails_app/app/assets/javascripts/cable.js +13 -0
  24. data/test/rails_app/app/assets/stylesheets/application.css +15 -0
  25. data/test/rails_app/app/channels/application_cable/channel.rb +4 -0
  26. data/test/rails_app/app/channels/application_cable/connection.rb +4 -0
  27. data/test/rails_app/app/controllers/application_controller.rb +3 -0
  28. data/test/rails_app/app/controllers/spreadsheets_controller.rb +74 -0
  29. data/test/rails_app/app/helpers/application_helper.rb +2 -0
  30. data/test/rails_app/app/jobs/application_job.rb +2 -0
  31. data/test/rails_app/app/mailers/application_mailer.rb +4 -0
  32. data/test/rails_app/app/models/active_model_object.rb +14 -0
  33. data/test/rails_app/app/models/application_record.rb +3 -0
  34. data/test/rails_app/app/models/bad_plain_ruby_object.rb +3 -0
  35. data/test/rails_app/app/models/custom_post.rb +15 -0
  36. data/test/rails_app/app/models/plain_ruby_object.rb +19 -0
  37. data/test/rails_app/app/models/post.rb +3 -0
  38. data/test/rails_app/app/views/layouts/application.html.erb +14 -0
  39. data/test/rails_app/app/views/layouts/mailer.html.erb +13 -0
  40. data/test/rails_app/app/views/layouts/mailer.text.erb +1 -0
  41. data/test/rails_app/bin/bundle +3 -0
  42. data/test/rails_app/bin/rails +9 -0
  43. data/test/rails_app/bin/rake +9 -0
  44. data/test/rails_app/bin/setup +34 -0
  45. data/test/rails_app/bin/spring +16 -0
  46. data/test/rails_app/bin/update +29 -0
  47. data/test/rails_app/config.ru +5 -0
  48. data/test/rails_app/config/application.rb +15 -0
  49. data/test/rails_app/config/boot.rb +3 -0
  50. data/test/rails_app/config/cable.yml +9 -0
  51. data/test/rails_app/config/database.yml +16 -0
  52. data/test/rails_app/config/environment.rb +5 -0
  53. data/test/rails_app/config/environments/development.rb +54 -0
  54. data/test/rails_app/config/environments/production.rb +86 -0
  55. data/test/rails_app/config/environments/test.rb +42 -0
  56. data/test/rails_app/config/initializers/application_controller_renderer.rb +6 -0
  57. data/test/rails_app/config/initializers/assets.rb +11 -0
  58. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  59. data/test/rails_app/config/initializers/cookies_serializer.rb +5 -0
  60. data/test/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
  61. data/test/rails_app/config/initializers/inflections.rb +16 -0
  62. data/test/rails_app/config/initializers/mime_types.rb +4 -0
  63. data/test/rails_app/config/initializers/new_framework_defaults.rb +24 -0
  64. data/test/rails_app/config/initializers/session_store.rb +3 -0
  65. data/test/rails_app/config/initializers/wrap_parameters.rb +14 -0
  66. data/test/rails_app/config/locales/en.yml +23 -0
  67. data/test/rails_app/config/routes.rb +7 -0
  68. data/test/rails_app/config/secrets.yml +22 -0
  69. data/test/{spreadsheet_architect.sqlite3.db → rails_app/db/development.sqlite3} +0 -0
  70. data/test/rails_app/db/migrate/20170103234524_add_posts.rb +10 -0
  71. data/test/rails_app/db/schema.rb +23 -0
  72. data/test/rails_app/db/seeds.rb +7 -0
  73. data/test/rails_app/db/test.sqlite3 +0 -0
  74. data/test/rails_app/log/development.log +1195 -0
  75. data/test/rails_app/log/test.log +52766 -0
  76. data/test/rails_app/public/404.html +67 -0
  77. data/test/rails_app/public/422.html +67 -0
  78. data/test/rails_app/public/500.html +66 -0
  79. data/test/rails_app/public/apple-touch-icon-precomposed.png +0 -0
  80. data/test/rails_app/public/apple-touch-icon.png +0 -0
  81. data/test/rails_app/public/favicon.ico +0 -0
  82. data/test/rails_app/public/robots.txt +5 -0
  83. data/test/rails_app/test/controllers/spreadsheets_controller_test.rb +46 -0
  84. data/test/rails_app/test/models/active_model_object_test.rb +54 -0
  85. data/test/rails_app/test/models/bad_plain_ruby_object_test.rb +30 -0
  86. data/test/rails_app/test/models/csv_test.rb +60 -0
  87. data/test/rails_app/test/models/custom_post_test.rb +47 -0
  88. data/test/rails_app/test/models/ods_test.rb +68 -0
  89. data/test/rails_app/test/models/plain_ruby_object_test.rb +54 -0
  90. data/test/rails_app/test/models/post_test.rb +47 -0
  91. data/test/rails_app/test/models/spreadsheet_architect_utils_test.rb +68 -0
  92. data/test/rails_app/test/models/xlsx_test.rb +99 -0
  93. data/test/rails_app/test/test_helper.rb +21 -0
  94. data/test/rails_app/tmp/active_model_object/csv.csv +21 -0
  95. data/test/rails_app/tmp/active_model_object/ods.ods +0 -0
  96. data/test/rails_app/tmp/active_model_object/xlsx.xlsx +0 -0
  97. data/test/rails_app/tmp/controller_tests/alt_xlsx.xlsx +0 -0
  98. data/test/rails_app/tmp/controller_tests/csv.csv +1 -0
  99. data/test/rails_app/tmp/controller_tests/ods.ods +0 -0
  100. data/test/rails_app/tmp/controller_tests/xlsx.xlsx +0 -0
  101. data/test/rails_app/tmp/custom_posts/csv.csv +1 -0
  102. data/test/rails_app/tmp/custom_posts/empty.xlsx +0 -0
  103. data/test/rails_app/tmp/custom_posts/ods.ods +0 -0
  104. data/test/rails_app/tmp/custom_posts/xlsx.xlsx +0 -0
  105. data/test/rails_app/tmp/empty_model.csv +1 -0
  106. data/test/rails_app/tmp/empty_model.xlsx +0 -0
  107. data/test/rails_app/tmp/empty_sa.csv +0 -0
  108. data/test/rails_app/tmp/empty_sa.xlsx +0 -0
  109. data/test/rails_app/tmp/extreme.xlsx +0 -0
  110. data/test/rails_app/tmp/model.csv +1 -0
  111. data/test/rails_app/tmp/model.xlsx +0 -0
  112. data/test/rails_app/tmp/ods/empty_model.ods +0 -0
  113. data/test/rails_app/tmp/ods/empty_sa.ods +0 -0
  114. data/test/rails_app/tmp/ods/model.ods +0 -0
  115. data/test/rails_app/tmp/ods/model_options.ods +0 -0
  116. data/test/rails_app/tmp/ods/sa.ods +0 -0
  117. data/test/rails_app/tmp/options.csv +1 -0
  118. data/test/rails_app/tmp/plain_ruby_object/csv.csv +4 -0
  119. data/test/rails_app/tmp/plain_ruby_object/ods.ods +0 -0
  120. data/test/rails_app/tmp/plain_ruby_object/xlsx.xlsx +0 -0
  121. data/test/rails_app/tmp/posts/csv.csv +1 -0
  122. data/test/rails_app/tmp/posts/empty.xlsx +0 -0
  123. data/test/rails_app/tmp/posts/ods.ods +0 -0
  124. data/test/rails_app/tmp/posts/xlsx.xlsx +0 -0
  125. data/test/rails_app/tmp/sa.csv +4 -0
  126. data/test/rails_app/tmp/sa.xlsx +0 -0
  127. metadata +255 -21
  128. data/lib/spreadsheet_architect/axlsx_column_width_patch.rb +0 -13
  129. data/test/database.yml +0 -3
  130. data/test/helper.rb +0 -52
  131. data/test/tc_spreadsheet_architect.rb +0 -84
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ba54bf20a206113ae9aaa6f365d6ede5ce5da8e
4
- data.tar.gz: cf706a260a73b220b98516c644fcd03ed71f57a7
3
+ metadata.gz: 4d4000e6f14557a9a68ad0c48c9b0af57e537f50
4
+ data.tar.gz: 8d38d5252918e37378b38d98fac0ec73a85cd396
5
5
  SHA512:
6
- metadata.gz: 899a3edfe864b869c077e651d998be65fd0d7871e95f27c0160a0964312cee173caba47547af58cdbd939a1b26c431b37924589882c556180167aa4b529baecc
7
- data.tar.gz: 4fdff1744122edc359486e77b4e524a293e776f28e23e1708416837e02fa22fb1a224a5ce2d784d8cdc2537ad7d54dd44ce4c43ef93d6772bf523c7fce287605
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.12.2016**: 1.4.6
9
- - Fix ruby <= 2.1 hash syntax
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="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VKY8YAWAS5XRQ&lc=CA&item_name=Weston%20Ganger&item_number=spreadsheet_architect&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHostedGuest" target="_blank" title="Buy Me A Coffee"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" alt="Buy Me A Coffee"/></a>
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, or a Class/Model's spreadsheet_columns method, or one creation with 2D array of data
9
- - Plain Ruby support
10
- - Plain from ActiveRecord relations or Ruby Objects from models ActiveRecord, or 2d Array Data
11
- - Easily style headers and rows
12
- - Model/Class or Project specific defaults
13
- - Simple to use ActionController renderers
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
- gem install spreadsheet_architect
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 rescue nil)],
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.to_odf(instances: @posts) }
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 realtion
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
- # Method & Options
160
+ # Methods & Options
160
161
 
161
- <br>
162
- #### `.to_xlsx` - (on custom class/model)
163
- |Option|Type|Default|Notes|
164
- |---|---|---|---|
165
- |**spreadsheet_columns**|Array| AR Model column_names | Required if `spreadsheet_columns` not defined on class except with ActiveRecord models which default to the `column_names` method. Will override models `spreadsheet_columns` method |
166
- |**instances**|Array| |**Required for Non-ActiveRecord classes** Array of class/model instances.|
167
- |**headers**|Boolean|`true`|Pass false to skip the header row.|
168
- |**sheet_name**|String|Class name||
169
- |**header_style**|Hash|`{background_color: "AAAAAA", color: "FFFFFF", align: :center, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false}`||
170
- |**row_style**|Hash|`{background_color: nil, color: "FFFFFF", align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false, number_format_code: nil}`|Styles for non-header rows.|
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
- #### `.to_ods` - (on custom class/model)
174
- |Option|Type|Default|Notes|
175
- |---|---|---|---|
176
- |**spreadsheet_columns**|Array| AR Model column_names | Required if `spreadsheet_columns` not defined on class except with ActiveRecord models which default to the `column_names` method. Will override models `spreadsheet_columns` method |
177
- |**instances**|Array| |**Required for Non-ActiveRecord classes** Array of class/model instances.|
178
- |**headers**|Boolean|`true`|Pass false to skip the header row.|
179
- |**sheet_name**|String|Class name||
180
- |**header_style**|Hash|`{color: "000000", align: :center, font_size: 10, bold: true}`|Note: Currently only supports these options (values can be changed though)|
181
- |**row_style**|Hash|`{color: "000000", align: :left, font_size: 10, bold: false}`|Styles for non-header rows. Currently only supports these options (values can be changed though)|
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
- #### `.to_csv` - (on custom class/model)
185
- |Option|Type|Default|Notes|
186
- |---|---|---|---|
187
- |**spreadsheet_columns**|Array| AR Model column_names | Required if `spreadsheet_columns` not defined on class except with ActiveRecord models which default to the `column_names` method. Will override models `spreadsheet_columns` method |
188
- |**instances**|Array| |**Required for Non-ActiveRecord classes** Array of class/model instances.|
189
- |**headers**|Boolean|`true`|Pass false to skip the header row.|
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
- #### `SpreadsheetArchitect.to_xlsx`
193
- |Option|Type|Default|Notes|
194
- |---|---|---|---|
195
- |**data**|Array| |**Required** 2D Array of data for the non-header row cells. |
196
- |**headers**|Array|`false`|2D Array of data for the header rows cells. Pass false to skip the header row.|
197
- |**sheet_name**|String|`SpreadsheetArchitect`||
198
- |**header_style**|Hash|`{background_color: "AAAAAA", color: "FFFFFF", align: :center, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false}`||
199
- |**row_style**|Hash|`{background_color: nil, color: "FFFFFF", align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false, number_format_code: nil}`|Styles for non-header rows.|
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
- #### `SpreadsheetArchitect.to_ods`
203
- |Option|Type|Default|Notes|
204
- |---|---|---|---|
205
- |**data**|Array| |**Required** 2D Array of data for the non-header row cells.|
206
- |**headers**|Array|`false`|2D Array of data for the header rows cells. Pass false to skip the header row.|
207
- |**sheet_name**|String|`SpreadsheetArchitect`||
208
- |**header_style**|Hash|`{color: "000000", align: :center, font_size: 10, bold: true}`|Note: Currently only supports these options (values can be changed though)|
209
- |**row_style**|Hash|`{color: "000000", align: :left, font_size: 10, bold: false}`|Styles for non-header rows. Currently only supports these options (values can be changed though)|
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
- #### `SpreadsheetArchitect.to_csv`
213
- |Option|Type|Default|Notes|
214
- |---|---|---|---|
215
- |**data**|Array| |**Required** 2D Array of data for the non-header row cells.|
216
- |**headers**|Array|`false`|2D Array of data for the header rows cells. Pass false to skip the header row.|
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: true,
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: 'FFFFFF', align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
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.module_eval do
242
- const_set('SPREADSHEET_OPTIONS', {
243
- headers: true,
244
- header_style: {background_color: 'AAAAAA', color: 'FFFFFF', align: :center, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
245
- row_style: {background_color: nil, color: 'FFFFFF', align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
246
- sheet_name: 'My Project Export'
247
- })
248
- end
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
- # Format all numbers, money, or currency in xlsx only
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
- # Ex. dollar sign, comma's, and minumum two decimal places
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
- Would love for any help with new features for this projects. Some desired features are:
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="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VKY8YAWAS5XRQ&lc=CA&item_name=Weston%20Ganger&item_number=spreadsheet_architect&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHostedGuest" target="_blank" title="Buy Me A Coffee"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" alt="Buy Me A Coffee"/></a>
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/**/tc_*.rb']
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 AddProjectDefaultsGenerator < Rails::Generators::Base
4
+ class AddDefaultOptionsGenerator < Rails::Generators::Base
5
5
 
6
- def add_project_defaults
7
- create_file "config/initializers/spreadsheet_architect.rb", "SpreadsheetArchitect.module_eval do\n const_set('SPREADSHEET_OPTIONS', {\n headers: true,\n header_style: {background_color: 'AAAAAA', color: 'FFFFFF', align: :center, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},\n row_style: {background_color: nil, color: 'FFFFFF', align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},\n sheet_name: 'My Project Export'\n })\nend"
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/set_mime_types'
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
- module SpreadsheetArchitect
9
- def self.included(base)
10
- base.send :extend, ClassMethods
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
- if defined?(klass::SPREADSHEET_OPTIONS)
183
- sheet_name = options[:sheet_name] || klass::SPREADSHEET_OPTIONS[:sheet_name] || SpreadsheetArchitect::SPREADSHEET_OPTIONS[:sheet_name] || klass.name
184
- else
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
- SPREADSHEET_OPTIONS = {
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