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
@@ -0,0 +1,66 @@
1
+ module SpreadsheetArchitect
2
+ module Utils
3
+ module ODS
4
+
5
+ def self.get_cell_type(value, type=nil)
6
+ if type && !type.empty?
7
+ case type
8
+ when :hyperlink
9
+ return :string
10
+ when :date, :time
11
+ return :string
12
+ end
13
+
14
+ return type unless (type.respond_to?(:empty?) ? type.empty? : type.nil?)
15
+ end
16
+
17
+ if value.is_a?(Numeric)
18
+ type = :float
19
+ elsif value.respond_to?(:strftime)
20
+ type = :string
21
+ else
22
+ type = :string
23
+ end
24
+
25
+ return type
26
+ end
27
+
28
+ def self.convert_styles(styles={})
29
+ styles = {} unless styles.is_a?(Hash)
30
+ styles = SpreadsheetArchitect::Utils.stringify_keys(styles)
31
+
32
+ property_styles = {}
33
+
34
+ text_styles = {}
35
+ text_styles['font-weight'] = styles.delete('bold') ? 'bold' : styles.delete('font-weight')
36
+ text_styles['font-size'] = styles.delete('font_size') || styles.delete('font-size')
37
+ text_styles['font-style'] = styles.delete('italic') ? 'italic' : styles.delete('font-style')
38
+ if styles['underline']
39
+ styles.delete('underline')
40
+ text_styles['text-underline-style'] = 'solid'
41
+ text_styles['text-underline-type'] = 'single'
42
+ end
43
+ if styles['align']
44
+ text_styles['align'] = true
45
+ end
46
+ if styles['color'].respond_to?(:sub) && !styles['color'].empty?
47
+ text_styles['color'] = "##{styles.delete('color').sub('#','')}"
48
+ end
49
+ text_styles.delete_if{|_,v| v.nil?}
50
+ property_styles['text'] = text_styles
51
+
52
+ cell_styles = {}
53
+ styles['background_color'] ||= styles.delete('background-color')
54
+ if styles['background_color'].respond_to?(:sub) && !styles['background_color'].empty?
55
+ cell_styles['background-color'] = "##{styles.delete('background_color').sub('#','')}"
56
+ end
57
+
58
+ cell_styles.delete_if{|_,v| v.nil?}
59
+ property_styles['cell'] = cell_styles
60
+
61
+ return property_styles
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -3,7 +3,14 @@ module SpreadsheetArchitect
3
3
  module XLSX
4
4
 
5
5
  def self.get_type(value, type=nil)
6
- return type unless (type.respond_to?(:empty?) ? type.empty? : type.nil?)
6
+ if type && !type.empty?
7
+ case type
8
+ when :hyperlink
9
+ return :string
10
+ end
11
+
12
+ return type unless (type.respond_to?(:empty?) ? type.empty? : type.nil?)
13
+ end
7
14
 
8
15
  if value.is_a?(Numeric)
9
16
  if value.is_a?(Float) || value.is_a?(BigDecimal)
@@ -25,10 +32,30 @@ module SpreadsheetArchitect
25
32
  end
26
33
 
27
34
  def self.convert_styles_to_axlsx(styles={})
28
- styles = {} unless styles.is_a?(Hash)
35
+ if [nil, false, true].include?(styles)
36
+ return {}
37
+ end
29
38
 
30
39
  styles = SpreadsheetArchitect::Utils.symbolize_keys(styles)
31
40
 
41
+ ### BOOLEAN VALUES
42
+ if styles[:b].nil? && styles.has_key?(:bold)
43
+ styles[:b] = !!styles.delete(:bold)
44
+ end
45
+
46
+ if styles[:i].nil? && styles.has_key?(:italic)
47
+ styles[:i] = !!styles.delete(:italic)
48
+ end
49
+
50
+ if styles[:u].nil? && styles.has_key?(:underline)
51
+ styles[:u] = !!styles.delete(:underline)
52
+ end
53
+
54
+ ### OTHER VALUES
55
+ if styles[:sz].nil? && !styles[:font_size].nil?
56
+ styles[:sz] = styles.delete(:font_size)
57
+ end
58
+
32
59
  if styles[:fg_color].nil? && styles[:color] && styles[:color].respond_to?(:sub) && !styles[:color].empty?
