spreadsheet_architect 4.1.0 → 5.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 (219) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -16
  3. data/README.md +22 -25
  4. data/lib/spreadsheet_architect/class_methods/ods.rb +18 -8
  5. data/lib/spreadsheet_architect/class_methods/xlsx.rb +76 -32
  6. data/lib/spreadsheet_architect/exceptions.rb +30 -13
  7. data/lib/spreadsheet_architect/utils/ods.rb +66 -0
  8. data/lib/spreadsheet_architect/utils/xlsx.rb +61 -32
  9. data/lib/spreadsheet_architect/utils.rb +29 -51
  10. data/lib/spreadsheet_architect/version.rb +1 -1
  11. data/lib/spreadsheet_architect.rb +3 -2
  12. data/test/dummy_app/app/controllers/spreadsheets_controller.rb +6 -3
  13. data/test/dummy_app/config/application.rb +4 -12
  14. data/test/dummy_app/config/environments/test.rb +1 -1
  15. data/test/dummy_app/config/routes.rb +1 -1
  16. data/test/dummy_app/db/migrate/20170103234524_add_posts.rb +1 -1
  17. data/test/dummy_app/db/test.sqlite3 +0 -0
  18. data/test/dummy_app/log/test.log +82177 -58559
  19. data/test/dummy_app/tmp/2.0.1/integration/alt_xlsx.xlsx +0 -0
  20. data/test/dummy_app/tmp/2.0.1/integration/csv.csv +6 -0
  21. data/test/dummy_app/tmp/2.0.1/integration/ods.ods +0 -0
  22. data/test/dummy_app/tmp/2.0.1/integration/xlsx.xlsx +0 -0
  23. data/test/dummy_app/tmp/2.0.1/kitchen_sink.ods +0 -0
  24. data/test/dummy_app/tmp/2.0.1/kitchen_sink.xlsx +0 -0
  25. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/data.csv +3 -0
  26. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/data.ods +0 -0
  27. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/data.xlsx +0 -0
  28. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/empty.csv +1 -0
  29. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/empty.ods +0 -0
  30. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/empty.xlsx +0 -0
  31. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/instances.csv +6 -0
  32. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/instances.ods +0 -0
  33. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/instances.xlsx +0 -0
  34. data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/data.csv +3 -0
  35. data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/data.ods +0 -0
  36. data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/data.xlsx +0 -0
  37. data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/empty.csv +0 -0
  38. data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/empty.ods +0 -0
  39. data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/empty.xlsx +0 -0
  40. data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/instances.csv +6 -0
  41. data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/instances.ods +0 -0
  42. data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/instances.xlsx +0 -0
  43. data/test/dummy_app/tmp/2.0.1/models/CustomPost/data.csv +3 -0
  44. data/test/dummy_app/tmp/2.0.1/models/CustomPost/data.ods +0 -0
  45. data/test/dummy_app/tmp/2.0.1/models/CustomPost/data.xlsx +0 -0
  46. data/test/dummy_app/tmp/2.0.1/models/CustomPost/empty.csv +1 -0
  47. data/test/dummy_app/tmp/2.0.1/models/CustomPost/empty.ods +0 -0
  48. data/test/dummy_app/tmp/2.0.1/models/CustomPost/empty.xlsx +0 -0
  49. data/test/dummy_app/tmp/2.0.1/models/CustomPost/instances.csv +6 -0
  50. data/test/dummy_app/tmp/2.0.1/models/CustomPost/instances.ods +0 -0
  51. data/test/dummy_app/tmp/2.0.1/models/CustomPost/instances.xlsx +0 -0
  52. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/data.csv +3 -0
  53. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/data.ods +0 -0
  54. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/data.xlsx +0 -0
  55. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/empty.csv +1 -0
  56. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/empty.ods +0 -0
  57. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/empty.xlsx +0 -0
  58. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/instances.csv +6 -0
  59. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/instances.ods +0 -0
  60. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/instances.xlsx +0 -0
  61. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/data.csv +3 -0
  62. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/data.ods +0 -0
  63. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/data.xlsx +0 -0
  64. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/empty.csv +1 -0
  65. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/empty.ods +0 -0
  66. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/empty.xlsx +0 -0
  67. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/instances.csv +6 -0
  68. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/instances.ods +0 -0
  69. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/instances.xlsx +0 -0
  70. data/test/dummy_app/tmp/2.0.1/models/Post/data.csv +3 -0
  71. data/test/dummy_app/tmp/2.0.1/models/Post/data.ods +0 -0
  72. data/test/dummy_app/tmp/2.0.1/models/Post/data.xlsx +0 -0
  73. data/test/dummy_app/tmp/2.0.1/models/Post/empty.csv +0 -0
  74. data/test/dummy_app/tmp/2.0.1/models/Post/empty.ods +0 -0
  75. data/test/dummy_app/tmp/2.0.1/models/Post/empty.xlsx +0 -0
  76. data/test/dummy_app/tmp/2.0.1/models/Post/instances.csv +6 -0
  77. data/test/dummy_app/tmp/2.0.1/models/Post/instances.ods +0 -0
  78. data/test/dummy_app/tmp/2.0.1/models/Post/instances.xlsx +0 -0
  79. data/test/dummy_app/tmp/2.0.1/multi_sheet.ods +0 -0
  80. data/test/dummy_app/tmp/2.0.1/multi_sheet.xlsx +0 -0
  81. data/test/dummy_app/tmp/3.0.0.pre/integration/alt_xlsx.xlsx +0 -0
  82. data/test/dummy_app/tmp/3.0.0.pre/integration/csv.csv +5 -5
  83. data/test/dummy_app/tmp/3.0.0.pre/integration/ods.ods +0 -0
  84. data/test/dummy_app/tmp/3.0.0.pre/integration/xlsx.xlsx +0 -0
  85. data/test/dummy_app/tmp/3.0.0.pre/kitchen_sink.ods +0 -0
  86. data/test/dummy_app/tmp/3.0.0.pre/kitchen_sink.xlsx +0 -0
  87. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/data.csv +1 -1
  88. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/data.ods +0 -0
  89. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/data.xlsx +0 -0
  90. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/empty.ods +0 -0
  91. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/empty.xlsx +0 -0
  92. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/instances.csv +5 -5
  93. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/instances.ods +0 -0
  94. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/instances.xlsx +0 -0
  95. data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/data.csv +1 -1
  96. data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/data.ods +0 -0
  97. data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/data.xlsx +0 -0
  98. data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/empty.ods +0 -0
  99. data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/empty.xlsx +0 -0
  100. data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/instances.csv +5 -5
  101. data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/instances.ods +0 -0
  102. data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/instances.xlsx +0 -0
  103. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/data.csv +1 -1
  104. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/data.ods +0 -0
  105. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/data.xlsx +0 -0
  106. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/empty.ods +0 -0
  107. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/empty.xlsx +0 -0
  108. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/instances.csv +5 -5
  109. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/instances.ods +0 -0
  110. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/instances.xlsx +0 -0
  111. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/data.csv +1 -1
  112. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/data.ods +0 -0
  113. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/data.xlsx +0 -0
  114. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/empty.ods +0 -0
  115. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/empty.xlsx +0 -0
  116. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/instances.csv +5 -5
  117. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/instances.ods +0 -0
  118. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/instances.xlsx +0 -0
  119. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/data.csv +1 -1
  120. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/data.ods +0 -0
  121. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/data.xlsx +0 -0
  122. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/empty.csv +0 -1
  123. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/empty.ods +0 -0
  124. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/empty.xlsx +0 -0
  125. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/instances.csv +5 -5
  126. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/instances.ods +0 -0
  127. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/instances.xlsx +0 -0
  128. data/test/dummy_app/tmp/3.0.0.pre/models/Post/data.csv +1 -1
  129. data/test/dummy_app/tmp/3.0.0.pre/models/Post/data.ods +0 -0
  130. data/test/dummy_app/tmp/3.0.0.pre/models/Post/data.xlsx +0 -0
  131. data/test/dummy_app/tmp/3.0.0.pre/models/Post/empty.csv +1 -0
  132. data/test/dummy_app/tmp/3.0.0.pre/models/Post/empty.ods +0 -0
  133. data/test/dummy_app/tmp/3.0.0.pre/models/Post/empty.xlsx +0 -0
  134. data/test/dummy_app/tmp/3.0.0.pre/models/Post/instances.csv +5 -5
  135. data/test/dummy_app/tmp/3.0.0.pre/models/Post/instances.ods +0 -0
  136. data/test/dummy_app/tmp/3.0.0.pre/models/Post/instances.xlsx +0 -0
  137. data/test/dummy_app/tmp/3.0.0.pre/multi_sheet.ods +0 -0
  138. data/test/dummy_app/tmp/3.0.0.pre/multi_sheet.xlsx +0 -0
  139. data/test/dummy_app/tmp/axlsx-master/integration/alt_xlsx.xlsx +0 -0
  140. data/test/dummy_app/tmp/axlsx-master/integration/csv.csv +6 -0
  141. data/test/dummy_app/tmp/axlsx-master/integration/ods.ods +0 -0
  142. data/test/dummy_app/tmp/axlsx-master/integration/xlsx.xlsx +0 -0
  143. data/test/dummy_app/tmp/axlsx-master/kitchen_sink.ods +0 -0
  144. data/test/dummy_app/tmp/axlsx-master/kitchen_sink.xlsx +0 -0
  145. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/data.csv +4 -0
  146. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/data.ods +0 -0
  147. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/data.xlsx +0 -0
  148. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/empty.csv +1 -0
  149. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/empty.ods +0 -0
  150. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/empty.xlsx +0 -0
  151. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/instances.csv +6 -0
  152. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/instances.ods +0 -0
  153. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/instances.xlsx +0 -0
  154. data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/data.csv +4 -0
  155. data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/data.ods +0 -0
  156. data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/data.xlsx +0 -0
  157. data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/empty.csv +1 -0
  158. data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/empty.ods +0 -0
  159. data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/empty.xlsx +0 -0
  160. data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/instances.csv +6 -0
  161. data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/instances.ods +0 -0
  162. data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/instances.xlsx +0 -0
  163. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/data.csv +4 -0
  164. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/data.ods +0 -0
  165. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/data.xlsx +0 -0
  166. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/empty.csv +1 -0
  167. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/empty.ods +0 -0
  168. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/empty.xlsx +0 -0
  169. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/instances.csv +6 -0
  170. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/instances.ods +0 -0
  171. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/instances.xlsx +0 -0
  172. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/data.csv +4 -0
  173. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/data.ods +0 -0
  174. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/data.xlsx +0 -0
  175. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/empty.csv +1 -0
  176. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/empty.ods +0 -0
  177. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/empty.xlsx +0 -0
  178. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/instances.csv +6 -0
  179. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/instances.ods +0 -0
  180. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/instances.xlsx +0 -0
  181. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/data.csv +4 -0
  182. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/data.ods +0 -0
  183. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/data.xlsx +0 -0
  184. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/empty.csv +1 -0
  185. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/empty.ods +0 -0
  186. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/empty.xlsx +0 -0
  187. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/instances.csv +6 -0
  188. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/instances.ods +0 -0
  189. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/instances.xlsx +0 -0
  190. data/test/dummy_app/tmp/axlsx-master/models/Post/data.csv +4 -0
  191. data/test/dummy_app/tmp/axlsx-master/models/Post/data.ods +0 -0
  192. data/test/dummy_app/tmp/axlsx-master/models/Post/data.xlsx +0 -0
  193. data/test/dummy_app/tmp/axlsx-master/models/Post/empty.csv +1 -0
  194. data/test/dummy_app/tmp/axlsx-master/models/Post/empty.ods +0 -0
  195. data/test/dummy_app/tmp/axlsx-master/models/Post/empty.xlsx +0 -0
  196. data/test/dummy_app/tmp/axlsx-master/models/Post/instances.csv +6 -0
  197. data/test/dummy_app/tmp/axlsx-master/models/Post/instances.ods +0 -0
  198. data/test/dummy_app/tmp/axlsx-master/models/Post/instances.xlsx +0 -0
  199. data/test/dummy_app/tmp/axlsx-master/multi_sheet.ods +0 -0
  200. data/test/dummy_app/tmp/axlsx-master/multi_sheet.xlsx +0 -0
  201. data/test/integration/application_test.rb +8 -16
  202. data/test/models/all_models_test.rb +15 -19
  203. data/test/test_helper.rb +48 -9
  204. data/test/unit/ods/general_test.rb +121 -0
  205. data/test/unit/{formats_test.rb → rails/formats_test.rb} +1 -1
  206. data/test/unit/{exceptions_test.rb → spreadsheet_architect/exceptions_test.rb} +19 -15
  207. data/test/unit/{general_test.rb → spreadsheet_architect/spreadsheet_architect_test.rb} +3 -3
  208. data/test/unit/spreadsheet_architect/utils/ods_test.rb +58 -0
  209. data/test/unit/{xlsx_utils_test.rb → spreadsheet_architect/utils/xlsx_test.rb} +13 -21
  210. data/test/unit/{utils_test.rb → spreadsheet_architect/utils_test.rb} +15 -31
  211. data/test/unit/xlsx/freeze_test.rb +79 -0
  212. data/test/unit/xlsx/general_test.rb +199 -0
  213. metadata +395 -128
  214. data/test/dummy_app/config/environments/development.rb +0 -30
  215. data/test/dummy_app/config/environments/production.rb +0 -60
  216. data/test/unit/kitchen_sink_test.rb +0 -110
  217. data/test/unit/multi_sheet_test.rb +0 -29
  218. data/test/unit/regressions_test.rb +0 -11
  219. data/test/unit/xlsx_freeze_test.rb +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0e103cc275bf05dabe10a86cb7f74dcc4a412daa2328e607ca70d7af22ea40b
