spreadsheet_architect 2.1.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +17 -2
- data/README.md +149 -129
- data/lib/spreadsheet_architect/class_methods/csv.rb +2 -2
- data/lib/spreadsheet_architect/class_methods/ods.rb +2 -2
- data/lib/spreadsheet_architect/class_methods/xlsx.rb +26 -30
- data/lib/spreadsheet_architect/exceptions.rb +32 -30
- data/lib/spreadsheet_architect/utils/xlsx.rb +46 -25
- data/lib/spreadsheet_architect/utils.rb +116 -121
- data/lib/spreadsheet_architect/version.rb +1 -1
- data/lib/spreadsheet_architect.rb +5 -1
- data/test/dummy_app/app/models/active_model_object.rb +1 -0
- data/test/dummy_app/app/models/custom_post.rb +1 -0
- data/test/dummy_app/app/models/legacy_plain_ruby_object.rb +14 -0
- data/test/dummy_app/app/models/plain_ruby_object.rb +2 -9
- data/test/dummy_app/app/models/post.rb +3 -0
- data/test/dummy_app/config/routes.rb +4 -5
- data/test/dummy_app/db/test.sqlite3 +0 -0
- data/test/dummy_app/log/test.log +26911 -21739
- data/test/dummy_app/tmp/2.0.1/integration/alt_xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/integration/csv.csv +6 -0
- data/test/dummy_app/tmp/2.0.1/integration/ods.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/integration/xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/kitchen_sink.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/kitchen_sink.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/data.csv +3 -0
- data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/data.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/data.xlsx +0 -0
- data/test/dummy_app/tmp/{empty_sa.csv → 2.0.1/models/ActiveModelObject/empty.csv} +0 -0
- data/test/dummy_app/tmp/{ods/empty_model.ods → 2.0.1/models/ActiveModelObject/empty.ods} +0 -0
- data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/empty.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/instances.csv +6 -0
- data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/instances.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/instances.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomPost/data.csv +3 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomPost/data.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomPost/data.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomPost/empty.csv +1 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomPost/empty.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomPost/empty.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomPost/instances.csv +6 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomPost/instances.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomPost/instances.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/data.csv +3 -0
- data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/data.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/data.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/empty.csv +1 -0
- data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/empty.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/empty.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/instances.csv +6 -0
- data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/instances.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/instances.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/data.csv +3 -0
- data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/data.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/data.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/empty.csv +0 -0
- data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/empty.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/empty.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/instances.csv +6 -0
- data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/instances.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/instances.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/Post/data.csv +3 -0
- data/test/dummy_app/tmp/2.0.1/models/Post/data.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/Post/data.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/Post/empty.csv +0 -0
- data/test/dummy_app/tmp/2.0.1/models/Post/empty.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/Post/empty.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/data.csv +3 -0
- data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/data.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/data.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/empty.csv +0 -0
- data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/empty.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/empty.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/multi_sheet.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/multi_sheet.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/integration/alt_xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/integration/csv.csv +6 -0
- data/test/dummy_app/tmp/3.0.0.pre/integration/ods.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/integration/xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/kitchen_sink.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/kitchen_sink.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/data.csv +3 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/data.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/data.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/empty.csv +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/empty.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/empty.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/instances.csv +6 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/instances.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/instances.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/data.csv +3 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/data.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/data.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/empty.csv +1 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/empty.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/empty.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/instances.csv +6 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/instances.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/instances.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/data.csv +3 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/data.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/data.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/empty.csv +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/empty.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/empty.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/instances.csv +6 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/instances.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/instances.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/data.csv +3 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/data.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/data.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/empty.csv +1 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/empty.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/empty.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/instances.csv +6 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/instances.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/instances.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/Post/data.csv +3 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/Post/data.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/Post/data.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/Post/empty.csv +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/Post/empty.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/Post/empty.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/data.csv +3 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/data.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/data.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/empty.csv +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/empty.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/empty.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/multi_sheet.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/multi_sheet.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/integration/alt_xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/integration/csv.csv +6 -0
- data/test/dummy_app/tmp/axlsx-master/integration/ods.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/integration/xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/kitchen_sink.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/kitchen_sink.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/data.csv +3 -0
- data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/data.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/data.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/empty.csv +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/empty.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/empty.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/instances.csv +6 -0
- data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/instances.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/instances.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomPost/data.csv +3 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomPost/data.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomPost/data.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomPost/empty.csv +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomPost/empty.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomPost/empty.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomPost/instances.csv +6 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomPost/instances.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomPost/instances.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/data.csv +3 -0
- data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/data.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/data.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/empty.csv +1 -0
- data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/empty.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/empty.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/instances.csv +6 -0
- data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/instances.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/instances.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/data.csv +3 -0
- data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/data.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/data.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/empty.csv +1 -0
- data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/empty.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/empty.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/instances.csv +6 -0
- data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/instances.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/instances.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/Post/data.csv +3 -0
- data/test/dummy_app/tmp/axlsx-master/models/Post/data.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/Post/data.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/Post/empty.csv +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/Post/empty.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/Post/empty.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/data.csv +3 -0
- data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/data.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/data.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/empty.csv +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/empty.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/empty.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/multi_sheet.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/multi_sheet.xlsx +0 -0
- data/test/integration/application_test.rb +8 -11
- data/test/models/all_models_test.rb +107 -0
- data/test/test_helper.rb +13 -4
- data/test/unit/exceptions_test.rb +168 -0
- data/test/unit/formats_test.rb +15 -0
- data/test/unit/general_test.rb +15 -0
- data/test/unit/kitchen_sink_test.rb +87 -0
- data/test/unit/multi_sheet_test.rb +29 -0
- data/test/unit/utils_test.rb +179 -0
- data/test/unit/xlsx_utils_test.rb +143 -0
- metadata +409 -116
- data/lib/generators/spreadsheet_architect/add_project_defaults_generator.rb +0 -20
- data/test/dummy_app/app/models/bad_plain_ruby_object.rb +0 -3
- data/test/dummy_app/app/views/reports/sample.html.erb +0 -1
- data/test/dummy_app/log/development.log +0 -28
- data/test/dummy_app/tmp/active_model_object/csv.csv +0 -21
- data/test/dummy_app/tmp/active_model_object/ods.ods +0 -0
- data/test/dummy_app/tmp/active_model_object/xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/custom_posts/csv.csv +0 -6
- data/test/dummy_app/tmp/custom_posts/empty.xlsx +0 -0
- data/test/dummy_app/tmp/custom_posts/ods.ods +0 -0
- data/test/dummy_app/tmp/custom_posts/xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/empty_model.csv +0 -1
- data/test/dummy_app/tmp/empty_model.xlsx +0 -0
- data/test/dummy_app/tmp/empty_sa.xlsx +0 -0
- data/test/dummy_app/tmp/extreme.xlsx +0 -0
- data/test/dummy_app/tmp/integration_tests/alt_xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/integration_tests/csv.csv +0 -6
- data/test/dummy_app/tmp/integration_tests/ods.ods +0 -0
- data/test/dummy_app/tmp/integration_tests/xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/model.csv +0 -6
- data/test/dummy_app/tmp/model.xlsx +0 -0
- data/test/dummy_app/tmp/ods/empty_sa.ods +0 -0
- data/test/dummy_app/tmp/ods/model.ods +0 -0
- data/test/dummy_app/tmp/ods/model_options.ods +0 -0
- data/test/dummy_app/tmp/ods/sa.ods +0 -0
- data/test/dummy_app/tmp/options.csv +0 -6
- data/test/dummy_app/tmp/plain_ruby_object/csv.csv +0 -4
- data/test/dummy_app/tmp/plain_ruby_object/ods.ods +0 -0
- data/test/dummy_app/tmp/plain_ruby_object/xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/posts/csv.csv +0 -6
- data/test/dummy_app/tmp/posts/empty.xlsx +0 -0
- data/test/dummy_app/tmp/posts/ods.ods +0 -0
- data/test/dummy_app/tmp/posts/xlsx.xlsx +0 -0
- data/test/dummy_app/tmp/sa.csv +0 -4
- data/test/dummy_app/tmp/sa.xlsx +0 -0
- data/test/models/active_model_object_test.rb +0 -51
- data/test/models/bad_plain_ruby_object_test.rb +0 -28
- data/test/models/csv_test.rb +0 -59
- data/test/models/custom_post_test.rb +0 -51
- data/test/models/ods_test.rb +0 -65
- data/test/models/plain_ruby_object_test.rb +0 -51
- data/test/models/post_test.rb +0 -44
- data/test/models/spreadsheet_architect_utils_test.rb +0 -73
- data/test/models/xlsx_test.rb +0 -98
- data/test/spreadsheet_architect_test.rb +0 -11
@@ -1,33 +1,30 @@
|
|
1
1
|
module SpreadsheetArchitect
|
2
2
|
module Exceptions
|
3
3
|
|
4
|
-
class
|
5
|
-
def initialize
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
class InvalidRangeError < StandardError
|
5
|
+
def initialize(type, range)
|
6
|
+
case type
|
7
|
+
when :columns, :rows
|
8
|
+
super("Invalid range `#{range}` passed. Some of the #{type} specified were greater than the total number of #{type}")
|
9
|
+
when :format
|
10
|
+
super("Invalid range `#{range}` passed. Format must be as follows: A1:D4")
|
11
|
+
when :type
|
12
|
+
super("Invalid range type `#{range}`. Valid types are String and Hash")
|
13
|
+
else
|
14
|
+
super("Invalid range `#{range}` passed.")
|
15
|
+
end
|
13
16
|
end
|
14
17
|
end
|
15
18
|
|
16
|
-
class
|
17
|
-
def initialize(
|
18
|
-
super("
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class SpreadsheetColumnsNotDefinedError < StandardError
|
23
|
-
def initialize(klass=nil)
|
24
|
-
super("The spreadsheet_columns option is not defined on #{klass.name}")
|
19
|
+
class InvalidTypeError < StandardError
|
20
|
+
def initialize(which)
|
21
|
+
super("Invalid data type for the #{which}")
|
25
22
|
end
|
26
23
|
end
|
27
24
|
|
28
25
|
class InvalidColumnError < StandardError
|
29
|
-
def initialize(
|
30
|
-
super("Invalid Column `#{
|
26
|
+
def initialize(col)
|
27
|
+
super("Invalid Column `#{col}` given for column_types options")
|
31
28
|
end
|
32
29
|
end
|
33
30
|
|
@@ -37,16 +34,21 @@ module SpreadsheetArchitect
|
|
37
34
|
end
|
38
35
|
end
|
39
36
|
|
40
|
-
class
|
41
|
-
def initialize
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
37
|
+
class NoDataError < StandardError
|
38
|
+
def initialize
|
39
|
+
super("Missing :data or :instances option")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class MultipleDataSourcesError < StandardError
|
44
|
+
def initialize
|
45
|
+
super("Both :data and :instances options cannot be combined, please choose one.")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class SpreadsheetColumnsNotDefinedError < StandardError
|
50
|
+
def initialize(klass)
|
51
|
+
super("The instance method `spreadsheet_columns` is not defined on #{klass}")
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
@@ -28,16 +28,12 @@ module SpreadsheetArchitect
|
|
28
28
|
styles = {} unless styles.is_a?(Hash)
|
29
29
|
styles = self.symbolize_keys(styles)
|
30
30
|
|
31
|
-
if styles[:fg_color].nil?
|
32
|
-
|
33
|
-
styles[:fg_color] = styles.delete(:color).sub('#','')
|
34
|
-
end
|
31
|
+
if styles[:fg_color].nil? && styles[:color] && styles[:color].respond_to?(:sub) && !styles[:color].empty?
|
32
|
+
styles[:fg_color] = styles.delete(:color).sub('#','')
|
35
33
|
end
|
36
34
|
|
37
|
-
if styles[:bg_color].nil?
|
38
|
-
|
39
|
-
styles[:bg_color] = styles.delete(:background_color).sub('#','')
|
40
|
-
end
|
35
|
+
if styles[:bg_color].nil? && styles[:background_color] && styles[:background_color].respond_to?(:sub) && !styles[:background_color].empty?
|
36
|
+
styles[:bg_color] = styles.delete(:background_color).sub('#','')
|
41
37
|
end
|
42
38
|
|
43
39
|
if styles[:alignment].nil? && styles[:align]
|
@@ -48,26 +44,26 @@ module SpreadsheetArchitect
|
|
48
44
|
wrap_text: styles[:align][:wrap_text]
|
49
45
|
}
|
50
46
|
else
|
51
|
-
styles[:alignment] = {horizontal: styles.delete(:align)}
|
47
|
+
styles[:alignment] = {horizontal: (styles.delete(:align) || nil) }
|
52
48
|
end
|
53
49
|
|
54
50
|
styles.delete(:align)
|
55
51
|
end
|
56
52
|
|
57
53
|
if styles[:b].nil?
|
58
|
-
styles[:b] = styles.delete(:bold)
|
54
|
+
styles[:b] = styles.delete(:bold) || nil
|
59
55
|
end
|
60
56
|
|
61
57
|
if styles[:sz].nil?
|
62
|
-
styles[:sz] = styles.delete(:font_size)
|
58
|
+
styles[:sz] = styles.delete(:font_size) || nil
|
63
59
|
end
|
64
60
|
|
65
61
|
if styles[:i].nil?
|
66
|
-
styles[:i] = styles.delete(:italic)
|
62
|
+
styles[:i] = styles.delete(:italic) || nil
|
67
63
|
end
|
68
64
|
|
69
65
|
if styles[:u].nil?
|
70
|
-
styles[:u] = styles.delete(:underline)
|
66
|
+
styles[:u] = styles.delete(:underline) || nil
|
71
67
|
end
|
72
68
|
|
73
69
|
### If `:u` is false instead of nil, it may be incorrectly rendered as true in Excel
|
@@ -78,16 +74,26 @@ module SpreadsheetArchitect
|
|
78
74
|
styles.delete_if{|k,v| v.nil?}
|
79
75
|
end
|
80
76
|
|
81
|
-
def self.range_hash_to_str(hash, num_columns, num_rows
|
77
|
+
def self.range_hash_to_str(hash, num_columns, num_rows)
|
82
78
|
case hash[:columns]
|
83
79
|
when Integer
|
84
|
-
start_col = end_col =
|
80
|
+
start_col = end_col = COL_NAMES[hash[:columns]]
|
81
|
+
when String
|
82
|
+
start_col = hash[:columns].first
|
83
|
+
end_col = hash[:columns].last
|
85
84
|
when Range
|
86
|
-
start_col =
|
87
|
-
|
85
|
+
start_col = hash[:columns].first
|
86
|
+
unless start_col.is_a?(String)
|
87
|
+
start_col = COL_NAMES[start_col]
|
88
|
+
end
|
89
|
+
|
90
|
+
end_col = hash[:columns].last
|
91
|
+
unless end_col.is_a?(String)
|
92
|
+
end_col = COL_NAMES[end_col]
|
93
|
+
end
|
88
94
|
when :all
|
89
95
|
start_col = 'A'
|
90
|
-
end_col =
|
96
|
+
end_col = COL_NAMES[num_columns-1]
|
91
97
|
else
|
92
98
|
raise SpreadsheetArchitect::Exceptions::InvalidRangeStylesOptionError.new(:columns, hash)
|
93
99
|
end
|
@@ -105,28 +111,40 @@ module SpreadsheetArchitect
|
|
105
111
|
raise SpreadsheetArchitect::Exceptions::InvalidRangeStylesOptionError.new(:rows, hash)
|
106
112
|
end
|
107
113
|
|
108
|
-
|
114
|
+
range_str = "#{start_col}#{start_row}:#{end_col}#{end_row}"
|
115
|
+
|
116
|
+
unless hash[:columns] == :all && hash[:rows] == :all
|
117
|
+
verify_range(range_str, num_rows)
|
118
|
+
end
|
119
|
+
|
120
|
+
return range_str
|
109
121
|
end
|
110
122
|
|
111
|
-
def self.verify_range(range, num_rows
|
123
|
+
def self.verify_range(range, num_rows)
|
112
124
|
if range.is_a?(String)
|
113
125
|
if range.include?(':')
|
114
126
|
front, back = range.split(':')
|
115
127
|
start_col, start_row = front.scan(/\d+|\D+/)
|
116
128
|
end_col, end_row = back.scan(/\d+|\D+/)
|
117
129
|
|
118
|
-
unless
|
119
|
-
raise SpreadsheetArchitect::Exceptions::
|
130
|
+
unless COL_NAMES.include?(start_col) && COL_NAMES.include?(end_col)
|
131
|
+
raise SpreadsheetArchitect::Exceptions::InvalidRangeError.new(:columns, range)
|
120
132
|
end
|
121
133
|
|
122
134
|
unless start_row.to_i <= num_rows && end_row.to_i <= num_rows
|
123
|
-
raise SpreadsheetArchitect::Exceptions::
|
135
|
+
raise SpreadsheetArchitect::Exceptions::InvalidRangeError.new(:rows, range)
|
124
136
|
end
|
125
137
|
else
|
126
|
-
raise SpreadsheetArchitect::Exceptions::
|
138
|
+
raise SpreadsheetArchitect::Exceptions::InvalidRangeError.new(:format, range)
|
127
139
|
end
|
128
140
|
else
|
129
|
-
raise SpreadsheetArchitect::Exceptions::
|
141
|
+
raise SpreadsheetArchitect::Exceptions::InvalidRangeError.new(:type, range)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.verify_column(col, num_columns)
|
146
|
+
unless (col.is_a?(String) && COL_NAMES.include?(col)) || (col.is_a?(Integer) && col >= 0 && col < num_columns)
|
147
|
+
raise SpreadsheetArchitect::Exceptions::InvalidColumnError.new(col)
|
130
148
|
end
|
131
149
|
end
|
132
150
|
|
@@ -144,6 +162,9 @@ module SpreadsheetArchitect
|
|
144
162
|
new_hash
|
145
163
|
end
|
146
164
|
|
165
|
+
### Limit of 16384 columns as per Excel limitations
|
166
|
+
COL_NAMES = Array('A'..'XFD').freeze
|
167
|
+
|
147
168
|
end
|
148
169
|
end
|
149
170
|
end
|
@@ -1,90 +1,83 @@
|
|
1
1
|
module SpreadsheetArchitect
|
2
2
|
module Utils
|
3
|
-
def self.
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
def self.get_cell_data(options, klass)
|
4
|
+
if options[:data] && options[:instances]
|
5
|
+
raise SpreadsheetArchitect::Exceptions::MultipleDataSourcesError
|
6
|
+
elsif options[:data]
|
7
|
+
data = options[:data]
|
7
8
|
end
|
8
|
-
return str
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.get_cell_data(options={}, klass)
|
12
|
-
self.check_options_types
|
13
9
|
|
14
|
-
if
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
if options[:headers] && options[:headers].is_a?(Array) && !options[:headers].empty?
|
20
|
-
headers = options[:headers]
|
21
|
-
else
|
22
|
-
headers = false
|
23
|
-
end
|
24
|
-
|
25
|
-
data = options[:data]
|
10
|
+
if !options[:data] && options[:headers] == true
|
11
|
+
headers = []
|
12
|
+
needs_headers = true
|
13
|
+
elsif options[:headers].is_a?(Array)
|
14
|
+
headers = options[:headers]
|
26
15
|
else
|
27
|
-
|
16
|
+
headers = false
|
17
|
+
end
|
28
18
|
|
29
|
-
|
30
|
-
|
31
|
-
|
19
|
+
if options[:column_types]
|
20
|
+
column_types = options[:column_types]
|
21
|
+
else
|
22
|
+
column_types = []
|
23
|
+
needs_column_types = true
|
24
|
+
end
|
32
25
|
|
26
|
+
if !data
|
33
27
|
if !options[:instances]
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
headers ||= SpreadsheetArchitect.default_options[:headers]
|
40
|
-
elsif options[:headers].is_a?(Array)
|
41
|
-
headers = options[:headers]
|
42
|
-
end
|
43
|
-
|
44
|
-
if headers == false || headers.is_a?(Array)
|
45
|
-
needs_headers = false
|
46
|
-
else
|
47
|
-
headers = true
|
48
|
-
needs_headers = true
|
28
|
+
if is_ar_model?(klass)
|
29
|
+
options[:instances] = klass.where(nil).to_a # triggers the relation call, not sure how this works but it does
|
30
|
+
else
|
31
|
+
raise SpreadsheetArchitect::Exceptions::NoDataError
|
32
|
+
end
|
49
33
|
end
|
50
34
|
|
51
|
-
if
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
columns.push x[1]
|
59
|
-
else
|
60
|
-
headers.push(str_humanize(x.to_s)) if needs_headers
|
61
|
-
columns.push x
|
62
|
-
end
|
35
|
+
if !options[:spreadsheet_columns] && klass != SpreadsheetArchitect && !klass.instance_methods.include?(:spreadsheet_columns)
|
36
|
+
if is_ar_model?(klass)
|
37
|
+
the_column_names = klass.column_names
|
38
|
+
headers = the_column_names.map{|x| str_titleize(x)} if needs_headers
|
39
|
+
columns = the_column_names.map{|x| x.to_sym}
|
40
|
+
else
|
41
|
+
raise SpreadsheetArchitect::Exceptions::SpreadsheetColumnsNotDefinedError.new(klass)
|
63
42
|
end
|
64
|
-
elsif !has_custom_columns && defined?(ActiveRecord) && klass.ancestors.include?(ActiveRecord::Base)
|
65
|
-
ignored_columns = ["id","created_at","updated_at","deleted_at"]
|
66
|
-
the_column_names = (klass.column_names - ignored_columns)
|
67
|
-
headers = the_column_names.map{|x| str_humanize(x)} if needs_headers
|
68
|
-
columns = the_column_names.map{|x| x.to_sym}
|
69
|
-
else
|
70
|
-
raise SpreadsheetArchitect::Exceptions::SpreadsheetColumnsNotDefinedError, klass
|
71
43
|
end
|
72
44
|
|
73
45
|
data = []
|
74
46
|
options[:instances].each do |instance|
|
75
|
-
if
|
47
|
+
if columns
|
48
|
+
data.push columns.map{|col| col.is_a?(Symbol) ? instance.instance_eval(col.to_s) : col}
|
49
|
+
else
|
76
50
|
row_data = []
|
77
|
-
|
51
|
+
|
52
|
+
if !options[:spreadsheet_columns]
|
53
|
+
if klass == SpreadsheetArchitect && !instance.respond_to?(:spreadsheet_columns)
|
54
|
+
raise SpreadsheetArchitect::Exceptions::SpreadsheetColumnsNotDefinedError.new(instance.class)
|
55
|
+
else
|
56
|
+
instance_cols = instance.spreadsheet_columns
|
57
|
+
end
|
58
|
+
else
|
59
|
+
instance_cols = options[:spreadsheet_columns].call(instance)
|
60
|
+
end
|
61
|
+
|
62
|
+
instance_cols.each_with_index do |x,i|
|
78
63
|
if x.is_a?(Array)
|
64
|
+
headers.push(x[0].to_s) if needs_headers
|
79
65
|
row_data.push(x[1].is_a?(Symbol) ? instance.instance_eval(x[1].to_s) : x[1])
|
66
|
+
if needs_column_types
|
67
|
+
column_types[i] = x[2]
|
68
|
+
end
|
80
69
|
else
|
70
|
+
headers.push(str_titleize(x.to_s)) if needs_headers
|
81
71
|
row_data.push(x.is_a?(Symbol) ? instance.instance_eval(x.to_s) : x)
|
82
72
|
end
|
83
73
|
end
|
74
|
+
|
84
75
|
data.push row_data
|
85
|
-
|
86
|
-
|
76
|
+
|
77
|
+
needs_headers = false
|
78
|
+
needs_column_types = false
|
87
79
|
end
|
80
|
+
|
88
81
|
end
|
89
82
|
end
|
90
83
|
|
@@ -92,54 +85,50 @@ module SpreadsheetArchitect
|
|
92
85
|
headers = [headers]
|
93
86
|
end
|
94
87
|
|
95
|
-
|
88
|
+
if column_types.compact.empty?
|
89
|
+
column_types = nil
|
90
|
+
end
|
91
|
+
|
92
|
+
return options.merge(headers: headers, data: data, column_types: column_types)
|
96
93
|
end
|
97
94
|
|
98
|
-
def self.get_options(options
|
99
|
-
|
100
|
-
|
101
|
-
|
95
|
+
def self.get_options(options, klass)
|
96
|
+
verify_option_types(options)
|
97
|
+
|
98
|
+
if defined?(klass::SPREADSHEET_OPTIONS)
|
99
|
+
if klass::SPREADSHEET_OPTIONS.is_a?(Hash)
|
100
|
+
options = SpreadsheetArchitect.default_options.merge(
|
101
|
+
klass::SPREADSHEET_OPTIONS.merge(options)
|
102
|
+
)
|
102
103
|
else
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
|
-
if options[:header_style]
|
107
|
-
header_style.merge!(options[:header_style])
|
108
|
-
elsif options[:header_style] == false
|
109
|
-
header_style = false
|
104
|
+
raise SpreadsheetArchitect::Exceptions::InvalidTypeError.new("#{klass}::SPREADSHEET_OPTIONS constant")
|
110
105
|
end
|
111
106
|
else
|
112
|
-
|
107
|
+
options = SpreadsheetArchitect.default_options.merge(options)
|
113
108
|
end
|
114
109
|
|
115
|
-
if options[:
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
110
|
+
if !options[:headers]
|
111
|
+
options[:header_style] = false
|
112
|
+
end
|
113
|
+
|
114
|
+
if !options[:sheet_name]
|
115
|
+
if klass == SpreadsheetArchitect
|
116
|
+
options[:sheet_name] = 'Sheet1'
|
120
117
|
else
|
121
|
-
|
122
|
-
end
|
118
|
+
options[:sheet_name] = klass.name
|
123
119
|
|
124
|
-
|
125
|
-
|
120
|
+
if options[:sheet_name].respond_to?(:pluralize)
|
121
|
+
options[:sheet_name] = options[:sheet_name].pluralize
|
122
|
+
end
|
126
123
|
end
|
127
124
|
end
|
128
125
|
|
129
|
-
|
130
|
-
sheet_name = options[:sheet_name] || klass::SPREADSHEET_OPTIONS[:sheet_name] || SpreadsheetArchitect.default_options[:sheet_name]
|
131
|
-
else
|
132
|
-
sheet_name = options[:sheet_name] || SpreadsheetArchitect.default_options[:sheet_name]
|
133
|
-
end
|
134
|
-
|
135
|
-
sheet_name ||= (klass.name == 'SpreadsheetArchitect' ? 'Sheet1' : klass.name)
|
136
|
-
|
137
|
-
return options.merge(header_style: header_style, row_style: row_style, sheet_name: sheet_name)
|
126
|
+
return options
|
138
127
|
end
|
139
128
|
|
140
129
|
def self.convert_styles_to_ods(styles={})
|
141
130
|
styles = {} unless styles.is_a?(Hash)
|
142
|
-
styles =
|
131
|
+
styles = stringify_keys(styles)
|
143
132
|
|
144
133
|
property_styles = {}
|
145
134
|
|
@@ -175,48 +164,54 @@ module SpreadsheetArchitect
|
|
175
164
|
|
176
165
|
private
|
177
166
|
|
178
|
-
def self.
|
179
|
-
|
167
|
+
def self.is_ar_model?(klass)
|
168
|
+
defined?(ActiveRecord) && klass.ancestors.include?(ActiveRecord::Base)
|
180
169
|
end
|
181
170
|
|
182
|
-
def self.
|
183
|
-
|
184
|
-
|
171
|
+
def self.str_titleize(str)
|
172
|
+
str = str.sub(/\A_+/, '')
|
173
|
+
.gsub(/[_\.]/,' ')
|
174
|
+
.sub(' rescue nil','')
|
175
|
+
.gsub(/(\A|\ )\w/){|x| x.upcase}
|
185
176
|
|
177
|
+
return str
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.check_option_type(options, option_name, type)
|
181
|
+
val = options[option_name]
|
182
|
+
|
183
|
+
if val
|
186
184
|
if type.is_a?(Array)
|
187
|
-
|
188
|
-
elsif
|
189
|
-
|
185
|
+
invalid = type.all?{|t| !val.is_a?(t) }
|
186
|
+
elsif !val.is_a?(type)
|
187
|
+
invalid = true
|
190
188
|
end
|
191
189
|
|
192
|
-
if
|
193
|
-
raise SpreadsheetArchitect::Exceptions::
|
190
|
+
if invalid
|
191
|
+
raise SpreadsheetArchitect::Exceptions::InvalidTypeError.new(":#{option_name} option")
|
194
192
|
end
|
195
193
|
end
|
196
194
|
end
|
197
195
|
|
198
|
-
def self.
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
196
|
+
def self.verify_option_types(options)
|
197
|
+
check_option_type(options, :spreadsheet_columns, Proc)
|
198
|
+
check_option_type(options, :data, Array)
|
199
|
+
check_option_type(options, :instances, Array)
|
200
|
+
check_option_type(options, :headers, [TrueClass, Array])
|
201
|
+
check_option_type(options, :header_style, Hash)
|
202
|
+
check_option_type(options, :row_style, Hash)
|
203
|
+
check_option_type(options, :column_styles, Array)
|
204
|
+
check_option_type(options, :range_styles, Array)
|
205
|
+
check_option_type(options, :merges, Array)
|
206
|
+
check_option_type(options, :borders, Array)
|
207
|
+
check_option_type(options, :column_widths, Array)
|
210
208
|
end
|
211
209
|
|
212
|
-
# only converts the first 2 levels
|
213
210
|
def self.stringify_keys(hash={})
|
214
211
|
new_hash = {}
|
215
212
|
hash.each do |k,v|
|
216
213
|
if v.is_a?(Hash)
|
217
|
-
|
218
|
-
new_hash[k2.to_s] = v2
|
219
|
-
end
|
214
|
+
new_hash[k.to_s] = self.stringify_keys(v)
|
220
215
|
else
|
221
216
|
new_hash[k.to_s] = v
|
222
217
|
end
|
@@ -23,7 +23,11 @@ module SpreadsheetArchitect
|
|
23
23
|
}
|
24
24
|
|
25
25
|
def self.default_options=(val)
|
26
|
-
|
26
|
+
if val.is_a?(Hash)
|
27
|
+
@default_options = val
|
28
|
+
else
|
29
|
+
raise SpreadsheetArchitect::Exceptions::InvalidTypeError.new("SpreadsheetArchitect.default_options")
|
30
|
+
end
|
27
31
|
end
|
28
32
|
|
29
33
|
def self.default_options
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class LegacyPlainRubyObject
|
2
|
+
include SpreadsheetArchitect ### old syntax, not in readme anymore, should easily remain compatible though
|
3
|
+
|
4
|
+
attr_accessor :name, :content, :created_at
|
5
|
+
|
6
|
+
def spreadsheet_columns
|
7
|
+
[
|
8
|
+
['Name', :name],
|
9
|
+
:content,
|
10
|
+
['Object ID', (object_id)]
|
11
|
+
]
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -1,19 +1,12 @@
|
|
1
1
|
class PlainRubyObject
|
2
|
-
|
2
|
+
attr_accessor :name, :content, :created_at
|
3
3
|
|
4
4
|
def spreadsheet_columns
|
5
5
|
[
|
6
|
-
['
|
6
|
+
['Name', :name],
|
7
7
|
:content,
|
8
8
|
['Object ID', (object_id)]
|
9
9
|
]
|
10
10
|
end
|
11
11
|
|
12
|
-
def title
|
13
|
-
'My Title'
|
14
|
-
end
|
15
|
-
|
16
|
-
def content
|
17
|
-
'The content...'
|
18
|
-
end
|
19
12
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
Dummy::Application.routes.draw do
|
2
|
-
get '
|
3
|
-
get '
|
4
|
-
get '
|
5
|
-
get '
|
6
|
-
get 'test', to: 'spreadsheets#test_xlsx'
|
2
|
+
get 'spreadsheets/csv', to: 'spreadsheets#csv'
|
3
|
+
get 'spreadsheets/ods', to: 'spreadsheets#ods'
|
4
|
+
get 'spreadsheets/xlsx', to: 'spreadsheets#xlsx'
|
5
|
+
get 'spreadsheets/alt_xlsx', to: 'spreadsheets#alt_xlsx'
|
7
6
|
end
|
Binary file
|