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.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +4 -0
  3. data/.rubocop.yml +9 -0
  4. data/CHANGELOG.md +29 -0
  5. data/CONTRIBUTING.md +110 -0
  6. data/LICENSE +22 -0
  7. data/QUICK_START.md +187 -0
  8. data/README.md +372 -0
  9. data/Rakefile +18 -0
  10. data/SETUP.md +178 -0
  11. data/lib/enumerable.rb +47 -0
  12. data/lib/zaxcel/README.md +37 -0
  13. data/lib/zaxcel/arithmetic.rb +88 -0
  14. data/lib/zaxcel/binary_expression.rb +74 -0
  15. data/lib/zaxcel/binary_expressions/addition.rb +36 -0
  16. data/lib/zaxcel/binary_expressions/division.rb +24 -0
  17. data/lib/zaxcel/binary_expressions/multiplication.rb +24 -0
  18. data/lib/zaxcel/binary_expressions/subtraction.rb +41 -0
  19. data/lib/zaxcel/binary_expressions.rb +38 -0
  20. data/lib/zaxcel/cell.rb +141 -0
  21. data/lib/zaxcel/cell_formula.rb +16 -0
  22. data/lib/zaxcel/column.rb +142 -0
  23. data/lib/zaxcel/document.rb +136 -0
  24. data/lib/zaxcel/function.rb +6 -0
  25. data/lib/zaxcel/functions/abs.rb +18 -0
  26. data/lib/zaxcel/functions/and.rb +23 -0
  27. data/lib/zaxcel/functions/average.rb +17 -0
  28. data/lib/zaxcel/functions/choose.rb +20 -0
  29. data/lib/zaxcel/functions/concatenate.rb +20 -0
  30. data/lib/zaxcel/functions/if.rb +38 -0
  31. data/lib/zaxcel/functions/if_error.rb +25 -0
  32. data/lib/zaxcel/functions/index.rb +20 -0
  33. data/lib/zaxcel/functions/len.rb +16 -0
  34. data/lib/zaxcel/functions/match/match_type.rb +13 -0
  35. data/lib/zaxcel/functions/match.rb +27 -0
  36. data/lib/zaxcel/functions/max.rb +17 -0
  37. data/lib/zaxcel/functions/min.rb +17 -0
  38. data/lib/zaxcel/functions/negate.rb +26 -0
  39. data/lib/zaxcel/functions/or.rb +23 -0
  40. data/lib/zaxcel/functions/round.rb +20 -0
  41. data/lib/zaxcel/functions/sum.rb +18 -0
  42. data/lib/zaxcel/functions/sum_if.rb +20 -0
  43. data/lib/zaxcel/functions/sum_ifs.rb +34 -0
  44. data/lib/zaxcel/functions/sum_product.rb +18 -0
  45. data/lib/zaxcel/functions/text.rb +17 -0
  46. data/lib/zaxcel/functions/unique.rb +23 -0
  47. data/lib/zaxcel/functions/x_lookup.rb +28 -0
  48. data/lib/zaxcel/functions/xirr.rb +27 -0
  49. data/lib/zaxcel/functions.rb +169 -0
  50. data/lib/zaxcel/if_builder.rb +22 -0
  51. data/lib/zaxcel/lang.rb +23 -0
  52. data/lib/zaxcel/reference.rb +28 -0
  53. data/lib/zaxcel/references/cell.rb +42 -0
  54. data/lib/zaxcel/references/column.rb +49 -0
  55. data/lib/zaxcel/references/range.rb +35 -0
  56. data/lib/zaxcel/references/row.rb +34 -0
  57. data/lib/zaxcel/references.rb +5 -0
  58. data/lib/zaxcel/roundable.rb +14 -0
  59. data/lib/zaxcel/row.rb +93 -0
  60. data/lib/zaxcel/sheet.rb +425 -0
  61. data/lib/zaxcel/sorbet/enumerizable_enum.rb +50 -0
  62. data/lib/zaxcel/version.rb +6 -0
  63. data/lib/zaxcel.rb +73 -0
  64. data/zaxcel.gemspec +73 -0
  65. metadata +266 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5af2f7d221d3fb5e8955cd42f4d1e8e33d337786a832965ba35daf37fb7fdcce
