zaxcel 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +4 -0
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +29 -0
- data/CONTRIBUTING.md +110 -0
- data/LICENSE +22 -0
- data/QUICK_START.md +187 -0
- data/README.md +372 -0
- data/Rakefile +18 -0
- data/SETUP.md +178 -0
- data/lib/enumerable.rb +47 -0
- data/lib/zaxcel/README.md +37 -0
- data/lib/zaxcel/arithmetic.rb +88 -0
- data/lib/zaxcel/binary_expression.rb +74 -0
- data/lib/zaxcel/binary_expressions/addition.rb +36 -0
- data/lib/zaxcel/binary_expressions/division.rb +24 -0
- data/lib/zaxcel/binary_expressions/multiplication.rb +24 -0
- data/lib/zaxcel/binary_expressions/subtraction.rb +41 -0
- data/lib/zaxcel/binary_expressions.rb +38 -0
- data/lib/zaxcel/cell.rb +141 -0
- data/lib/zaxcel/cell_formula.rb +16 -0
- data/lib/zaxcel/column.rb +142 -0
- data/lib/zaxcel/document.rb +136 -0
- data/lib/zaxcel/function.rb +6 -0
- data/lib/zaxcel/functions/abs.rb +18 -0
- data/lib/zaxcel/functions/and.rb +23 -0
- data/lib/zaxcel/functions/average.rb +17 -0
- data/lib/zaxcel/functions/choose.rb +20 -0
- data/lib/zaxcel/functions/concatenate.rb +20 -0
- data/lib/zaxcel/functions/if.rb +38 -0
- data/lib/zaxcel/functions/if_error.rb +25 -0
- data/lib/zaxcel/functions/index.rb +20 -0
- data/lib/zaxcel/functions/len.rb +16 -0
- data/lib/zaxcel/functions/match/match_type.rb +13 -0
- data/lib/zaxcel/functions/match.rb +27 -0
- data/lib/zaxcel/functions/max.rb +17 -0
- data/lib/zaxcel/functions/min.rb +17 -0
- data/lib/zaxcel/functions/negate.rb +26 -0
- data/lib/zaxcel/functions/or.rb +23 -0
- data/lib/zaxcel/functions/round.rb +20 -0
- data/lib/zaxcel/functions/sum.rb +18 -0
- data/lib/zaxcel/functions/sum_if.rb +20 -0
- data/lib/zaxcel/functions/sum_ifs.rb +34 -0
- data/lib/zaxcel/functions/sum_product.rb +18 -0
- data/lib/zaxcel/functions/text.rb +17 -0
- data/lib/zaxcel/functions/unique.rb +23 -0
- data/lib/zaxcel/functions/x_lookup.rb +28 -0
- data/lib/zaxcel/functions/xirr.rb +27 -0
- data/lib/zaxcel/functions.rb +169 -0
- data/lib/zaxcel/if_builder.rb +22 -0
- data/lib/zaxcel/lang.rb +23 -0
- data/lib/zaxcel/reference.rb +28 -0
- data/lib/zaxcel/references/cell.rb +42 -0
- data/lib/zaxcel/references/column.rb +49 -0
- data/lib/zaxcel/references/range.rb +35 -0
- data/lib/zaxcel/references/row.rb +34 -0
- data/lib/zaxcel/references.rb +5 -0
- data/lib/zaxcel/roundable.rb +14 -0
- data/lib/zaxcel/row.rb +93 -0
- data/lib/zaxcel/sheet.rb +425 -0
- data/lib/zaxcel/sorbet/enumerizable_enum.rb +50 -0
- data/lib/zaxcel/version.rb +6 -0
- data/lib/zaxcel.rb +73 -0
- data/zaxcel.gemspec +73 -0
- metadata +266 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
# https://support.microsoft.com/en-us/office/xirr-function-de1242ec-6477-445b-b11b-a303ad9adc9d
|
|
5
|
+
class Zaxcel::Functions::Xirr < Zaxcel::Function
|
|
6
|
+
extend T::Sig
|
|
7
|
+
|
|
8
|
+
sig do
|
|
9
|
+
params(
|
|
10
|
+
values: Zaxcel::References::Range,
|
|
11
|
+
dates: Zaxcel::References::Range,
|
|
12
|
+
guess: T.nilable(Zaxcel::CellFormula),
|
|
13
|
+
).void
|
|
14
|
+
end
|
|
15
|
+
def initialize(values, dates, guess: nil)
|
|
16
|
+
@values = values
|
|
17
|
+
@dates = dates
|
|
18
|
+
@guess = guess
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
sig { override.params(on_sheet: String).returns(String) }
|
|
22
|
+
def format(on_sheet:)
|
|
23
|
+
guess_string = ", #{Zaxcel::Cell.format(@guess, on_sheet: on_sheet)}" if @guess.present?
|
|
24
|
+
|
|
25
|
+
"XIRR(#{@values.format(on_sheet: on_sheet)},#{@dates.format(on_sheet: on_sheet)}#{guess_string})"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
module Zaxcel::Functions
|
|
5
|
+
class << self
|
|
6
|
+
extend T::Sig
|
|
7
|
+
|
|
8
|
+
sig { params(value: Zaxcel::Cell::ValueType).returns(Zaxcel::Functions::Abs) }
|
|
9
|
+
def abs(value)
|
|
10
|
+
Zaxcel::Functions::Abs.new(value)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
sig do
|
|
14
|
+
params(
|
|
15
|
+
lh_value: Zaxcel::Cell::ValueType,
|
|
16
|
+
rh_value: Zaxcel::Cell::ValueType,
|
|
17
|
+
).returns(Zaxcel::Functions::And)
|
|
18
|
+
end
|
|
19
|
+
def and(lh_value, rh_value)
|
|
20
|
+
Zaxcel::Functions::And.new(lh_value, rh_value)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
sig { params(range: Zaxcel::References::Range).returns(Zaxcel::Functions::Average) }
|
|
24
|
+
def average(range)
|
|
25
|
+
Zaxcel::Functions::Average.new(range)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
sig { params(values: Zaxcel::Cell::ValueType).returns(Zaxcel::Functions::Concatenate) }
|
|
29
|
+
def concatenate(*values)
|
|
30
|
+
Zaxcel::Functions::Concatenate.new(values)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
sig do
|
|
34
|
+
params(
|
|
35
|
+
choice_index: Zaxcel::Cell::ValueType,
|
|
36
|
+
choices: T::Array[Zaxcel::Cell::ValueType],
|
|
37
|
+
).returns(Zaxcel::Functions::Choose)
|
|
38
|
+
end
|
|
39
|
+
def choose(choice_index, choices:)
|
|
40
|
+
Zaxcel::Functions::Choose.new(choice_index, choices: choices)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
sig do
|
|
44
|
+
params(
|
|
45
|
+
value: Zaxcel::Cell::ValueType,
|
|
46
|
+
default_value: Zaxcel::Cell::ValueType,
|
|
47
|
+
).returns(Zaxcel::Functions::IfError)
|
|
48
|
+
end
|
|
49
|
+
def if_error(value, default_value:)
|
|
50
|
+
Zaxcel::Functions::IfError.new(value, default_value: default_value)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
sig do
|
|
54
|
+
params(
|
|
55
|
+
index_value: Zaxcel::Cell::ValueType,
|
|
56
|
+
range: Zaxcel::References::Column,
|
|
57
|
+
).returns(Zaxcel::Functions::Index)
|
|
58
|
+
end
|
|
59
|
+
def index(index_value:, range:)
|
|
60
|
+
Zaxcel::Functions::Index.new(index_value: index_value, range: Zaxcel::Lang.range(range))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
sig { params(value: Zaxcel::Cell::ValueType, range: Zaxcel::References::Column, match_type: T.nilable(Zaxcel::Functions::Match::MatchType)).returns(Zaxcel::Functions::Match) }
|
|
64
|
+
def match(value:, range:, match_type: nil)
|
|
65
|
+
Zaxcel::Functions::Match.new(value: value, range: Zaxcel::Lang.range(range), match_type: match_type)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
sig { params(values: T.any(Zaxcel::Cell::ValueType, Zaxcel::References::Range)).returns(Zaxcel::Functions::Max) }
|
|
69
|
+
def max(*values)
|
|
70
|
+
Zaxcel::Functions::Max.new(values)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
sig { params(values: T.any(Zaxcel::Cell::ValueType, Zaxcel::References::Range)).returns(Zaxcel::Functions::Min) }
|
|
74
|
+
def min(*values)
|
|
75
|
+
Zaxcel::Functions::Min.new(values)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
sig do
|
|
79
|
+
params(
|
|
80
|
+
lh_value: Zaxcel::Cell::ValueType,
|
|
81
|
+
rh_value: Zaxcel::Cell::ValueType,
|
|
82
|
+
).returns(Zaxcel::Functions::Or)
|
|
83
|
+
end
|
|
84
|
+
def or(lh_value, rh_value)
|
|
85
|
+
Zaxcel::Functions::Or.new(lh_value, rh_value)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
sig { params(value: Zaxcel::Cell::ValueType, precision: Integer).returns(Zaxcel::Functions::Round) }
|
|
89
|
+
def round(value, precision: 0)
|
|
90
|
+
Zaxcel::Functions::Round.new(value, precision: precision)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
sig { params(values: T.any(Zaxcel::Cell::ValueType, Zaxcel::References::Range)).returns(Zaxcel::Functions::Sum) }
|
|
94
|
+
def sum(*values)
|
|
95
|
+
Zaxcel::Functions::Sum.new(values)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
sig do
|
|
99
|
+
params(
|
|
100
|
+
column_to_check: Zaxcel::References::Column,
|
|
101
|
+
value_to_check: Zaxcel::Cell::ValueType,
|
|
102
|
+
column_to_sum: Zaxcel::References::Column,
|
|
103
|
+
).returns(Zaxcel::Functions::SumIf)
|
|
104
|
+
end
|
|
105
|
+
def sum_if(column_to_check:, value_to_check:, column_to_sum:)
|
|
106
|
+
Zaxcel::Functions::SumIf.new(
|
|
107
|
+
range_to_check: Zaxcel::Lang.range(column_to_check),
|
|
108
|
+
value_to_check: value_to_check,
|
|
109
|
+
range_to_sum: Zaxcel::Lang.range(column_to_sum),
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
sig do
|
|
114
|
+
params(
|
|
115
|
+
ranges_to_check: T::Array[Zaxcel::References::Range],
|
|
116
|
+
values_to_check: T::Array[Zaxcel::Cell::ValueType],
|
|
117
|
+
range_to_sum: Zaxcel::References::Range,
|
|
118
|
+
).returns(Zaxcel::Functions::SumIfs)
|
|
119
|
+
end
|
|
120
|
+
def sum_ifs(ranges_to_check:, values_to_check:, range_to_sum:)
|
|
121
|
+
Zaxcel::Functions::SumIfs.new(
|
|
122
|
+
ranges_to_check: ranges_to_check,
|
|
123
|
+
values_to_check: values_to_check,
|
|
124
|
+
range_to_sum: range_to_sum,
|
|
125
|
+
)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
sig { params(range_values: T::Enumerable[Zaxcel::References::Range::RangeableType]).returns(Zaxcel::Functions::Sum) }
|
|
129
|
+
def sum_range(range_values)
|
|
130
|
+
range = Zaxcel::Lang.range(range_values.first!, range_values.last!) if range_values.any?
|
|
131
|
+
Zaxcel::Functions::Sum.new([range].compact)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
sig { params(value: Zaxcel::Cell::ValueType, format_string: String).returns(Zaxcel::Functions::Text) }
|
|
135
|
+
def text(value, format_string:)
|
|
136
|
+
Zaxcel::Functions::Text.new(value, format_string: format_string)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
sig { params(value: Zaxcel::Cell::ValueType).returns(Zaxcel::Functions::Len) }
|
|
140
|
+
def len(value)
|
|
141
|
+
Zaxcel::Functions::Len.new(value)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
sig do
|
|
145
|
+
params(
|
|
146
|
+
condition: Zaxcel::Cell::ValueType,
|
|
147
|
+
idx_range: Zaxcel::References::Range,
|
|
148
|
+
value_range: Zaxcel::References::Range,
|
|
149
|
+
).returns(Zaxcel::Functions::XLookup)
|
|
150
|
+
end
|
|
151
|
+
def x_lookup(condition, idx_range:, value_range:)
|
|
152
|
+
Zaxcel::Functions::XLookup.new(condition, idx_range: idx_range, value_range: value_range)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
sig do
|
|
156
|
+
params(
|
|
157
|
+
values: T::Array[Zaxcel::References::Cell],
|
|
158
|
+
dates: T::Array[Zaxcel::References::Cell],
|
|
159
|
+
guess: T.nilable(Zaxcel::CellFormula),
|
|
160
|
+
).returns(Zaxcel::Functions::Xirr)
|
|
161
|
+
end
|
|
162
|
+
def xirr(values:, dates:, guess: nil)
|
|
163
|
+
value_range = Zaxcel::References::Range.new(values.first!, values.last!)
|
|
164
|
+
date_range = Zaxcel::References::Range.new(dates.first!, dates.last!)
|
|
165
|
+
|
|
166
|
+
Zaxcel::Functions::Xirr.new(value_range, date_range, guess: guess)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
class Zaxcel::IfBuilder
|
|
5
|
+
extend T::Sig
|
|
6
|
+
|
|
7
|
+
sig { params(condition: Zaxcel::Cell::ValueType).void }
|
|
8
|
+
def initialize(condition)
|
|
9
|
+
@condition = T.let(condition, Zaxcel::Cell::ValueType)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
sig { params(result: Zaxcel::Cell::ValueType).returns(Zaxcel::IfBuilder) }
|
|
13
|
+
def then(result)
|
|
14
|
+
@then = T.let(result, Zaxcel::Cell::ValueType)
|
|
15
|
+
self
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
sig { params(result: Zaxcel::Cell::ValueType).returns(Zaxcel::Functions::If) }
|
|
19
|
+
def else(result)
|
|
20
|
+
Zaxcel::Functions::If.new(@condition, if_true: @then, if_false: result)
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/zaxcel/lang.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
module Zaxcel::Lang
|
|
5
|
+
class << self
|
|
6
|
+
extend T::Sig
|
|
7
|
+
|
|
8
|
+
sig { params(condition: Zaxcel::Cell::ValueType).returns(Zaxcel::IfBuilder) }
|
|
9
|
+
def if(condition)
|
|
10
|
+
Zaxcel::IfBuilder.new(condition)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
sig do
|
|
14
|
+
params(
|
|
15
|
+
lh_value: Zaxcel::References::Range::RangeableType,
|
|
16
|
+
rh_value: T.nilable(Zaxcel::References::Range::RangeableType),
|
|
17
|
+
).returns(Zaxcel::References::Range)
|
|
18
|
+
end
|
|
19
|
+
def range(lh_value, rh_value = nil)
|
|
20
|
+
Zaxcel::References::Range.new(lh_value, rh_value)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
class Zaxcel::Reference
|
|
5
|
+
extend T::Sig
|
|
6
|
+
extend T::Helpers
|
|
7
|
+
|
|
8
|
+
abstract!
|
|
9
|
+
|
|
10
|
+
sig { abstract.returns(String) }
|
|
11
|
+
def sheet_name; end
|
|
12
|
+
|
|
13
|
+
sig { abstract.returns(String) }
|
|
14
|
+
def excel_sheet_name; end
|
|
15
|
+
|
|
16
|
+
sig { abstract.returns(String) }
|
|
17
|
+
def resolve; end
|
|
18
|
+
|
|
19
|
+
sig { params(on_sheet: String).returns(T.nilable(String)) }
|
|
20
|
+
def format(on_sheet:)
|
|
21
|
+
formatted_string = resolve
|
|
22
|
+
return if formatted_string.blank?
|
|
23
|
+
|
|
24
|
+
formatted_string = "'#{excel_sheet_name}'!#{formatted_string}" if on_sheet.present? && on_sheet != sheet_name
|
|
25
|
+
|
|
26
|
+
formatted_string
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
class Zaxcel::References::Cell < Zaxcel::Reference
|
|
5
|
+
include Zaxcel::Arithmetic
|
|
6
|
+
include Zaxcel::Roundable
|
|
7
|
+
extend T::Sig
|
|
8
|
+
|
|
9
|
+
sig { override.returns(String) }
|
|
10
|
+
attr_reader :sheet_name
|
|
11
|
+
|
|
12
|
+
sig { returns(Zaxcel::Document) }
|
|
13
|
+
attr_reader :document
|
|
14
|
+
|
|
15
|
+
sig { returns(Symbol) }
|
|
16
|
+
attr_reader :column_name, :row_name
|
|
17
|
+
|
|
18
|
+
sig { params(document: Zaxcel::Document, sheet_name: String, row_name: Symbol, col_name: Symbol).void }
|
|
19
|
+
def initialize(document:, sheet_name:, row_name:, col_name:)
|
|
20
|
+
super()
|
|
21
|
+
|
|
22
|
+
@document = document
|
|
23
|
+
@sheet_name = sheet_name
|
|
24
|
+
@column_name = col_name
|
|
25
|
+
@row_name = row_name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
sig { override.returns(String) }
|
|
29
|
+
def resolve
|
|
30
|
+
cell&.to_excel || ''
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
sig { override.returns(String) }
|
|
34
|
+
def excel_sheet_name
|
|
35
|
+
T.must(@document.sheet_by_name[@sheet_name]&.to_excel)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
sig { returns(T.nilable(Zaxcel::Cell)) }
|
|
39
|
+
def cell
|
|
40
|
+
@document.sheet(@sheet_name)&.column(@column_name)&.cell(@row_name)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
class Zaxcel::References::Column < Zaxcel::Reference
|
|
5
|
+
extend T::Sig
|
|
6
|
+
|
|
7
|
+
sig { override.returns(String) }
|
|
8
|
+
attr_reader :sheet_name
|
|
9
|
+
|
|
10
|
+
sig { params(sheet_name: String, col_name: Symbol, document: Zaxcel::Document).void }
|
|
11
|
+
def initialize(sheet_name:, col_name:, document:)
|
|
12
|
+
super()
|
|
13
|
+
|
|
14
|
+
@sheet_name = sheet_name
|
|
15
|
+
@col_name = col_name
|
|
16
|
+
@document = document
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
sig { override.returns(String) }
|
|
20
|
+
def resolve
|
|
21
|
+
T.must_because(column) { "No column on sheet #{sheet_name} named #{@col_name}" }
|
|
22
|
+
.to_excel
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
sig { returns(T.nilable(Zaxcel::Column)) }
|
|
26
|
+
def column
|
|
27
|
+
@column ||= T.let(@document.sheet(@sheet_name)&.column(@col_name), T.nilable(Zaxcel::Column))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
sig { override.returns(String) }
|
|
31
|
+
def excel_sheet_name
|
|
32
|
+
T.must(@document.sheet_by_name[@sheet_name]&.to_excel)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
sig { returns(T::Array[Zaxcel::Cell]) }
|
|
36
|
+
def cells
|
|
37
|
+
return [] if column.nil?
|
|
38
|
+
|
|
39
|
+
@cells ||= T.let(
|
|
40
|
+
begin
|
|
41
|
+
cells_in_column = T.must(column).cell_by_row_name.values
|
|
42
|
+
raise 'Must position cells before resolving references.' if cells_in_column.any? { |cell| cell.col_position.nil? }
|
|
43
|
+
|
|
44
|
+
cells_in_column.sort_by { |cell| T.must(cell.row_position) }
|
|
45
|
+
end,
|
|
46
|
+
T.nilable(T::Array[Zaxcel::Cell]),
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
class Zaxcel::References::Range < Zaxcel::Reference
|
|
5
|
+
extend T::Sig
|
|
6
|
+
|
|
7
|
+
RangeableType = T.type_alias { T.any(Zaxcel::References::Cell, Zaxcel::References::Row, Zaxcel::References::Column) }
|
|
8
|
+
|
|
9
|
+
sig { params(lh_value: RangeableType, rh_value: T.nilable(RangeableType)).void }
|
|
10
|
+
def initialize(lh_value, rh_value)
|
|
11
|
+
super()
|
|
12
|
+
|
|
13
|
+
rh_value ||= lh_value
|
|
14
|
+
raise 'Ranges must be from cells on the same sheet' if lh_value.sheet_name != rh_value.sheet_name
|
|
15
|
+
raise "Incompatible range values #{lh_value.class.name}:#{rh_value.class.name}" if lh_value.class != rh_value.class
|
|
16
|
+
|
|
17
|
+
@lh_value = lh_value
|
|
18
|
+
@rh_value = T.let(rh_value, RangeableType)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
sig { override.returns(String) }
|
|
22
|
+
def resolve
|
|
23
|
+
"#{@lh_value.resolve}:#{@rh_value.resolve}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
sig { override.returns(String) }
|
|
27
|
+
def excel_sheet_name
|
|
28
|
+
@lh_value.excel_sheet_name
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
sig { override.returns(String) }
|
|
32
|
+
def sheet_name
|
|
33
|
+
@lh_value.sheet_name
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
class Zaxcel::References::Row < Zaxcel::Reference
|
|
5
|
+
extend T::Sig
|
|
6
|
+
|
|
7
|
+
sig { override.returns(String) }
|
|
8
|
+
attr_reader :sheet_name
|
|
9
|
+
|
|
10
|
+
sig { params(sheet_name: String, row_name: Symbol, document: Zaxcel::Document).void }
|
|
11
|
+
def initialize(sheet_name:, row_name:, document:)
|
|
12
|
+
super()
|
|
13
|
+
|
|
14
|
+
@sheet_name = sheet_name
|
|
15
|
+
@row_name = row_name
|
|
16
|
+
@document = document
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
sig { override.returns(String) }
|
|
20
|
+
def resolve
|
|
21
|
+
T.must_because(row) { "No row on sheet #{sheet_name} named #{@row_name}" }
|
|
22
|
+
.to_excel
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
sig { override.returns(String) }
|
|
26
|
+
def excel_sheet_name
|
|
27
|
+
T.must(@document.sheet_by_name[@sheet_name]&.to_excel)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
sig { returns(T.nilable(Zaxcel::Row)) }
|
|
31
|
+
def row
|
|
32
|
+
@row ||= T.let(@document.sheet(sheet_name)&.row(@row_name), T.nilable(Zaxcel::Row))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
module Zaxcel::Roundable
|
|
5
|
+
extend T::Sig
|
|
6
|
+
extend T::Helpers
|
|
7
|
+
|
|
8
|
+
requires_ancestor { Zaxcel::Arithmetic }
|
|
9
|
+
|
|
10
|
+
sig { params(precision: Integer).returns(Zaxcel::Functions::Round) }
|
|
11
|
+
def round(precision: 0)
|
|
12
|
+
Zaxcel::Functions::Round.new(T.bind(self, Zaxcel::Arithmetic), precision: precision)
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/zaxcel/row.rb
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
class Zaxcel::Row
|
|
5
|
+
extend T::Sig
|
|
6
|
+
|
|
7
|
+
sig { returns(Symbol) }
|
|
8
|
+
attr_reader :name, :style_group
|
|
9
|
+
|
|
10
|
+
sig { returns(T.nilable(Integer)) }
|
|
11
|
+
attr_reader :height
|
|
12
|
+
|
|
13
|
+
sig { returns(T.nilable(Integer)) }
|
|
14
|
+
attr_reader :position
|
|
15
|
+
|
|
16
|
+
sig { params(row_name: Symbol, sheet: Zaxcel::Sheet, style_group: Symbol, height: T.nilable(Integer), hidden: T::Boolean).void }
|
|
17
|
+
def initialize(row_name, sheet:, style_group: :row_style, height: nil, hidden: false)
|
|
18
|
+
@name = row_name
|
|
19
|
+
@sheet = sheet
|
|
20
|
+
@style_group = style_group
|
|
21
|
+
@height = height
|
|
22
|
+
@print_boundary = T.let(false, T::Boolean)
|
|
23
|
+
@hidden = hidden
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
sig { params(col_name: T.any(String, Symbol), sheet_name: T.nilable(String)).returns(Zaxcel::References::Cell) }
|
|
27
|
+
def ref(col_name, sheet_name: nil)
|
|
28
|
+
Zaxcel::References::Cell.new(document: @sheet.document, sheet_name: sheet_name || @sheet.name, col_name: col_name.to_sym, row_name: @name)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
sig { params(column_name: T.any(Symbol, String), value: Zaxcel::Cell::ValueType, style: T.nilable(Symbol), to_extract: T::Boolean).returns(Zaxcel::Row) }
|
|
32
|
+
def add!(column_name, value:, style: nil, to_extract: false)
|
|
33
|
+
column = @sheet.column(column_name)
|
|
34
|
+
raise "Cannot add a cell to a non-existent column #{column_name}" if column.nil?
|
|
35
|
+
|
|
36
|
+
cell_by_column_name[column_name.to_sym] = column.add_cell!(value: value, row: self, style: style, to_extract: to_extract)
|
|
37
|
+
|
|
38
|
+
self
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
sig { params(col_name: T.any(Symbol, String)).void }
|
|
42
|
+
def add_empty!(col_name)
|
|
43
|
+
add!(col_name, value: Zaxcel::Cell::EMPTY_VALUE)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
sig { params(cell_value_hash: T::Hash[Symbol, Zaxcel::Cell::ValueType]).returns(Zaxcel::Row) }
|
|
47
|
+
def add_many!(cell_value_hash)
|
|
48
|
+
cell_value_hash.each do |col_name, value|
|
|
49
|
+
add!(col_name.to_sym, value: value)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
self
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
sig { params(column_name: T.any(Symbol, String)).returns(T.nilable(Zaxcel::Cell)) }
|
|
56
|
+
def cell(column_name)
|
|
57
|
+
cell_by_column_name[column_name.to_sym]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
sig { params(row_position: Integer).void }
|
|
61
|
+
def position!(row_position)
|
|
62
|
+
@position = T.let(row_position, T.nilable(Integer))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
sig { returns(T::Hash[Symbol, Zaxcel::Cell]) }
|
|
66
|
+
def cell_by_column_name
|
|
67
|
+
@cell_by_column_name ||= T.let({}, T.nilable(T::Hash[Symbol, Zaxcel::Cell]))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
sig { returns(String) }
|
|
71
|
+
def to_excel
|
|
72
|
+
raise 'Must position cells before calling to_excel' if @position.nil?
|
|
73
|
+
|
|
74
|
+
@position.to_s
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
sig { void }
|
|
78
|
+
def set_print_boundary!
|
|
79
|
+
raise 'Print boundary row already exists' if @sheet.print_boundary_row.present?
|
|
80
|
+
|
|
81
|
+
@print_boundary = true
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
sig { returns(T::Boolean) }
|
|
85
|
+
def print_boundary?
|
|
86
|
+
@print_boundary
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
sig { returns(T::Boolean) }
|
|
90
|
+
def hidden?
|
|
91
|
+
@hidden
|
|
92
|
+
end
|
|
93
|
+
end
|