spreadsheet_architect 4.2.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/README.md +10 -14
- data/lib/spreadsheet_architect/class_methods/ods.rb +18 -8
- data/lib/spreadsheet_architect/class_methods/xlsx.rb +76 -32
- data/lib/spreadsheet_architect/exceptions.rb +30 -13
- data/lib/spreadsheet_architect/utils/ods.rb +66 -0
- data/lib/spreadsheet_architect/utils/xlsx.rb +29 -8
- data/lib/spreadsheet_architect/utils.rb +13 -38
- data/lib/spreadsheet_architect/version.rb +1 -1
- data/lib/spreadsheet_architect.rb +3 -2
- data/test/dummy_app/app/controllers/spreadsheets_controller.rb +1 -1
- data/test/dummy_app/config/application.rb +4 -12
- data/test/dummy_app/config/routes.rb +1 -1
- data/test/dummy_app/db/test.sqlite3 +0 -0
- data/test/dummy_app/log/test.log +79842 -63691
- 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/2.0.1/models/ActiveModelObject/empty.csv +1 -0
- data/test/dummy_app/tmp/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/CustomColumnsMethodPost/data.csv +3 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/data.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/data.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/empty.csv +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/empty.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/empty.xlsx +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/instances.csv +6 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/instances.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/CustomColumnsMethodPost/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 +1 -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/Post/instances.csv +6 -0
- data/test/dummy_app/tmp/2.0.1/models/Post/instances.ods +0 -0
- data/test/dummy_app/tmp/2.0.1/models/Post/instances.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 +5 -5
- 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 +1 -1
- 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.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 +5 -5
- 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/CustomColumnsMethodPost/data.csv +1 -1
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/data.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/data.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/empty.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/empty.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/instances.csv +5 -5
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/instances.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomColumnsMethodPost/instances.xlsx +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/data.csv +1 -1
- 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.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 +5 -5
- 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 +1 -1
- 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.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 +5 -5
- 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 +1 -1
- 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 +0 -1
- 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 +5 -5
- 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 +1 -1
- 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 +1 -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/Post/instances.csv +5 -5
- data/test/dummy_app/tmp/3.0.0.pre/models/Post/instances.ods +0 -0
- data/test/dummy_app/tmp/3.0.0.pre/models/Post/instances.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 +4 -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 +1 -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/CustomColumnsMethodPost/data.csv +4 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/data.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/data.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/empty.csv +1 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/empty.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/empty.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/instances.csv +6 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/instances.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomColumnsMethodPost/instances.xlsx +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/CustomPost/data.csv +4 -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 +1 -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 +4 -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 +4 -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 +4 -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 +1 -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/Post/instances.csv +6 -0
- data/test/dummy_app/tmp/axlsx-master/models/Post/instances.ods +0 -0
- data/test/dummy_app/tmp/axlsx-master/models/Post/instances.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 -16
- data/test/models/all_models_test.rb +15 -19
- data/test/test_helper.rb +38 -9
- data/test/unit/ods/general_test.rb +121 -0
- data/test/unit/{formats_test.rb → rails/formats_test.rb} +1 -1
- data/test/unit/{exceptions_test.rb → spreadsheet_architect/exceptions_test.rb} +19 -15
- data/test/unit/{general_test.rb → spreadsheet_architect/spreadsheet_architect_test.rb} +3 -3
- data/test/unit/spreadsheet_architect/utils/ods_test.rb +58 -0
- data/test/unit/{xlsx_utils_test.rb → spreadsheet_architect/utils/xlsx_test.rb} +13 -21
- data/test/unit/{utils_test.rb → spreadsheet_architect/utils_test.rb} +12 -35
- data/test/unit/xlsx/freeze_test.rb +79 -0
- data/test/unit/xlsx/general_test.rb +199 -0
- metadata +381 -128
- data/test/dummy_app/config/environments/development.rb +0 -30
- data/test/dummy_app/config/environments/production.rb +0 -60
- data/test/unit/kitchen_sink_test.rb +0 -110
- data/test/unit/multi_sheet_test.rb +0 -29
- data/test/unit/options_test.rb +0 -9
- data/test/unit/xlsx_freeze_test.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c88ecaffa3abed6ef127dc13d42c612ebf224c6d8552590d68ae544af2713f93
|
4
|
+
data.tar.gz: d0e864c2f50e99040f932da595b7270dd0e9c0161fc1189e6d99cb43126f6b5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dfc0caea596d57bd5aa88cd3b5ff3cebfca8b1299d1660e9995ca93837746d21420a90e0f427df9b3f8e73c13914a24b137572c005ee16fafdeeb6ddaf18b95d
|
7
|
+
data.tar.gz: c31f408e271453d46454e4f85ad2437a2539e39973186a8889c917a338f9e5f57f9ef3f3f28797955d61f8daa6a7100ffb46624ab3974c4bfd9273cc5cacba29
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,20 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
---------
|
3
3
|
|
4
|
-
- **Unreleased** - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/
|
4
|
+
- **Unreleased** - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v5.0.0...master)
|
5
5
|
- Nothing yet
|
6
6
|
|
7
|
+
- **5.0.0** - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v4.2.0...v5.0.0)
|
8
|
+
- [#52](https://github.com/westonganger/spreadsheet_architect/pull/52) - Update to caxlsx v3.3.0+ which now contains the axlsx_styler code, so we drop the dependency on axlsx_styler
|
9
|
+
- [#38](https://github.com/westonganger/spreadsheet_architect/pull/38) - **Breaking Change** - Add `escape_formulas` option for xlsx spreadsheets. This is a breaking change because we default to `escape_formulas: true` whereas before there was no formula escaping at all. The reasoning for this breaking change is that creating spreadsheets where many of the fields contain direct user input are a large majority compared to use cases that involve formulas.
|
10
|
+
- [#39](https://github.com/westonganger/spreadsheet_architect/pull/39) - Add option `use_zero_based_row_index: true` (Default `false`) which allows you to use zero-based row indexes instead of the default 1-based row indexes. Recomended to set this option for the whole project. The original reason it was designed to be 1-based is because spreadsheet row numbers literally start with 1. However this tends to be unituitive for the developer because columns use zero based indexes because they use letter-based notation instead.
|
11
|
+
- [#40](https://github.com/westonganger/spreadsheet_architect/pull/40) - Improve argument handling for freeze option and add support for all Axlsx supported options for panes using the `:freeze` hash. See test case for example (./test/unit/xlsx_freeze_test.rb)
|
12
|
+
- [#42](https://github.com/westonganger/spreadsheet_architect/pull/42) - Improve exceptions and messages regarding invalid ranges
|
13
|
+
- [#45](https://github.com/westonganger/spreadsheet_architect/pull/45) - For `to_xlsx`, dont add empty header row when `header: true`
|
14
|
+
- [#44](https://github.com/westonganger/spreadsheet_architect/pull/44) - Add support for hyperlinks in XLSX and ODS
|
15
|
+
- [#49](https://github.com/westonganger/spreadsheet_architect/pulls/49) - Extracted some ODS methods from `SpreadsheetArchitect::Utils` to `SpreadsheetArchitect::Utils::ODS`
|
16
|
+
- [#51](https://github.com/westonganger/spreadsheet_architect/pulls/51) - Add Proc support to `:column_types`
|
17
|
+
|
7
18
|
- **4.2.0** - May 27, 2021 - [View Diff](https://github.com/westonganger/spreadsheet_architect/compare/v4.1.0...v4.2.0)
|
8
19
|
- Add option `:skip_defaults` which removes the defaults and default styles. Particularily useful for heavily customized spreadsheets where the default styles get in the way.
|
9
20
|
- Fix bug where styles werent being un-applied when using the `false` value.
|
data/README.md
CHANGED
@@ -91,7 +91,7 @@ If you want to use a different method name then `spreadsheet_columns` you can pa
|
|
91
91
|
Post.to_xlsx(instances: posts, spreadsheet_columns: :my_special_method)
|
92
92
|
```
|
93
93
|
|
94
|
-
Alternatively, you can pass a Proc
|
94
|
+
Alternatively, you can pass a Proc to the `spreadsheet_columns` option. For those purists that really dont want to define any extra `spreadsheet_columns` instance method on your model, this option can help you work with that methodology.
|
95
95
|
|
96
96
|
```ruby
|
97
97
|
Post.to_xlsx(instances: posts, spreadsheet_columns: Proc.new{|instance|
|
@@ -103,7 +103,8 @@ Post.to_xlsx(instances: posts, spreadsheet_columns: Proc.new{|instance|
|
|
103
103
|
:published_at, # uses the method name as header title Einstance. 'Published At'
|
104
104
|
['# of Views', :number_of_views, :float],
|
105
105
|
['Rating', :rating],
|
106
|
-
['Category/Tags', "#{instance.category.name} - #{instance.tags.collect(&:name).join(', ')}"]
|
106
|
+
['Category/Tags', "#{instance.category.name} - #{instance.tags.collect(&:name).join(', ')}"],
|
107
|
+
['URL', :url, (val.start_with?("http") ? :hyperlink : :string)],
|
107
108
|
]
|
108
109
|
})
|
109
110
|
```
|
@@ -189,20 +190,16 @@ File.open('path/to/multi_sheet_file.xlsx', 'w+b') do |f|
|
|
189
190
|
end
|
190
191
|
```
|
191
192
|
|
192
|
-
See this file for more details: [test/unit/multi_sheet_test.rb](./test/unit/multi_sheet_test.rb)
|
193
|
-
|
194
193
|
### ODS
|
195
194
|
```ruby
|
196
195
|
ods_spreadsheet = SpreadsheetArchitect.to_rodf_spreadsheet({headers: headers, data: data})
|
197
196
|
ods_spreadsheet = SpreadsheetArchitect.to_rodf_spreadsheet({headers: headers, data: data}, ods_spreadsheet)
|
198
197
|
|
199
198
|
File.open('path/to/multi_sheet_file.ods', 'w+b') do |f|
|
200
|
-
f.write ods_spreadsheet
|
199
|
+
f.write ods_spreadsheet.bytes
|
201
200
|
end
|
202
201
|
```
|
203
202
|
|
204
|
-
See this file for more details: [test/unit/multi_sheet_test.rb](./test/unit/multi_sheet_test.rb)
|
205
|
-
|
206
203
|
# Methods
|
207
204
|
|
208
205
|
## `to_xlsx(options={})`
|
@@ -221,11 +218,13 @@ See this file for more details: [test/unit/multi_sheet_test.rb](./test/unit/mult
|
|
221
218
|
|**conditional_row_styles**<br>*Array*||[See this example for usage](./test/unit/kitchen_sink_test.rb). The if/unless proc will called with the following args: `row_index`, `row_data`|
|
222
219
|
|**merges**<br>*Array*||Merge cells. [See this example for usage](./test/unit/kitchen_sink_test.rb). Warning merges cannot overlap eachother, if you attempt to do so Excel will claim your spreadsheet is corrupt and refuse to open your spreadsheet.|
|
223
220
|
|**borders**<br>*Array*||[See this example for usage](./test/unit/kitchen_sink_test.rb)|
|
224
|
-
|**column_types**<br>*Array*||Valid types for XLSX are :string, :integer, :float, :date, :time, :boolean, nil = auto determine
|
221
|
+
|**column_types**<br>*Array*||Valid types for XLSX are :string, :integer, :float, :date, :time, :boolean, :hyperlink, nil = auto determine. You may also pass a Proc which evaluates to any of the valid types, for example `->(cell_val){ cell_val.start_with?('http') ? :hyperlink : :string }`|
|
225
222
|
|**column_widths**<br>*Array*||Sometimes you may want explicit column widths. Use nil if you want a column to autofit again.|
|
226
223
|
|**freeze_headers**<br>*Boolean*||Make all header rows frozen/fixed so they do not scroll.|
|
227
|
-
|**freeze**<br>*Hash
|
224
|
+
|**freeze**<br>*Hash*||Make all specified row and/or column frozen/fixed so they do not scroll. See [example usage](./test/unit/xlsx_freeze_test.rb)|
|
228
225
|
|**skip_defaults**<br>*Boolean*|`false`|Removes defaults and default styles. Particularily useful for heavily customized spreadsheets where the default styles get in the way.|
|
226
|
+
|**escape_formulas**<br>*Boolean* or *Array*|`true`|Pass a single boolean to apply to all cells, or an array of booleans to control column-by-column. Advisable to be set true when involved with untrusted user input. See [an example of the underlying functionality](https://github.com/caxlsx/caxlsx/blob/master/examples/escape_formula_example.md). NOTE: Header row cells are not escaped. |
|
227
|
+
|**use_zero_based_row_index**<br>*Boolean*|`false`|Allows you to use zero-based row indexes when defining `range_styles`, `merges`, etc. Recomended to set this option for the whole project rather than per call. The original reason it was designed to be 1-based is because spreadsheet row numbers actually start with 1.|
|
229
228
|
|
230
229
|
## `to_axlsx_spreadsheet(options={}, axlsx_package_to_join=nil)`
|
231
230
|
Same options as `to_xlsx`
|
@@ -241,7 +240,7 @@ Same options as `to_xlsx`
|
|
241
240
|
|**sheet_name**<br>*String*|`Sheet1`||
|
242
241
|
|**header_style**<br>*Hash*|`{background_color: "AAAAAA", color: "FFFFFF", align: :center, font_size: 10, bold: true}`|Note: Currently ODS only supports these options|
|
243
242
|
|**row_style**<br>*Hash*|`{background_color: nil, color: "000000", align: :left, font_size: 10, bold: false}`|Styles for non-header rows. Currently ODS only supports these options|
|
244
|
-
|**column_types**<br>*Array*||Valid types for ODS are :string, :float, :date, :time, :boolean, nil = auto determine. Due to [RODF Issue #19](https://github.com/thiagoarrais/rodf/issues/19), :date/:time will be converted to :string |
|
243
|
+
|**column_types**<br>*Array*||Valid types for ODS are :string, :float, :date, :time, :boolean, :hyperlink, nil = auto determine. Due to [RODF Issue #19](https://github.com/thiagoarrais/rodf/issues/19), :date/:time will be converted to :string. You may also pass a Proc which evaluates to any of the valid types, for example `->(cell_val){ cell_val.start_with?('http') ? :hyperlink : :string }` |
|
245
244
|
|**skip_defaults**<br>*Boolean*|`false`|Skip defaults and default styles. Particularily useful for heavily customized spreadsheets where the default styles get in the way.|
|
246
245
|
|
247
246
|
## `to_rodf_spreadsheet(options={}, spreadsheet_to_join=nil)`
|
@@ -303,6 +302,7 @@ SpreadsheetArchitect.default_options = {
|
|
303
302
|
merges: [],
|
304
303
|
borders: [],
|
305
304
|
column_types: [],
|
305
|
+
use_zero_based_row_index: false,
|
306
306
|
}
|
307
307
|
```
|
308
308
|
|
@@ -329,7 +329,3 @@ At this time the spreadsheets generated by the test suite are manually inspected
|
|
329
329
|
# Credits
|
330
330
|
|
331
331
|
Created & Maintained by [Weston Ganger](https://westonganger.com) - [@westonganger](https://github.com/westonganger)
|
332
|
-
|
333
|
-
For any consulting or contract work please contact me via my company website: [Solid Foundation Web Development](https://solidfoundationwebdev.com)
|
334
|
-
|
335
|
-
[![Solid Foundation Web Development Logo](https://solidfoundationwebdev.com/logo-sm.png)](https://solidfoundationwebdev.com)
|
@@ -11,7 +11,7 @@ module SpreadsheetArchitect
|
|
11
11
|
opts = SpreadsheetArchitect::Utils.get_options(opts, self)
|
12
12
|
options = SpreadsheetArchitect::Utils.get_cell_data(opts, self)
|
13
13
|
|
14
|
-
if options[:column_types] && !(options[:column_types].compact.collect(&:to_sym) - SpreadsheetArchitect::ODS_COLUMN_TYPES).empty?
|
14
|
+
if options[:column_types] && !(options[:column_types].compact.reject{|x| x.is_a?(Proc) }.collect(&:to_sym) - SpreadsheetArchitect::ODS_COLUMN_TYPES).empty?
|
15
15
|
raise SpreadsheetArchitect::Exceptions::ArgumentError.new("Invalid column type. Valid ODS values are #{SpreadsheetArchitect::ODS_COLUMN_TYPES}")
|
16
16
|
end
|
17
17
|
|
@@ -21,7 +21,7 @@ module SpreadsheetArchitect
|
|
21
21
|
|
22
22
|
spreadsheet.office_style :header_style, family: :cell do
|
23
23
|
if options[:header_style]
|
24
|
-
SpreadsheetArchitect::Utils.
|
24
|
+
SpreadsheetArchitect::Utils::ODS.convert_styles(options[:header_style]).each do |prop, styles|
|
25
25
|
styles.each do |k,v|
|
26
26
|
property prop.to_sym, k => v
|
27
27
|
end
|
@@ -31,7 +31,7 @@ module SpreadsheetArchitect
|
|
31
31
|
|
32
32
|
spreadsheet.office_style :row_style, family: :cell do
|
33
33
|
if options[:row_style]
|
34
|
-
SpreadsheetArchitect::Utils.
|
34
|
+
SpreadsheetArchitect::Utils::ODS.convert_styles(options[:row_style]).each do |prop, styles|
|
35
35
|
styles.each do |k,v|
|
36
36
|
property prop.to_sym, k => v
|
37
37
|
end
|
@@ -54,15 +54,25 @@ module SpreadsheetArchitect
|
|
54
54
|
row do
|
55
55
|
row_data.each_with_index do |val, i|
|
56
56
|
if options[:column_types]
|
57
|
-
|
57
|
+
provided_column_type = options[:column_types][i]
|
58
|
+
|
59
|
+
if provided_column_type.is_a?(Proc)
|
60
|
+
provided_column_type = provided_column_type.call(val)
|
61
|
+
end
|
58
62
|
end
|
59
63
|
|
60
|
-
|
61
|
-
|
62
|
-
|
64
|
+
type = SpreadsheetArchitect::Utils::ODS.get_cell_type(val, provided_column_type)
|
65
|
+
|
66
|
+
cell_opts = {
|
67
|
+
style: :row_style,
|
68
|
+
type: type,
|
69
|
+
}
|
70
|
+
|
71
|
+
if provided_column_type == :hyperlink
|
72
|
+
cell_opts[:url] = val
|
63
73
|
end
|
64
74
|
|
65
|
-
cell
|
75
|
+
cell(val, **cell_opts)
|
66
76
|
end
|
67
77
|
end
|
68
78
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'axlsx'
|
2
|
-
require 'axlsx_styler'
|
3
2
|
|
4
3
|
require 'spreadsheet_architect/axlsx_string_width_patch'
|
5
4
|
|
@@ -14,7 +13,7 @@ module SpreadsheetArchitect
|
|
14
13
|
opts = SpreadsheetArchitect::Utils.get_options(opts, self)
|
15
14
|
options = SpreadsheetArchitect::Utils.get_cell_data(opts, self)
|
16
15
|
|
17
|
-
if options[:column_types] && !(options[:column_types].compact.collect(&:to_sym) - SpreadsheetArchitect::XLSX_COLUMN_TYPES).empty?
|
16
|
+
if options[:column_types] && !(options[:column_types].compact.reject{|x| x.is_a?(Proc) }.collect(&:to_sym) - SpreadsheetArchitect::XLSX_COLUMN_TYPES).empty?
|
18
17
|
raise SpreadsheetArchitect::Exceptions::ArgumentError.new("Invalid column type. Valid XLSX values are #{SpreadsheetArchitect::XLSX_COLUMN_TYPES}")
|
19
18
|
end
|
20
19
|
|
@@ -79,16 +78,27 @@ module SpreadsheetArchitect
|
|
79
78
|
|
80
79
|
types = []
|
81
80
|
styles = []
|
82
|
-
|
83
|
-
|
81
|
+
hyperlink_cell_indexes = []
|
82
|
+
|
83
|
+
row_data.each_with_index do |val,i|
|
84
|
+
if (val.respond_to?(:empty) ? val.empty? : val.nil?)
|
84
85
|
types[i] = nil
|
85
86
|
styles[i] = row_style_index
|
86
87
|
else
|
87
88
|
if options[:column_types]
|
88
|
-
|
89
|
+
provided_column_type = options[:column_types][i]
|
90
|
+
|
91
|
+
if provided_column_type.is_a?(Proc)
|
92
|
+
provided_column_type = provided_column_type.call(val)
|
93
|
+
end
|
89
94
|
end
|
90
95
|
|
91
|
-
|
96
|
+
if provided_column_type == :hyperlink
|
97
|
+
hyperlink_cell_indexes << i
|
98
|
+
row_data[i] = val.to_s
|
99
|
+
end
|
100
|
+
|
101
|
+
types[i] = SpreadsheetArchitect::Utils::XLSX.get_type(val, provided_column_type)
|
92
102
|
|
93
103
|
if [:date, :time].include?(types[i])
|
94
104
|
if types[i] == :date
|
@@ -104,7 +114,12 @@ module SpreadsheetArchitect
|
|
104
114
|
end
|
105
115
|
end
|
106
116
|
|
107
|
-
sheet.add_row row_data, style: styles, types: types
|
117
|
+
sheet.add_row row_data, style: styles, types: types, escape_formulas: options[:escape_formulas]
|
118
|
+
|
119
|
+
hyperlink_cell_indexes.each do |cell_index|
|
120
|
+
cell_ref = "#{SpreadsheetArchitect::Utils::XLSX::COL_NAMES[cell_index]}#{row_index+1}"
|
121
|
+
sheet.add_hyperlink location: row_data[cell_index], ref: cell_ref
|
122
|
+
end
|
108
123
|
|
109
124
|
if options[:conditional_row_styles]
|
110
125
|
options[:conditional_row_styles] = SpreadsheetArchitect::Utils.hash_array_symbolize_keys(options[:conditional_row_styles])
|
@@ -133,12 +148,12 @@ module SpreadsheetArchitect
|
|
133
148
|
|
134
149
|
options[:borders].each do |x|
|
135
150
|
if x[:range].is_a?(Hash)
|
136
|
-
x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows)
|
151
|
+
x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows, use_zero_based_row_index: options[:use_zero_based_row_index])
|
137
152
|
else
|
138
153
|
SpreadsheetArchitect::Utils::XLSX.verify_range(x[:range], num_rows)
|
139
154
|
end
|
140
155
|
|
141
|
-
sheet.add_border x[:range], (x[:border_styles] || x[:styles])
|
156
|
+
sheet.add_border x[:range], (x[:border_styles] || x[:styles] || Axlsx::Border::EDGES)
|
142
157
|
end
|
143
158
|
end
|
144
159
|
|
@@ -182,7 +197,7 @@ module SpreadsheetArchitect
|
|
182
197
|
styles = SpreadsheetArchitect::Utils::XLSX.convert_styles_to_axlsx(x[:styles])
|
183
198
|
|
184
199
|
if x[:range].is_a?(Hash)
|
185
|
-
x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows)
|
200
|
+
x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows, use_zero_based_row_index: options[:use_zero_based_row_index])
|
186
201
|
else
|
187
202
|
SpreadsheetArchitect::Utils::XLSX.verify_range(x[:range], num_rows)
|
188
203
|
end
|
@@ -196,7 +211,7 @@ module SpreadsheetArchitect
|
|
196
211
|
|
197
212
|
options[:merges].each do |x|
|
198
213
|
if x[:range].is_a?(Hash)
|
199
|
-
x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows)
|
214
|
+
x[:range] = SpreadsheetArchitect::Utils::XLSX.range_hash_to_str(x[:range], max_row_length, num_rows, use_zero_based_row_index: options[:use_zero_based_row_index])
|
200
215
|
else
|
201
216
|
SpreadsheetArchitect::Utils::XLSX.verify_range(x[:range], num_rows)
|
202
217
|
end
|
@@ -212,33 +227,62 @@ module SpreadsheetArchitect
|
|
212
227
|
end
|
213
228
|
|
214
229
|
elsif options[:freeze]
|
215
|
-
options[:freeze]
|
230
|
+
case options[:freeze][:type].to_s
|
231
|
+
when "split_panes"
|
232
|
+
options[:freeze][:state] == "split"
|
233
|
+
when "frozen", "freeze"
|
234
|
+
options[:freeze][:state] == "frozen"
|
235
|
+
end
|
236
|
+
|
237
|
+
if options[:freeze][:rows]
|
238
|
+
options[:freeze][:row] ||= options[:freeze][:rows]
|
239
|
+
end
|
240
|
+
|
241
|
+
if options[:freeze][:columns]
|
242
|
+
options[:freeze][:column] ||= options[:freeze][:columns]
|
243
|
+
end
|
244
|
+
|
245
|
+
if options[:freeze][:row] == :all
|
246
|
+
options[:freeze][:row] = nil
|
247
|
+
elsif options[:freeze][:row].is_a?(Range)
|
248
|
+
options[:freeze][:row] = options[:freeze][:row].last
|
249
|
+
end
|
250
|
+
|
251
|
+
if options[:freeze][:column] == :all
|
252
|
+
options[:freeze][:column] = nil
|
253
|
+
elsif options[:freeze][:column].is_a?(Range)
|
254
|
+
options[:freeze][:column] = options[:freeze][:column].last
|
255
|
+
end
|
256
|
+
|
257
|
+
if !options[:freeze][:row] && !options[:freeze][:column]
|
258
|
+
raise SpreadsheetArchitect::Exceptions::ArgumentError.new("Missing required :row or :column value in the :freeze option hash")
|
259
|
+
elsif options[:freeze][:row] && !options[:freeze][:row].is_a?(Integer)
|
260
|
+
raise SpreadsheetArchitect::Exceptions::ArgumentError.new("Invalid :row value provided for in :freeze option hash, must be an Integer")
|
261
|
+
elsif options[:freeze][:column] && !options[:freeze][:column].is_a?(Integer)
|
262
|
+
raise SpreadsheetArchitect::Exceptions::ArgumentError.new("Invalid :column value provided for in :freeze option hash, must be an Integer")
|
263
|
+
end
|
216
264
|
|
217
265
|
sheet.sheet_view.pane do |pane|
|
218
|
-
pane.state = :frozen
|
266
|
+
pane.state = (options[:freeze][:state] || :frozen).to_sym ### Other options are :split and :frozen_split
|
219
267
|
|
220
|
-
|
221
|
-
|
222
|
-
# Axlsx.validate_pane_type(options[:freeze][:active_pane])
|
223
|
-
# pane.active_pane = options[:freeze][:active_pane]
|
224
|
-
#else
|
225
|
-
# pane.active_pane = :bottom_right
|
226
|
-
#end
|
227
|
-
|
228
|
-
if !options[:freeze][:rows]
|
229
|
-
raise SpreadsheetArchitect::Exceptions::ArgumentError.new("The :rows key must be specified in the :freeze option hash")
|
230
|
-
elsif options[:freeze][:rows].is_a?(Range)
|
231
|
-
pane.y_split = options[:freeze][:rows].count
|
232
|
-
else
|
233
|
-
pane.y_split = 1
|
268
|
+
if options[:freeze][:active_pane]
|
269
|
+
pane.active_pane = options[:freeze][:active_pane].to_sym
|
234
270
|
end
|
235
271
|
|
236
|
-
if options[:freeze][:
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
272
|
+
if options[:freeze][:top_left_cell]
|
273
|
+
pane.top_left_cell = options[:freeze][:top_left_cell]
|
274
|
+
end
|
275
|
+
|
276
|
+
if options[:freeze][:row]
|
277
|
+
if options[:use_zero_based_row_index]
|
278
|
+
options[:freeze][:row] += 1
|
241
279
|
end
|
280
|
+
|
281
|
+
pane.y_split = options[:freeze][:row]
|
282
|
+
end
|
283
|
+
|
284
|
+
if options[:freeze][:column]
|
285
|
+
pane.x_split = options[:freeze][:column]
|
242
286
|
end
|
243
287
|
end
|
244
288
|
end
|
@@ -14,17 +14,27 @@ module SpreadsheetArchitect
|
|
14
14
|
end
|
15
15
|
|
16
16
|
class InvalidRangeError < ArgumentError
|
17
|
-
def initialize(type, range)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
def initialize(type, range, message: nil)
|
18
|
+
default_msg = "Invalid range `#{range}` passed"
|
19
|
+
|
20
|
+
if message.nil?
|
21
|
+
case type
|
22
|
+
when :missing_range_keys
|
23
|
+
message = "Missing :rows or :columns key"
|
24
|
+
when :format
|
25
|
+
message = "Format must be as follows: A1:D4"
|
26
|
+
when :type
|
27
|
+
message = "Valid types are Hash and String"
|
28
|
+
end
|
27
29
|
end
|
30
|
+
|
31
|
+
super([default_msg, message].compact.join(". "))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class InvalidRangeValue < ArgumentError
|
36
|
+
def initialize(type, range)
|
37
|
+
super("Invalid range `#{range}` passed. Some of the :#{type} specified are either an invalid value or are greater than the total number of #{type}")
|
28
38
|
end
|
29
39
|
end
|
30
40
|
|
@@ -34,9 +44,16 @@ module SpreadsheetArchitect
|
|
34
44
|
end
|
35
45
|
end
|
36
46
|
|
37
|
-
class
|
38
|
-
def initialize(
|
39
|
-
|
47
|
+
class InvalidRangeOptionError < ArgumentError
|
48
|
+
def initialize(key, opt)
|
49
|
+
default_msg = "Invalid :#{key} option for `#{opt}`"
|
50
|
+
|
51
|
+
case key
|
52
|
+
when :columns, :rows
|
53
|
+
message = ":#{key} can be an integer, range, or :all"
|
54
|
+
end
|
55
|
+
|
56
|
+
super([default_msg, message].compact.join(". "))
|
40
57
|
end
|
41
58
|
end
|
42
59
|
|
@@ -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
|
-
|
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)
|
@@ -83,7 +90,11 @@ module SpreadsheetArchitect
|
|
83
90
|
return styles
|
84
91
|
end
|
85
92
|
|
86
|
-
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
|
+
|
87
98
|
case hash[:columns]
|
88
99
|
when Integer
|
89
100
|
start_col = end_col = COL_NAMES[hash[:columns]]
|
@@ -100,24 +111,34 @@ module SpreadsheetArchitect
|
|
100
111
|
unless end_col.is_a?(String)
|
101
112
|
end_col = COL_NAMES[end_col]
|
102
113
|
end
|
103
|
-
when :all
|
114
|
+
when :all, nil
|
104
115
|
start_col = 'A'
|
105
116
|
end_col = COL_NAMES[num_columns-1]
|
106
117
|
else
|
107
|
-
raise SpreadsheetArchitect::Exceptions::
|
118
|
+
raise SpreadsheetArchitect::Exceptions::InvalidRangeOptionError.new(:columns, hash)
|
108
119
|
end
|
109
120
|
|
110
121
|
case hash[:rows]
|
111
122
|
when Integer
|
112
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
|
113
129
|
when Range
|
114
130
|
start_row = hash[:rows].first
|
115
131
|
end_row = hash[:rows].last
|
116
|
-
|
132
|
+
|
133
|
+
if use_zero_based_row_index
|
134
|
+
start_row += 1
|
135
|
+
end_row += 1
|
136
|
+
end
|
137
|
+
when :all, nil
|
117
138
|
start_row = 1
|
118
139
|
end_row = num_rows
|
119
140
|
else
|
120
|
-
raise SpreadsheetArchitect::Exceptions::
|
141
|
+
raise SpreadsheetArchitect::Exceptions::InvalidRangeOptionError.new(:rows, hash)
|
121
142
|
end
|
122
143
|
|
123
144
|
range_str = "#{start_col}#{start_row}:#{end_col}#{end_row}"
|
@@ -137,11 +158,11 @@ module SpreadsheetArchitect
|
|
137
158
|
end_col, end_row = back.scan(/\d+|\D+/)
|
138
159
|
|
139
160
|
unless COL_NAMES.include?(start_col) && COL_NAMES.include?(end_col)
|
140
|
-
raise SpreadsheetArchitect::Exceptions::
|
161
|
+
raise SpreadsheetArchitect::Exceptions::InvalidRangeValue.new(:columns, range)
|
141
162
|
end
|
142
163
|
|
143
164
|
unless start_row.to_i <= num_rows && end_row.to_i <= num_rows
|
144
|
-
raise SpreadsheetArchitect::Exceptions::
|
165
|
+
raise SpreadsheetArchitect::Exceptions::InvalidRangeValue.new(:rows, range)
|
145
166
|
end
|
146
167
|
else
|
147
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
|
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)
|
@@ -143,50 +145,22 @@ module SpreadsheetArchitect
|
|
143
145
|
end
|
144
146
|
|
145
147
|
if options[:freeze]
|
148
|
+
options[:freeze] = SpreadsheetArchitect::Utils.symbolize_keys(options[:freeze])
|
149
|
+
|
146
150
|
if options[:freeze_headers]
|
147
151
|
raise SpreadsheetArchitect::Exceptions::ArgumentError.new('Cannot use both :freeze and :freeze_headers options at the same time')
|
148
|
-
elsif options[:freeze].is_a?(Hash) && !options[:freeze][:rows]
|
149
|
-
raise SpreadsheetArchitect::Exceptions::ArgumentError.new('Must provide a :rows key when passing a hash to the :freeze option')
|
150
152
|
end
|
151
153
|
end
|
152
154
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
def self.convert_styles_to_ods(styles={})
|
157
|
-
styles = {} unless styles.is_a?(Hash)
|
158
|
-
styles = stringify_keys(styles)
|
159
|
-
|
160
|
-
property_styles = {}
|
161
|
-
|
162
|
-
text_styles = {}
|
163
|
-
text_styles['font-weight'] = styles.delete('bold') ? 'bold' : styles.delete('font-weight')
|
164
|
-
text_styles['font-size'] = styles.delete('font_size') || styles.delete('font-size')
|
165
|
-
text_styles['font-style'] = styles.delete('italic') ? 'italic' : styles.delete('font-style')
|
166
|
-
if styles['underline']
|
167
|
-
styles.delete('underline')
|
168
|
-
text_styles['text-underline-style'] = 'solid'
|
169
|
-
text_styles['text-underline-type'] = 'single'
|
170
|
-
end
|
171
|
-
if styles['align']
|
172
|
-
text_styles['align'] = true
|
173
|
-
end
|
174
|
-
if styles['color'].respond_to?(:sub) && !styles['color'].empty?
|
175
|
-
text_styles['color'] = "##{styles.delete('color').sub('#','')}"
|
176
|
-
end
|
177
|
-
text_styles.delete_if{|_,v| v.nil?}
|
178
|
-
property_styles['text'] = text_styles
|
179
|
-
|
180
|
-
cell_styles = {}
|
181
|
-
styles['background_color'] ||= styles.delete('background-color')
|
182
|
-
if styles['background_color'].respond_to?(:sub) && !styles['background_color'].empty?
|
183
|
-
cell_styles['background-color'] = "##{styles.delete('background_color').sub('#','')}"
|
155
|
+
if options[:escape_formulas].nil?
|
156
|
+
options[:escape_formulas] = true
|
184
157
|
end
|
185
158
|
|
186
|
-
|
187
|
-
|
159
|
+
if options[:use_zero_based_row_index].nil?
|
160
|
+
options[:use_zero_based_row_index] = false
|
161
|
+
end
|
188
162
|
|
189
|
-
return
|
163
|
+
return options
|
190
164
|
end
|
191
165
|
|
192
166
|
private
|
@@ -290,8 +264,9 @@ module SpreadsheetArchitect
|
|
290
264
|
row_style: Hash,
|
291
265
|
sheet_name: String,
|
292
266
|
spreadsheet_columns: [Proc, Symbol, String],
|
267
|
+
escape_formulas: [TrueClass, FalseClass, Array],
|
268
|
+
use_zero_based_row_index: [TrueClass, FalseClass],
|
293
269
|
}.freeze
|
294
270
|
|
295
|
-
|
296
271
|
end
|
297
272
|
end
|