4
- data.tar.gz: 5799934cf9f9e177ca49ed33d749d01e535143cc18bf6990082b834fe6d9a6d5
3
+ metadata.gz: c88ecaffa3abed6ef127dc13d42c612ebf224c6d8552590d68ae544af2713f93
4
+ data.tar.gz: d0e864c2f50e99040f932da595b7270dd0e9c0161fc1189e6d99cb43126f6b5a
5
5
  SHA512:
6
- metadata.gz: cee7b3f8dfc727d63c1f84f06f94c1bf3eaf46283b15b698724a5d0f57d3ef39728838b5295376df6e112bbb3141579c6ebc4189e8af85bd82558abe0cbd2546
7
- data.tar.gz: 13c7e7db2193bb37be8911592e5eab725700e047dc8437c455adcad0ae8574f3187ac2d40412b82e706e90a286ec38b15be248c013b0fc5ed9db1d0c0b943e98
6
+ metadata.gz: dfc0caea596d57bd5aa88cd3b5ff3cebfca8b1299d1660e9995ca93837746d21420a90e0f427df9b3f8e73c13914a24b137572c005ee16fafdeeb6ddaf18b95d
7
+ data.tar.gz: c31f408e271453d46454e4f85ad2437a2539e39973186a8889c917a338f9e5f57f9ef3f3f28797955d61f8daa6a7100ffb46624ab3974c4bfd9273cc5cacba29
data/CHANGELOG.md CHANGED
@@ -1,14 +1,34 @@
1
1
  CHANGELOG