33
60
  styles[:fg_color] = styles.delete(:color).sub('#','')
34
61
  end
@@ -37,7 +64,7 @@ module SpreadsheetArchitect
37
64
  styles[:bg_color] = styles.delete(:background_color).sub('#','')
38
65
  end
39
66
 
40
- if styles[:alignment].nil? && styles[:align]
67
+ if styles[:alignment].nil? && [:align, :valign, :wrap_text].any?{|k| styles.has_key?(k) }
41
68
  if styles[:align].is_a?(Hash)
42
69
  styles[:alignment] = {
43
70
  horizontal: styles[:align][:horizontal],
@@ -45,37 +72,29 @@ module SpreadsheetArchitect
45
72
  wrap_text: styles[:align][:wrap_text]
46
73
  }
47
74
  else
48
- styles[:alignment] = {horizontal: (styles.delete(:align) || nil) }
75
+ styles[:alignment] = {horizontal: styles.delete(:align), vertical: styles.delete(:valign), wrap_text: styles.delete(:wrap_text) }.compact
49
76
  end
50
-
51
- styles.delete(:align)
52
- end
53
-
54
- if styles[:b].nil?
55
- styles[:b] = styles.delete(:bold) || nil
56
- end
57
-
58
- if styles[:sz].nil?
59
- styles[:sz] = styles.delete(:font_size) || nil
60
- end
61
-
62
- if styles[:i].nil?
63
- styles[:i] = styles.delete(:italic) || nil
64
- end
65
-
66
- if styles[:u].nil?
67
- styles[:u] = styles.delete(:underline) || nil
68
77
  end
69
78
 
79
+ ### COMMENT SEEMS WRONG, TO BE RECONFIRMED
70
80
  ### If `:u` is false instead of nil, it may be incorrectly rendered as true in Excel
71
- if styles[:u] == false
72
- styles[:u] = nil
81
+ #if styles[:u] == false
82
+ # styles[:u] = nil
83
+ #end
84
+
85
+ ### ENSURE CLEANUP OF ALL ALIAS KEYS
86
+ [:bold, :font_size, :italic, :underline, :align, :valign, :wrap_text, :color, :background_color].each do |k|
87
+ styles.delete(k)
73
88
  end
74
89
 
75
- styles.delete_if{|k,v| v.nil?}
90
+ return styles
76
91
  end
77
92
 
78
- def self.range_hash_to_str(hash, num_columns, num_rows)
93
+ def self.range_hash_to_str(hash, num_columns, num_rows, use_zero_based_row_index: false)
94
+ if !hash.has_key?(:rows) && !hash.has_key?(:columns)
95
+ raise SpreadsheetArchitect::Exceptions::InvalidRangeError.new(:missing_range_keys, hash)
96
+ end
97
+
79
98
  case hash[:columns]
80
99
  when Integer
81
100
  start_col = end_col = COL_NAMES[hash[:columns]]
@@ -92,24 +111,34 @@ module SpreadsheetArchitect
92
111
  unless end_col.is_a?(String)
93
112
  end_col = COL_NAMES[end_col]
94
113
  end
95
- when :all
114
+ when :all, nil
96
115
  start_col = 'A'
97
116
  end_col = COL_NAMES[num_columns-1]
98
117
  else
99
- raise SpreadsheetArchitect::Exceptions::InvalidRangeStylesOptionError.new(:columns, hash)
118
+ raise SpreadsheetArchitect::Exceptions::InvalidRangeOptionError.new(:columns, hash)
100
119
  end
101
120
 