4
+ data.tar.gz: 403fde35db97b0dbb5ee1c333ef9f517e3bc159324c6aba79a9bb1ffa0c77f62
5
+ SHA512:
6
+ metadata.gz: 214988bd63bf56d06901b168413023fccfce1c0b6230f75b1085035bf57458b8808fc33404ccfdb33b9effb4cabef7f124aa985e1450bc7dcc046009e2baf8e8
7
+ data.tar.gz: c02164fbca4b8bc3c91036744ba69ea40dc7e527f32d4e3c527d68fe1437f33ec9741005191a4402a488e3e37bf5b2ae685fef8d40cd90003aaeb4725eca9510
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --require spec_helper
2
+ --color
3
+ --format documentation
4
+
data/.rubocop.yml ADDED
@@ -0,0 +1,9 @@
1
+ inherit_gem:
2
+ rubocop-angellist: rubocop.yml
3
+
4
+ # Local project tweaks can go below. Keep minimal; rely on shared config.
5
+ AllCops:
6
+ Exclude:
7
+ - "vendor/**/*"
8
+ - "sorbet/**/*"
9
+ - "tmp/**/*"
data/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.1] - 2025-10-29
9
+
10
+ ### Changed
11
+
12
+ - Updated specs
13
+
14
+ ## [0.1.0] - 2025-10-29
15
+
16
+ ### Added
17
+
18
+ - Initial public release
19
+ - Core DSL for building Excel documents
20
+ - Support for cross-sheet references
21
+ - Formula building with Ruby operators
22
+ - Comprehensive Excel function library (SUM, SUMIF, SUMIFS, XLOOKUP, etc.)
23
+ - Cell styling and formatting
24
+ - Sheet visibility controls
25
+ - Column width configuration
26
+ - Type safety with Sorbet
27
+
28
+ [0.1.0]: https://github.com/angellist/zaxcel/releases/tag/v0.1.0
29
+ [0.1.1]: https://github.com/angellist/zaxcel/releases/tag/v0.1.1
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,110 @@
1
+ # Contributing to Zaxcel
2
+
3
+ Thank you for considering contributing to Zaxcel! This document outlines the process for contributing to this project.
4
+
5
+ ## Code of Conduct
6
+
7
+ This project adheres to a code of conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to engineering@angellist.com.
8
+
9
+ ## How Can I Contribute?
10
+
11
+ ### Reporting Bugs
12
+
13
+ Before creating bug reports, please check the existing issues to avoid duplicates. When creating a bug report, include:
14
+
15
+ * A clear and descriptive title
16
+ * Detailed steps to reproduce the problem
17
+ * Expected behavior
18
+ * Actual behavior
19
+ * Ruby version and gem version
20
+ * Any relevant code samples or test cases
21
+
22
+ ### Suggesting Enhancements
23
+
24
+ Enhancement suggestions are welcome! Please include:
25
+
26
+ * A clear and descriptive title
27
+ * A detailed description of the proposed functionality
28
+ * Examples of how the feature would be used
29
+ * Any relevant implementation details
30
+
31
+ ### Pull Requests
32
+
33
+ 1. Fork the repo and create your branch from `main`
34
+ 2. If you've added code, add tests
35
+ 3. If you've changed APIs, update the documentation
36
+ 4. Ensure the test suite passes (`bundle exec rspec`)
37
+ 5. Ensure type checking passes (`bundle exec srb tc`)
38
+ 6. Make sure your code follows the existing style (run `bundle exec rubocop`)
39
+ 7. Write a clear commit message
40
+
41
+ ## Development Setup
42
+
43
+ ```bash
44
+ git clone https://github.com/angellist/zaxcel.git
45
+ cd zaxcel
46
+ bundle install
47
+ bundle exec rspec
48
+ ```
49
+
50
+ ## Type Checking with Sorbet
51
+
52
+ This project uses Sorbet for type safety. Please ensure all new code includes type signatures:
53
+
54
+ ```ruby
55
+ extend T::Sig
56
+
57
+ sig { params(name: String).returns(Integer) }
58
+ def my_method(name)
59
+ # implementation
60
+ end
61
+ ```
62
+
63
+ Run type checking with:
64
+
65
+ ```bash
66
+ bundle exec srb tc
67
+ ```
68
+
69
+ ## Testing Guidelines
70
+
71
+ * Write RSpec tests for all new functionality
72
+ * Aim for high test coverage
73
+ * Test both success and error cases
74
+ * Include integration tests for complex features
75
+
76
+ ## Style Guide
77
+
78
+ This project follows standard Ruby style guidelines enforced by RuboCop. Run:
79
+
80
+ ```bash
81
+ bundle exec rubocop
82
+ ```
83
+
84
+ To auto-correct issues:
85
+
86
+ ```bash
87
+ bundle exec rubocop -a
88
+ ```
89
+
90
+ ## Documentation
91
+
92
+ * Update README.md for user-facing changes
93
+ * Add YARD comments for new public methods
94
+ * Update CHANGELOG.md following Keep a Changelog format
95
+
96
+ ## Release Process
97
+
98
+ (For maintainers)
99
+
100
+ 1. Update version in `lib/zaxcel.rb`
101
+ 2. Update CHANGELOG.md with release date
102
+ 3. Create a git tag: `git tag -a v1.0.0 -m "Release 1.0.0"`
103
+ 4. Push tag: `git push origin v1.0.0`
104
+ 5. Build gem: `gem build zaxcel.gemspec`
105
+ 6. Push to RubyGems: `gem push zaxcel-1.0.0.gem`
106
+
107
+ ## Questions?
108
+
109
+ Feel free to open an issue for questions or discussion!
110
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 AngelList
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/QUICK_START.md ADDED
@@ -0,0 +1,187 @@
1
+ # Zaxcel Quick Start Guide
2
+
3
+ Get started with Zaxcel in 5 minutes!
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ cd zaxcel_gem
9
+ bundle install
10
+ ```
11
+
12
+ ## Your First Spreadsheet
13
+
14
+ Create a file called `my_first_sheet.rb`:
15
+
16
+ ```ruby
17
+ require 'bundler/setup'
18
+ require 'zaxcel'
19
+
20
+ # Create a document
21
+ document = Zaxcel::Document.new
22
+ sheet = document.add_sheet!('My Sheet')
23
+
24
+ # Add columns
25
+ sheet.add_column!(:name)
26
+ sheet.add_column!(:age)
27
+
28
+ # Add rows
29
+ sheet.add_row!(:person1)
30
+ .add!(:name, value: 'Alice')
31
+ .add!(:age, value: 30)
32
+
33
+ sheet.add_row!(:person2)
34
+ .add!(:name, value: 'Bob')
35
+ .add!(:age, value: 25)
36
+
37
+ # Position and generate sheet (after all content is added)
38
+ sheet.position_rows!
39
+ sheet.generate_sheet!
40
+ File.write('people.xlsx', document.file_contents)
41
+
42
+ puts "Created people.xlsx!"
43
+ ```
44
+
45
+ Run it:
46
+
47
+ ```bash
48
+ ruby my_first_sheet.rb
49
+ ```
50
+
51
+ Open `people.xlsx` in Excel or LibreOffice!
52
+
53
+ ## Adding Formulas
54
+
55
+ Let's add some calculations:
56
+
57
+ ```ruby
58
+ require 'bundler/setup'
59
+ require 'zaxcel'
60
+
61
+ document = Zaxcel::Document.new
62
+ sheet = document.add_sheet!('Math')
63
+
64
+ sheet.add_column!(:label)
65
+ sheet.add_column!(:value)
66
+
67
+ # Add some numbers
68
+ row1 = sheet.add_row!(:num1).add!(:label, value: 'First').add!(:value, value: 10)
69
+ row2 = sheet.add_row!(:num2).add!(:label, value: 'Second').add!(:value, value: 20)
70
+
71
+ # Add a sum formula
72
+ sheet.add_row!(:total)
73
+ .add!(:label, value: 'Total')
74
+ .add!(:value, row1.ref(:value) + row2.ref(:value))
75
+
76
+ # Position and generate sheet (after all content is added)
77
+ sheet.position_rows!
78
+ sheet.generate_sheet!
79
+ File.write('math.xlsx', document.file_contents)
80
+ ```
81
+
82
+ ## Styling Cells
83
+
84
+ Add some color:
85
+
86
+ ```ruby
87
+ require 'bundler/setup'
88
+ require 'zaxcel'
89
+
90
+ document = Zaxcel::Document.new
91
+
92
+ # Define a style
93
+ document.add_style!(:header, {
94
+ bg_color: '0066CC',
95
+ fg_color: 'FFFFFF',
96
+ b: true
97
+ })
98
+
99
+ sheet = document.add_sheet!('Styled')
100
+ sheet.add_column!(:category)
101
+
102
+ # Use the style
103
+ sheet.add_row!(:header)
104
+ .add!(:category, value: 'Category', style: :header)
105
+
106
+ sheet.add_row!(:data)
107
+ .add!(:category, value: 'Data')
108
+
109
+ # Position and generate sheet (after all content is added)
110
+ sheet.position_rows!
111
+ sheet.generate_sheet!
112
+ File.write('styled.xlsx', document.file_contents)
113
+ ```
114
+
115
+ ## Try the Examples
116
+
117
+ Check out the `examples/` directory for more:
118
+
119
+ ```bash
120
+ ruby examples/basic_spreadsheet.rb
121
+ ruby examples/cross_sheet_references.rb
122
+ ```
123
+
124
+ ## Next Steps
125
+
126
+ - Read the full [README.md](README.md) for comprehensive documentation
127
+ - Browse example code in `examples/`
128
+ - Check out the test suite in `spec/` for more usage patterns
129
+ - Try building your own spreadsheets!
130
+
131
+ ## Common Patterns
132
+
133
+ ### Building a Report
134
+
135
+ ```ruby
136
+ # Create document
137
+ document = Zaxcel::Document.new
138
+ sheet = document.add_sheet!('Report')
139
+
140
+ # Set up columns
141
+ [:date, :description, :amount].each { |col| sheet.add_column!(col) }
142
+
143
+ # Add data
144
+ data = [
145
+ { date: '2025-01-01', description: 'Sale', amount: 100 },
146
+ { date: '2025-01-02', description: 'Purchase', amount: -50 }
147
+ ]
148
+
149
+ data.each_with_index do |item, i|
150
+ sheet.add_row!(:"row_#{i}")
151
+ .add!(:date, value: item[:date])
152
+ .add!(:description, value: item[:description])
153
+ .add!(:amount, value: item[:amount])
154
+ end
155
+
156
+ # Position and generate sheet (after all content is added)
157
+ sheet.position_rows!
158
+ sheet.generate_sheet!
159
+ ```
160
+
161
+ ### Using Functions
162
+
163
+ ```ruby
164
+ # Sum a range
165
+ sum = Zaxcel::Functions.sum_range([first_row.ref(:amount), last_row.ref(:amount)])
166
+
167
+ # Average
168
+ avg = Zaxcel::Functions::Average.new(values)
169
+
170
+ # Conditional
171
+ status = Zaxcel::Functions::If.new(
172
+ condition: row.ref(:amount) > 100,
173
+ true_value: 'High',
174
+ false_value: 'Low'
175
+ )
176
+
177
+ # Round
178
+ rounded = Zaxcel::Functions.round(value, precision: 2)
179
+ ```
180
+
181
+ ## Need Help?
182
+
183
+ - Check [README.md](README.md) for full documentation
184
+ - Look at [examples/](examples/) for working code
185
+ - Open an issue on GitHub
186
+
187
+ Happy spreadsheet building! 📊