2
2
  ---------
3
3
 
4
- - **Unreleased**
4
+ - **Unreleased** - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v5.0.0...master)
5
5
  - Nothing yet
6
- - **4.1.0**
6
+
7
+ - **5.0.0** - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v4.2.0...v5.0.0)
8
+ - [#52](https://github.com/westonganger/spreadsheet_architect/pull/52) - Update to caxlsx v3.3.0+ which now contains the axlsx_styler code, so we drop the dependency on axlsx_styler
9
+ - [#38](https://github.com/westonganger/spreadsheet_architect/pull/38) - **Breaking Change** - Add `escape_formulas` option for xlsx spreadsheets. This is a breaking change because we default to `escape_formulas: true` whereas before there was no formula escaping at all. The reasoning for this breaking change is that creating spreadsheets where many of the fields contain direct user input are a large majority compared to use cases that involve formulas.
10
+ - [#39](https://github.com/westonganger/spreadsheet_architect/pull/39) - Add option `use_zero_based_row_index: true` (Default `false`) which allows you to use zero-based row indexes instead of the default 1-based row indexes. Recomended to set this option for the whole project. The original reason it was designed to be 1-based is because spreadsheet row numbers literally start with 1. However this tends to be unituitive for the developer because columns use zero based indexes because they use letter-based notation instead.
11
+ - [#40](https://github.com/westonganger/spreadsheet_architect/pull/40) - Improve argument handling for freeze option and add support for all Axlsx supported options for panes using the `:freeze` hash. See test case for example (./test/unit/xlsx_freeze_test.rb)
12
+ - [#42](https://github.com/westonganger/spreadsheet_architect/pull/42) - Improve exceptions and messages regarding invalid ranges
13
+ - [#45](https://github.com/westonganger/spreadsheet_architect/pull/45) - For `to_xlsx`, dont add empty header row when `header: true`
14
+ - [#44](https://github.com/westonganger/spreadsheet_architect/pull/44) - Add support for hyperlinks in XLSX and ODS
15
+ - [#49](https://github.com/westonganger/spreadsheet_architect/pulls/49) - Extracted some ODS methods from `SpreadsheetArchitect::Utils` to `SpreadsheetArchitect::Utils::ODS`
16
+ - [#51](https://github.com/westonganger/spreadsheet_architect/pulls/51) - Add Proc support to `:column_types`
17
+
18
+ - **4.2.0** - May 27, 2021 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v4.1.0...v4.2.0)
19
+ - Add option `:skip_defaults` which removes the defaults and default styles. Particularily useful for heavily customized spreadsheets where the default styles get in the way.
20
+ - Fix bug where styles werent being un-applied when using the `false` value.
21
+ - Add style aliases for `:valign` and `:wrap_text`
22
+ - Fix error with `headers: false`, previously had to use `headers: []`
23
+
24
+ - **4.1.0** - Nov 20, 2020 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v4.0.1...v4.1.0)
7
25
  - Raise ArgumentError when invalid option names are given
8
- - **4.0.1**
26
+
27
+ - **4.0.1** - Nov 20, 2020 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v4.0.0...v4.0.1)
9
28
  - Fix bug with `headers: false` where a blank header row is still added
10
29
  - Fix Bug for older version of `caxlsx` v2.0.2
11
- - **4.0.0**
30
+
31
+ - **4.0.0** - Mar 3, 2020 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v3.3.1...v4.0.0)
12
32
  - Switch to the `caxlsx` gem (Community Axlsx) from the legacy unmaintained `axlsx` gem. Axlsx has had a long history of being poorly maintained so this community gem improves the situation.
13
33
  - Require Ruby 2.3+
14
34
  - Ensure all options using Hash are automatically converted to symbol only hashes
@@ -16,29 +36,35 @@ CHANGELOG
16
36
  - Add XLSX option `:freeze_headers` to freeze the headers of your spreadsheet
17
37
  - Remove old Axlsx patch for column width
18
38
  - Backport new code for `string_width` calculations to Axlsx 3.0.1 and below.
19
- - **3.3.1**
39
+
40
+ - **3.3.1** - Dec 2, 2019 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v3.3.0...v3.3.1)
20
41
  - [Issue #30](https://github.com/westonganger/spreadsheet_architect/issues/30) - Fix duplicate constant warning for XLSX_COLUMN_TYPES
21
- - **3.3.0**
42
+
43
+ - **3.3.0** - Nov 28, 2019 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v3.2.1...v3.3.0)
22
44
  - Fix `:borders` option, was broken in v3.2.1
23
45
  - Fix bug when passing `false` to `:headers` option
24
46
  - Raise error when unsupported column type is passed
25
47
  - Remove claimed support for `:currency` and `:percent` for ODS spreadsheets as they were not working. PR Wanted.
26
- - **3.2.1** - April 10, 2019
48
+
49
+ - **3.2.1** - April 10, 2019 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v3.2.0...v3.2.1)
27
50
  - Fix bug when using `column_style` option with `include_header: true` & letter based column numbering
28
- - **3.2.0** - September 14, 2018
51
+
52
+ - **3.2.0** - September 14, 2018 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v3.1.0...v3.2.0)
29
53
  - Change implementation of `:column_styles` option to utilize `axlsx_styler` instead of the built-in axlsx `col_style` method. The reason for the switch is that `col_style` would overwrite all previously set styles. `axlsx_styler` already has the ability to add onto existing styles and is what is currently utilized by `range_styles`.
30
54
  - Date / Time formatting is now set per cell instead of on the entire column.
31
55
  - Default Date formatting for `xlsx` changed from `m/d/yyyy` to `yyyy-mm-dd`
32
56
  - Default Time/DateTime formatting for `xlsx` changed from `yyyy/m/d h:mm AM/PM` to `yyyy-mm-dd h:mm AM/PM`
33
57
  - Fix bug where the ActionController::Renderer `:filename` option was ignored when an AR::Relation passed directly to the renderer without first calling `to_#{format}`
34
- - **3.1.0** - August 19, 2018
58
+
59
+ - **3.1.0** - August 19, 2018 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v3.0.0...v3.1.0)
35
60
  - Add new option `:conditional_row_styles` to `to_xlsx`.
36
61
  - Add ability to pass an alternative method name as a Symbol/String to the `:spreadsheet_columns` option.
37
62
  - Replace all usage of the legacy method `instance_eval` with the proper method `send`.
38
63
  - [#23](https://github.com/westonganger/spreadsheet_architect/issues/23#issuecomment-412803761) - Fix bug where custom `columns_widths` in xlsx spreadsheets might not get set correctly.
39
64
  - All exceptions now inherit from the appropriate ruby core exception classes
40
65
  - `SpreadsheetArchitect::Exceptions::InvalidOptionError` renamed to `SpreadsheetArchitect::Exceptions::OptionTypeError`
41
- - **3.0.0** - July 6, 2018
66
+
67
+ - **3.0.0** - July 6, 2018 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v2.1.2...v3.0.0)
42
68
  - [#16](https://github.com/westonganger/spreadsheet_architect/issues/16) - Add ability to pass :instances option to SpreadsheetArchitect class methods
43
69
  - [#16](https://github.com/westonganger/spreadsheet_architect/issues/16) - Remove Plain Ruby syntax `Post.to_xlsx(instances: posts_array)` in favor of `SpreadsheetArchitect.to_xlsx(instance: posts_array)`. However, it may still work at this time if configured correctly.
44
70
  - Fix project-wide and model-level defaults before only `header_style`, `row_style`, & `sheet_name` were being utilized.
@@ -53,12 +79,15 @@ CHANGELOG
53
79
  - Remove all Rails generators `spreadsheet_architect:add_default_options`. No need since its just as easy to copy from the README
54
80
  - Major overhaul of test suite, add a ton more tests, for DRYness use resursion for tests when appropriate
55
81
  - Use appraisal to test various `axlsx` versions
56
- - **2.1.2** - July 6, 2018
82
+
83
+ - **2.1.2** - July 6, 2018 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v2.1.1...v2.1.2)
57
84
  - Fix bug where everything was underlined by default in Excel (LibreOffice was working correctly). For some reason, `false` in `:u` or `:underline` was incorrectly being treated as `true` but only within Excel. Now anytime `false` is encountered for either `:u` or `:underline` it is now converted to `nil`
58
85
  - Fix bug where empty xlsx spreadsheets were corrupt when trying to open with Excel (LibreOffice was working correctly). This only occured when containing no headers and empty `:data` option which resulted in a package with no sheets.
59
- - **2.1.1** - July 4, 2018
86
+
87
+ - **2.1.1** - July 4, 2018 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v2.1.0...v2.1.1)
60
88
  - [#18](https://github.com/westonganger/spreadsheet_architect/pull/18) - Fix controller bug when using an non-ActiveRecord ORM only within Rails
61
- - **2.1.0** - June 20, 2018
89
+
90
+ - **2.1.0** - June 20, 2018 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v2.0.2...v2.1.0)
62
91
  - [#15](https://github.com/westonganger/spreadsheet_architect/pull/15) - Improved the method symbolize_keys. This method did not work properly for nested objects.
63
92
  - [PR #15](https://github.com/westonganger/spreadsheet_architect/pull/15) - Added the ability to pass `:text_wrap` option within the `:alignment` style
64
93
  - Make axlsx styles higher precendence over Spreadsheet Architect style aliases
@@ -66,14 +95,17 @@ CHANGELOG
66
95
  - Due to [RODF bug](https://github.com/thiagoarrais/rodf/issues/19) convert all Date and Time cells to String in ODS spreadsheets
67
96
  - Improve test suite
68
97
  - Dont test against Ruby versions that Rails no longer supports. Gem code should remain compatible with Ruby 1.9.3.
69
- - **2.0.2** - July 14 2017
98
+
99
+ - **2.0.2** - July 14 2017 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v2.0.1...v2.0.2)
70
100
  - Fix bug with range styles rows option not counting headers
71
101
  - Fix bug with range styles rows :all option
72
- - **2.0.1** - February 16 2017
102
+
103
+ - **2.0.1** - February 16 2017 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v2.0.0...v2.0.1)
73
104
  - Fix bug where `SpreadsheetArchitect.default_options` and `SPREADSHEET_OPTIONS` were being overwritten
74
105
  - Fix bug where col_styles ignored previous styles on header when using `include_header` option
75
106
  - Errors now try to provide which value is the cause
76
- - **2.0.0** - January 28 2017
107
+
108
+ - **2.0.0** - January 28 2017 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v1.4.8...v2.0.0)
77
109
  - Add to xlsx: `merges`, `column_styles`, `range_styles`, `borders`, `column_widths` multi-row headers, date/time default format_code
78
110
  - Add `column_types` option for xlsx and ods
79
111
  - Add ability to make multi-sheet spreadsheets in XLSX & ODS
@@ -81,52 +113,74 @@ CHANGELOG
81
113
  - Add Examples
82
114
  - Add Axlsx Style Reference
83
115
  - Refractor into smaller files
116
+
84
117
  - **1.4.8** - December 6 2016
85
118
  - Lock `rodf` gem to v0.3.7 for last v1 version of this gem
119
+
86
120
  - **1.4.7** - November 7 2016
87
121
  - Fix method arguments for `to_rodf_spreadsheet` method
122
+
88
123
  - **1.4.6** - May 16 2016
89
124
  - Fix hash syntax for support of ruby v2.1 and below
125
+
90
126
  - **1.4.5** - May 4 2016
91
127
  - Bug fixes
128
+
92
129
  - **1.4.4** - May 3 2016
93
130
  - Add Ability to add format_code to all numbers body rows
131
+
94
132
  - **1.4.3** - May 3 2016
95
133
  - Bug fixes
134
+
96
135
  - **1.4.2** - May 3 2016
97
136
  - Add to_axlsx_package, to_rodf_spreadsheet methods for the item to be further manipulated. Ex. axlsx_styler
137
+
98
138
  - **1.4.1** - May 2 2016
99
139
  - Add rails generator for project defaults initializer
140
+
100
141
  - **1.4.0** - April 29 2016
101
142
  - Add to_xlsx, to_ods, & to_csv to SpreadsheetArchitect model for direct calling by passing in cell data
143
+
102
144
  - **1.3.0** - April 21 2016
103
145
  - Add ability to create class/model and project option defaults
146
+
104
147
  - **1.2.5** - March 25 2016
105
148
  - Fix each_with_index bug
149
+
106
150
  - **1.2.4** - March 24 2016
107
151
  - Fix cell type logic for symbol methods
152
+
108
153
  - **1.2.3** - March 20 2016
109
154
  - Fix cell type logic
155
+
110
156
  - **1.2.2** - March 19 2016
111
157
  - Make cell type numeric if value is numeric
158
+
112
159
  - **1.2.1** - March 13 2016
113
160
  - Better error reporting
114
161
  - Fix for Plain ruby models
162
+
115
163
  - **1.2.0** - March 10 2016
116
164
  - Fix Bug: first row data repeated for all records on custom values
165
+
117
166
  - **1.1.0** - March 3 2016
118
167
  - Breaking Change - Move spreadsheet_columns method from the class to the instance
119
168
  - Fix Bug: remove default underline on cells
169
+
120
170
  - **1.0.4** - March 1 2016
121
171
  - Extract helper methods to seperate module
122
172
  - Improve readme
173
+
123
174
  - **1.0.3** - March 1 2016
124
175
  - Fix/Improve renderers
125
176
  - Fix header default background color
126
177
  - Fix default columns
178
+
127
179
  - **1.0.2** - February 26 2016
128
180
  - Enhance Style options
181
+
129
182
  - **1.0.1** - February 26 2016
130
183
  - Fix bug in renderers
184
+
131
185
  - **1.0.0** - February 26 2016
132
186
  - Gem Initial Release
data/README.md CHANGED
@@ -1,9 +1,8 @@
1
1
  # Spreadsheet Architect
2
2
 
3
3
  <a href="https://badge.fury.io/rb/spreadsheet_architect" target="_blank"><img height="21" style='border:0px;height:21px;' border='0' src="https://badge.fury.io/rb/spreadsheet_architect.svg" alt="Gem Version"></a>
4
- <a href='https://travis-ci.com/westonganger/spreadsheet_architect' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://api.travis-ci.org/westonganger/spreadsheet_architect.svg?branch=master' border='0' alt='Build Status' /></a>
4
+ <a href='https://github.com/westonganger/spreadsheet_architect/actions' target='_blank'><img src="https://github.com/westonganger/spreadsheet_architect/workflows/Tests/badge.svg" style="max-width:100%;" height='21' style='border:0px;height:21px;' border='0' alt="CI Status"></a>
5
5
  <a href='https://rubygems.org/gems/spreadsheet_architect' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://ruby-gem-downloads-badge.herokuapp.com/spreadsheet_architect?label=rubygems&type=total&total_label=downloads&color=brightgreen' border='0' alt='RubyGems Downloads' /></a>
6
- <a href='https://ko-fi.com/A5071NK' target='_blank'><img height='22' style='border:0px;height:22px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=a' border='0' alt='Buy Me a Coffee' /></a>
7
6
 
8
7
  Spreadsheet Architect is a library that allows you to create XLSX, ODS, or CSV spreadsheets super easily from ActiveRecord relations, plain Ruby objects, or tabular data.
9
8
 
@@ -92,7 +91,7 @@ If you want to use a different method name then `spreadsheet_columns` you can pa
92
91
  Post.to_xlsx(instances: posts, spreadsheet_columns: :my_special_method)
93
92
  ```
94
93
 
95
- Alternatively, you can pass a Proc/lambda to the `spreadsheet_columns` option. For those purists that really dont want to define any extra `spreadsheet_columns` instance method on your model, this option can help you work with that methodology.
94
+ Alternatively, you can pass a Proc to the `spreadsheet_columns` option. For those purists that really dont want to define any extra `spreadsheet_columns` instance method on your model, this option can help you work with that methodology.
96
95
 
97
96
  ```ruby
98
97
  Post.to_xlsx(instances: posts, spreadsheet_columns: Proc.new{|instance|
@@ -104,7 +103,8 @@ Post.to_xlsx(instances: posts, spreadsheet_columns: Proc.new{|instance|
104
103
  :published_at, # uses the method name as header title Einstance. 'Published At'
105
104
  ['# of Views', :number_of_views, :float],
106
105
  ['Rating', :rating],
107
- ['Category/Tags', "#{instance.category.name} - #{instance.tags.collect(&:name).join(', ')}"]
106
+ ['Category/Tags', "#{instance.category.name} - #{instance.tags.collect(&:name).join(', ')}"],
107
+ ['URL', :url, (val.start_with?("http") ? :hyperlink : :string)],
108
108
  ]
109
109
  })
110
110
  ```
@@ -190,20 +190,16 @@ File.open('path/to/multi_sheet_file.xlsx', 'w+b') do |f|
190
190
  end
191
191
  ```
192
192
 
193
- See this file for more details: https://github.com/westonganger/spreadsheet_architect/blob/master/test/spreadsheet_architect/multi_sheet_test.rb
194
-
195
193
  ### ODS
196
194
  ```ruby
197
195
  ods_spreadsheet = SpreadsheetArchitect.to_rodf_spreadsheet({headers: headers, data: data})
198
196
  ods_spreadsheet = SpreadsheetArchitect.to_rodf_spreadsheet({headers: headers, data: data}, ods_spreadsheet)
199
197
 
200
198
  File.open('path/to/multi_sheet_file.ods', 'w+b') do |f|
201
- f.write ods_spreadsheet
199
+ f.write ods_spreadsheet.bytes
202
200
  end
203
201
  ```
204
202
 
205
- See this file for more details: https://github.com/westonganger/spreadsheet_architect/blob/master/test/spreadsheet_architect/multi_sheet_test.rb
206
-
207
203
  # Methods
208
204
 
209
205
  ## `to_xlsx(options={})`
@@ -215,17 +211,20 @@ See this file for more details: https://github.com/westonganger/spreadsheet_arch
215
211
  |**spreadsheet_columns**<br>*Proc/Symbol/String*| Use this option to override or define the spreadsheet columns. Normally, if this option is not specified and are using the instances option/ActiveRecord relation, it uses the classes custom `spreadsheet_columns` method or any custom defaults defined.<br>If neither of those and is an ActiveRecord model, then it will falls back to the models `self.column_names` | Cannot be used with the `:data` option.<br><br>If a Proc value is passed it will be evaluated on the instance object.<br><br>If a Symbol or String value is passed then it will search the instance for a method name that matches and call it. |
216
212
  |**headers**<br>*Array / 2D Array*| |Data for the header row cells. If using on a class/relation, this defaults to the ones provided via `spreadsheet_columns`. Pass `false` to skip the header row. |
217
213
  |**sheet_name**<br>*String*|`Sheet1`||
218
- |**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_style_reference.md)|
219
- |**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_style_reference.md)|
220
- |**column_styles**<br>*Array*||[See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/test/unit/kitchen_sink_test.rb)|
221
- |**range_styles**<br>*Array*||[See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/test/unit/kitchen_sink_test.rb)|
222
- |**conditional_row_styles**<br>*Array*||[See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/test/unit/kitchen_sink_test.rb). The if/unless proc will called with the following args: `row_index`, `row_data`|
223
- |**merges**<br>*Array*||Merge cells. [See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/test/unit/kitchen_sink_test.rb). Warning merges cannot overlap eachother, if you attempt to do so Excel will claim your spreadsheet is corrupt and refuse to open your spreadsheet.|
224
- |**borders**<br>*Array*||[See this example for usage](https://github.com/westonganger/spreadsheet_architect/blob/master/test/unit/kitchen_sink_test.rb)|
225
- |**column_types**<br>*Array*||Valid types for XLSX are :string, :integer, :float, :date, :time, :boolean, nil = auto determine.|
214
+ |**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](./docs/axlsx_style_reference.md)|
215
+ |**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](./docs/axlsx_style_reference.md)|
216
+ |**column_styles**<br>*Array*||[See this example for usage](./test/unit/kitchen_sink_test.rb)|
217
+ |**range_styles**<br>*Array*||[See this example for usage](./test/unit/kitchen_sink_test.rb)|
218
+ |**conditional_row_styles**<br>*Array*||[See this example for usage](./test/unit/kitchen_sink_test.rb). The if/unless proc will called with the following args: `row_index`, `row_data`|
219
+ |**merges**<br>*Array*||Merge cells. [See this example for usage](./test/unit/kitchen_sink_test.rb). Warning merges cannot overlap eachother, if you attempt to do so Excel will claim your spreadsheet is corrupt and refuse to open your spreadsheet.|
220
+ |**borders**<br>*Array*||[See this example for usage](./test/unit/kitchen_sink_test.rb)|
221
+ |**column_types**<br>*Array*||Valid types for XLSX are :string, :integer, :float, :date, :time, :boolean, :hyperlink, nil = auto determine. You may also pass a Proc which evaluates to any of the valid types, for example `->(cell_val){ cell_val.start_with?('http') ? :hyperlink : :string }`|
226
222
  |**column_widths**<br>*Array*||Sometimes you may want explicit column widths. Use nil if you want a column to autofit again.|