102
121
  case hash[:rows]
103
122
  when Integer
104
123
  start_row = end_row = hash[:rows]
124
+
125
+ if use_zero_based_row_index
126
+ start_row += 1
127
+ end_row += 1
128
+ end
105
129
  when Range
106
130
  start_row = hash[:rows].first
107
131
  end_row = hash[:rows].last
108
- when :all
132
+
133
+ if use_zero_based_row_index
134
+ start_row += 1
135
+ end_row += 1
136
+ end
137
+ when :all, nil
109
138
  start_row = 1
110
139
  end_row = num_rows
111
140
  else
112
- raise SpreadsheetArchitect::Exceptions::InvalidRangeStylesOptionError.new(:rows, hash)
141
+ raise SpreadsheetArchitect::Exceptions::InvalidRangeOptionError.new(:rows, hash)
113
142
  end
114
143
 
115
144
  range_str = "#{start_col}#{start_row}:#{end_col}#{end_row}"
@@ -129,11 +158,11 @@ module SpreadsheetArchitect
129
158
  end_col, end_row = back.scan(/\d+|\D+/)
130
159
 
131
160
  unless COL_NAMES.include?(start_col) && COL_NAMES.include?(end_col)
132
- raise SpreadsheetArchitect::Exceptions::InvalidRangeError.new(:columns, range)
161
+ raise SpreadsheetArchitect::Exceptions::InvalidRangeValue.new(:columns, range)
133
162
  end
134
163
 
135
164
  unless start_row.to_i <= num_rows && end_row.to_i <= num_rows
136
- raise SpreadsheetArchitect::Exceptions::InvalidRangeError.new(:rows, range)
165
+ raise SpreadsheetArchitect::Exceptions::InvalidRangeValue.new(:rows, range)
137
166
  end
138
167
  else
139
168
  raise SpreadsheetArchitect::Exceptions::InvalidRangeError.new(:format, range)
@@ -10,7 +10,9 @@ module SpreadsheetArchitect
10
10
  if options[:headers] == true
11
11
  headers = []
12
12
 
13
- if !options[:data]
13
+ if options[:data]
14
+ headers = false
15
+ else
14
16
  needs_headers = true
15
17
  end
16
18
  elsif options[:headers].is_a?(Array)
@@ -112,24 +114,22 @@ module SpreadsheetArchitect
112
114
  def self.get_options(options, klass)
113
115
  verify_option_types(options)
114
116
 
115
- if options[:freeze] && options[:freeze_headers]
116
- raise SpreadsheetArchitect::Exceptions::ArgumentError.new('Cannot use both :freeze and :freeze_headers options at the same time')
117
- end
118
-
119
- if defined?(klass::SPREADSHEET_OPTIONS)
120
- if klass::SPREADSHEET_OPTIONS.is_a?(Hash)
121
- options = SpreadsheetArchitect.default_options.merge(
122
- klass::SPREADSHEET_OPTIONS.merge(options)
123
- )
117
+ if !options[:skip_defaults]
118
+ if defined?(klass::SPREADSHEET_OPTIONS)
119
+ if klass::SPREADSHEET_OPTIONS.is_a?(Hash)
120
+ defaults = SpreadsheetArchitect.default_options.merge(klass::SPREADSHEET_OPTIONS)
121
+ else
122
+ raise SpreadsheetArchitect::Exceptions::OptionTypeError.new("#{klass}::SPREADSHEET_OPTIONS constant")
123
+ end
124
124
  else
125
- raise SpreadsheetArchitect::Exceptions::OptionTypeError.new("#{klass}::SPREADSHEET_OPTIONS constant")
125
+ defaults = SpreadsheetArchitect.default_options
126
126
  end
127
- else
128
- options = SpreadsheetArchitect.default_options.merge(options)
127
+
128
+ options = defaults.merge(options)
129
129
  end
130
130
 
131
131
  if !options[:headers]
