spreadsheet_architect 4.1.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
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