227
223
  |**freeze_headers**<br>*Boolean*||Make all header rows frozen/fixed so they do not scroll.|
228
- |**freeze**<br>* Hash*|`{rows: (1..4), columns: :all}`|Make all specified rows and columns frozen/fixed so they do not scroll.|
224
+ |**freeze**<br>*Hash*||Make all specified row and/or column frozen/fixed so they do not scroll. See [example usage](./test/unit/xlsx_freeze_test.rb)|
225
+ |**skip_defaults**<br>*Boolean*|`false`|Removes defaults and default styles. Particularily useful for heavily customized spreadsheets where the default styles get in the way.|
226
+ |**escape_formulas**<br>*Boolean* or *Array*|`true`|Pass a single boolean to apply to all cells, or an array of booleans to control column-by-column. Advisable to be set true when involved with untrusted user input. See [an example of the underlying functionality](https://github.com/caxlsx/caxlsx/blob/master/examples/escape_formula_example.md). NOTE: Header row cells are not escaped. |
227
+ |**use_zero_based_row_index**<br>*Boolean*|`false`|Allows you to use zero-based row indexes when defining `range_styles`, `merges`, etc. Recomended to set this option for the whole project rather than per call. The original reason it was designed to be 1-based is because spreadsheet row numbers actually start with 1.|
229
228
 
230
229
  ## `to_axlsx_spreadsheet(options={}, axlsx_package_to_join=nil)`
231
230
  Same options as `to_xlsx`
@@ -241,7 +240,8 @@ Same options as `to_xlsx`
241
240
  |**sheet_name**<br>*String*|`Sheet1`||
242
241
  |**header_style**<br>*Hash*|`{background_color: "AAAAAA", color: "FFFFFF", align: :center, font_size: 10, bold: true}`|Note: Currently ODS only supports these options|
243
242
  |**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|
244
- |**column_types**<br>*Array*||Valid types for ODS are :string, :float, :date, :time, :boolean, nil = auto determine. Due to [RODF Issue #19](https://github.com/thiagoarrais/rodf/issues/19), :date/:time will be converted to :string |
243
+ |**column_types**<br>*Array*||Valid types for ODS are :string, :float, :date, :time, :boolean, :hyperlink, nil = auto determine. Due to [RODF Issue #19](https://github.com/thiagoarrais/rodf/issues/19), :date/:time will be converted to :string. You may also pass a Proc which evaluates to any of the valid types, for example `->(cell_val){ cell_val.start_with?('http') ? :hyperlink : :string }` |
244
+ |**skip_defaults**<br>*Boolean*|`false`|Skip defaults and default styles. Particularily useful for heavily customized spreadsheets where the default styles get in the way.|
245
245
 
246
246
  ## `to_rodf_spreadsheet(options={}, spreadsheet_to_join=nil)`
247
247
  Same options as `to_ods`
@@ -302,15 +302,16 @@ SpreadsheetArchitect.default_options = {
302
302
  merges: [],
303
303
  borders: [],
304
304
  column_types: [],
305
+ use_zero_based_row_index: false,
305
306
  }
306
307
  ```
307
308
 
308
309
  # Kitchen Sink Examples with Styling for XLSX and ODS
309
- See this example: https://github.com/westonganger/spreadsheet_architect/blob/master/test/unit/kitchen_sink_test.rb
310
+ See this example: [test/unit/kitchen_sink_test.rb](./test/unit/kitchen_sink_test.rb)
310
311
 
311
312
  # Axlsx Style Reference
312
313
 
313
- I have compiled a list of all available style options for axlsx here: https://github.com/westonganger/spreadsheet_architect/blob/master/docs/axlsx_style_reference.md
314
+ I have compiled a list of all available style options for axlsx here: [docs/axlsx_style_reference.md](./docs/axlsx_style_reference.md)
314
315
 
315
316
  # Testing / Validating your Spreadsheets
316
317
 
@@ -328,7 +329,3 @@ At this time the spreadsheets generated by the test suite are manually inspected
328
329
  # Credits
329
330
 
330
331
  Created & Maintained by [Weston Ganger](https://westonganger.com) - [@westonganger](https://github.com/westonganger)
331
-
332
- For any consulting or contract work please contact me via my company website: [Solid Foundation Web Development](https://solidfoundationwebdev.com)
333
-
334
- [![Solid Foundation Web Development Logo](https://solidfoundationwebdev.com/logo-sm.png)](https://solidfoundationwebdev.com)
@@ -11,7 +11,7 @@ module SpreadsheetArchitect
11
11
  opts = SpreadsheetArchitect::Utils.get_options(opts, self)
12
12
  options = SpreadsheetArchitect::Utils.get_cell_data(opts, self)
13
13
 
14
- if options[:column_types] && !(options[:column_types].compact.collect(&:to_sym) - SpreadsheetArchitect::ODS_COLUMN_TYPES).empty?
14
+ if options[:column_types] && !(options[:column_types].compact.reject{|x| x.is_a?(Proc) }.collect(&:to_sym) - SpreadsheetArchitect::ODS_COLUMN_TYPES).empty?
15
15
  raise SpreadsheetArchitect::Exceptions::ArgumentError.new("Invalid column type. Valid ODS values are #{SpreadsheetArchitect::ODS_COLUMN_TYPES}")
16
16
  end
17
17
 
@@ -21,7 +21,7 @@ module SpreadsheetArchitect
21
21
 
22
22
  spreadsheet.office_style :header_style, family: :cell do
23
23
  if options[:header_style]
24
- SpreadsheetArchitect::Utils.convert_styles_to_ods(options[:header_style]).each do |prop, styles|
24
+ SpreadsheetArchitect::Utils::ODS.convert_styles(options[:header_style]).each do |prop, styles|
25
25
  styles.each do |k,v|
26
26
  property prop.to_sym, k => v
27
27
  end
@@ -31,7 +31,7 @@ module SpreadsheetArchitect
31
31
 
32
32
  spreadsheet.office_style :row_style, family: :cell do
33
33
  if options[:row_style]
34
- SpreadsheetArchitect::Utils.convert_styles_to_ods(options[:row_style]).each do |prop, styles|
34
+ SpreadsheetArchitect::Utils::ODS.convert_styles(options[:row_style]).each do |prop, styles|
35
35
  styles.each do |k,v|
36
36
  property prop.to_sym, k => v
37
37
  end
@@ -54,15 +54,25 @@ module SpreadsheetArchitect
54
54
  row do
55
55
  row_data.each_with_index do |val, i|
56
56
  if options[:column_types]
57
- type = options[:column_types][i]
57
+ provided_column_type = options[:column_types][i]
58
+
59
+ if provided_column_type.is_a?(Proc)
60
+ provided_column_type = provided_column_type.call(val)
61
+ end
58
62
  end
59
63
 
60
- if (type && [:date, :time].include?(type)) || val.respond_to?(:strftime)
61
- type = :string
62
- val = val.to_s
64
+ type = SpreadsheetArchitect::Utils::ODS.get_cell_type(val, provided_column_type)
65
+
66
+ cell_opts = {
67
+ style: :row_style,
68
+ type: type,
69
+ }
70
+
71
+ if provided_column_type == :hyperlink
72
+ cell_opts[:url] = val
63
73
  end
64
74
 
65
- cell val, style: :row_style, type: type
75
+ cell(val, **cell_opts)
66
76
  end
67
77
  end
68
78
  end
@@ -1,5 +1,4 @@
1
1
  require 'axlsx'
2
- require 'axlsx_styler'
3
2
 
4
3
  require 'spreadsheet_architect/axlsx_string_width_patch'
5
4
 
@@ -14,7 +13,7 @@ module SpreadsheetArchitect
14
13
  opts = SpreadsheetArchitect::Utils.get_options(opts, self)
15
14
  options = SpreadsheetArchitect::Utils.get_cell_data(opts, self)
16
15
 
17
- if options[:column_types] && !(options[:column_types].compact.collect(&:to_sym) - SpreadsheetArchitect::XLSX_COLUMN_TYPES).empty?
16
+ if options[:column_types] && !(options[:column_types].compact.reject{|x| x.is_a?(Proc) }.collect(&:to_sym) - SpreadsheetArchitect::XLSX_COLUMN_TYPES).empty?
18
17
  raise SpreadsheetArchitect::Exceptions::ArgumentError.new("Invalid column type. Valid XLSX values are #{SpreadsheetArchitect::XLSX_COLUMN_TYPES}")
19
18
  end
20
19
 
@@ -79,16 +78,27 @@ module SpreadsheetArchitect
79
78
 
80
79
  types = []
81
80
  styles = []
82
- row_data.each_with_index do |x,i|
83
- if (x.respond_to?(:empty) ? x.empty? : x.nil?)
81
+ hyperlink_cell_indexes = []
82
+
83
+ row_data.each_with_index do |val,i|
84
+ if (val.respond_to?(:empty) ? val.empty? : val.nil?)
84
85
  types[i] = nil
85
86
  styles[i] = row_style_index
86
87
  else
87
88
  if options[:column_types]
88
- types[i] = options[:column_types][i]
89
+ provided_column_type = options[:column_types][i]
90
+
91
+ if provided_column_type.is_a?(Proc)
92
+ provided_column_type = provided_column_type.call(val)
93
+ end
89
94
  end
90
95
 
91
- types[i] ||= SpreadsheetArchitect::Utils::XLSX.get_type(x)
96
+ if provided_column_type == :hyperlink
97
+ hyperlink_cell_indexes << i
98
+ row_data[i] = val.to_s
99
+ end
100
+
101
+ types[i] = SpreadsheetArchitect::Utils::XLSX.get_type(val, provided_column_type)
92
102
 
93
103
  if [:date, :time].include?(types[i])
94
104
  if types[i] == :date
@@ -104,7 +114,12 @@ module SpreadsheetArchitect
104
114
  end
105
115
  end
106
116
 
107
- sheet.add_row row_data, style: styles, types: types
117
+ sheet.add_row row_data, style: styles, types: types, escape_formulas: options[:escape_formulas]
118
+
119
+ hyperlink_cell_indexes.each do |cell_index|
120
+ cell_ref = "#{SpreadsheetArchitect::Utils::XLSX::COL_NAMES[cell_index]}#{row_index+1}"
121
+ sheet.add_hyperlink location: row_data[cell_index], ref: cell_ref
122
+ end
108
123
 
109
124
  if options[:conditional_row_styles]
110
125
  options[:conditional_row_styles] = SpreadsheetArchitect::Utils.hash_array_symbolize_keys(options[:conditional_row_styles])
@@ -133,12 +148,12 @@ module SpreadsheetArchitect
133
148
 
134
149
  options[:borders].each do |x|
135
150
  if x[:range].is_a?(Hash)
136
- x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows)
151
+ x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows, use_zero_based_row_index: options[:use_zero_based_row_index])
137
152
  else
138
153
  SpreadsheetArchitect::Utils::XLSX.verify_range(x[:range], num_rows)
139
154
  end
140
155
 
141
- sheet.add_border x[:range], (x[:border_styles] || x[:styles])
156
+ sheet.add_border x[:range], (x[:border_styles] || x[:styles] || Axlsx::Border::EDGES)
142
157
  end
143
158
  end
144
159
 
@@ -182,7 +197,7 @@ module SpreadsheetArchitect
182
197
  styles = SpreadsheetArchitect::Utils::XLSX.convert_styles_to_axlsx(x[:styles])
183
198
 
184
199
  if x[:range].is_a?(Hash)
185
- x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows)
200
+ x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows, use_zero_based_row_index: options[:use_zero_based_row_index])
186
201
  else
187
202
  SpreadsheetArchitect::Utils::XLSX.verify_range(x[:range], num_rows)
188
203
  end
@@ -196,7 +211,7 @@ module SpreadsheetArchitect
196
211
 
197
212
  options[:merges].each do |x|
198
213
  if x[:range].is_a?(Hash)
199
- x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows)
214
+ x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows, use_zero_based_row_index: options[:use_zero_based_row_index])
200
215
  else
201
216
  SpreadsheetArchitect::Utils::XLSX.verify_range(x[:range], num_rows)
202
217
  end
@@ -212,33 +227,62 @@ module SpreadsheetArchitect
212
227
  end
213
228
 
214
229
  elsif options[:freeze]
215
- options[:freeze] = SpreadsheetArchitect::Utils.symbolize_keys(options[:freeze])
230
+ case options[:freeze][:type].to_s
231
+ when "split_panes"
232
+ options[:freeze][:state] == "split"
233
+ when "frozen", "freeze"
234
+ options[:freeze][:state] == "frozen"
235
+ end
236
+
237
+ if options[:freeze][:rows]
238
+ options[:freeze][:row] ||= options[:freeze][:rows]
239
+ end
240
+
241
+ if options[:freeze][:columns]
242
+ options[:freeze][:column] ||= options[:freeze][:columns]
243
+ end
244
+
245
+ if options[:freeze][:row] == :all
246
+ options[:freeze][:row] = nil
247
+ elsif options[:freeze][:row].is_a?(Range)
248
+ options[:freeze][:row] = options[:freeze][:row].last
249
+ end
250
+
251
+ if options[:freeze][:column] == :all
252
+ options[:freeze][:column] = nil
253
+ elsif options[:freeze][:column].is_a?(Range)
254
+ options[:freeze][:column] = options[:freeze][:column].last
255
+ end
256
+
257
+ if !options[:freeze][:row] && !options[:freeze][:column]
258
+ raise SpreadsheetArchitect::Exceptions::ArgumentError.new("Missing required :row or :column value in the :freeze option hash")
259
+ elsif options[:freeze][:row] && !options[:freeze][:row].is_a?(Integer)
260
+ raise SpreadsheetArchitect::Exceptions::ArgumentError.new("Invalid :row value provided for in :freeze option hash, must be an Integer")
261
+ elsif options[:freeze][:column] && !options[:freeze][:column].is_a?(Integer)
262
+ raise SpreadsheetArchitect::Exceptions::ArgumentError.new("Invalid :column value provided for in :freeze option hash, must be an Integer")
263
+ end
216
264
 
217
265
  sheet.sheet_view.pane do |pane|
218
- pane.state = :frozen
266
+ pane.state = (options[:freeze][:state] || :frozen).to_sym ### Other options are :split and :frozen_split
219
267
 
220
- ### Currently not working
221
- #if options[:freeze][:active_pane]
222
- # Axlsx.validate_pane_type(options[:freeze][:active_pane])
223
- # pane.active_pane = options[:freeze][:active_pane]
224
- #else
225
- # pane.active_pane = :bottom_right
226
- #end
227
-
228
- if !options[:freeze][:rows]
229
- raise SpreadsheetArchitect::Exceptions::ArgumentError.new("The :rows key must be specified in the :freeze option hash")
230
- elsif options[:freeze][:rows].is_a?(Range)
231
- pane.y_split = options[:freeze][:rows].count
232
- else
233
- pane.y_split = 1
268
+ if options[:freeze][:active_pane]
269
+ pane.active_pane = options[:freeze][:active_pane].to_sym
234
270
  end
235
271
 
236
- if options[:freeze][:columns] && options[:freeze][:columns] != :all
237
- if options[:freeze][:columns].is_a?(Range)
238
- pane.x_split = options[:freeze][:columns].count
239
- else
240
- pane.x_split = 1
272
+ if options[:freeze][:top_left_cell]
273
+ pane.top_left_cell = options[:freeze][:top_left_cell]
274
+ end
275
+
276
+ if options[:freeze][:row]
277
+ if options[:use_zero_based_row_index]
278
+ options[:freeze][:row] += 1
241
279
  end
280
+
281
+ pane.y_split = options[:freeze][:row]
282
+ end
283
+
284
+ if options[:freeze][:column]
285
+ pane.x_split = options[:freeze][:column]
242
286
  end
243
287
  end
244
288
  end
@@ -14,17 +14,27 @@ module SpreadsheetArchitect
14
14
  end
15
15
 
16
16
  class InvalidRangeError < ArgumentError
17
- def initialize(type, range)
18
- case type
19
- when :columns, :rows
20
- super("Invalid range `#{range}` passed. Some of the #{type} specified were greater than the total number of #{type}")
21
- when :format
22
- super("Invalid range `#{range}` passed. Format must be as follows: A1:D4")
23
- when :type
24
- super("Invalid range type `#{range}`. Valid types are String and Hash")
25
- else
26
- super("Invalid range `#{range}` passed.")
17
+ def initialize(type, range, message: nil)
18
+ default_msg = "Invalid range `#{range}` passed"
19
+
20
+ if message.nil?
21
+ case type
22
+ when :missing_range_keys
23
+ message = "Missing :rows or :columns key"
24
+ when :format
25
+ message = "Format must be as follows: A1:D4"
26
+ when :type
27
+ message = "Valid types are Hash and String"
28
+ end
27
29
  end
30
+
31
+ super([default_msg, message].compact.join(". "))
32
+ end
33
+ end
34
+
35
+ class InvalidRangeValue < ArgumentError
36
+ def initialize(type, range)
37
+ super("Invalid range `#{range}` passed. Some of the :#{type} specified are either an invalid value or are greater than the total number of #{type}")
28
38
  end
29
39
  end
30
40
 
@@ -34,9 +44,16 @@ module SpreadsheetArchitect
34
44
  end
35
45
  end
36
46
 
37
- class InvalidRangeStylesOptionError < ArgumentError
38
- def initialize(type, opt)
39
- super("Invalid or missing :#{type} option for `#{opt}`. :#{type} can be an integer, range, or :all")
47
+ class InvalidRangeOptionError < ArgumentError
48
+ def initialize(key, opt)
49
+ default_msg = "Invalid :#{key} option for `#{opt}`"
50
+
51
+ case key
52
+ when :columns, :rows
53
+ message = ":#{key} can be an integer, range, or :all"
54
+ end
55
+
56
+ super([default_msg, message].compact.join(". "))
40
57
  end
41
58
  end
42
59