132
- options[:header_style] = false
132
+ options.delete(:header_style)
133
133
  end
134
134
 
135
135
  if !options[:sheet_name]
@@ -144,47 +144,23 @@ module SpreadsheetArchitect
144
144
  end
145
145
  end
146
146
 
147
- if options[:freeze] && options[:freeze].is_a?(Hash) && !options[:freeze][:rows]
148
- raise SpreadsheetArchitect::Exceptions::ArgumentError.new('Must provide a :rows key when passing a hash to the :freeze option')
149
- end
147
+ if options[:freeze]
148
+ options[:freeze] = SpreadsheetArchitect::Utils.symbolize_keys(options[:freeze])
150
149
 
151
- return options
152
- end
153
-
154
- def self.convert_styles_to_ods(styles={})
155
- styles = {} unless styles.is_a?(Hash)
156
- styles = stringify_keys(styles)
157
-
158
- property_styles = {}
159
-
160
- text_styles = {}
161
- text_styles['font-weight'] = styles.delete('bold') ? 'bold' : styles.delete('font-weight')
162
- text_styles['font-size'] = styles.delete('font_size') || styles.delete('font-size')
163
- text_styles['font-style'] = styles.delete('italic') ? 'italic' : styles.delete('font-style')
164
- if styles['underline']
165
- styles.delete('underline')
166
- text_styles['text-underline-style'] = 'solid'
167
- text_styles['text-underline-type'] = 'single'
168
- end
169
- if styles['align']
170
- text_styles['align'] = true
171
- end
172
- if styles['color'].respond_to?(:sub) && !styles['color'].empty?
173
- text_styles['color'] = "##{styles.delete('color').sub('#','')}"
150
+ if options[:freeze_headers]
151
+ raise SpreadsheetArchitect::Exceptions::ArgumentError.new('Cannot use both :freeze and :freeze_headers options at the same time')
152
+ end
174
153
  end
175
- text_styles.delete_if{|_,v| v.nil?}
176
- property_styles['text'] = text_styles
177
-
178
- cell_styles = {}
179
- styles['background_color'] ||= styles.delete('background-color')
180
- if styles['background_color'].respond_to?(:sub) && !styles['background_color'].empty?
181
- cell_styles['background-color'] = "##{styles.delete('background_color').sub('#','')}"
154
+
155
+ if options[:escape_formulas].nil?
156
+ options[:escape_formulas] = true
182
157
  end
183
158
 
184
- cell_styles.delete_if{|_,v| v.nil?}
185
- property_styles['cell'] = cell_styles
159
+ if options[:use_zero_based_row_index].nil?
160
+ options[:use_zero_based_row_index] = false
161
+ end
186
162
 
187
- return property_styles
163
+ return options
188
164
  end
189
165
 
190
166
  private
@@ -284,11 +260,13 @@ module SpreadsheetArchitect
284
260
  instances: Array,
285
261
  merges: Array,
286
262
  range_styles: Array,
263
+ skip_defaults: [TrueClass, FalseClass],
287
264
  row_style: Hash,
288
265
  sheet_name: String,
289
266
  spreadsheet_columns: [Proc, Symbol, String],
267
+ escape_formulas: [TrueClass, FalseClass, Array],
268
+ use_zero_based_row_index: [TrueClass, FalseClass],
290
269
  }.freeze
291
270
 
292
-
293
271
  end
294
272
  end
@@ -1,3 +1,3 @@
1
1
  module SpreadsheetArchitect
2
- VERSION = "4.1.0"
2
+ VERSION = "5.0.0"
3
3
  end
@@ -4,6 +4,7 @@ require 'spreadsheet_architect/action_controller_renderers'
4
4
  require 'spreadsheet_architect/exceptions'
5
5
  require 'spreadsheet_architect/utils'
6
6
  require 'spreadsheet_architect/utils/xlsx'
7
+ require 'spreadsheet_architect/utils/ods'
7
8
 
