xlsxrb 0.1.10 → 0.1.12
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 +4 -4
- data/.mutant.yml +8 -0
- data/CHANGELOG.md +54 -0
- data/README.md +1 -0
- data/Rakefile +66 -0
- data/benchmark.rb +3 -1
- data/docs/ARCHITECTURE.md +1 -1
- data/docs/DEVELOPMENT.md +6 -2
- data/docs/MUTATION_TESTING.md +52 -0
- data/docs/PEER_LIBRARIES.md +14 -14
- data/docs/QUALITY_ASSURANCE.md +1 -0
- data/docs/assets/benchmark_results.svg +49 -49
- data/docs/visual/VisualGallery.md +38 -27
- data/docs/wasm/ruby.wasm +0 -0
- data/lib/xlsxrb/chart_builder.rb +18 -18
- data/lib/xlsxrb/dsl_helpers.rb +116 -0
- data/lib/xlsxrb/elements/cell.rb +122 -34
- data/lib/xlsxrb/elements/column.rb +27 -3
- data/lib/xlsxrb/elements/row.rb +27 -8
- data/lib/xlsxrb/elements/workbook.rb +16 -14
- data/lib/xlsxrb/elements/worksheet.rb +17 -1
- data/lib/xlsxrb/ooxml/cfb.rb +9 -6
- data/lib/xlsxrb/ooxml/crypto/agile.rb +5 -5
- data/lib/xlsxrb/ooxml/reader/listeners/core_listeners.rb +784 -0
- data/lib/xlsxrb/ooxml/reader/listeners/drawing_listeners.rb +3478 -0
- data/lib/xlsxrb/ooxml/reader/listeners/feature_listeners.rb +1796 -0
- data/lib/xlsxrb/ooxml/reader/listeners/style_listeners.rb +428 -0
- data/lib/xlsxrb/ooxml/reader/listeners.rb +4 -6446
- data/lib/xlsxrb/ooxml/utils.rb +5 -6
- data/lib/xlsxrb/ooxml/workbook_writer.rb +287 -226
- data/lib/xlsxrb/ooxml/worksheet_parser.rb +115 -208
- data/lib/xlsxrb/ooxml/worksheet_writer.rb +122 -9
- data/lib/xlsxrb/ooxml/writer/drawing_xml.rb +1602 -0
- data/lib/xlsxrb/ooxml/writer/features_xml.rb +731 -0
- data/lib/xlsxrb/ooxml/writer/styles_xml.rb +348 -0
- data/lib/xlsxrb/ooxml/writer.rb +7 -2645
- data/lib/xlsxrb/ooxml/xml_builder.rb +11 -2
- data/lib/xlsxrb/ooxml/zip_generator.rb +26 -5
- data/lib/xlsxrb/ooxml/zip_writer.rb +31 -38
- data/lib/xlsxrb/stream_row.rb +30 -6
- data/lib/xlsxrb/stream_sheet.rb +2 -8
- data/lib/xlsxrb/stream_writer.rb +186 -133
- data/lib/xlsxrb/style_builder.rb +10 -1
- data/lib/xlsxrb/version.rb +1 -1
- data/lib/xlsxrb/worksheet_builder.rb +16 -50
- data/lib/xlsxrb.rb +1 -0
- data/sig/generated/xlsxrb/chart_builder.rbs +36 -36
- data/sig/generated/xlsxrb/dsl_helpers.rbs +60 -0
- data/sig/generated/xlsxrb/elements/cell.rbs +166 -12
- data/sig/generated/xlsxrb/elements/column.rbs +32 -21
- data/sig/generated/xlsxrb/elements/row.rbs +94 -14
- data/sig/generated/xlsxrb/elements/workbook.rbs +95 -10
- data/sig/generated/xlsxrb/elements/worksheet.rbs +9 -0
- data/sig/generated/xlsxrb/ooxml/reader/listeners/core_listeners.rbs +173 -0
- data/sig/generated/xlsxrb/ooxml/reader/listeners/drawing_listeners.rbs +400 -0
- data/sig/generated/xlsxrb/ooxml/reader/listeners/feature_listeners.rbs +442 -0
- data/sig/generated/xlsxrb/ooxml/reader/listeners/style_listeners.rbs +80 -0
- data/sig/generated/xlsxrb/ooxml/reader/listeners.rbs +0 -1072
- data/sig/generated/xlsxrb/ooxml/utils.rbs +2 -0
- data/sig/generated/xlsxrb/ooxml/workbook_writer.rbs +17 -1
- data/sig/generated/xlsxrb/ooxml/worksheet_parser.rbs +16 -2
- data/sig/generated/xlsxrb/ooxml/worksheet_writer.rbs +4 -0
- data/sig/generated/xlsxrb/ooxml/writer/drawing_xml.rbs +79 -0
- data/sig/generated/xlsxrb/ooxml/writer/features_xml.rbs +83 -0
- data/sig/generated/xlsxrb/ooxml/writer/styles_xml.rbs +53 -0
- data/sig/generated/xlsxrb/ooxml/writer.rbs +6 -185
- data/sig/generated/xlsxrb/ooxml/xml_builder.rbs +7 -0
- data/sig/generated/xlsxrb/ooxml/zip_generator.rbs +15 -0
- data/sig/generated/xlsxrb/stream_row.rbs +3 -0
- data/sig/generated/xlsxrb/stream_writer.rbs +7 -1
- data/sig/generated/xlsxrb/style_builder.rbs +7 -0
- metadata +19 -1
|
@@ -1136,8 +1136,8 @@ end
|
|
|
1136
1136
|
```text
|
|
1137
1137
|
=== Read Validation ===
|
|
1138
1138
|
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
|
|
1139
|
-
Row 1: A2: "Positive Yen" (Format ID: , Code: nil), B2: 12500 (Format ID:
|
|
1140
|
-
Row 2: A3: "Negative Yen" (Format ID: , Code: nil), B3: -8000 (Format ID:
|
|
1139
|
+
Row 1: A2: "Positive Yen" (Format ID: , Code: nil), B2: 12500 (Format ID: 166, Code: "¥#,##0;[Red]¥-#,##0")
|
|
1140
|
+
Row 2: A3: "Negative Yen" (Format ID: , Code: nil), B3: -8000 (Format ID: 166, Code: "¥#,##0;[Red]¥-#,##0")
|
|
1141
1141
|
```
|
|
1142
1142
|
|
|
1143
1143
|
<hr/>
|
|
@@ -1187,8 +1187,8 @@ end
|
|
|
1187
1187
|
```text
|
|
1188
1188
|
=== Read Validation ===
|
|
1189
1189
|
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
|
|
1190
|
-
Row 1: A2: "Positive (Green)" (Format ID: , Code: nil), B2: 5000 (Format ID:
|
|
1191
|
-
Row 2: A3: "Negative (Red)" (Format ID: , Code: nil), B3: -2500 (Format ID:
|
|
1190
|
+
Row 1: A2: "Positive (Green)" (Format ID: , Code: nil), B2: 5000 (Format ID: 166, Code: "[Green]#,##0;[Red]-#,##0")
|
|
1191
|
+
Row 2: A3: "Negative (Red)" (Format ID: , Code: nil), B3: -2500 (Format ID: 166, Code: "[Green]#,##0;[Red]-#,##0")
|
|
1192
1192
|
```
|
|
1193
1193
|
|
|
1194
1194
|
<hr/>
|
|
@@ -1239,9 +1239,9 @@ end
|
|
|
1239
1239
|
```text
|
|
1240
1240
|
=== Read Validation ===
|
|
1241
1241
|
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
|
|
1242
|
-
Row 1: A2: "Half" (Format ID: , Code: nil), B2: 0.5 (Format ID:
|
|
1243
|
-
Row 2: A3: "Third" (Format ID: , Code: nil), B3: 0.3333 (Format ID:
|
|
1244
|
-
Row 3: A4: "Quarter" (Format ID: , Code: nil), B4: 0.75 (Format ID:
|
|
1242
|
+
Row 1: A2: "Half" (Format ID: , Code: nil), B2: 0.5 (Format ID: 166, Code: "# ?/?")
|
|
1243
|
+
Row 2: A3: "Third" (Format ID: , Code: nil), B3: 0.3333 (Format ID: 166, Code: "# ?/?")
|
|
1244
|
+
Row 3: A4: "Quarter" (Format ID: , Code: nil), B4: 0.75 (Format ID: 166, Code: "# ?/?")
|
|
1245
1245
|
```
|
|
1246
1246
|
|
|
1247
1247
|
<hr/>
|
|
@@ -1290,7 +1290,7 @@ end
|
|
|
1290
1290
|
```text
|
|
1291
1291
|
=== Read Validation ===
|
|
1292
1292
|
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
|
|
1293
|
-
Row 1: A2: "Percent with 2 Decimals" (Format ID: , Code: nil), B2: 0.12345 (Format ID:
|
|
1293
|
+
Row 1: A2: "Percent with 2 Decimals" (Format ID: , Code: nil), B2: 0.12345 (Format ID: 166, Code: "0.00%")
|
|
1294
1294
|
```
|
|
1295
1295
|
|
|
1296
1296
|
<hr/>
|
|
@@ -1340,8 +1340,8 @@ end
|
|
|
1340
1340
|
```text
|
|
1341
1341
|
=== Read Validation ===
|
|
1342
1342
|
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
|
|
1343
|
-
Row 1: A2: "Scientific" (Format ID: , Code: nil), B2: 123456789.0 (Format ID:
|
|
1344
|
-
Row 2: A3: "Small Scientific" (Format ID: , Code: nil), B3: 1.234e-05 (Format ID:
|
|
1343
|
+
Row 1: A2: "Scientific" (Format ID: , Code: nil), B2: 123456789.0 (Format ID: 166, Code: "0.00E+00")
|
|
1344
|
+
Row 2: A3: "Small Scientific" (Format ID: , Code: nil), B3: 1.234e-05 (Format ID: 166, Code: "0.00E+00")
|
|
1345
1345
|
```
|
|
1346
1346
|
|
|
1347
1347
|
<hr/>
|
|
@@ -2867,8 +2867,6 @@ Visual demonstration for Drawing Shapes.
|
|
|
2867
2867
|
|
|
2868
2868
|
<div><img src="../../test/visual/baselines/drawing_shapes/page-1.png" width="100%" alt="Preview"/></div>
|
|
2869
2869
|
|
|
2870
|
-
<div><img src="../../test/visual/baselines/drawing_shapes/page-2.png" width="100%" alt="Preview"/></div>
|
|
2871
|
-
|
|
2872
2870
|
### DSL Code
|
|
2873
2871
|
|
|
2874
2872
|
```ruby
|
|
@@ -2880,12 +2878,12 @@ output_path = ARGV[0] || "drawing_shapes.xlsx"
|
|
|
2880
2878
|
|
|
2881
2879
|
Xlsxrb.write(output_path) do |wb|
|
|
2882
2880
|
wb.sheet("Shapes") do |sheet|
|
|
2883
|
-
sheet.column(0..
|
|
2881
|
+
sheet.column(0..4, width: 12)
|
|
2884
2882
|
sheet.row(["Diagram with shapes and annotations"])
|
|
2885
2883
|
sheet.row([])
|
|
2886
|
-
sheet.shape(preset: "rect", text: "
|
|
2887
|
-
sheet.shape(preset: "rightArrow", text: "Next", from_col:
|
|
2888
|
-
sheet.shape(preset: "roundRect", text: "Processing", from_col:
|
|
2884
|
+
sheet.shape(preset: "rect", text: "Start", from_col: 0, from_row: 2, to_col: 1, to_row: 4)
|
|
2885
|
+
sheet.shape(preset: "rightArrow", text: "Next", from_col: 1, from_row: 3, to_col: 2, to_row: 4)
|
|
2886
|
+
sheet.shape(preset: "roundRect", text: "Processing", from_col: 2, from_row: 2, to_col: 4, to_row: 4)
|
|
2889
2887
|
end
|
|
2890
2888
|
end
|
|
2891
2889
|
|
|
@@ -4082,8 +4080,6 @@ Visual demonstration for Pivot Table.
|
|
|
4082
4080
|
|
|
4083
4081
|
<div><img src="../../test/visual/baselines/pivot_table/page-1.png" width="100%" alt="Preview"/></div>
|
|
4084
4082
|
|
|
4085
|
-
<div><img src="../../test/visual/baselines/pivot_table/page-2.png" width="100%" alt="Preview"/></div>
|
|
4086
|
-
|
|
4087
4083
|
### DSL Code
|
|
4088
4084
|
|
|
4089
4085
|
```ruby
|
|
@@ -4095,7 +4091,7 @@ output_path = ARGV[0] || "pivot_table.xlsx"
|
|
|
4095
4091
|
|
|
4096
4092
|
Xlsxrb.write(output_path) do |wb|
|
|
4097
4093
|
wb.sheet("SalesData") do |sheet|
|
|
4098
|
-
sheet.column(0..3, width:
|
|
4094
|
+
sheet.column(0..3, width: 14)
|
|
4099
4095
|
sheet.row(%w[Region Quarter Sales Rep])
|
|
4100
4096
|
sheet.row(["East", "Q1", 1000, "Alice"])
|
|
4101
4097
|
sheet.row(["West", "Q1", 1500, "Bob"])
|
|
@@ -4104,12 +4100,22 @@ Xlsxrb.write(output_path) do |wb|
|
|
|
4104
4100
|
sheet.row(["North", "Q1", 800, "Charlie"])
|
|
4105
4101
|
sheet.row(["North", "Q2", 950, "Charlie"])
|
|
4106
4102
|
|
|
4103
|
+
sheet.row([])
|
|
4104
|
+
sheet.row([])
|
|
4105
|
+
# Pre-populate summary cells in the pivot table target region (A10:D15) for headless renderers
|
|
4106
|
+
sheet.row(["Sum of Sales", "Quarter", nil, nil])
|
|
4107
|
+
sheet.row(["Region", "Q1", "Q2", "Grand Total"])
|
|
4108
|
+
sheet.row(["East", 1000, 1200, 2200])
|
|
4109
|
+
sheet.row(["North", 800, 950, 1750])
|
|
4110
|
+
sheet.row(["West", 1500, 1800, 3300])
|
|
4111
|
+
sheet.row(["Grand Total", 3300, 3950, 7250])
|
|
4112
|
+
|
|
4107
4113
|
sheet.pivot_table(
|
|
4108
4114
|
"SalesData!A1:D7",
|
|
4109
4115
|
row_fields: ["Region"],
|
|
4110
4116
|
data_fields: [{ name: "Sales", subtotal: "sum" }],
|
|
4111
4117
|
col_fields: ["Quarter"],
|
|
4112
|
-
dest_ref: "
|
|
4118
|
+
dest_ref: "A10",
|
|
4113
4119
|
name: "RegionalSalesSummary"
|
|
4114
4120
|
)
|
|
4115
4121
|
end
|
|
@@ -4135,6 +4141,14 @@ Row 3: A4: "East", B4: "Q2", C4: 1200, D4: "Alice"
|
|
|
4135
4141
|
Row 4: A5: "West", B5: "Q2", C5: 1800, D5: "Bob"
|
|
4136
4142
|
Row 5: A6: "North", B6: "Q1", C6: 800, D6: "Charlie"
|
|
4137
4143
|
Row 6: A7: "North", B7: "Q2", C7: 950, D7: "Charlie"
|
|
4144
|
+
Row 7:
|
|
4145
|
+
Row 8:
|
|
4146
|
+
Row 9: A10: "Sum of Sales", B10: "Quarter"
|
|
4147
|
+
Row 10: A11: "Region", B11: "Q1", C11: "Q2", D11: "Grand Total"
|
|
4148
|
+
Row 11: A12: "East", B12: 1000, C12: 1200, D12: 2200
|
|
4149
|
+
Row 12: A13: "North", B13: 800, C13: 950, D13: 1750
|
|
4150
|
+
Row 13: A14: "West", B14: 1500, C14: 1800, D14: 3300
|
|
4151
|
+
Row 14: A15: "Grand Total", B15: 3300, C15: 3950, D15: 7250
|
|
4138
4152
|
```
|
|
4139
4153
|
|
|
4140
4154
|
<hr/>
|
|
@@ -4494,8 +4508,6 @@ Visual demonstration for Table Styles.
|
|
|
4494
4508
|
|
|
4495
4509
|
<div><img src="../../test/visual/baselines/table_styles/page-1.png" width="100%" alt="Preview"/></div>
|
|
4496
4510
|
|
|
4497
|
-
<div><img src="../../test/visual/baselines/table_styles/page-2.png" width="100%" alt="Preview"/></div>
|
|
4498
|
-
|
|
4499
4511
|
### DSL Code
|
|
4500
4512
|
|
|
4501
4513
|
```ruby
|
|
@@ -4507,7 +4519,10 @@ output_path = ARGV[0] || "table_styles.xlsx"
|
|
|
4507
4519
|
|
|
4508
4520
|
Xlsxrb.write(output_path) do |wb|
|
|
4509
4521
|
wb.sheet("Table Example") do |sheet|
|
|
4510
|
-
sheet.column(0
|
|
4522
|
+
sheet.column(0, width: 8)
|
|
4523
|
+
sheet.column(1, width: 16)
|
|
4524
|
+
sheet.column(2, width: 16)
|
|
4525
|
+
sheet.column(3, width: 14)
|
|
4511
4526
|
sheet.row(%w[ID Name Department Salary])
|
|
4512
4527
|
sheet.row([101, "Alice Smith", "Engineering", 120_000])
|
|
4513
4528
|
sheet.row([102, "Bob Jones", "Marketing", 95_000])
|
|
@@ -4548,8 +4563,6 @@ Demonstrates disabling visible grid lines in spreadsheet view.
|
|
|
4548
4563
|
|
|
4549
4564
|
<div><img src="../../test/visual/baselines/view_show_grid_lines/page-1.png" width="100%" alt="Preview"/></div>
|
|
4550
4565
|
|
|
4551
|
-
<div><img src="../../test/visual/support/illustrations/view_show_grid_lines_page-2.png" width="100%" alt="Preview"/></div>
|
|
4552
|
-
|
|
4553
4566
|
### DSL Code
|
|
4554
4567
|
|
|
4555
4568
|
```ruby
|
|
@@ -4593,8 +4606,6 @@ Demonstrates setting custom zoom scale in sheet view (e.g. 150%).
|
|
|
4593
4606
|
|
|
4594
4607
|
<div><img src="../../test/visual/baselines/view_zoom_scale/page-1.png" width="100%" alt="Preview"/></div>
|
|
4595
4608
|
|
|
4596
|
-
<div><img src="../../test/visual/support/illustrations/view_zoom_scale_page-2.png" width="100%" alt="Preview"/></div>
|
|
4597
|
-
|
|
4598
4609
|
### DSL Code
|
|
4599
4610
|
|
|
4600
4611
|
```ruby
|
data/docs/wasm/ruby.wasm
CHANGED
|
Binary file
|
data/lib/xlsxrb/chart_builder.rb
CHANGED
|
@@ -80,7 +80,7 @@ module Xlsxrb
|
|
|
80
80
|
# @param kwargs [Hash] Keyword arguments for legend styling/layout.
|
|
81
81
|
# @return [Object] The configured legend property.
|
|
82
82
|
# @api public
|
|
83
|
-
#: (*(Hash[Symbol, String |
|
|
83
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
84
84
|
def legend(*args, **kwargs)
|
|
85
85
|
@options[:legend] = kwargs.empty? ? args.first : kwargs
|
|
86
86
|
end
|
|
@@ -91,7 +91,7 @@ module Xlsxrb
|
|
|
91
91
|
# @param kwargs [Hash] Keyword arguments for plot area configuration.
|
|
92
92
|
# @return [Object] The configured plot_area property.
|
|
93
93
|
# @api public
|
|
94
|
-
#: (*(Hash[Symbol, String |
|
|
94
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
95
95
|
def plot_area(*args, **kwargs)
|
|
96
96
|
@options[:plot_area] = kwargs.empty? ? args.first : kwargs
|
|
97
97
|
end
|
|
@@ -102,7 +102,7 @@ module Xlsxrb
|
|
|
102
102
|
# @param kwargs [Hash] Keyword arguments.
|
|
103
103
|
# @return [Object] The configured chart_space property.
|
|
104
104
|
# @api public
|
|
105
|
-
#: (*(Hash[Symbol, String |
|
|
105
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
106
106
|
def chart_space(*args, **kwargs)
|
|
107
107
|
@options[:chart_space] = kwargs.empty? ? args.first : kwargs
|
|
108
108
|
end
|
|
@@ -113,7 +113,7 @@ module Xlsxrb
|
|
|
113
113
|
# @param kwargs [Hash] Keyword arguments.
|
|
114
114
|
# @return [Object] The configured style property.
|
|
115
115
|
# @api public
|
|
116
|
-
#: (*(Hash[Symbol, String |
|
|
116
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String | Integer) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String | Integer)
|
|
117
117
|
def style(*args, **kwargs)
|
|
118
118
|
@options[:style] = kwargs.empty? ? args.first : kwargs
|
|
119
119
|
end
|
|
@@ -124,7 +124,7 @@ module Xlsxrb
|
|
|
124
124
|
# @param kwargs [Hash] Keyword arguments.
|
|
125
125
|
# @return [Object] The configured data_labels property.
|
|
126
126
|
# @api public
|
|
127
|
-
#: (*(Hash[Symbol, String |
|
|
127
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
128
128
|
def data_labels(*args, **kwargs)
|
|
129
129
|
@options[:data_labels] = kwargs.empty? ? args.first : kwargs
|
|
130
130
|
end
|
|
@@ -135,7 +135,7 @@ module Xlsxrb
|
|
|
135
135
|
# @param kwargs [Hash] Keyword arguments.
|
|
136
136
|
# @return [Boolean, String]
|
|
137
137
|
# @api public
|
|
138
|
-
#: (*(bool | String) args, **String |
|
|
138
|
+
#: (*(bool | String) args, **String | Numeric | bool | nil kwargs) -> (bool | String)
|
|
139
139
|
def plot_visible_only(*args, **kwargs)
|
|
140
140
|
@options[:plot_visible_only] = kwargs.empty? ? args.first : kwargs
|
|
141
141
|
end
|
|
@@ -146,7 +146,7 @@ module Xlsxrb
|
|
|
146
146
|
# @param kwargs [Hash] Keyword arguments.
|
|
147
147
|
# @return [String]
|
|
148
148
|
# @api public
|
|
149
|
-
#: (*(String) args, **String |
|
|
149
|
+
#: (*(String) args, **String | Numeric | bool | nil kwargs) -> String
|
|
150
150
|
def display_blanks_as(*args, **kwargs)
|
|
151
151
|
@options[:display_blanks_as] = kwargs.empty? ? args.first : kwargs
|
|
152
152
|
end
|
|
@@ -157,7 +157,7 @@ module Xlsxrb
|
|
|
157
157
|
# @param kwargs [Hash] Keyword arguments.
|
|
158
158
|
# @return [Object]
|
|
159
159
|
# @api public
|
|
160
|
-
#: (*(Hash[Symbol, String |
|
|
160
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
161
161
|
def view3d(*args, **kwargs)
|
|
162
162
|
@options[:view3d] = kwargs.empty? ? args.first : kwargs
|
|
163
163
|
end
|
|
@@ -168,7 +168,7 @@ module Xlsxrb
|
|
|
168
168
|
# @param kwargs [Hash] Keyword arguments.
|
|
169
169
|
# @return [Object]
|
|
170
170
|
# @api public
|
|
171
|
-
#: (*(Hash[Symbol, String |
|
|
171
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
172
172
|
def category_axis(*args, **kwargs)
|
|
173
173
|
@options[:category_axis] = kwargs.empty? ? args.first : kwargs
|
|
174
174
|
end
|
|
@@ -179,7 +179,7 @@ module Xlsxrb
|
|
|
179
179
|
# @param kwargs [Hash] Keyword arguments.
|
|
180
180
|
# @return [Object]
|
|
181
181
|
# @api public
|
|
182
|
-
#: (*(Hash[Symbol, String |
|
|
182
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
183
183
|
def value_axis(*args, **kwargs)
|
|
184
184
|
@options[:value_axis] = kwargs.empty? ? args.first : kwargs
|
|
185
185
|
end
|
|
@@ -190,7 +190,7 @@ module Xlsxrb
|
|
|
190
190
|
# @param kwargs [Hash] Keyword arguments.
|
|
191
191
|
# @return [Boolean, String]
|
|
192
192
|
# @api public
|
|
193
|
-
#: (*(bool | String) args, **String |
|
|
193
|
+
#: (*(bool | String) args, **String | Numeric | bool | nil kwargs) -> (bool | String)
|
|
194
194
|
def show_legend_key(*args, **kwargs)
|
|
195
195
|
@options[:show_legend_key] = kwargs.empty? ? args.first : kwargs
|
|
196
196
|
end
|
|
@@ -258,7 +258,7 @@ module Xlsxrb
|
|
|
258
258
|
# @param kwargs [Hash] Keyword arguments.
|
|
259
259
|
# @return [Object]
|
|
260
260
|
# @api public
|
|
261
|
-
#: (*(Hash[Symbol, String |
|
|
261
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
262
262
|
def fill(*args, **kwargs)
|
|
263
263
|
@options[:fill] = kwargs.empty? ? args.first : kwargs
|
|
264
264
|
end
|
|
@@ -269,7 +269,7 @@ module Xlsxrb
|
|
|
269
269
|
# @param kwargs [Hash] Keyword arguments.
|
|
270
270
|
# @return [Object]
|
|
271
271
|
# @api public
|
|
272
|
-
#: (*(Hash[Symbol, String |
|
|
272
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
273
273
|
def line(*args, **kwargs)
|
|
274
274
|
@options[:line] = kwargs.empty? ? args.first : kwargs
|
|
275
275
|
end
|
|
@@ -280,7 +280,7 @@ module Xlsxrb
|
|
|
280
280
|
# @param kwargs [Hash] Keyword arguments.
|
|
281
281
|
# @return [Object]
|
|
282
282
|
# @api public
|
|
283
|
-
#: (*(Hash[Symbol, String |
|
|
283
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
284
284
|
def trendline(*args, **kwargs)
|
|
285
285
|
@options[:trendline] = kwargs.empty? ? args.first : kwargs
|
|
286
286
|
end
|
|
@@ -291,7 +291,7 @@ module Xlsxrb
|
|
|
291
291
|
# @param kwargs [Hash] Keyword arguments.
|
|
292
292
|
# @return [Object]
|
|
293
293
|
# @api public
|
|
294
|
-
#: (*(Hash[Symbol, String |
|
|
294
|
+
#: (*(Hash[Symbol, String | Numeric | bool | nil] | String) args, **String | Numeric | bool | nil kwargs) -> (Hash[Symbol, String | Numeric | bool | nil] | String)
|
|
295
295
|
def data_labels(*args, **kwargs)
|
|
296
296
|
@options[:data_labels] = kwargs.empty? ? args.first : kwargs
|
|
297
297
|
end
|
|
@@ -302,7 +302,7 @@ module Xlsxrb
|
|
|
302
302
|
# @param kwargs [Hash] Keyword arguments.
|
|
303
303
|
# @return [Boolean, String]
|
|
304
304
|
# @api public
|
|
305
|
-
#: (*(bool | String) args, **String |
|
|
305
|
+
#: (*(bool | String) args, **String | Numeric | bool | nil kwargs) -> (bool | String)
|
|
306
306
|
def smooth(*args, **kwargs)
|
|
307
307
|
@options[:smooth] = kwargs.empty? ? args.first : kwargs
|
|
308
308
|
end
|
|
@@ -313,7 +313,7 @@ module Xlsxrb
|
|
|
313
313
|
# @param kwargs [Hash] Keyword arguments.
|
|
314
314
|
# @return [String]
|
|
315
315
|
# @api public
|
|
316
|
-
#: (*(String) args, **String |
|
|
316
|
+
#: (*(String) args, **String | Numeric | bool | nil kwargs) -> String
|
|
317
317
|
def shape(*args, **kwargs)
|
|
318
318
|
@options[:shape] = kwargs.empty? ? args.first : kwargs
|
|
319
319
|
end
|
|
@@ -324,7 +324,7 @@ module Xlsxrb
|
|
|
324
324
|
# @param kwargs [Hash] Keyword arguments.
|
|
325
325
|
# @return [String]
|
|
326
326
|
# @api public
|
|
327
|
-
#: (*(String) args, **String |
|
|
327
|
+
#: (*(String) args, **String | Numeric | bool | nil kwargs) -> String
|
|
328
328
|
def type(*args, **kwargs)
|
|
329
329
|
@options[:type] = kwargs.empty? ? args.first : kwargs
|
|
330
330
|
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rbs_inline: enabled
|
|
4
|
+
|
|
5
|
+
require_relative "elements/cell"
|
|
6
|
+
require_relative "ooxml/utils"
|
|
7
|
+
|
|
8
|
+
module Xlsxrb
|
|
9
|
+
# Internal helper module for normalizing and validating DSL arguments
|
|
10
|
+
# shared between {WorksheetBuilder} (in-memory) and {StreamWriter} (streaming).
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
13
|
+
module DslHelpers
|
|
14
|
+
# Normalizes merge cell range string or coordinate components into a canonical range reference (e.g. "A1:C3").
|
|
15
|
+
#
|
|
16
|
+
# @param range [String, Hash, nil]
|
|
17
|
+
# @param row [Integer, nil]
|
|
18
|
+
# @param col_start [Integer, String, nil]
|
|
19
|
+
# @param col_end [Integer, String, nil]
|
|
20
|
+
# @param row_start [Integer, nil]
|
|
21
|
+
# @param row_end [Integer, nil]
|
|
22
|
+
# @param strict_excel_mode [Boolean]
|
|
23
|
+
# @return [String]
|
|
24
|
+
#: (untyped range, ?row: Integer?, ?col_start: (Integer | String)?, ?col_end: (Integer | String)?, ?row_start: Integer?, ?row_end: Integer?, ?strict_excel_mode: bool) -> String
|
|
25
|
+
def self.normalize_merge_range(range = nil, row: nil, col_start: nil, col_end: nil, row_start: nil, row_end: nil, strict_excel_mode: true)
|
|
26
|
+
if range.is_a?(Hash)
|
|
27
|
+
row = range[:row]
|
|
28
|
+
row_start = range[:row_start]
|
|
29
|
+
row_end = range[:row_end]
|
|
30
|
+
col_start = range[:col_start]
|
|
31
|
+
col_end = range[:col_end]
|
|
32
|
+
range = nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if range
|
|
36
|
+
raise ArgumentError, "Invalid merge range format: '#{range}'. Expected format like 'A1:B2'." if strict_excel_mode && !range.match?(/\A[A-Za-z]{1,3}\d+(:[A-Za-z]{1,3}\d+)?\z/)
|
|
37
|
+
|
|
38
|
+
range
|
|
39
|
+
else
|
|
40
|
+
r_start = row || row_start || 0
|
|
41
|
+
r_end = row || row_end || 0
|
|
42
|
+
c_start = Elements::Cell.column_index(col_start || 0)
|
|
43
|
+
c_end = Elements::Cell.column_index(col_end || 0)
|
|
44
|
+
start_ref = "#{Elements::Cell.column_letter(c_start)}#{r_start + 1}"
|
|
45
|
+
end_ref = "#{Elements::Cell.column_letter(c_end)}#{r_end + 1}"
|
|
46
|
+
"#{start_ref}:#{end_ref}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Normalizes sheet protection options and hashes plain-text password if supplied.
|
|
51
|
+
#
|
|
52
|
+
# @param opts [Hash]
|
|
53
|
+
# @return [Hash]
|
|
54
|
+
#: (Hash[Symbol, untyped] opts) -> Hash[Symbol, untyped]
|
|
55
|
+
def self.normalize_protection_options(opts)
|
|
56
|
+
normalized = opts.dup
|
|
57
|
+
plain_password = normalized[:password]
|
|
58
|
+
needs_hash = plain_password.is_a?(String) && !plain_password.empty? &&
|
|
59
|
+
normalized[:algorithm_name].nil? && normalized[:hash_value].nil? &&
|
|
60
|
+
normalized[:salt_value].nil? && normalized[:spin_count].nil? &&
|
|
61
|
+
!plain_password.match?(/\A[0-9A-Fa-f]{4}\z/)
|
|
62
|
+
if needs_hash
|
|
63
|
+
normalized.delete(:password)
|
|
64
|
+
normalized.merge!(Ooxml::Utils.hash_password(plain_password))
|
|
65
|
+
end
|
|
66
|
+
normalized
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Normalizes column index or letter or Range to an array of 0-based column integers.
|
|
70
|
+
#
|
|
71
|
+
# @param index [Integer, String, Symbol, Range, Array]
|
|
72
|
+
# @return [Array<Integer>]
|
|
73
|
+
#: (untyped index) -> Array[Integer]
|
|
74
|
+
def self.normalize_column_indices(index)
|
|
75
|
+
case index
|
|
76
|
+
when Range, Array
|
|
77
|
+
index.map { |i| Elements::Cell.column_index(i) }
|
|
78
|
+
else
|
|
79
|
+
[Elements::Cell.column_index(index)]
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Normalizes page margins into a compact hash.
|
|
84
|
+
#
|
|
85
|
+
# @param left [Float, nil]
|
|
86
|
+
# @param right [Float, nil]
|
|
87
|
+
# @param top [Float, nil]
|
|
88
|
+
# @param bottom [Float, nil]
|
|
89
|
+
# @param header [Float, nil]
|
|
90
|
+
# @param footer [Float, nil]
|
|
91
|
+
# @return [Hash{Symbol => Float}]
|
|
92
|
+
#: (?left: Float?, ?right: Float?, ?top: Float?, ?bottom: Float?, ?header: Float?, ?footer: Float?) -> Hash[Symbol, Float]
|
|
93
|
+
def self.normalize_page_margins(left: nil, right: nil, top: nil, bottom: nil, header: nil, footer: nil)
|
|
94
|
+
{ left: left, right: right, top: top, bottom: bottom, header: header, footer: footer }.compact
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Normalizes table options hash.
|
|
98
|
+
#
|
|
99
|
+
# @param ref [String]
|
|
100
|
+
# @param columns [Array<String>, Array<Hash>]
|
|
101
|
+
# @param name [String, nil]
|
|
102
|
+
# @param display_name [String, nil]
|
|
103
|
+
# @param style [String, nil]
|
|
104
|
+
# @param opts [Hash]
|
|
105
|
+
# @return [Hash]
|
|
106
|
+
#: (String ref, columns: untyped, ?name: String?, ?display_name: String?, ?style: String?, **untyped opts) -> Hash[Symbol, untyped]
|
|
107
|
+
def self.normalize_table_options(ref, columns:, name: nil, display_name: nil, style: nil, **opts)
|
|
108
|
+
tbl = { ref: ref, columns: columns }
|
|
109
|
+
tbl[:name] = name if name
|
|
110
|
+
tbl[:display_name] = display_name if display_name
|
|
111
|
+
tbl[:style] = style if style
|
|
112
|
+
tbl.merge!(opts)
|
|
113
|
+
tbl
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|