8
9
  require 'spreadsheet_architect/class_methods/csv'
9
10
  require 'spreadsheet_architect/class_methods/ods'
@@ -35,7 +36,7 @@ module SpreadsheetArchitect
35
36
  @default_options
36
37
  end
37
38
 
38
- XLSX_COLUMN_TYPES = [:string, :integer, :float, :date, :time, :boolean].freeze
39
- ODS_COLUMN_TYPES = [:string, :float, :date, :time, :boolean].freeze
39
+ XLSX_COLUMN_TYPES = [:string, :integer, :float, :date, :time, :boolean, :hyperlink].freeze
40
+ ODS_COLUMN_TYPES = [:string, :float, :date, :time, :boolean, :hyperlink].freeze
40
41
 
41
42
  end
@@ -14,9 +14,12 @@ class SpreadsheetsController < ApplicationController
14
14
  render xlsx: Post.to_xlsx, filename: 'Posts'
15
15
  end
16
16
 
17
- def alt_xlsx
18
- @posts = Post.all
19
- respond_with @posts
17
+ def test_respond_with
18
+ if Rails::VERSION::MAJOR >= 5
19
+ @posts = Post.all
20
+
21
+ respond_with @posts
22
+ end
20
23
  end
21
24
 
22
25
  def test_xlsx
@@ -2,9 +2,6 @@ require File.expand_path('../boot', __FILE__)
2
2
 
3
3
  require 'rails/all'
4
4
 
5
- require 'axlsx'
6
- require 'axlsx_styler'
7
-
8
5
  Bundler.require
9
6
 
10
7
  require "spreadsheet_architect"
@@ -39,14 +36,6 @@ module Dummy
39
36
  # Configure sensitive parameters which will be filtered from the log file.
40
37
  config.filter_parameters += [:password]
41
38
 
42
- # Enable the asset pipeline
43
- config.assets.enabled = true
44
-
45
- config.assets.quiet = true
46
-
47
- # Version of your assets, change this if you want to expire all your assets
48
- config.assets.version = '1.0'
49
-
50
39
  config.generators.test_framework = false
51
40
  config.generators.helper = false
52
41
  config.generators.stylesheets = false
@@ -58,7 +47,10 @@ module Dummy
58
47
 
59
48
  if ActiveRecord.respond_to?(:gem_version)
60
49
  gem_version = ActiveRecord.gem_version
61
- if gem_version.to_s.starts_with?("5.2.")
50
+
51
+ if gem_version >= Gem::Version.new("7.0.0")
52
+ config.active_record.legacy_connection_handling = false
53
+ elsif gem_version.to_s.start_with?("5.2.")
62
54
  config.active_record.sqlite3.represent_boolean_as_integer = true
63
55
  end
64
56
  end
@@ -9,7 +9,7 @@ Dummy::Application.configure do
9
9
 
10
10
  # Configure static asset server for tests with Cache-Control for performance
11
11
  config.serve_static_files = true
12
- config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
12
+ config.public_file_server.enabled = true
13
13
 
14
14
  # Log error messages when you accidentally call methods on nil
15
15
  config.whiny_nils = true
@@ -2,5 +2,5 @@ Dummy::Application.routes.draw do
2
2
  get 'spreadsheets/csv', to: 'spreadsheets#csv'
3
3
  get 'spreadsheets/ods', to: 'spreadsheets#ods'
4
4
  get 'spreadsheets/xlsx', to: 'spreadsheets#xlsx'
5
- get 'spreadsheets/alt_xlsx', to: 'spreadsheets#alt_xlsx'
5
+ get 'spreadsheets/test_respond_with', to: 'spreadsheets#test_respond_with'
6
6
  end
@@ -1,4 +1,4 @@
1
- class AddPosts < ActiveRecord::Migration[5.0]
1
+ class AddPosts < ActiveRecord::Migration::Current
2
2
  def change
3
3
  create_table :posts do |t|
4
4
  t.string :name
Binary file