xlsxrb 0.1.0
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/.devcontainer/Dockerfile +64 -0
- data/.devcontainer/devcontainer.json +17 -0
- data/CHANGELOG.md +12 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +384 -0
- data/Rakefile +290 -0
- data/benchmark.rb +390 -0
- data/docs/ARCHITECTURE.md +488 -0
- data/docs/SPEC_SOURCES.md +42 -0
- data/docs/visual/VisualGallery.md +4684 -0
- data/docs/wasm/wasm_doc_helper.css +189 -0
- data/docs/wasm/wasm_doc_helper.js +320 -0
- data/lib/xlsxrb/elements/cell.rb +77 -0
- data/lib/xlsxrb/elements/column.rb +28 -0
- data/lib/xlsxrb/elements/row.rb +47 -0
- data/lib/xlsxrb/elements/types.rb +36 -0
- data/lib/xlsxrb/elements/workbook.rb +47 -0
- data/lib/xlsxrb/elements/worksheet.rb +50 -0
- data/lib/xlsxrb/elements.rb +15 -0
- data/lib/xlsxrb/ooxml/reader.rb +8048 -0
- data/lib/xlsxrb/ooxml/shared_strings_parser.rb +75 -0
- data/lib/xlsxrb/ooxml/styles_parser.rb +194 -0
- data/lib/xlsxrb/ooxml/utils.rb +122 -0
- data/lib/xlsxrb/ooxml/workbook_parser.rb +78 -0
- data/lib/xlsxrb/ooxml/workbook_writer.rb +1000 -0
- data/lib/xlsxrb/ooxml/worksheet_parser.rb +455 -0
- data/lib/xlsxrb/ooxml/worksheet_writer.rb +1008 -0
- data/lib/xlsxrb/ooxml/writer.rb +5450 -0
- data/lib/xlsxrb/ooxml/xml_builder.rb +113 -0
- data/lib/xlsxrb/ooxml/xml_parser.rb +68 -0
- data/lib/xlsxrb/ooxml/zip_generator.rb +162 -0
- data/lib/xlsxrb/ooxml/zip_reader.rb +158 -0
- data/lib/xlsxrb/ooxml/zip_writer.rb +213 -0
- data/lib/xlsxrb/ooxml.rb +22 -0
- data/lib/xlsxrb/style_builder.rb +241 -0
- data/lib/xlsxrb/version.rb +5 -0
- data/lib/xlsxrb.rb +1427 -0
- data/measure_memory.rb +42 -0
- data/sig/xlsxrb.rbs +23 -0
- data/vendor/sdk_runner/Program.cs +91 -0
- data/vendor/sdk_runner/sdk_runner.csproj +13 -0
- metadata +144 -0
|
@@ -0,0 +1,4684 @@
|
|
|
1
|
+
# Visual Examples Gallery
|
|
2
|
+
|
|
3
|
+
This gallery showcases `xlsxrb` DSL usage side-by-side with the visual rendering in LibreOffice Calc.
|
|
4
|
+
|
|
5
|
+
[◄ Back to README](../../README.md)
|
|
6
|
+
|
|
7
|
+
## Capability Overview
|
|
8
|
+
|
|
9
|
+
<table>
|
|
10
|
+
<thead>
|
|
11
|
+
<tr>
|
|
12
|
+
<th align="left">Feature</th>
|
|
13
|
+
<th align="center">Visual Preview</th>
|
|
14
|
+
<th align="center">Download XLSX</th>
|
|
15
|
+
<th align="center">Link to Detail</th>
|
|
16
|
+
</tr>
|
|
17
|
+
</thead>
|
|
18
|
+
<tbody>
|
|
19
|
+
<tr>
|
|
20
|
+
<td><strong>Align Horizontal</strong></td>
|
|
21
|
+
<td align="center"><img src="../../test/visual/baselines/align_horizontal/page-1.png" width="160" alt="Align Horizontal"/></td>
|
|
22
|
+
<td align="center"><a href="files/align_horizontal.xlsx">Download</a></td>
|
|
23
|
+
<td align="center"><a href="#align-horizontal">View Code & Detail</a></td>
|
|
24
|
+
</tr>
|
|
25
|
+
<tr>
|
|
26
|
+
<td><strong>Align Horizontal Fill</strong></td>
|
|
27
|
+
<td align="center"><img src="../../test/visual/baselines/align_horizontal_fill/page-1.png" width="160" alt="Align Horizontal Fill"/></td>
|
|
28
|
+
<td align="center"><a href="files/align_horizontal_fill.xlsx">Download</a></td>
|
|
29
|
+
<td align="center"><a href="#align-horizontal-fill">View Code & Detail</a></td>
|
|
30
|
+
</tr>
|
|
31
|
+
<tr>
|
|
32
|
+
<td><strong>Align Horizontal Justify</strong></td>
|
|
33
|
+
<td align="center"><img src="../../test/visual/baselines/align_horizontal_justify/page-1.png" width="160" alt="Align Horizontal Justify"/></td>
|
|
34
|
+
<td align="center"><a href="files/align_horizontal_justify.xlsx">Download</a></td>
|
|
35
|
+
<td align="center"><a href="#align-horizontal-justify">View Code & Detail</a></td>
|
|
36
|
+
</tr>
|
|
37
|
+
<tr>
|
|
38
|
+
<td><strong>Align Indent</strong></td>
|
|
39
|
+
<td align="center"><img src="../../test/visual/baselines/align_indent/page-1.png" width="160" alt="Align Indent"/></td>
|
|
40
|
+
<td align="center"><a href="files/align_indent.xlsx">Download</a></td>
|
|
41
|
+
<td align="center"><a href="#align-indent">View Code & Detail</a></td>
|
|
42
|
+
</tr>
|
|
43
|
+
<tr>
|
|
44
|
+
<td><strong>Align Text Rotation</strong></td>
|
|
45
|
+
<td align="center"><img src="../../test/visual/baselines/align_text_rotation/page-1.png" width="160" alt="Align Text Rotation"/></td>
|
|
46
|
+
<td align="center"><a href="files/align_text_rotation.xlsx">Download</a></td>
|
|
47
|
+
<td align="center"><a href="#align-text-rotation">View Code & Detail</a></td>
|
|
48
|
+
</tr>
|
|
49
|
+
<tr>
|
|
50
|
+
<td><strong>Align Text Wrap</strong></td>
|
|
51
|
+
<td align="center"><img src="../../test/visual/baselines/align_text_wrap/page-1.png" width="160" alt="Align Text Wrap"/></td>
|
|
52
|
+
<td align="center"><a href="files/align_text_wrap.xlsx">Download</a></td>
|
|
53
|
+
<td align="center"><a href="#align-text-wrap">View Code & Detail</a></td>
|
|
54
|
+
</tr>
|
|
55
|
+
<tr>
|
|
56
|
+
<td><strong>Align Vertical</strong></td>
|
|
57
|
+
<td align="center"><img src="../../test/visual/baselines/align_vertical/page-1.png" width="160" alt="Align Vertical"/></td>
|
|
58
|
+
<td align="center"><a href="files/align_vertical.xlsx">Download</a></td>
|
|
59
|
+
<td align="center"><a href="#align-vertical">View Code & Detail</a></td>
|
|
60
|
+
</tr>
|
|
61
|
+
<tr>
|
|
62
|
+
<td><strong>Basic Data</strong></td>
|
|
63
|
+
<td align="center"><img src="../../test/visual/baselines/basic_data/page-1.png" width="160" alt="Basic Data"/></td>
|
|
64
|
+
<td align="center"><a href="files/basic_data.xlsx">Download</a></td>
|
|
65
|
+
<td align="center"><a href="#basic-data">View Code & Detail</a></td>
|
|
66
|
+
</tr>
|
|
67
|
+
<tr>
|
|
68
|
+
<td><strong>Borders</strong></td>
|
|
69
|
+
<td align="center"><img src="../../test/visual/baselines/borders/page-1.png" width="160" alt="Borders"/></td>
|
|
70
|
+
<td align="center"><a href="files/borders.xlsx">Download</a></td>
|
|
71
|
+
<td align="center"><a href="#borders">View Code & Detail</a></td>
|
|
72
|
+
</tr>
|
|
73
|
+
<tr>
|
|
74
|
+
<td><strong>Cell Booleans</strong></td>
|
|
75
|
+
<td align="center"><img src="../../test/visual/baselines/cell_booleans/page-1.png" width="160" alt="Cell Booleans"/></td>
|
|
76
|
+
<td align="center"><a href="files/cell_booleans.xlsx">Download</a></td>
|
|
77
|
+
<td align="center"><a href="#cell-booleans">View Code & Detail</a></td>
|
|
78
|
+
</tr>
|
|
79
|
+
<tr>
|
|
80
|
+
<td><strong>Cell Dates</strong></td>
|
|
81
|
+
<td align="center"><img src="../../test/visual/baselines/cell_dates/page-1.png" width="160" alt="Cell Dates"/></td>
|
|
82
|
+
<td align="center"><a href="files/cell_dates.xlsx">Download</a></td>
|
|
83
|
+
<td align="center"><a href="#cell-dates">View Code & Detail</a></td>
|
|
84
|
+
</tr>
|
|
85
|
+
<tr>
|
|
86
|
+
<td><strong>Cell Formulas</strong></td>
|
|
87
|
+
<td align="center"><img src="../../test/visual/baselines/cell_formulas/page-1.png" width="160" alt="Cell Formulas"/></td>
|
|
88
|
+
<td align="center"><a href="files/cell_formulas.xlsx">Download</a></td>
|
|
89
|
+
<td align="center"><a href="#cell-formulas">View Code & Detail</a></td>
|
|
90
|
+
</tr>
|
|
91
|
+
<tr>
|
|
92
|
+
<td><strong>Cell Num Currency Jpy</strong></td>
|
|
93
|
+
<td align="center"><img src="../../test/visual/baselines/cell_num_currency_jpy/page-1.png" width="160" alt="Cell Num Currency Jpy"/></td>
|
|
94
|
+
<td align="center"><a href="files/cell_num_currency_jpy.xlsx">Download</a></td>
|
|
95
|
+
<td align="center"><a href="#cell-num-currency-jpy">View Code & Detail</a></td>
|
|
96
|
+
</tr>
|
|
97
|
+
<tr>
|
|
98
|
+
<td><strong>Cell Num Custom Colors</strong></td>
|
|
99
|
+
<td align="center"><img src="../../test/visual/baselines/cell_num_custom_colors/page-1.png" width="160" alt="Cell Num Custom Colors"/></td>
|
|
100
|
+
<td align="center"><a href="files/cell_num_custom_colors.xlsx">Download</a></td>
|
|
101
|
+
<td align="center"><a href="#cell-num-custom-colors">View Code & Detail</a></td>
|
|
102
|
+
</tr>
|
|
103
|
+
<tr>
|
|
104
|
+
<td><strong>Cell Num Fractions</strong></td>
|
|
105
|
+
<td align="center"><img src="../../test/visual/baselines/cell_num_fractions/page-1.png" width="160" alt="Cell Num Fractions"/></td>
|
|
106
|
+
<td align="center"><a href="files/cell_num_fractions.xlsx">Download</a></td>
|
|
107
|
+
<td align="center"><a href="#cell-num-fractions">View Code & Detail</a></td>
|
|
108
|
+
</tr>
|
|
109
|
+
<tr>
|
|
110
|
+
<td><strong>Cell Num Percent Decimals</strong></td>
|
|
111
|
+
<td align="center"><img src="../../test/visual/baselines/cell_num_percent_decimals/page-1.png" width="160" alt="Cell Num Percent Decimals"/></td>
|
|
112
|
+
<td align="center"><a href="files/cell_num_percent_decimals.xlsx">Download</a></td>
|
|
113
|
+
<td align="center"><a href="#cell-num-percent-decimals">View Code & Detail</a></td>
|
|
114
|
+
</tr>
|
|
115
|
+
<tr>
|
|
116
|
+
<td><strong>Cell Num Scientific</strong></td>
|
|
117
|
+
<td align="center"><img src="../../test/visual/baselines/cell_num_scientific/page-1.png" width="160" alt="Cell Num Scientific"/></td>
|
|
118
|
+
<td align="center"><a href="files/cell_num_scientific.xlsx">Download</a></td>
|
|
119
|
+
<td align="center"><a href="#cell-num-scientific">View Code & Detail</a></td>
|
|
120
|
+
</tr>
|
|
121
|
+
<tr>
|
|
122
|
+
<td><strong>Cell Numbers</strong></td>
|
|
123
|
+
<td align="center"><img src="../../test/visual/baselines/cell_numbers/page-1.png" width="160" alt="Cell Numbers"/></td>
|
|
124
|
+
<td align="center"><a href="files/cell_numbers.xlsx">Download</a></td>
|
|
125
|
+
<td align="center"><a href="#cell-numbers">View Code & Detail</a></td>
|
|
126
|
+
</tr>
|
|
127
|
+
<tr>
|
|
128
|
+
<td><strong>Cell Rich Text</strong></td>
|
|
129
|
+
<td align="center"><img src="../../test/visual/baselines/cell_rich_text/page-1.png" width="160" alt="Cell Rich Text"/></td>
|
|
130
|
+
<td align="center"><a href="files/cell_rich_text.xlsx">Download</a></td>
|
|
131
|
+
<td align="center"><a href="#cell-rich-text">View Code & Detail</a></td>
|
|
132
|
+
</tr>
|
|
133
|
+
<tr>
|
|
134
|
+
<td><strong>Cell Times</strong></td>
|
|
135
|
+
<td align="center"><img src="../../test/visual/baselines/cell_times/page-1.png" width="160" alt="Cell Times"/></td>
|
|
136
|
+
<td align="center"><a href="files/cell_times.xlsx">Download</a></td>
|
|
137
|
+
<td align="center"><a href="#cell-times">View Code & Detail</a></td>
|
|
138
|
+
</tr>
|
|
139
|
+
<tr>
|
|
140
|
+
<td><strong>Cf Begins With</strong></td>
|
|
141
|
+
<td align="center"><img src="../../test/visual/baselines/cf_begins_with/page-1.png" width="160" alt="Cf Begins With"/></td>
|
|
142
|
+
<td align="center"><a href="files/cf_begins_with.xlsx">Download</a></td>
|
|
143
|
+
<td align="center"><a href="#cf-begins-with">View Code & Detail</a></td>
|
|
144
|
+
</tr>
|
|
145
|
+
<tr>
|
|
146
|
+
<td><strong>Cf Cell Between</strong></td>
|
|
147
|
+
<td align="center"><img src="../../test/visual/baselines/cf_cell_between/page-1.png" width="160" alt="Cf Cell Between"/></td>
|
|
148
|
+
<td align="center"><a href="files/cf_cell_between.xlsx">Download</a></td>
|
|
149
|
+
<td align="center"><a href="#cf-cell-between">View Code & Detail</a></td>
|
|
150
|
+
</tr>
|
|
151
|
+
<tr>
|
|
152
|
+
<td><strong>Cf Cell Equal To</strong></td>
|
|
153
|
+
<td align="center"><img src="../../test/visual/baselines/cf_cell_equal_to/page-1.png" width="160" alt="Cf Cell Equal To"/></td>
|
|
154
|
+
<td align="center"><a href="files/cf_cell_equal_to.xlsx">Download</a></td>
|
|
155
|
+
<td align="center"><a href="#cf-cell-equal-to">View Code & Detail</a></td>
|
|
156
|
+
</tr>
|
|
157
|
+
<tr>
|
|
158
|
+
<td><strong>Cf Cell Greater Equal</strong></td>
|
|
159
|
+
<td align="center"><img src="../../test/visual/baselines/cf_cell_greater_equal/page-1.png" width="160" alt="Cf Cell Greater Equal"/></td>
|
|
160
|
+
<td align="center"><a href="files/cf_cell_greater_equal.xlsx">Download</a></td>
|
|
161
|
+
<td align="center"><a href="#cf-cell-greater-equal">View Code & Detail</a></td>
|
|
162
|
+
</tr>
|
|
163
|
+
<tr>
|
|
164
|
+
<td><strong>Cf Cell Greater Than</strong></td>
|
|
165
|
+
<td align="center"><img src="../../test/visual/baselines/cf_cell_greater_than/page-1.png" width="160" alt="Cf Cell Greater Than"/></td>
|
|
166
|
+
<td align="center"><a href="files/cf_cell_greater_than.xlsx">Download</a></td>
|
|
167
|
+
<td align="center"><a href="#cf-cell-greater-than">View Code & Detail</a></td>
|
|
168
|
+
</tr>
|
|
169
|
+
<tr>
|
|
170
|
+
<td><strong>Cf Cell Less Than</strong></td>
|
|
171
|
+
<td align="center"><img src="../../test/visual/baselines/cf_cell_less_than/page-1.png" width="160" alt="Cf Cell Less Than"/></td>
|
|
172
|
+
<td align="center"><a href="files/cf_cell_less_than.xlsx">Download</a></td>
|
|
173
|
+
<td align="center"><a href="#cf-cell-less-than">View Code & Detail</a></td>
|
|
174
|
+
</tr>
|
|
175
|
+
<tr>
|
|
176
|
+
<td><strong>Cf Color Scale</strong></td>
|
|
177
|
+
<td align="center"><img src="../../test/visual/baselines/cf_color_scale/page-1.png" width="160" alt="Cf Color Scale"/></td>
|
|
178
|
+
<td align="center"><a href="files/cf_color_scale.xlsx">Download</a></td>
|
|
179
|
+
<td align="center"><a href="#cf-color-scale">View Code & Detail</a></td>
|
|
180
|
+
</tr>
|
|
181
|
+
<tr>
|
|
182
|
+
<td><strong>Cf Contains Text</strong></td>
|
|
183
|
+
<td align="center"><img src="../../test/visual/baselines/cf_contains_text/page-1.png" width="160" alt="Cf Contains Text"/></td>
|
|
184
|
+
<td align="center"><a href="files/cf_contains_text.xlsx">Download</a></td>
|
|
185
|
+
<td align="center"><a href="#cf-contains-text">View Code & Detail</a></td>
|
|
186
|
+
</tr>
|
|
187
|
+
<tr>
|
|
188
|
+
<td><strong>Cf Data Bar</strong></td>
|
|
189
|
+
<td align="center"><img src="../../test/visual/baselines/cf_data_bar/page-1.png" width="160" alt="Cf Data Bar"/></td>
|
|
190
|
+
<td align="center"><a href="files/cf_data_bar.xlsx">Download</a></td>
|
|
191
|
+
<td align="center"><a href="#cf-data-bar">View Code & Detail</a></td>
|
|
192
|
+
</tr>
|
|
193
|
+
<tr>
|
|
194
|
+
<td><strong>Cf Ends With</strong></td>
|
|
195
|
+
<td align="center"><img src="../../test/visual/baselines/cf_ends_with/page-1.png" width="160" alt="Cf Ends With"/></td>
|
|
196
|
+
<td align="center"><a href="files/cf_ends_with.xlsx">Download</a></td>
|
|
197
|
+
<td align="center"><a href="#cf-ends-with">View Code & Detail</a></td>
|
|
198
|
+
</tr>
|
|
199
|
+
<tr>
|
|
200
|
+
<td><strong>Cf Expression Formula</strong></td>
|
|
201
|
+
<td align="center"><img src="../../test/visual/baselines/cf_expression_formula/page-1.png" width="160" alt="Cf Expression Formula"/></td>
|
|
202
|
+
<td align="center"><a href="files/cf_expression_formula.xlsx">Download</a></td>
|
|
203
|
+
<td align="center"><a href="#cf-expression-formula">View Code & Detail</a></td>
|
|
204
|
+
</tr>
|
|
205
|
+
<tr>
|
|
206
|
+
<td><strong>Cf Icon Set</strong></td>
|
|
207
|
+
<td align="center"><img src="../../test/visual/baselines/cf_icon_set/page-1.png" width="160" alt="Cf Icon Set"/></td>
|
|
208
|
+
<td align="center"><a href="files/cf_icon_set.xlsx">Download</a></td>
|
|
209
|
+
<td align="center"><a href="#cf-icon-set">View Code & Detail</a></td>
|
|
210
|
+
</tr>
|
|
211
|
+
<tr>
|
|
212
|
+
<td><strong>Chart Area</strong></td>
|
|
213
|
+
<td align="center"><img src="../../test/visual/baselines/chart_area/page-1.png" width="160" alt="Chart Area"/></td>
|
|
214
|
+
<td align="center"><a href="files/chart_area.xlsx">Download</a></td>
|
|
215
|
+
<td align="center"><a href="#chart-area">View Code & Detail</a></td>
|
|
216
|
+
</tr>
|
|
217
|
+
<tr>
|
|
218
|
+
<td><strong>Chart Area Stacked</strong></td>
|
|
219
|
+
<td align="center"><img src="../../test/visual/baselines/chart_area_stacked/page-1.png" width="160" alt="Chart Area Stacked"/></td>
|
|
220
|
+
<td align="center"><a href="files/chart_area_stacked.xlsx">Download</a></td>
|
|
221
|
+
<td align="center"><a href="#chart-area-stacked">View Code & Detail</a></td>
|
|
222
|
+
</tr>
|
|
223
|
+
<tr>
|
|
224
|
+
<td><strong>Chart Bar</strong></td>
|
|
225
|
+
<td align="center"><img src="../../test/visual/baselines/chart_bar/page-1.png" width="160" alt="Chart Bar"/></td>
|
|
226
|
+
<td align="center"><a href="files/chart_bar.xlsx">Download</a></td>
|
|
227
|
+
<td align="center"><a href="#chart-bar">View Code & Detail</a></td>
|
|
228
|
+
</tr>
|
|
229
|
+
<tr>
|
|
230
|
+
<td><strong>Chart Bar Percent Stacked</strong></td>
|
|
231
|
+
<td align="center"><img src="../../test/visual/baselines/chart_bar_percent_stacked/page-1.png" width="160" alt="Chart Bar Percent Stacked"/></td>
|
|
232
|
+
<td align="center"><a href="files/chart_bar_percent_stacked.xlsx">Download</a></td>
|
|
233
|
+
<td align="center"><a href="#chart-bar-percent-stacked">View Code & Detail</a></td>
|
|
234
|
+
</tr>
|
|
235
|
+
<tr>
|
|
236
|
+
<td><strong>Chart Bar Stacked</strong></td>
|
|
237
|
+
<td align="center"><img src="../../test/visual/baselines/chart_bar_stacked/page-1.png" width="160" alt="Chart Bar Stacked"/></td>
|
|
238
|
+
<td align="center"><a href="files/chart_bar_stacked.xlsx">Download</a></td>
|
|
239
|
+
<td align="center"><a href="#chart-bar-stacked">View Code & Detail</a></td>
|
|
240
|
+
</tr>
|
|
241
|
+
<tr>
|
|
242
|
+
<td><strong>Chart Doughnut</strong></td>
|
|
243
|
+
<td align="center"><img src="../../test/visual/baselines/chart_doughnut/page-1.png" width="160" alt="Chart Doughnut"/></td>
|
|
244
|
+
<td align="center"><a href="files/chart_doughnut.xlsx">Download</a></td>
|
|
245
|
+
<td align="center"><a href="#chart-doughnut">View Code & Detail</a></td>
|
|
246
|
+
</tr>
|
|
247
|
+
<tr>
|
|
248
|
+
<td><strong>Chart Line</strong></td>
|
|
249
|
+
<td align="center"><img src="../../test/visual/baselines/chart_line/page-1.png" width="160" alt="Chart Line"/></td>
|
|
250
|
+
<td align="center"><a href="files/chart_line.xlsx">Download</a></td>
|
|
251
|
+
<td align="center"><a href="#chart-line">View Code & Detail</a></td>
|
|
252
|
+
</tr>
|
|
253
|
+
<tr>
|
|
254
|
+
<td><strong>Chart Line Stacked</strong></td>
|
|
255
|
+
<td align="center"><img src="../../test/visual/baselines/chart_line_stacked/page-1.png" width="160" alt="Chart Line Stacked"/></td>
|
|
256
|
+
<td align="center"><a href="files/chart_line_stacked.xlsx">Download</a></td>
|
|
257
|
+
<td align="center"><a href="#chart-line-stacked">View Code & Detail</a></td>
|
|
258
|
+
</tr>
|
|
259
|
+
<tr>
|
|
260
|
+
<td><strong>Chart Pie</strong></td>
|
|
261
|
+
<td align="center"><img src="../../test/visual/baselines/chart_pie/page-1.png" width="160" alt="Chart Pie"/></td>
|
|
262
|
+
<td align="center"><a href="files/chart_pie.xlsx">Download</a></td>
|
|
263
|
+
<td align="center"><a href="#chart-pie">View Code & Detail</a></td>
|
|
264
|
+
</tr>
|
|
265
|
+
<tr>
|
|
266
|
+
<td><strong>Chart Radar</strong></td>
|
|
267
|
+
<td align="center"><img src="../../test/visual/baselines/chart_radar/page-1.png" width="160" alt="Chart Radar"/></td>
|
|
268
|
+
<td align="center"><a href="files/chart_radar.xlsx">Download</a></td>
|
|
269
|
+
<td align="center"><a href="#chart-radar">View Code & Detail</a></td>
|
|
270
|
+
</tr>
|
|
271
|
+
<tr>
|
|
272
|
+
<td><strong>Chart Scatter</strong></td>
|
|
273
|
+
<td align="center"><img src="../../test/visual/baselines/chart_scatter/page-1.png" width="160" alt="Chart Scatter"/></td>
|
|
274
|
+
<td align="center"><a href="files/chart_scatter.xlsx">Download</a></td>
|
|
275
|
+
<td align="center"><a href="#chart-scatter">View Code & Detail</a></td>
|
|
276
|
+
</tr>
|
|
277
|
+
<tr>
|
|
278
|
+
<td><strong>Col Grouping</strong></td>
|
|
279
|
+
<td align="center"><img src="../../test/visual/baselines/col_grouping/page-1.png" width="160" alt="Col Grouping"/></td>
|
|
280
|
+
<td align="center"><a href="files/col_grouping.xlsx">Download</a></td>
|
|
281
|
+
<td align="center"><a href="#col-grouping">View Code & Detail</a></td>
|
|
282
|
+
</tr>
|
|
283
|
+
<tr>
|
|
284
|
+
<td><strong>Col Width Tall</strong></td>
|
|
285
|
+
<td align="center"><img src="../../test/visual/baselines/col_width_tall/page-1.png" width="160" alt="Col Width Tall"/></td>
|
|
286
|
+
<td align="center"><a href="files/col_width_tall.xlsx">Download</a></td>
|
|
287
|
+
<td align="center"><a href="#col-width-tall">View Code & Detail</a></td>
|
|
288
|
+
</tr>
|
|
289
|
+
<tr>
|
|
290
|
+
<td><strong>Col Widths</strong></td>
|
|
291
|
+
<td align="center"><img src="../../test/visual/baselines/col_widths/page-1.png" width="160" alt="Col Widths"/></td>
|
|
292
|
+
<td align="center"><a href="files/col_widths.xlsx">Download</a></td>
|
|
293
|
+
<td align="center"><a href="#col-widths">View Code & Detail</a></td>
|
|
294
|
+
</tr>
|
|
295
|
+
<tr>
|
|
296
|
+
<td><strong>Conditional Formatting</strong></td>
|
|
297
|
+
<td align="center"><img src="../../test/visual/baselines/conditional_formatting/page-1.png" width="160" alt="Conditional Formatting"/></td>
|
|
298
|
+
<td align="center"><a href="files/conditional_formatting.xlsx">Download</a></td>
|
|
299
|
+
<td align="center"><a href="#conditional-formatting">View Code & Detail</a></td>
|
|
300
|
+
</tr>
|
|
301
|
+
<tr>
|
|
302
|
+
<td><strong>Embedded Images</strong></td>
|
|
303
|
+
<td align="center"><img src="../../test/visual/baselines/embedded_images/page-1.png" width="160" alt="Embedded Images"/></td>
|
|
304
|
+
<td align="center"><a href="files/embedded_images.xlsx">Download</a></td>
|
|
305
|
+
<td align="center"><a href="#embedded-images">View Code & Detail</a></td>
|
|
306
|
+
</tr>
|
|
307
|
+
<tr>
|
|
308
|
+
<td><strong>Fill Gradients</strong></td>
|
|
309
|
+
<td align="center"><img src="../../test/visual/baselines/fill_gradients/page-1.png" width="160" alt="Fill Gradients"/></td>
|
|
310
|
+
<td align="center"><a href="files/fill_gradients.xlsx">Download</a></td>
|
|
311
|
+
<td align="center"><a href="#fill-gradients">View Code & Detail</a></td>
|
|
312
|
+
</tr>
|
|
313
|
+
<tr>
|
|
314
|
+
<td><strong>Fill Patterns</strong></td>
|
|
315
|
+
<td align="center"><img src="../../test/visual/baselines/fill_patterns/page-1.png" width="160" alt="Fill Patterns"/></td>
|
|
316
|
+
<td align="center"><a href="files/fill_patterns.xlsx">Download</a></td>
|
|
317
|
+
<td align="center"><a href="#fill-patterns">View Code & Detail</a></td>
|
|
318
|
+
</tr>
|
|
319
|
+
<tr>
|
|
320
|
+
<td><strong>Fill Solid Colors</strong></td>
|
|
321
|
+
<td align="center"><img src="../../test/visual/baselines/fill_solid_colors/page-1.png" width="160" alt="Fill Solid Colors"/></td>
|
|
322
|
+
<td align="center"><a href="files/fill_solid_colors.xlsx">Download</a></td>
|
|
323
|
+
<td align="center"><a href="#fill-solid-colors">View Code & Detail</a></td>
|
|
324
|
+
</tr>
|
|
325
|
+
<tr>
|
|
326
|
+
<td><strong>Fonts</strong></td>
|
|
327
|
+
<td align="center"><img src="../../test/visual/baselines/fonts/page-1.png" width="160" alt="Fonts"/></td>
|
|
328
|
+
<td align="center"><a href="files/fonts.xlsx">Download</a></td>
|
|
329
|
+
<td align="center"><a href="#fonts">View Code & Detail</a></td>
|
|
330
|
+
</tr>
|
|
331
|
+
<tr>
|
|
332
|
+
<td><strong>Interactive Autofilter</strong></td>
|
|
333
|
+
<td align="center"><img src="../../test/visual/baselines/interactive_autofilter/page-1.png" width="160" alt="Interactive Autofilter"/></td>
|
|
334
|
+
<td align="center"><a href="files/interactive_autofilter.xlsx">Download</a></td>
|
|
335
|
+
<td align="center"><a href="#interactive-autofilter">View Code & Detail</a></td>
|
|
336
|
+
</tr>
|
|
337
|
+
<tr>
|
|
338
|
+
<td><strong>Interactive Comments</strong></td>
|
|
339
|
+
<td align="center"><img src="../../test/visual/baselines/interactive_comments/page-1.png" width="160" alt="Interactive Comments"/></td>
|
|
340
|
+
<td align="center"><a href="files/interactive_comments.xlsx">Download</a></td>
|
|
341
|
+
<td align="center"><a href="#interactive-comments">View Code & Detail</a></td>
|
|
342
|
+
</tr>
|
|
343
|
+
<tr>
|
|
344
|
+
<td><strong>Interactive Validation Custom</strong></td>
|
|
345
|
+
<td align="center"><img src="../../test/visual/baselines/interactive_validation_custom/page-1.png" width="160" alt="Interactive Validation Custom"/></td>
|
|
346
|
+
<td align="center"><a href="files/interactive_validation_custom.xlsx">Download</a></td>
|
|
347
|
+
<td align="center"><a href="#interactive-validation-custom">View Code & Detail</a></td>
|
|
348
|
+
</tr>
|
|
349
|
+
<tr>
|
|
350
|
+
<td><strong>Interactive Validation Date</strong></td>
|
|
351
|
+
<td align="center"><img src="../../test/visual/baselines/interactive_validation_date/page-1.png" width="160" alt="Interactive Validation Date"/></td>
|
|
352
|
+
<td align="center"><a href="files/interactive_validation_date.xlsx">Download</a></td>
|
|
353
|
+
<td align="center"><a href="#interactive-validation-date">View Code & Detail</a></td>
|
|
354
|
+
</tr>
|
|
355
|
+
<tr>
|
|
356
|
+
<td><strong>Interactive Validation List</strong></td>
|
|
357
|
+
<td align="center"><img src="../../test/visual/baselines/interactive_validation_list/page-1.png" width="160" alt="Interactive Validation List"/></td>
|
|
358
|
+
<td align="center"><a href="files/interactive_validation_list.xlsx">Download</a></td>
|
|
359
|
+
<td align="center"><a href="#interactive-validation-list">View Code & Detail</a></td>
|
|
360
|
+
</tr>
|
|
361
|
+
<tr>
|
|
362
|
+
<td><strong>Interactive Validation Range</strong></td>
|
|
363
|
+
<td align="center"><img src="../../test/visual/baselines/interactive_validation_range/page-1.png" width="160" alt="Interactive Validation Range"/></td>
|
|
364
|
+
<td align="center"><a href="files/interactive_validation_range.xlsx">Download</a></td>
|
|
365
|
+
<td align="center"><a href="#interactive-validation-range">View Code & Detail</a></td>
|
|
366
|
+
</tr>
|
|
367
|
+
<tr>
|
|
368
|
+
<td><strong>Interactive Validation Text Length</strong></td>
|
|
369
|
+
<td align="center"><img src="../../test/visual/baselines/interactive_validation_text_length/page-1.png" width="160" alt="Interactive Validation Text Length"/></td>
|
|
370
|
+
<td align="center"><a href="files/interactive_validation_text_length.xlsx">Download</a></td>
|
|
371
|
+
<td align="center"><a href="#interactive-validation-text-length">View Code & Detail</a></td>
|
|
372
|
+
</tr>
|
|
373
|
+
<tr>
|
|
374
|
+
<td><strong>Interactive Validation Time</strong></td>
|
|
375
|
+
<td align="center"><img src="../../test/visual/baselines/interactive_validation_time/page-1.png" width="160" alt="Interactive Validation Time"/></td>
|
|
376
|
+
<td align="center"><a href="files/interactive_validation_time.xlsx">Download</a></td>
|
|
377
|
+
<td align="center"><a href="#interactive-validation-time">View Code & Detail</a></td>
|
|
378
|
+
</tr>
|
|
379
|
+
<tr>
|
|
380
|
+
<td><strong>Japanese Text</strong></td>
|
|
381
|
+
<td align="center"><img src="../../test/visual/baselines/japanese_text/page-1.png" width="160" alt="Japanese Text"/></td>
|
|
382
|
+
<td align="center"><a href="files/japanese_text.xlsx">Download</a></td>
|
|
383
|
+
<td align="center"><a href="#japanese-text">View Code & Detail</a></td>
|
|
384
|
+
</tr>
|
|
385
|
+
<tr>
|
|
386
|
+
<td><strong>Merge Freeze</strong></td>
|
|
387
|
+
<td align="center"><img src="../../test/visual/baselines/merge_freeze/page-1.png" width="160" alt="Merge Freeze"/></td>
|
|
388
|
+
<td align="center"><a href="files/merge_freeze.xlsx">Download</a></td>
|
|
389
|
+
<td align="center"><a href="#merge-freeze">View Code & Detail</a></td>
|
|
390
|
+
</tr>
|
|
391
|
+
<tr>
|
|
392
|
+
<td><strong>Page Grid Lines Print</strong></td>
|
|
393
|
+
<td align="center"><img src="../../test/visual/baselines/page_grid_lines_print/page-1.png" width="160" alt="Page Grid Lines Print"/></td>
|
|
394
|
+
<td align="center"><a href="files/page_grid_lines_print.xlsx">Download</a></td>
|
|
395
|
+
<td align="center"><a href="#page-grid-lines-print">View Code & Detail</a></td>
|
|
396
|
+
</tr>
|
|
397
|
+
<tr>
|
|
398
|
+
<td><strong>Page Header Footer</strong></td>
|
|
399
|
+
<td align="center"><img src="../../test/visual/baselines/page_header_footer/page-1.png" width="160" alt="Page Header Footer"/></td>
|
|
400
|
+
<td align="center"><a href="files/page_header_footer.xlsx">Download</a></td>
|
|
401
|
+
<td align="center"><a href="#page-header-footer">View Code & Detail</a></td>
|
|
402
|
+
</tr>
|
|
403
|
+
<tr>
|
|
404
|
+
<td><strong>Page Headings Print</strong></td>
|
|
405
|
+
<td align="center"><img src="../../test/visual/baselines/page_headings_print/page-1.png" width="160" alt="Page Headings Print"/></td>
|
|
406
|
+
<td align="center"><a href="files/page_headings_print.xlsx">Download</a></td>
|
|
407
|
+
<td align="center"><a href="#page-headings-print">View Code & Detail</a></td>
|
|
408
|
+
</tr>
|
|
409
|
+
<tr>
|
|
410
|
+
<td><strong>Page Margins Narrow</strong></td>
|
|
411
|
+
<td align="center"><img src="../../test/visual/baselines/page_margins_narrow/page-1.png" width="160" alt="Page Margins Narrow"/></td>
|
|
412
|
+
<td align="center"><a href="files/page_margins_narrow.xlsx">Download</a></td>
|
|
413
|
+
<td align="center"><a href="#page-margins-narrow">View Code & Detail</a></td>
|
|
414
|
+
</tr>
|
|
415
|
+
<tr>
|
|
416
|
+
<td><strong>Page Margins Wide</strong></td>
|
|
417
|
+
<td align="center"><img src="../../test/visual/baselines/page_margins_wide/page-1.png" width="160" alt="Page Margins Wide"/></td>
|
|
418
|
+
<td align="center"><a href="files/page_margins_wide.xlsx">Download</a></td>
|
|
419
|
+
<td align="center"><a href="#page-margins-wide">View Code & Detail</a></td>
|
|
420
|
+
</tr>
|
|
421
|
+
<tr>
|
|
422
|
+
<td><strong>Page Orientation Landscape</strong></td>
|
|
423
|
+
<td align="center"><img src="../../test/visual/baselines/page_orientation_landscape/page-1.png" width="160" alt="Page Orientation Landscape"/></td>
|
|
424
|
+
<td align="center"><a href="files/page_orientation_landscape.xlsx">Download</a></td>
|
|
425
|
+
<td align="center"><a href="#page-orientation-landscape">View Code & Detail</a></td>
|
|
426
|
+
</tr>
|
|
427
|
+
<tr>
|
|
428
|
+
<td><strong>Page Paper Size A3</strong></td>
|
|
429
|
+
<td align="center"><img src="../../test/visual/baselines/page_paper_size_a3/page-1.png" width="160" alt="Page Paper Size A3"/></td>
|
|
430
|
+
<td align="center"><a href="files/page_paper_size_a3.xlsx">Download</a></td>
|
|
431
|
+
<td align="center"><a href="#page-paper-size-a3">View Code & Detail</a></td>
|
|
432
|
+
</tr>
|
|
433
|
+
<tr>
|
|
434
|
+
<td><strong>Row Grouping</strong></td>
|
|
435
|
+
<td align="center"><img src="../../test/visual/baselines/row_grouping/page-1.png" width="160" alt="Row Grouping"/></td>
|
|
436
|
+
<td align="center"><a href="files/row_grouping.xlsx">Download</a></td>
|
|
437
|
+
<td align="center"><a href="#row-grouping">View Code & Detail</a></td>
|
|
438
|
+
</tr>
|
|
439
|
+
<tr>
|
|
440
|
+
<td><strong>Row Height Tall</strong></td>
|
|
441
|
+
<td align="center"><img src="../../test/visual/baselines/row_height_tall/page-1.png" width="160" alt="Row Height Tall"/></td>
|
|
442
|
+
<td align="center"><a href="files/row_height_tall.xlsx">Download</a></td>
|
|
443
|
+
<td align="center"><a href="#row-height-tall">View Code & Detail</a></td>
|
|
444
|
+
</tr>
|
|
445
|
+
<tr>
|
|
446
|
+
<td><strong>Row Heights</strong></td>
|
|
447
|
+
<td align="center"><img src="../../test/visual/baselines/row_heights/page-1.png" width="160" alt="Row Heights"/></td>
|
|
448
|
+
<td align="center"><a href="files/row_heights.xlsx">Download</a></td>
|
|
449
|
+
<td align="center"><a href="#row-heights">View Code & Detail</a></td>
|
|
450
|
+
</tr>
|
|
451
|
+
<tr>
|
|
452
|
+
<td><strong>Sheet Tab Colors</strong></td>
|
|
453
|
+
<td align="center"><img src="../../test/visual/baselines/sheet_tab_colors/page-1.png" width="160" alt="Sheet Tab Colors"/></td>
|
|
454
|
+
<td align="center"><a href="files/sheet_tab_colors.xlsx">Download</a></td>
|
|
455
|
+
<td align="center"><a href="#sheet-tab-colors">View Code & Detail</a></td>
|
|
456
|
+
</tr>
|
|
457
|
+
<tr>
|
|
458
|
+
<td><strong>Sparkline Column</strong></td>
|
|
459
|
+
<td align="center"><img src="../../test/visual/baselines/sparkline_column/page-1.png" width="160" alt="Sparkline Column"/></td>
|
|
460
|
+
<td align="center"><a href="files/sparkline_column.xlsx">Download</a></td>
|
|
461
|
+
<td align="center"><a href="#sparkline-column">View Code & Detail</a></td>
|
|
462
|
+
</tr>
|
|
463
|
+
<tr>
|
|
464
|
+
<td><strong>Sparkline Line</strong></td>
|
|
465
|
+
<td align="center"><img src="../../test/visual/baselines/sparkline_line/page-1.png" width="160" alt="Sparkline Line"/></td>
|
|
466
|
+
<td align="center"><a href="files/sparkline_line.xlsx">Download</a></td>
|
|
467
|
+
<td align="center"><a href="#sparkline-line">View Code & Detail</a></td>
|
|
468
|
+
</tr>
|
|
469
|
+
<tr>
|
|
470
|
+
<td><strong>Styles Fonts Fills</strong></td>
|
|
471
|
+
<td align="center"><img src="../../test/visual/baselines/styles_fonts_fills/page-1.png" width="160" alt="Styles Fonts Fills"/></td>
|
|
472
|
+
<td align="center"><a href="files/styles_fonts_fills.xlsx">Download</a></td>
|
|
473
|
+
<td align="center"><a href="#styles-fonts-fills">View Code & Detail</a></td>
|
|
474
|
+
</tr>
|
|
475
|
+
<tr>
|
|
476
|
+
<td><strong>View Show Grid Lines</strong></td>
|
|
477
|
+
<td align="center"><img src="../../test/visual/baselines/view_show_grid_lines/page-1.png" width="160" alt="View Show Grid Lines"/></td>
|
|
478
|
+
<td align="center"><a href="files/view_show_grid_lines.xlsx">Download</a></td>
|
|
479
|
+
<td align="center"><a href="#view-show-grid-lines">View Code & Detail</a></td>
|
|
480
|
+
</tr>
|
|
481
|
+
<tr>
|
|
482
|
+
<td><strong>View Zoom Scale</strong></td>
|
|
483
|
+
<td align="center"><img src="../../test/visual/baselines/view_zoom_scale/page-1.png" width="160" alt="View Zoom Scale"/></td>
|
|
484
|
+
<td align="center"><a href="files/view_zoom_scale.xlsx">Download</a></td>
|
|
485
|
+
<td align="center"><a href="#view-zoom-scale">View Code & Detail</a></td>
|
|
486
|
+
</tr>
|
|
487
|
+
<tr>
|
|
488
|
+
<td><strong>Workbook Three Sheets</strong></td>
|
|
489
|
+
<td align="center"><img src="../../test/visual/baselines/workbook_three_sheets/page-1.png" width="160" alt="Workbook Three Sheets"/></td>
|
|
490
|
+
<td align="center"><a href="files/workbook_three_sheets.xlsx">Download</a></td>
|
|
491
|
+
<td align="center"><a href="#workbook-three-sheets">View Code & Detail</a></td>
|
|
492
|
+
</tr>
|
|
493
|
+
</tbody>
|
|
494
|
+
</table>
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## Align Horizontal
|
|
500
|
+
|
|
501
|
+
[Download .xlsx](files/align_horizontal.xlsx)
|
|
502
|
+
|
|
503
|
+
Demonstrates horizontal text alignment (left, center, right).
|
|
504
|
+
|
|
505
|
+
### Rendered Output (LibreOffice Calc)
|
|
506
|
+
|
|
507
|
+
<div><img src="../../test/visual/baselines/align_horizontal/page-1.png" width="100%" alt="Preview"/></div>
|
|
508
|
+
|
|
509
|
+
### DSL Code
|
|
510
|
+
|
|
511
|
+
```ruby
|
|
512
|
+
# frozen_string_literal: true
|
|
513
|
+
require "xlsxrb"
|
|
514
|
+
output_path = ARGV[0] || "align_horizontal.xlsx"
|
|
515
|
+
Xlsxrb.generate(output_path) do |w|
|
|
516
|
+
w.add_style("left") { |s| s.align_horizontal("left") }
|
|
517
|
+
w.add_style("center") { |s| s.align_horizontal("center") }
|
|
518
|
+
w.add_style("right") { |s| s.align_horizontal("right") }
|
|
519
|
+
w.add_sheet("Alignment") do |s|
|
|
520
|
+
s.set_print_option(:grid_lines, true)
|
|
521
|
+
s.set_column(0, width: 20)
|
|
522
|
+
s.set_column(1, width: 20)
|
|
523
|
+
s.set_column(2, width: 20)
|
|
524
|
+
s.add_row(["Left", "Center", "Right"], styles: { 0 => "left", 1 => "center", 2 => "right" })
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
# 2. Read the generated sheet and print the parsed alignments
|
|
529
|
+
puts "=== Read Alignment (Xlsxrb.read) ==="
|
|
530
|
+
workbook = Xlsxrb.read(output_path)
|
|
531
|
+
sheet = workbook.sheets.first
|
|
532
|
+
row = sheet.rows.first
|
|
533
|
+
|
|
534
|
+
row.cells.each do |c|
|
|
535
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
536
|
+
align_h = xf ? xf.dig(:alignment, :horizontal) : nil
|
|
537
|
+
puts "Cell #{c.ref} ('#{c.value}'): align_horizontal = #{align_h.inspect}"
|
|
538
|
+
end
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### Console Output
|
|
542
|
+
|
|
543
|
+
```text
|
|
544
|
+
=== Read Alignment (Xlsxrb.read) ===
|
|
545
|
+
Cell A1 ('Left'): align_horizontal = "left"
|
|
546
|
+
Cell B1 ('Center'): align_horizontal = "center"
|
|
547
|
+
Cell C1 ('Right'): align_horizontal = "right"
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
<hr/>
|
|
551
|
+
|
|
552
|
+
## Align Horizontal Fill
|
|
553
|
+
|
|
554
|
+
[Download .xlsx](files/align_horizontal_fill.xlsx)
|
|
555
|
+
|
|
556
|
+
Demonstrates horizontal fill alignment (repeats value to fill cell width).
|
|
557
|
+
|
|
558
|
+
### Rendered Output (LibreOffice Calc)
|
|
559
|
+
|
|
560
|
+
<div><img src="../../test/visual/baselines/align_horizontal_fill/page-1.png" width="100%" alt="Preview"/></div>
|
|
561
|
+
|
|
562
|
+
### DSL Code
|
|
563
|
+
|
|
564
|
+
```ruby
|
|
565
|
+
# frozen_string_literal: true
|
|
566
|
+
require "xlsxrb"
|
|
567
|
+
output_path = ARGV[0] || "align_horizontal_fill.xlsx"
|
|
568
|
+
Xlsxrb.generate(output_path) do |w|
|
|
569
|
+
w.add_style("fill_align") { |s| s.align_horizontal("fill") }
|
|
570
|
+
w.add_sheet("Alignment") do |s|
|
|
571
|
+
s.set_column(0, width: 30)
|
|
572
|
+
s.add_row(["X "], styles: { 0 => "fill_align" })
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
# 2. Read the generated sheet and print the parsed alignments
|
|
577
|
+
puts "=== Read Validation ==="
|
|
578
|
+
workbook = Xlsxrb.read(output_path)
|
|
579
|
+
sheet = workbook.sheets.first
|
|
580
|
+
row = sheet.rows.first
|
|
581
|
+
row.cells.each do |c|
|
|
582
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
583
|
+
align_h = xf ? xf.dig(:alignment, :horizontal) : nil
|
|
584
|
+
align_v = xf ? xf.dig(:alignment, :vertical) : nil
|
|
585
|
+
wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
|
|
586
|
+
indent = xf ? xf.dig(:alignment, :indent) : nil
|
|
587
|
+
rot = xf ? xf.dig(:alignment, :text_rotation) : nil
|
|
588
|
+
shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
|
|
589
|
+
puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
|
|
590
|
+
end
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
### Console Output
|
|
594
|
+
|
|
595
|
+
```text
|
|
596
|
+
=== Read Validation ===
|
|
597
|
+
Cell A1 ('X '): align_h="fill", align_v=nil, wrap=nil, indent=nil, rotation=nil, shrink=nil
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
<hr/>
|
|
601
|
+
|
|
602
|
+
## Align Horizontal Justify
|
|
603
|
+
|
|
604
|
+
[Download .xlsx](files/align_horizontal_justify.xlsx)
|
|
605
|
+
|
|
606
|
+
Demonstrates horizontal justify text alignment.
|
|
607
|
+
|
|
608
|
+
### Rendered Output (LibreOffice Calc)
|
|
609
|
+
|
|
610
|
+
<div><img src="../../test/visual/baselines/align_horizontal_justify/page-1.png" width="100%" alt="Preview"/></div>
|
|
611
|
+
|
|
612
|
+
### DSL Code
|
|
613
|
+
|
|
614
|
+
```ruby
|
|
615
|
+
# frozen_string_literal: true
|
|
616
|
+
require "xlsxrb"
|
|
617
|
+
output_path = ARGV[0] || "align_horizontal_justify.xlsx"
|
|
618
|
+
Xlsxrb.generate(output_path) do |w|
|
|
619
|
+
w.add_style("justify_align") do |s|
|
|
620
|
+
s.align_horizontal("justify")
|
|
621
|
+
s.wrap_text(true)
|
|
622
|
+
end
|
|
623
|
+
w.add_sheet("Alignment") do |s|
|
|
624
|
+
s.set_column(0, width: 25)
|
|
625
|
+
s.add_row(["Justified alignment wraps and distributes text evenly."], styles: { 0 => "justify_align" })
|
|
626
|
+
end
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
# 2. Read the generated sheet and print the parsed alignments
|
|
630
|
+
puts "=== Read Validation ==="
|
|
631
|
+
workbook = Xlsxrb.read(output_path)
|
|
632
|
+
sheet = workbook.sheets.first
|
|
633
|
+
row = sheet.rows.first
|
|
634
|
+
row.cells.each do |c|
|
|
635
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
636
|
+
align_h = xf ? xf.dig(:alignment, :horizontal) : nil
|
|
637
|
+
align_v = xf ? xf.dig(:alignment, :vertical) : nil
|
|
638
|
+
wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
|
|
639
|
+
indent = xf ? xf.dig(:alignment, :indent) : nil
|
|
640
|
+
rot = xf ? xf.dig(:alignment, :text_rotation) : nil
|
|
641
|
+
shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
|
|
642
|
+
puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
|
|
643
|
+
end
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
### Console Output
|
|
647
|
+
|
|
648
|
+
```text
|
|
649
|
+
=== Read Validation ===
|
|
650
|
+
Cell A1 ('Justified alignment wraps and distributes text evenly.'): align_h="justify", align_v=nil, wrap=true, indent=nil, rotation=nil, shrink=nil
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
<hr/>
|
|
654
|
+
|
|
655
|
+
## Align Indent
|
|
656
|
+
|
|
657
|
+
[Download .xlsx](files/align_indent.xlsx)
|
|
658
|
+
|
|
659
|
+
Demonstrates text indentation inside cells.
|
|
660
|
+
|
|
661
|
+
### Rendered Output (LibreOffice Calc)
|
|
662
|
+
|
|
663
|
+
<div><img src="../../test/visual/baselines/align_indent/page-1.png" width="100%" alt="Preview"/></div>
|
|
664
|
+
|
|
665
|
+
### DSL Code
|
|
666
|
+
|
|
667
|
+
```ruby
|
|
668
|
+
# frozen_string_literal: true
|
|
669
|
+
require "xlsxrb"
|
|
670
|
+
output_path = ARGV[0] || "align_indent.xlsx"
|
|
671
|
+
Xlsxrb.generate(output_path) do |w|
|
|
672
|
+
w.add_style("indent_1") { |s| s.align_horizontal("left").indent(1) }
|
|
673
|
+
w.add_style("indent_3") { |s| s.align_horizontal("left").indent(3) }
|
|
674
|
+
w.add_sheet("Indent") do |s|
|
|
675
|
+
s.set_column(0, width: 25)
|
|
676
|
+
s.set_column(1, width: 25)
|
|
677
|
+
s.set_print_option(:grid_lines, true)
|
|
678
|
+
s.add_row(["No Indent"])
|
|
679
|
+
s.add_row(["Indent 1"], styles: { 0 => "indent_1" })
|
|
680
|
+
s.add_row(["Indent 3"], styles: { 0 => "indent_3" })
|
|
681
|
+
end
|
|
682
|
+
end
|
|
683
|
+
|
|
684
|
+
# 2. Read the generated sheet and print the parsed alignments
|
|
685
|
+
puts "=== Read Validation ==="
|
|
686
|
+
workbook = Xlsxrb.read(output_path)
|
|
687
|
+
sheet = workbook.sheets.first
|
|
688
|
+
row = sheet.rows.first
|
|
689
|
+
row.cells.each do |c|
|
|
690
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
691
|
+
align_h = xf ? xf.dig(:alignment, :horizontal) : nil
|
|
692
|
+
align_v = xf ? xf.dig(:alignment, :vertical) : nil
|
|
693
|
+
wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
|
|
694
|
+
indent = xf ? xf.dig(:alignment, :indent) : nil
|
|
695
|
+
rot = xf ? xf.dig(:alignment, :text_rotation) : nil
|
|
696
|
+
shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
|
|
697
|
+
puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
|
|
698
|
+
end
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Console Output
|
|
702
|
+
|
|
703
|
+
```text
|
|
704
|
+
=== Read Validation ===
|
|
705
|
+
Cell A1 ('No Indent'): align_h=nil, align_v=nil, wrap=nil, indent=nil, rotation=nil, shrink=nil
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
<hr/>
|
|
709
|
+
|
|
710
|
+
## Align Text Rotation
|
|
711
|
+
|
|
712
|
+
[Download .xlsx](files/align_text_rotation.xlsx)
|
|
713
|
+
|
|
714
|
+
Demonstrates text rotated by specific angles (45, 90 degrees).
|
|
715
|
+
|
|
716
|
+
### Rendered Output (LibreOffice Calc)
|
|
717
|
+
|
|
718
|
+
<div><img src="../../test/visual/baselines/align_text_rotation/page-1.png" width="100%" alt="Preview"/></div>
|
|
719
|
+
|
|
720
|
+
### DSL Code
|
|
721
|
+
|
|
722
|
+
```ruby
|
|
723
|
+
# frozen_string_literal: true
|
|
724
|
+
require "xlsxrb"
|
|
725
|
+
output_path = ARGV[0] || "align_text_rotation.xlsx"
|
|
726
|
+
Xlsxrb.generate(output_path) do |w|
|
|
727
|
+
w.add_style("rot_45") { |s| s.text_rotation(45) }
|
|
728
|
+
w.add_style("rot_90") { |s| s.text_rotation(90) }
|
|
729
|
+
w.add_sheet("Rotation") do |s|
|
|
730
|
+
s.set_column(0, width: 25)
|
|
731
|
+
s.set_column(1, width: 25)
|
|
732
|
+
s.set_print_option(:grid_lines, true)
|
|
733
|
+
s.add_row(["Rotated 45", "Rotated 90"], styles: { 0 => "rot_45", 1 => "rot_90" }, height: 50)
|
|
734
|
+
end
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
# 2. Read the generated sheet and print the parsed alignments
|
|
738
|
+
puts "=== Read Validation ==="
|
|
739
|
+
workbook = Xlsxrb.read(output_path)
|
|
740
|
+
sheet = workbook.sheets.first
|
|
741
|
+
row = sheet.rows.first
|
|
742
|
+
row.cells.each do |c|
|
|
743
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
744
|
+
align_h = xf ? xf.dig(:alignment, :horizontal) : nil
|
|
745
|
+
align_v = xf ? xf.dig(:alignment, :vertical) : nil
|
|
746
|
+
wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
|
|
747
|
+
indent = xf ? xf.dig(:alignment, :indent) : nil
|
|
748
|
+
rot = xf ? xf.dig(:alignment, :text_rotation) : nil
|
|
749
|
+
shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
|
|
750
|
+
puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
|
|
751
|
+
end
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
### Console Output
|
|
755
|
+
|
|
756
|
+
```text
|
|
757
|
+
=== Read Validation ===
|
|
758
|
+
Cell A1 ('Rotated 45'): align_h=nil, align_v=nil, wrap=nil, indent=nil, rotation=45, shrink=nil
|
|
759
|
+
Cell B1 ('Rotated 90'): align_h=nil, align_v=nil, wrap=nil, indent=nil, rotation=90, shrink=nil
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
<hr/>
|
|
763
|
+
|
|
764
|
+
## Align Text Wrap
|
|
765
|
+
|
|
766
|
+
[Download .xlsx](files/align_text_wrap.xlsx)
|
|
767
|
+
|
|
768
|
+
Demonstrates auto-wrapping multi-line text inside narrow cells.
|
|
769
|
+
|
|
770
|
+
### Rendered Output (LibreOffice Calc)
|
|
771
|
+
|
|
772
|
+
<div><img src="../../test/visual/baselines/align_text_wrap/page-1.png" width="100%" alt="Preview"/></div>
|
|
773
|
+
|
|
774
|
+
### DSL Code
|
|
775
|
+
|
|
776
|
+
```ruby
|
|
777
|
+
# frozen_string_literal: true
|
|
778
|
+
require "xlsxrb"
|
|
779
|
+
output_path = ARGV[0] || "align_text_wrap.xlsx"
|
|
780
|
+
Xlsxrb.generate(output_path) do |w|
|
|
781
|
+
w.add_style("wrap") { |s| s.wrap_text }
|
|
782
|
+
w.add_sheet("Text Wrap") do |s|
|
|
783
|
+
s.set_print_option(:grid_lines, true)
|
|
784
|
+
s.set_column(0, width: 15)
|
|
785
|
+
s.add_row(["This is a long sentence that wraps inside the cell."], styles: { 0 => "wrap" })
|
|
786
|
+
end
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
# 2. Read the generated sheet and print the parsed alignments
|
|
790
|
+
puts "=== Read Validation ==="
|
|
791
|
+
workbook = Xlsxrb.read(output_path)
|
|
792
|
+
sheet = workbook.sheets.first
|
|
793
|
+
row = sheet.rows.first
|
|
794
|
+
row.cells.each do |c|
|
|
795
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
796
|
+
align_h = xf ? xf.dig(:alignment, :horizontal) : nil
|
|
797
|
+
align_v = xf ? xf.dig(:alignment, :vertical) : nil
|
|
798
|
+
wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
|
|
799
|
+
indent = xf ? xf.dig(:alignment, :indent) : nil
|
|
800
|
+
rot = xf ? xf.dig(:alignment, :text_rotation) : nil
|
|
801
|
+
shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
|
|
802
|
+
puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
|
|
803
|
+
end
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
### Console Output
|
|
807
|
+
|
|
808
|
+
```text
|
|
809
|
+
=== Read Validation ===
|
|
810
|
+
Cell A1 ('This is a long sentence that wraps inside the cell.'): align_h=nil, align_v=nil, wrap=true, indent=nil, rotation=nil, shrink=nil
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
<hr/>
|
|
814
|
+
|
|
815
|
+
## Align Vertical
|
|
816
|
+
|
|
817
|
+
[Download .xlsx](files/align_vertical.xlsx)
|
|
818
|
+
|
|
819
|
+
Demonstrates vertical text alignment (top, center, bottom).
|
|
820
|
+
|
|
821
|
+
### Rendered Output (LibreOffice Calc)
|
|
822
|
+
|
|
823
|
+
<div><img src="../../test/visual/baselines/align_vertical/page-1.png" width="100%" alt="Preview"/></div>
|
|
824
|
+
|
|
825
|
+
### DSL Code
|
|
826
|
+
|
|
827
|
+
```ruby
|
|
828
|
+
# frozen_string_literal: true
|
|
829
|
+
require "xlsxrb"
|
|
830
|
+
output_path = ARGV[0] || "align_vertical.xlsx"
|
|
831
|
+
Xlsxrb.generate(output_path) do |w|
|
|
832
|
+
w.add_style("top") { |s| s.align_vertical("top") }
|
|
833
|
+
w.add_style("center") { |s| s.align_vertical("center") }
|
|
834
|
+
w.add_style("bottom") { |s| s.align_vertical("bottom") }
|
|
835
|
+
w.add_sheet("Vertical Alignment") do |s|
|
|
836
|
+
s.set_column(0, width: 25)
|
|
837
|
+
s.set_column(1, width: 25)
|
|
838
|
+
s.set_print_option(:grid_lines, true)
|
|
839
|
+
s.add_row(["Top", "Center", "Bottom"], styles: { 0 => "top", 1 => "center", 2 => "bottom" }, height: 40)
|
|
840
|
+
end
|
|
841
|
+
end
|
|
842
|
+
|
|
843
|
+
# 2. Read the generated sheet and print the parsed alignments
|
|
844
|
+
puts "=== Read Validation ==="
|
|
845
|
+
workbook = Xlsxrb.read(output_path)
|
|
846
|
+
sheet = workbook.sheets.first
|
|
847
|
+
row = sheet.rows.first
|
|
848
|
+
row.cells.each do |c|
|
|
849
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
850
|
+
align_h = xf ? xf.dig(:alignment, :horizontal) : nil
|
|
851
|
+
align_v = xf ? xf.dig(:alignment, :vertical) : nil
|
|
852
|
+
wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
|
|
853
|
+
indent = xf ? xf.dig(:alignment, :indent) : nil
|
|
854
|
+
rot = xf ? xf.dig(:alignment, :text_rotation) : nil
|
|
855
|
+
shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
|
|
856
|
+
puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
|
|
857
|
+
end
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
### Console Output
|
|
861
|
+
|
|
862
|
+
```text
|
|
863
|
+
=== Read Validation ===
|
|
864
|
+
Cell A1 ('Top'): align_h=nil, align_v="top", wrap=nil, indent=nil, rotation=nil, shrink=nil
|
|
865
|
+
Cell B1 ('Center'): align_h=nil, align_v="center", wrap=nil, indent=nil, rotation=nil, shrink=nil
|
|
866
|
+
Cell C1 ('Bottom'): align_h=nil, align_v="bottom", wrap=nil, indent=nil, rotation=nil, shrink=nil
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
<hr/>
|
|
870
|
+
|
|
871
|
+
## Basic Data
|
|
872
|
+
|
|
873
|
+
[Download .xlsx](files/basic_data.xlsx)
|
|
874
|
+
|
|
875
|
+
Demonstrates simple tabular data writing with basic Ruby types (Strings, Numbers, Dates, Booleans).
|
|
876
|
+
|
|
877
|
+
### Rendered Output (LibreOffice Calc)
|
|
878
|
+
|
|
879
|
+
<div><img src="../../test/visual/baselines/basic_data/page-1.png" width="100%" alt="Preview"/></div>
|
|
880
|
+
|
|
881
|
+
### DSL Code
|
|
882
|
+
|
|
883
|
+
```ruby
|
|
884
|
+
# frozen_string_literal: true
|
|
885
|
+
|
|
886
|
+
require "xlsxrb"
|
|
887
|
+
require "date"
|
|
888
|
+
|
|
889
|
+
output_path = ARGV[0] || "basic_data.xlsx"
|
|
890
|
+
|
|
891
|
+
Xlsxrb.generate(output_path) do |w|
|
|
892
|
+
w.add_style("currency") { |style| style.number_format("$#,##0.00") }
|
|
893
|
+
w.add_style("date") { |style| style.number_format("yyyy-mm-dd") }
|
|
894
|
+
w.add_sheet("Basic Data") do
|
|
895
|
+
w.set_sheet_property(:fit_to_page, true)
|
|
896
|
+
w.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
897
|
+
w.set_column(0, width: 25)
|
|
898
|
+
w.set_column(1, width: 25)
|
|
899
|
+
w.add_row(["Product", "Qty", "Price", "Date", "Active"])
|
|
900
|
+
w.add_row(["Gadget A", 10, 99.99, Date.new(2026, 1, 15), true], styles: { 2 => "currency", 3 => "date" })
|
|
901
|
+
w.add_row(["Widget B", 5, 49.50, Date.new(2026, 2, 20), false], styles: { 2 => "currency", 3 => "date" })
|
|
902
|
+
end
|
|
903
|
+
end
|
|
904
|
+
|
|
905
|
+
# 2. Read the generated sheet and print parsed cell values and Ruby classes
|
|
906
|
+
puts "=== Read Validation ==="
|
|
907
|
+
workbook = Xlsxrb.read(output_path)
|
|
908
|
+
sheet = workbook.sheets.first
|
|
909
|
+
sheet.rows.each do |row|
|
|
910
|
+
row_cells = row.cells.map do |c|
|
|
911
|
+
"#{c.ref}: #{c.value.inspect} (#{c.value.class})"
|
|
912
|
+
end
|
|
913
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
914
|
+
end
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
### Console Output
|
|
918
|
+
|
|
919
|
+
```text
|
|
920
|
+
=== Read Validation ===
|
|
921
|
+
Row 0: A1: "Product" (String), B1: "Qty" (String), C1: "Price" (String), D1: "Date" (String), E1: "Active" (String)
|
|
922
|
+
Row 1: A2: "Gadget A" (String), B2: 10 (Integer), C2: 99.99 (Float), D2: 46037 (Integer), E2: true (TrueClass)
|
|
923
|
+
Row 2: A3: "Widget B" (String), B3: 5 (Integer), C3: 49.5 (Float), D3: 46073 (Integer), E3: false (FalseClass)
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
<hr/>
|
|
927
|
+
|
|
928
|
+
## Borders
|
|
929
|
+
|
|
930
|
+
[Download .xlsx](files/borders.xlsx)
|
|
931
|
+
|
|
932
|
+
Demonstrates border styles (thin, medium, thick, hair, dashed, medium dashed, dotted, double, dash-dot, medium dash-dot, dash-dot-dot, slanted, and diagonal cross borders) applied to cell ranges.
|
|
933
|
+
|
|
934
|
+
### Rendered Output (LibreOffice Calc)
|
|
935
|
+
|
|
936
|
+
<div><img src="../../test/visual/baselines/borders/page-1.png" width="100%" alt="Preview"/></div>
|
|
937
|
+
|
|
938
|
+
### DSL Code
|
|
939
|
+
|
|
940
|
+
```ruby
|
|
941
|
+
# frozen_string_literal: true
|
|
942
|
+
|
|
943
|
+
require "xlsxrb"
|
|
944
|
+
|
|
945
|
+
output_path = ARGV[0] || "borders.xlsx"
|
|
946
|
+
|
|
947
|
+
Xlsxrb.generate(output_path) do |w|
|
|
948
|
+
w.add_style("thin") { |s| s.border_all(style: "thin", color: "FF000000") }
|
|
949
|
+
w.add_style("medium") { |s| s.border_all(style: "medium", color: "FF000000") }
|
|
950
|
+
w.add_style("thick") { |s| s.border_all(style: "thick", color: "FF000000") }
|
|
951
|
+
w.add_style("hair") { |s| s.border_all(style: "hair", color: "FF000000") }
|
|
952
|
+
w.add_style("dashed") { |s| s.border_all(style: "dashed", color: "FF000000") }
|
|
953
|
+
w.add_style("medium_dashed") { |s| s.border_all(style: "mediumDashed", color: "FF000000") }
|
|
954
|
+
w.add_style("dotted") { |s| s.border_all(style: "dotted", color: "FF000000") }
|
|
955
|
+
w.add_style("double") { |s| s.border_all(style: "double", color: "FF000000") }
|
|
956
|
+
w.add_style("dash_dot") { |s| s.border_all(style: "dashDot", color: "FF000000") }
|
|
957
|
+
w.add_style("medium_dash_dot") { |s| s.border_all(style: "mediumDashDot", color: "FF000000") }
|
|
958
|
+
w.add_style("dash_dot_dot") { |s| s.border_all(style: "dashDotDot", color: "FF000000") }
|
|
959
|
+
w.add_style("slanted") { |s| s.border_all(style: "slantedDashDot", color: "FF000000") }
|
|
960
|
+
w.add_style("diagonal") { |s| s.border_diagonal(style: "thin", color: "FF000000", up: true, down: true) }
|
|
961
|
+
|
|
962
|
+
w.add_sheet("Borders") do |s|
|
|
963
|
+
s.set_column(0, width: 25)
|
|
964
|
+
s.set_column(1, width: 25)
|
|
965
|
+
s.set_print_option(:grid_lines, true)
|
|
966
|
+
|
|
967
|
+
s.add_row(["Border Style", "Cell Preview"])
|
|
968
|
+
s.add_row(["Thin", "Thin Border"], styles: { 1 => "thin" })
|
|
969
|
+
s.add_row(["Medium", "Medium Border"], styles: { 1 => "medium" })
|
|
970
|
+
s.add_row(["Thick", "Thick Border"], styles: { 1 => "thick" })
|
|
971
|
+
s.add_row(["Hair", "Hair Border"], styles: { 1 => "hair" })
|
|
972
|
+
s.add_row(["Dashed", "Dashed Border"], styles: { 1 => "dashed" })
|
|
973
|
+
s.add_row(["Medium Dashed", "Medium Dashed"], styles: { 1 => "medium_dashed" })
|
|
974
|
+
s.add_row(["Dotted", "Dotted Border"], styles: { 1 => "dotted" })
|
|
975
|
+
s.add_row(["Double", "Double Border"], styles: { 1 => "double" })
|
|
976
|
+
s.add_row(["Dash-Dot", "Dash-Dot Border"], styles: { 1 => "dash_dot" })
|
|
977
|
+
s.add_row(["Medium Dash-Dot", "Medium Dash-Dot"], styles: { 1 => "medium_dash_dot" })
|
|
978
|
+
s.add_row(["Dash-Dot-Dot", "Dash-Dot-Dot"], styles: { 1 => "dash_dot_dot" })
|
|
979
|
+
s.add_row(["Slanted Dash-Dot", "Slanted Border"], styles: { 1 => "slanted" })
|
|
980
|
+
s.add_row(["Diagonal (Cross)", "Diagonal Border"], styles: { 1 => "diagonal" })
|
|
981
|
+
end
|
|
982
|
+
end
|
|
983
|
+
|
|
984
|
+
# Read check
|
|
985
|
+
puts "=== Read Validation ==="
|
|
986
|
+
workbook = Xlsxrb.read(output_path)
|
|
987
|
+
sheet = workbook.sheets.first
|
|
988
|
+
sheet.rows.each do |row|
|
|
989
|
+
row_cells = row.cells.map do |c|
|
|
990
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
991
|
+
border_id = xf ? xf[:border_id] : 0
|
|
992
|
+
"#{c.ref}: #{c.value.inspect} (border_id: #{border_id})"
|
|
993
|
+
end
|
|
994
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
995
|
+
end
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
### Console Output
|
|
999
|
+
|
|
1000
|
+
```text
|
|
1001
|
+
=== Read Validation ===
|
|
1002
|
+
Row 0: A1: "Border Style" (border_id: 0), B1: "Cell Preview" (border_id: 0)
|
|
1003
|
+
Row 1: A2: "Thin" (border_id: 0), B2: "Thin Border" (border_id: 1)
|
|
1004
|
+
Row 2: A3: "Medium" (border_id: 0), B3: "Medium Border" (border_id: 2)
|
|
1005
|
+
Row 3: A4: "Thick" (border_id: 0), B4: "Thick Border" (border_id: 3)
|
|
1006
|
+
Row 4: A5: "Hair" (border_id: 0), B5: "Hair Border" (border_id: 4)
|
|
1007
|
+
Row 5: A6: "Dashed" (border_id: 0), B6: "Dashed Border" (border_id: 5)
|
|
1008
|
+
Row 6: A7: "Medium Dashed" (border_id: 0), B7: "Medium Dashed" (border_id: 6)
|
|
1009
|
+
Row 7: A8: "Dotted" (border_id: 0), B8: "Dotted Border" (border_id: 7)
|
|
1010
|
+
Row 8: A9: "Double" (border_id: 0), B9: "Double Border" (border_id: 8)
|
|
1011
|
+
Row 9: A10: "Dash-Dot" (border_id: 0), B10: "Dash-Dot Border" (border_id: 9)
|
|
1012
|
+
Row 10: A11: "Medium Dash-Dot" (border_id: 0), B11: "Medium Dash-Dot" (border_id: 10)
|
|
1013
|
+
Row 11: A12: "Dash-Dot-Dot" (border_id: 0), B12: "Dash-Dot-Dot" (border_id: 11)
|
|
1014
|
+
Row 12: A13: "Slanted Dash-Dot" (border_id: 0), B13: "Slanted Border" (border_id: 12)
|
|
1015
|
+
Row 13: A14: "Diagonal (Cross)" (border_id: 0), B14: "Diagonal Border" (border_id: 13)
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
<hr/>
|
|
1019
|
+
|
|
1020
|
+
## Cell Booleans
|
|
1021
|
+
|
|
1022
|
+
[Download .xlsx](files/cell_booleans.xlsx)
|
|
1023
|
+
|
|
1024
|
+
Demonstrates boolean values serialized and rendered.
|
|
1025
|
+
|
|
1026
|
+
### Rendered Output (LibreOffice Calc)
|
|
1027
|
+
|
|
1028
|
+
<div><img src="../../test/visual/baselines/cell_booleans/page-1.png" width="100%" alt="Preview"/></div>
|
|
1029
|
+
|
|
1030
|
+
### DSL Code
|
|
1031
|
+
|
|
1032
|
+
```ruby
|
|
1033
|
+
# frozen_string_literal: true
|
|
1034
|
+
require "xlsxrb"
|
|
1035
|
+
output_path = ARGV[0] || "cell_booleans.xlsx"
|
|
1036
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1037
|
+
w.add_sheet("Booleans") do |s|
|
|
1038
|
+
s.set_column(0, width: 25)
|
|
1039
|
+
s.set_column(1, width: 25)
|
|
1040
|
+
s.add_row(["Label", "Boolean Value"])
|
|
1041
|
+
s.add_row(["Is Active", true])
|
|
1042
|
+
s.add_row(["Is Pending", false])
|
|
1043
|
+
end
|
|
1044
|
+
end
|
|
1045
|
+
|
|
1046
|
+
# 2. Read the generated sheet and print parsed cell values and Ruby classes
|
|
1047
|
+
puts "=== Read Validation ==="
|
|
1048
|
+
workbook = Xlsxrb.read(output_path)
|
|
1049
|
+
sheet = workbook.sheets.first
|
|
1050
|
+
sheet.rows.each do |row|
|
|
1051
|
+
row_cells = row.cells.map do |c|
|
|
1052
|
+
"#{c.ref}: #{c.value.inspect} (#{c.value.class})"
|
|
1053
|
+
end
|
|
1054
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1055
|
+
end
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
### Console Output
|
|
1059
|
+
|
|
1060
|
+
```text
|
|
1061
|
+
=== Read Validation ===
|
|
1062
|
+
Row 0: A1: "Label" (String), B1: "Boolean Value" (String)
|
|
1063
|
+
Row 1: A2: "Is Active" (String), B2: true (TrueClass)
|
|
1064
|
+
Row 2: A3: "Is Pending" (String), B3: false (FalseClass)
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
<hr/>
|
|
1068
|
+
|
|
1069
|
+
## Cell Dates
|
|
1070
|
+
|
|
1071
|
+
[Download .xlsx](files/cell_dates.xlsx)
|
|
1072
|
+
|
|
1073
|
+
Demonstrates dates serialized natively and formatted with standard or custom format strings.
|
|
1074
|
+
|
|
1075
|
+
### Rendered Output (LibreOffice Calc)
|
|
1076
|
+
|
|
1077
|
+
<div><img src="../../test/visual/baselines/cell_dates/page-1.png" width="100%" alt="Preview"/></div>
|
|
1078
|
+
|
|
1079
|
+
### DSL Code
|
|
1080
|
+
|
|
1081
|
+
```ruby
|
|
1082
|
+
# frozen_string_literal: true
|
|
1083
|
+
require "xlsxrb"
|
|
1084
|
+
require "date"
|
|
1085
|
+
output_path = ARGV[0] || "cell_dates.xlsx"
|
|
1086
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1087
|
+
w.add_style("custom_date") { |s| s.num_fmt("yyyy-mm-dd") }
|
|
1088
|
+
w.add_sheet("Dates") do |s|
|
|
1089
|
+
s.set_column(0, width: 25)
|
|
1090
|
+
s.set_column(1, width: 25)
|
|
1091
|
+
s.add_row(["Format", "Date Value"])
|
|
1092
|
+
s.add_row(["Default Date", Date.new(2026, 7, 1)])
|
|
1093
|
+
s.add_row(["Formatted Date", Date.new(2026, 12, 25)], styles: { 1 => "custom_date" })
|
|
1094
|
+
end
|
|
1095
|
+
end
|
|
1096
|
+
|
|
1097
|
+
# 2. Read the generated sheet and print parsed cell values and Ruby classes
|
|
1098
|
+
puts "=== Read Validation ==="
|
|
1099
|
+
workbook = Xlsxrb.read(output_path)
|
|
1100
|
+
sheet = workbook.sheets.first
|
|
1101
|
+
sheet.rows.each do |row|
|
|
1102
|
+
row_cells = row.cells.map do |c|
|
|
1103
|
+
"#{c.ref}: #{c.value.inspect} (#{c.value.class})"
|
|
1104
|
+
end
|
|
1105
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1106
|
+
end
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
### Console Output
|
|
1110
|
+
|
|
1111
|
+
```text
|
|
1112
|
+
=== Read Validation ===
|
|
1113
|
+
Row 0: A1: "Format" (String), B1: "Date Value" (String)
|
|
1114
|
+
Row 1: A2: "Default Date" (String), B2: 46204 (Integer)
|
|
1115
|
+
Row 2: A3: "Formatted Date" (String), B3: 46381 (Integer)
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
<hr/>
|
|
1119
|
+
|
|
1120
|
+
## Cell Formulas
|
|
1121
|
+
|
|
1122
|
+
[Download .xlsx](files/cell_formulas.xlsx)
|
|
1123
|
+
|
|
1124
|
+
Demonstrates standard spreadsheet calculations and formulas (SUM, AVERAGE).
|
|
1125
|
+
|
|
1126
|
+
### Rendered Output (LibreOffice Calc)
|
|
1127
|
+
|
|
1128
|
+
<div><img src="../../test/visual/baselines/cell_formulas/page-1.png" width="100%" alt="Preview"/></div>
|
|
1129
|
+
|
|
1130
|
+
### DSL Code
|
|
1131
|
+
|
|
1132
|
+
```ruby
|
|
1133
|
+
# frozen_string_literal: true
|
|
1134
|
+
require "xlsxrb"
|
|
1135
|
+
output_path = ARGV[0] || "cell_formulas.xlsx"
|
|
1136
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1137
|
+
w.add_sheet("Formulas") do |s|
|
|
1138
|
+
s.set_column(0, width: 25)
|
|
1139
|
+
s.set_column(1, width: 25)
|
|
1140
|
+
s.add_row(["Item", "Value"])
|
|
1141
|
+
s.add_row(["A", 10])
|
|
1142
|
+
s.add_row(["B", 20])
|
|
1143
|
+
s.add_row(["SUM", Xlsxrb::Elements::Formula.new(expression: "SUM(B2:B3)", cached_value: 30)])
|
|
1144
|
+
s.add_row(["AVERAGE", Xlsxrb::Elements::Formula.new(expression: "AVERAGE(B2:B3)", cached_value: 15)])
|
|
1145
|
+
end
|
|
1146
|
+
end
|
|
1147
|
+
|
|
1148
|
+
# 2. Read the generated sheet and print parsed cell values and Ruby classes
|
|
1149
|
+
puts "=== Read Validation ==="
|
|
1150
|
+
workbook = Xlsxrb.read(output_path)
|
|
1151
|
+
sheet = workbook.sheets.first
|
|
1152
|
+
sheet.rows.each do |row|
|
|
1153
|
+
row_cells = row.cells.map do |c|
|
|
1154
|
+
"#{c.ref}: #{c.value.inspect} (#{c.value.class})"
|
|
1155
|
+
end
|
|
1156
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1157
|
+
end
|
|
1158
|
+
```
|
|
1159
|
+
|
|
1160
|
+
### Console Output
|
|
1161
|
+
|
|
1162
|
+
```text
|
|
1163
|
+
=== Read Validation ===
|
|
1164
|
+
Row 0: A1: "Item" (String), B1: "Value" (String)
|
|
1165
|
+
Row 1: A2: "A" (String), B2: 10 (Integer)
|
|
1166
|
+
Row 2: A3: "B" (String), B3: 20 (Integer)
|
|
1167
|
+
Row 3: A4: "SUM" (String), B4: 30 (Integer)
|
|
1168
|
+
Row 4: A5: "AVERAGE" (String), B5: 15 (Integer)
|
|
1169
|
+
```
|
|
1170
|
+
|
|
1171
|
+
<hr/>
|
|
1172
|
+
|
|
1173
|
+
## Cell Num Currency Jpy
|
|
1174
|
+
|
|
1175
|
+
[Download .xlsx](files/cell_num_currency_jpy.xlsx)
|
|
1176
|
+
|
|
1177
|
+
Demonstrates Yen Currency format code formatting.
|
|
1178
|
+
|
|
1179
|
+
### Rendered Output (LibreOffice Calc)
|
|
1180
|
+
|
|
1181
|
+
<div><img src="../../test/visual/baselines/cell_num_currency_jpy/page-1.png" width="100%" alt="Preview"/></div>
|
|
1182
|
+
|
|
1183
|
+
### DSL Code
|
|
1184
|
+
|
|
1185
|
+
```ruby
|
|
1186
|
+
# frozen_string_literal: true
|
|
1187
|
+
require "xlsxrb"
|
|
1188
|
+
output_path = ARGV[0] || "cell_num_currency_jpy.xlsx"
|
|
1189
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1190
|
+
w.add_style("jpy") { |s| s.num_fmt("¥#,##0;[Red]¥-#,##0") }
|
|
1191
|
+
w.add_sheet("JPY Currency") do |s|
|
|
1192
|
+
s.set_column(0, width: 25)
|
|
1193
|
+
s.set_column(1, width: 25)
|
|
1194
|
+
s.add_row(["Format", "Value"])
|
|
1195
|
+
s.add_row(["Positive Yen", 12500], styles: { 1 => "jpy" })
|
|
1196
|
+
s.add_row(["Negative Yen", -8000], styles: { 1 => "jpy" })
|
|
1197
|
+
end
|
|
1198
|
+
end
|
|
1199
|
+
|
|
1200
|
+
# 2. Read the generated sheet and print parsed cell numbers and format codes
|
|
1201
|
+
puts "=== Read Validation ==="
|
|
1202
|
+
workbook = Xlsxrb.read(output_path)
|
|
1203
|
+
sheet = workbook.sheets.first
|
|
1204
|
+
sheet.rows.each do |row|
|
|
1205
|
+
row_cells = row.cells.map do |c|
|
|
1206
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
1207
|
+
num_fmt = xf ? workbook.styles[:num_fmts][xf[:num_fmt_id]] : nil
|
|
1208
|
+
"#{c.ref}: #{c.value.inspect} (Format ID: #{xf&.[](:num_fmt_id)}, Code: #{num_fmt.inspect})"
|
|
1209
|
+
end
|
|
1210
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1211
|
+
end
|
|
1212
|
+
```
|
|
1213
|
+
|
|
1214
|
+
### Console Output
|
|
1215
|
+
|
|
1216
|
+
```text
|
|
1217
|
+
=== Read Validation ===
|
|
1218
|
+
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
|
|
1219
|
+
Row 1: A2: "Positive Yen" (Format ID: , Code: nil), B2: 12500 (Format ID: 164, Code: "¥#,##0;[Red]¥-#,##0")
|
|
1220
|
+
Row 2: A3: "Negative Yen" (Format ID: , Code: nil), B3: -8000 (Format ID: 164, Code: "¥#,##0;[Red]¥-#,##0")
|
|
1221
|
+
```
|
|
1222
|
+
|
|
1223
|
+
<hr/>
|
|
1224
|
+
|
|
1225
|
+
## Cell Num Custom Colors
|
|
1226
|
+
|
|
1227
|
+
[Download .xlsx](files/cell_num_custom_colors.xlsx)
|
|
1228
|
+
|
|
1229
|
+
Demonstrates custom colored formats for positive and negative numbers.
|
|
1230
|
+
|
|
1231
|
+
### Rendered Output (LibreOffice Calc)
|
|
1232
|
+
|
|
1233
|
+
<div><img src="../../test/visual/baselines/cell_num_custom_colors/page-1.png" width="100%" alt="Preview"/></div>
|
|
1234
|
+
|
|
1235
|
+
### DSL Code
|
|
1236
|
+
|
|
1237
|
+
```ruby
|
|
1238
|
+
# frozen_string_literal: true
|
|
1239
|
+
require "xlsxrb"
|
|
1240
|
+
output_path = ARGV[0] || "cell_num_custom_colors.xlsx"
|
|
1241
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1242
|
+
w.add_style("custom_color") { |s| s.num_fmt("[Green]#,##0;[Red]-#,##0") }
|
|
1243
|
+
w.add_sheet("Custom Colors") do |s|
|
|
1244
|
+
s.set_column(0, width: 25)
|
|
1245
|
+
s.set_column(1, width: 25)
|
|
1246
|
+
s.add_row(["Format", "Value"])
|
|
1247
|
+
s.add_row(["Positive (Green)", 5000], styles: { 1 => "custom_color" })
|
|
1248
|
+
s.add_row(["Negative (Red)", -2500], styles: { 1 => "custom_color" })
|
|
1249
|
+
end
|
|
1250
|
+
end
|
|
1251
|
+
|
|
1252
|
+
# 2. Read the generated sheet and print parsed cell numbers and format codes
|
|
1253
|
+
puts "=== Read Validation ==="
|
|
1254
|
+
workbook = Xlsxrb.read(output_path)
|
|
1255
|
+
sheet = workbook.sheets.first
|
|
1256
|
+
sheet.rows.each do |row|
|
|
1257
|
+
row_cells = row.cells.map do |c|
|
|
1258
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
1259
|
+
num_fmt = xf ? workbook.styles[:num_fmts][xf[:num_fmt_id]] : nil
|
|
1260
|
+
"#{c.ref}: #{c.value.inspect} (Format ID: #{xf&.[](:num_fmt_id)}, Code: #{num_fmt.inspect})"
|
|
1261
|
+
end
|
|
1262
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1263
|
+
end
|
|
1264
|
+
```
|
|
1265
|
+
|
|
1266
|
+
### Console Output
|
|
1267
|
+
|
|
1268
|
+
```text
|
|
1269
|
+
=== Read Validation ===
|
|
1270
|
+
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
|
|
1271
|
+
Row 1: A2: "Positive (Green)" (Format ID: , Code: nil), B2: 5000 (Format ID: 164, Code: "[Green]#,##0;[Red]-#,##0")
|
|
1272
|
+
Row 2: A3: "Negative (Red)" (Format ID: , Code: nil), B3: -2500 (Format ID: 164, Code: "[Green]#,##0;[Red]-#,##0")
|
|
1273
|
+
```
|
|
1274
|
+
|
|
1275
|
+
<hr/>
|
|
1276
|
+
|
|
1277
|
+
## Cell Num Fractions
|
|
1278
|
+
|
|
1279
|
+
[Download .xlsx](files/cell_num_fractions.xlsx)
|
|
1280
|
+
|
|
1281
|
+
Demonstrates fraction number formats (# ?/?).
|
|
1282
|
+
|
|
1283
|
+
### Rendered Output (LibreOffice Calc)
|
|
1284
|
+
|
|
1285
|
+
<div><img src="../../test/visual/baselines/cell_num_fractions/page-1.png" width="100%" alt="Preview"/></div>
|
|
1286
|
+
|
|
1287
|
+
### DSL Code
|
|
1288
|
+
|
|
1289
|
+
```ruby
|
|
1290
|
+
# frozen_string_literal: true
|
|
1291
|
+
require "xlsxrb"
|
|
1292
|
+
output_path = ARGV[0] || "cell_num_fractions.xlsx"
|
|
1293
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1294
|
+
w.add_style("frac") { |s| s.num_fmt("# ?/?") }
|
|
1295
|
+
w.add_sheet("Fractions") do |s|
|
|
1296
|
+
s.set_column(0, width: 25)
|
|
1297
|
+
s.set_column(1, width: 25)
|
|
1298
|
+
s.add_row(["Format", "Value"])
|
|
1299
|
+
s.add_row(["Half", 0.5], styles: { 1 => "frac" })
|
|
1300
|
+
s.add_row(["Third", 0.3333], styles: { 1 => "frac" })
|
|
1301
|
+
s.add_row(["Quarter", 0.75], styles: { 1 => "frac" })
|
|
1302
|
+
end
|
|
1303
|
+
end
|
|
1304
|
+
|
|
1305
|
+
# 2. Read the generated sheet and print parsed cell numbers and format codes
|
|
1306
|
+
puts "=== Read Validation ==="
|
|
1307
|
+
workbook = Xlsxrb.read(output_path)
|
|
1308
|
+
sheet = workbook.sheets.first
|
|
1309
|
+
sheet.rows.each do |row|
|
|
1310
|
+
row_cells = row.cells.map do |c|
|
|
1311
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
1312
|
+
num_fmt = xf ? workbook.styles[:num_fmts][xf[:num_fmt_id]] : nil
|
|
1313
|
+
"#{c.ref}: #{c.value.inspect} (Format ID: #{xf&.[](:num_fmt_id)}, Code: #{num_fmt.inspect})"
|
|
1314
|
+
end
|
|
1315
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1316
|
+
end
|
|
1317
|
+
```
|
|
1318
|
+
|
|
1319
|
+
### Console Output
|
|
1320
|
+
|
|
1321
|
+
```text
|
|
1322
|
+
=== Read Validation ===
|
|
1323
|
+
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
|
|
1324
|
+
Row 1: A2: "Half" (Format ID: , Code: nil), B2: 0.5 (Format ID: 164, Code: "# ?/?")
|
|
1325
|
+
Row 2: A3: "Third" (Format ID: , Code: nil), B3: 0.3333 (Format ID: 164, Code: "# ?/?")
|
|
1326
|
+
Row 3: A4: "Quarter" (Format ID: , Code: nil), B4: 0.75 (Format ID: 164, Code: "# ?/?")
|
|
1327
|
+
```
|
|
1328
|
+
|
|
1329
|
+
<hr/>
|
|
1330
|
+
|
|
1331
|
+
## Cell Num Percent Decimals
|
|
1332
|
+
|
|
1333
|
+
[Download .xlsx](files/cell_num_percent_decimals.xlsx)
|
|
1334
|
+
|
|
1335
|
+
Demonstrates percentages with two decimal places (0.00%).
|
|
1336
|
+
|
|
1337
|
+
### Rendered Output (LibreOffice Calc)
|
|
1338
|
+
|
|
1339
|
+
<div><img src="../../test/visual/baselines/cell_num_percent_decimals/page-1.png" width="100%" alt="Preview"/></div>
|
|
1340
|
+
|
|
1341
|
+
### DSL Code
|
|
1342
|
+
|
|
1343
|
+
```ruby
|
|
1344
|
+
# frozen_string_literal: true
|
|
1345
|
+
require "xlsxrb"
|
|
1346
|
+
output_path = ARGV[0] || "cell_num_percent_decimals.xlsx"
|
|
1347
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1348
|
+
w.add_style("pct2") { |s| s.num_fmt("0.00%") }
|
|
1349
|
+
w.add_sheet("Percents") do |s|
|
|
1350
|
+
s.set_column(0, width: 25)
|
|
1351
|
+
s.set_column(1, width: 25)
|
|
1352
|
+
s.add_row(["Format", "Value"])
|
|
1353
|
+
s.add_row(["Percent with 2 Decimals", 0.12345], styles: { 1 => "pct2" })
|
|
1354
|
+
end
|
|
1355
|
+
end
|
|
1356
|
+
|
|
1357
|
+
# 2. Read the generated sheet and print parsed cell numbers and format codes
|
|
1358
|
+
puts "=== Read Validation ==="
|
|
1359
|
+
workbook = Xlsxrb.read(output_path)
|
|
1360
|
+
sheet = workbook.sheets.first
|
|
1361
|
+
sheet.rows.each do |row|
|
|
1362
|
+
row_cells = row.cells.map do |c|
|
|
1363
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
1364
|
+
num_fmt = xf ? workbook.styles[:num_fmts][xf[:num_fmt_id]] : nil
|
|
1365
|
+
"#{c.ref}: #{c.value.inspect} (Format ID: #{xf&.[](:num_fmt_id)}, Code: #{num_fmt.inspect})"
|
|
1366
|
+
end
|
|
1367
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1368
|
+
end
|
|
1369
|
+
```
|
|
1370
|
+
|
|
1371
|
+
### Console Output
|
|
1372
|
+
|
|
1373
|
+
```text
|
|
1374
|
+
=== Read Validation ===
|
|
1375
|
+
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
|
|
1376
|
+
Row 1: A2: "Percent with 2 Decimals" (Format ID: , Code: nil), B2: 0.12345 (Format ID: 164, Code: "0.00%")
|
|
1377
|
+
```
|
|
1378
|
+
|
|
1379
|
+
<hr/>
|
|
1380
|
+
|
|
1381
|
+
## Cell Num Scientific
|
|
1382
|
+
|
|
1383
|
+
[Download .xlsx](files/cell_num_scientific.xlsx)
|
|
1384
|
+
|
|
1385
|
+
Demonstrates scientific number formats (0.00E+00).
|
|
1386
|
+
|
|
1387
|
+
### Rendered Output (LibreOffice Calc)
|
|
1388
|
+
|
|
1389
|
+
<div><img src="../../test/visual/baselines/cell_num_scientific/page-1.png" width="100%" alt="Preview"/></div>
|
|
1390
|
+
|
|
1391
|
+
### DSL Code
|
|
1392
|
+
|
|
1393
|
+
```ruby
|
|
1394
|
+
# frozen_string_literal: true
|
|
1395
|
+
require "xlsxrb"
|
|
1396
|
+
output_path = ARGV[0] || "cell_num_scientific.xlsx"
|
|
1397
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1398
|
+
w.add_style("sci") { |s| s.num_fmt("0.00E+00") }
|
|
1399
|
+
w.add_sheet("Scientific") do |s|
|
|
1400
|
+
s.set_column(0, width: 25)
|
|
1401
|
+
s.set_column(1, width: 25)
|
|
1402
|
+
s.add_row(["Format", "Value"])
|
|
1403
|
+
s.add_row(["Scientific", 123456789.0], styles: { 1 => "sci" })
|
|
1404
|
+
s.add_row(["Small Scientific", 0.00001234], styles: { 1 => "sci" })
|
|
1405
|
+
end
|
|
1406
|
+
end
|
|
1407
|
+
|
|
1408
|
+
# 2. Read the generated sheet and print parsed cell numbers and format codes
|
|
1409
|
+
puts "=== Read Validation ==="
|
|
1410
|
+
workbook = Xlsxrb.read(output_path)
|
|
1411
|
+
sheet = workbook.sheets.first
|
|
1412
|
+
sheet.rows.each do |row|
|
|
1413
|
+
row_cells = row.cells.map do |c|
|
|
1414
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
1415
|
+
num_fmt = xf ? workbook.styles[:num_fmts][xf[:num_fmt_id]] : nil
|
|
1416
|
+
"#{c.ref}: #{c.value.inspect} (Format ID: #{xf&.[](:num_fmt_id)}, Code: #{num_fmt.inspect})"
|
|
1417
|
+
end
|
|
1418
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1419
|
+
end
|
|
1420
|
+
```
|
|
1421
|
+
|
|
1422
|
+
### Console Output
|
|
1423
|
+
|
|
1424
|
+
```text
|
|
1425
|
+
=== Read Validation ===
|
|
1426
|
+
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
|
|
1427
|
+
Row 1: A2: "Scientific" (Format ID: , Code: nil), B2: 123456789.0 (Format ID: 164, Code: "0.00E+00")
|
|
1428
|
+
Row 2: A3: "Small Scientific" (Format ID: , Code: nil), B3: 1.234e-05 (Format ID: 164, Code: "0.00E+00")
|
|
1429
|
+
```
|
|
1430
|
+
|
|
1431
|
+
<hr/>
|
|
1432
|
+
|
|
1433
|
+
## Cell Numbers
|
|
1434
|
+
|
|
1435
|
+
[Download .xlsx](files/cell_numbers.xlsx)
|
|
1436
|
+
|
|
1437
|
+
Demonstrates custom formatting for integers, floating point numbers, currencies, and percentages.
|
|
1438
|
+
|
|
1439
|
+
### Rendered Output (LibreOffice Calc)
|
|
1440
|
+
|
|
1441
|
+
<div><img src="../../test/visual/baselines/cell_numbers/page-1.png" width="100%" alt="Preview"/></div>
|
|
1442
|
+
|
|
1443
|
+
### DSL Code
|
|
1444
|
+
|
|
1445
|
+
```ruby
|
|
1446
|
+
# frozen_string_literal: true
|
|
1447
|
+
require "xlsxrb"
|
|
1448
|
+
output_path = ARGV[0] || "cell_numbers.xlsx"
|
|
1449
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1450
|
+
w.add_style("currency") { |s| s.num_fmt("$#,##0.00") }
|
|
1451
|
+
w.add_style("percent") { |s| s.num_fmt("0.0%") }
|
|
1452
|
+
w.add_sheet("Numbers") do |s|
|
|
1453
|
+
s.set_column(0, width: 25)
|
|
1454
|
+
s.set_column(1, width: 25)
|
|
1455
|
+
s.add_row(["Format", "Value"])
|
|
1456
|
+
s.add_row(["Integer", 12345])
|
|
1457
|
+
s.add_row(["Float", 123.456])
|
|
1458
|
+
s.add_row(["Currency", 1234.5], styles: { 1 => "currency" })
|
|
1459
|
+
s.add_row(["Percentage", 0.85], styles: { 1 => "percent" })
|
|
1460
|
+
end
|
|
1461
|
+
end
|
|
1462
|
+
|
|
1463
|
+
# 2. Read the generated sheet and print parsed cell values and Ruby classes
|
|
1464
|
+
puts "=== Read Validation ==="
|
|
1465
|
+
workbook = Xlsxrb.read(output_path)
|
|
1466
|
+
sheet = workbook.sheets.first
|
|
1467
|
+
sheet.rows.each do |row|
|
|
1468
|
+
row_cells = row.cells.map do |c|
|
|
1469
|
+
"#{c.ref}: #{c.value.inspect} (#{c.value.class})"
|
|
1470
|
+
end
|
|
1471
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1472
|
+
end
|
|
1473
|
+
```
|
|
1474
|
+
|
|
1475
|
+
### Console Output
|
|
1476
|
+
|
|
1477
|
+
```text
|
|
1478
|
+
=== Read Validation ===
|
|
1479
|
+
Row 0: A1: "Format" (String), B1: "Value" (String)
|
|
1480
|
+
Row 1: A2: "Integer" (String), B2: 12345 (Integer)
|
|
1481
|
+
Row 2: A3: "Float" (String), B3: 123.456 (Float)
|
|
1482
|
+
Row 3: A4: "Currency" (String), B4: 1234.5 (Float)
|
|
1483
|
+
Row 4: A5: "Percentage" (String), B5: 0.85 (Float)
|
|
1484
|
+
```
|
|
1485
|
+
|
|
1486
|
+
<hr/>
|
|
1487
|
+
|
|
1488
|
+
## Cell Rich Text
|
|
1489
|
+
|
|
1490
|
+
[Download .xlsx](files/cell_rich_text.xlsx)
|
|
1491
|
+
|
|
1492
|
+
Demonstrates Rich Text cells with multiple font weights, styles, and colors in a single cell.
|
|
1493
|
+
|
|
1494
|
+
### Rendered Output (LibreOffice Calc)
|
|
1495
|
+
|
|
1496
|
+
<div><img src="../../test/visual/baselines/cell_rich_text/page-1.png" width="100%" alt="Preview"/></div>
|
|
1497
|
+
|
|
1498
|
+
### DSL Code
|
|
1499
|
+
|
|
1500
|
+
```ruby
|
|
1501
|
+
# frozen_string_literal: true
|
|
1502
|
+
require "xlsxrb"
|
|
1503
|
+
output_path = ARGV[0] || "cell_rich_text.xlsx"
|
|
1504
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1505
|
+
rt = Xlsxrb::Elements::RichText.new(runs: [
|
|
1506
|
+
{ text: "Normal " },
|
|
1507
|
+
{ text: "BOLD RED ", font: { bold: true, color: "FFC00000", sz: 16 } },
|
|
1508
|
+
{ text: "ITALIC BLUE", font: { italic: true, color: "FF0000FF", sz: 20 } }
|
|
1509
|
+
])
|
|
1510
|
+
w.add_sheet("Rich Text") do |s|
|
|
1511
|
+
s.set_column(0, width: 25)
|
|
1512
|
+
s.set_column(1, width: 25)
|
|
1513
|
+
s.add_row(["Format", "Value"])
|
|
1514
|
+
s.add_row(["Rich Text Cell", rt])
|
|
1515
|
+
end
|
|
1516
|
+
end
|
|
1517
|
+
|
|
1518
|
+
# 2. Read the generated sheet and print parsed cell values and Ruby classes
|
|
1519
|
+
puts "=== Read Validation ==="
|
|
1520
|
+
workbook = Xlsxrb.read(output_path)
|
|
1521
|
+
sheet = workbook.sheets.first
|
|
1522
|
+
sheet.rows.each do |row|
|
|
1523
|
+
row_cells = row.cells.map do |c|
|
|
1524
|
+
"#{c.ref}: #{c.value.inspect} (#{c.value.class})"
|
|
1525
|
+
end
|
|
1526
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1527
|
+
end
|
|
1528
|
+
```
|
|
1529
|
+
|
|
1530
|
+
### Console Output
|
|
1531
|
+
|
|
1532
|
+
```text
|
|
1533
|
+
=== Read Validation ===
|
|
1534
|
+
Row 0: A1: "Format" (String), B1: "Value" (String)
|
|
1535
|
+
Row 1: A2: "Rich Text Cell" (String), B2: "Normal BOLD RED ITALIC BLUE" (String)
|
|
1536
|
+
```
|
|
1537
|
+
|
|
1538
|
+
<hr/>
|
|
1539
|
+
|
|
1540
|
+
## Cell Times
|
|
1541
|
+
|
|
1542
|
+
[Download .xlsx](files/cell_times.xlsx)
|
|
1543
|
+
|
|
1544
|
+
Demonstrates timestamp values serialized natively and formatted showing hours, minutes, and seconds.
|
|
1545
|
+
|
|
1546
|
+
### Rendered Output (LibreOffice Calc)
|
|
1547
|
+
|
|
1548
|
+
<div><img src="../../test/visual/baselines/cell_times/page-1.png" width="100%" alt="Preview"/></div>
|
|
1549
|
+
|
|
1550
|
+
### DSL Code
|
|
1551
|
+
|
|
1552
|
+
```ruby
|
|
1553
|
+
# frozen_string_literal: true
|
|
1554
|
+
require "xlsxrb"
|
|
1555
|
+
require "time"
|
|
1556
|
+
output_path = ARGV[0] || "cell_times.xlsx"
|
|
1557
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1558
|
+
w.add_style("time_fmt") { |s| s.num_fmt("hh:mm:ss") }
|
|
1559
|
+
w.add_sheet("Times") do |s|
|
|
1560
|
+
s.set_column(0, width: 25)
|
|
1561
|
+
s.set_column(1, width: 25)
|
|
1562
|
+
s.add_row(["Format", "Time Value"])
|
|
1563
|
+
s.add_row(["DateTime", Time.new(2026, 7, 1, 12, 34, 56)])
|
|
1564
|
+
s.add_row(["Time Only", Time.new(2026, 7, 1, 9, 15, 0)], styles: { 1 => "time_fmt" })
|
|
1565
|
+
end
|
|
1566
|
+
end
|
|
1567
|
+
|
|
1568
|
+
# 2. Read the generated sheet and print parsed cell values and Ruby classes
|
|
1569
|
+
puts "=== Read Validation ==="
|
|
1570
|
+
workbook = Xlsxrb.read(output_path)
|
|
1571
|
+
sheet = workbook.sheets.first
|
|
1572
|
+
sheet.rows.each do |row|
|
|
1573
|
+
row_cells = row.cells.map do |c|
|
|
1574
|
+
"#{c.ref}: #{c.value.inspect} (#{c.value.class})"
|
|
1575
|
+
end
|
|
1576
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1577
|
+
end
|
|
1578
|
+
```
|
|
1579
|
+
|
|
1580
|
+
### Console Output
|
|
1581
|
+
|
|
1582
|
+
```text
|
|
1583
|
+
=== Read Validation ===
|
|
1584
|
+
Row 0: A1: "Format" (String), B1: "Time Value" (String)
|
|
1585
|
+
Row 1: A2: "DateTime" (String), B2: 46204.52425925926 (Float)
|
|
1586
|
+
Row 2: A3: "Time Only" (String), B3: 46204.385416666664 (Float)
|
|
1587
|
+
```
|
|
1588
|
+
|
|
1589
|
+
<hr/>
|
|
1590
|
+
|
|
1591
|
+
## Cf Begins With
|
|
1592
|
+
|
|
1593
|
+
[Download .xlsx](files/cf_begins_with.xlsx)
|
|
1594
|
+
|
|
1595
|
+
Demonstrates conditional formatting highlighting cells starting with specific text.
|
|
1596
|
+
|
|
1597
|
+
### Rendered Output (LibreOffice Calc)
|
|
1598
|
+
|
|
1599
|
+
<div><img src="../../test/visual/baselines/cf_begins_with/page-1.png" width="100%" alt="Preview"/></div>
|
|
1600
|
+
|
|
1601
|
+
### DSL Code
|
|
1602
|
+
|
|
1603
|
+
```ruby
|
|
1604
|
+
# frozen_string_literal: true
|
|
1605
|
+
require "xlsxrb"
|
|
1606
|
+
output_path = ARGV[0] || "cf_begins_with.xlsx"
|
|
1607
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1608
|
+
w.add_sheet("CF Begins") do |s|
|
|
1609
|
+
s.set_column(0, width: 25)
|
|
1610
|
+
s.set_column(1, width: 25)
|
|
1611
|
+
s.add_row(["Code"])
|
|
1612
|
+
s.add_row(["A-100"])
|
|
1613
|
+
s.add_row(["B-200"])
|
|
1614
|
+
s.add_row(["A-300"])
|
|
1615
|
+
s.add_conditional_format("A2:A4", type: "beginsWith", operator: "beginsWith", text: "A", formula: 'LEFT(A2,1)="A"', fill_color: "FFFFC7CE")
|
|
1616
|
+
end
|
|
1617
|
+
end
|
|
1618
|
+
|
|
1619
|
+
# 2. Read the generated sheet and print cell values
|
|
1620
|
+
puts "=== Read Validation ==="
|
|
1621
|
+
workbook = Xlsxrb.read(output_path)
|
|
1622
|
+
sheet = workbook.sheets.first
|
|
1623
|
+
sheet.rows.first(5).each do |row|
|
|
1624
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
1625
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1626
|
+
end
|
|
1627
|
+
```
|
|
1628
|
+
|
|
1629
|
+
### Console Output
|
|
1630
|
+
|
|
1631
|
+
```text
|
|
1632
|
+
=== Read Validation ===
|
|
1633
|
+
Row 0: A1: "Code"
|
|
1634
|
+
Row 1: A2: "A-100"
|
|
1635
|
+
Row 2: A3: "B-200"
|
|
1636
|
+
Row 3: A4: "A-300"
|
|
1637
|
+
```
|
|
1638
|
+
|
|
1639
|
+
<hr/>
|
|
1640
|
+
|
|
1641
|
+
## Cf Cell Between
|
|
1642
|
+
|
|
1643
|
+
[Download .xlsx](files/cf_cell_between.xlsx)
|
|
1644
|
+
|
|
1645
|
+
Demonstrates conditional formatting highlighting cells within a range.
|
|
1646
|
+
|
|
1647
|
+
### Rendered Output (LibreOffice Calc)
|
|
1648
|
+
|
|
1649
|
+
<div><img src="../../test/visual/baselines/cf_cell_between/page-1.png" width="100%" alt="Preview"/></div>
|
|
1650
|
+
|
|
1651
|
+
### DSL Code
|
|
1652
|
+
|
|
1653
|
+
```ruby
|
|
1654
|
+
# frozen_string_literal: true
|
|
1655
|
+
require "xlsxrb"
|
|
1656
|
+
output_path = ARGV[0] || "cf_cell_between.xlsx"
|
|
1657
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1658
|
+
w.add_style("center") { |style| style.align_horizontal("center") }
|
|
1659
|
+
w.add_sheet("CF Between") do |s|
|
|
1660
|
+
s.set_column(0, width: 25)
|
|
1661
|
+
s.set_column(1, width: 25)
|
|
1662
|
+
s.add_row(["Values"])
|
|
1663
|
+
s.add_row([15], styles: ["center"])
|
|
1664
|
+
s.add_row([25], styles: ["center"])
|
|
1665
|
+
s.add_row([5], styles: ["center"])
|
|
1666
|
+
s.add_conditional_format("A2:A4", type: "cellIs", operator: "between", formulas: ["10", "20"], fill_color: "FF00FF00")
|
|
1667
|
+
end
|
|
1668
|
+
end
|
|
1669
|
+
|
|
1670
|
+
# 2. Read the generated sheet and print cell values
|
|
1671
|
+
puts "=== Read Validation ==="
|
|
1672
|
+
workbook = Xlsxrb.read(output_path)
|
|
1673
|
+
sheet = workbook.sheets.first
|
|
1674
|
+
sheet.rows.first(5).each do |row|
|
|
1675
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
1676
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1677
|
+
end
|
|
1678
|
+
```
|
|
1679
|
+
|
|
1680
|
+
### Console Output
|
|
1681
|
+
|
|
1682
|
+
```text
|
|
1683
|
+
=== Read Validation ===
|
|
1684
|
+
Row 0: A1: "Values"
|
|
1685
|
+
Row 1: A2: 15
|
|
1686
|
+
Row 2: A3: 25
|
|
1687
|
+
Row 3: A4: 5
|
|
1688
|
+
```
|
|
1689
|
+
|
|
1690
|
+
<hr/>
|
|
1691
|
+
|
|
1692
|
+
## Cf Cell Equal To
|
|
1693
|
+
|
|
1694
|
+
[Download .xlsx](files/cf_cell_equal_to.xlsx)
|
|
1695
|
+
|
|
1696
|
+
Demonstrates conditional formatting highlighting cells equal to a target value.
|
|
1697
|
+
|
|
1698
|
+
### Rendered Output (LibreOffice Calc)
|
|
1699
|
+
|
|
1700
|
+
<div><img src="../../test/visual/baselines/cf_cell_equal_to/page-1.png" width="100%" alt="Preview"/></div>
|
|
1701
|
+
|
|
1702
|
+
### DSL Code
|
|
1703
|
+
|
|
1704
|
+
```ruby
|
|
1705
|
+
# frozen_string_literal: true
|
|
1706
|
+
require "xlsxrb"
|
|
1707
|
+
output_path = ARGV[0] || "cf_cell_equal_to.xlsx"
|
|
1708
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1709
|
+
w.add_style("center") { |style| style.align_horizontal("center") }
|
|
1710
|
+
w.add_sheet("CF Equal") do |s|
|
|
1711
|
+
s.set_column(0, width: 25)
|
|
1712
|
+
s.set_column(1, width: 25)
|
|
1713
|
+
s.add_row(["Values"])
|
|
1714
|
+
s.add_row([10], styles: ["center"])
|
|
1715
|
+
s.add_row([20], styles: ["center"])
|
|
1716
|
+
s.add_row([10], styles: ["center"])
|
|
1717
|
+
s.add_conditional_format("A2:A4", type: "cellIs", operator: "equal", formula: "10", fill_color: "FFFFC7CE")
|
|
1718
|
+
end
|
|
1719
|
+
end
|
|
1720
|
+
|
|
1721
|
+
# 2. Read the generated sheet and print cell values
|
|
1722
|
+
puts "=== Read Validation ==="
|
|
1723
|
+
workbook = Xlsxrb.read(output_path)
|
|
1724
|
+
sheet = workbook.sheets.first
|
|
1725
|
+
sheet.rows.first(5).each do |row|
|
|
1726
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
1727
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1728
|
+
end
|
|
1729
|
+
```
|
|
1730
|
+
|
|
1731
|
+
### Console Output
|
|
1732
|
+
|
|
1733
|
+
```text
|
|
1734
|
+
=== Read Validation ===
|
|
1735
|
+
Row 0: A1: "Values"
|
|
1736
|
+
Row 1: A2: 10
|
|
1737
|
+
Row 2: A3: 20
|
|
1738
|
+
Row 3: A4: 10
|
|
1739
|
+
```
|
|
1740
|
+
|
|
1741
|
+
<hr/>
|
|
1742
|
+
|
|
1743
|
+
## Cf Cell Greater Equal
|
|
1744
|
+
|
|
1745
|
+
[Download .xlsx](files/cf_cell_greater_equal.xlsx)
|
|
1746
|
+
|
|
1747
|
+
Demonstrates conditional formatting highlighting cells greater than or equal to a threshold.
|
|
1748
|
+
|
|
1749
|
+
### Rendered Output (LibreOffice Calc)
|
|
1750
|
+
|
|
1751
|
+
<div><img src="../../test/visual/baselines/cf_cell_greater_equal/page-1.png" width="100%" alt="Preview"/></div>
|
|
1752
|
+
|
|
1753
|
+
### DSL Code
|
|
1754
|
+
|
|
1755
|
+
```ruby
|
|
1756
|
+
# frozen_string_literal: true
|
|
1757
|
+
require "xlsxrb"
|
|
1758
|
+
output_path = ARGV[0] || "cf_cell_greater_equal.xlsx"
|
|
1759
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1760
|
+
w.add_style("center") { |style| style.align_horizontal("center") }
|
|
1761
|
+
w.add_sheet("CF Greater Equal") do |s|
|
|
1762
|
+
s.set_column(0, width: 25)
|
|
1763
|
+
s.set_column(1, width: 25)
|
|
1764
|
+
s.add_row(["Values"])
|
|
1765
|
+
s.add_row([10], styles: ["center"])
|
|
1766
|
+
s.add_row([50], styles: ["center"])
|
|
1767
|
+
s.add_row([100], styles: ["center"])
|
|
1768
|
+
s.add_conditional_format("A2:A4", type: "cellIs", operator: "greaterThanOrEqual", formula: "50", fill_color: "FFFFC7CE")
|
|
1769
|
+
end
|
|
1770
|
+
end
|
|
1771
|
+
|
|
1772
|
+
# 2. Read the generated sheet and print cell values
|
|
1773
|
+
puts "=== Read Validation ==="
|
|
1774
|
+
workbook = Xlsxrb.read(output_path)
|
|
1775
|
+
sheet = workbook.sheets.first
|
|
1776
|
+
sheet.rows.first(5).each do |row|
|
|
1777
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
1778
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1779
|
+
end
|
|
1780
|
+
```
|
|
1781
|
+
|
|
1782
|
+
### Console Output
|
|
1783
|
+
|
|
1784
|
+
```text
|
|
1785
|
+
=== Read Validation ===
|
|
1786
|
+
Row 0: A1: "Values"
|
|
1787
|
+
Row 1: A2: 10
|
|
1788
|
+
Row 2: A3: 50
|
|
1789
|
+
Row 3: A4: 100
|
|
1790
|
+
```
|
|
1791
|
+
|
|
1792
|
+
<hr/>
|
|
1793
|
+
|
|
1794
|
+
## Cf Cell Greater Than
|
|
1795
|
+
|
|
1796
|
+
[Download .xlsx](files/cf_cell_greater_than.xlsx)
|
|
1797
|
+
|
|
1798
|
+
Demonstrates conditional formatting highlighting cells greater than a threshold.
|
|
1799
|
+
|
|
1800
|
+
### Rendered Output (LibreOffice Calc)
|
|
1801
|
+
|
|
1802
|
+
<div><img src="../../test/visual/baselines/cf_cell_greater_than/page-1.png" width="100%" alt="Preview"/></div>
|
|
1803
|
+
|
|
1804
|
+
### DSL Code
|
|
1805
|
+
|
|
1806
|
+
```ruby
|
|
1807
|
+
# frozen_string_literal: true
|
|
1808
|
+
require "xlsxrb"
|
|
1809
|
+
output_path = ARGV[0] || "cf_cell_greater_than.xlsx"
|
|
1810
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1811
|
+
w.add_style("center") { |style| style.align_horizontal("center") }
|
|
1812
|
+
w.add_sheet("CF Greater") do |s|
|
|
1813
|
+
s.set_column(0, width: 25)
|
|
1814
|
+
s.set_column(1, width: 25)
|
|
1815
|
+
s.add_row(["Values"])
|
|
1816
|
+
s.add_row([25], styles: ["center"])
|
|
1817
|
+
s.add_row([75], styles: ["center"])
|
|
1818
|
+
s.add_row([10], styles: ["center"])
|
|
1819
|
+
s.add_conditional_format("A2:A4", type: "cellIs", operator: "greaterThan", formula: "50", fill_color: "FFFFC7CE")
|
|
1820
|
+
end
|
|
1821
|
+
end
|
|
1822
|
+
|
|
1823
|
+
# 2. Read the generated sheet and print cell values
|
|
1824
|
+
puts "=== Read Validation ==="
|
|
1825
|
+
workbook = Xlsxrb.read(output_path)
|
|
1826
|
+
sheet = workbook.sheets.first
|
|
1827
|
+
sheet.rows.first(5).each do |row|
|
|
1828
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
1829
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1830
|
+
end
|
|
1831
|
+
```
|
|
1832
|
+
|
|
1833
|
+
### Console Output
|
|
1834
|
+
|
|
1835
|
+
```text
|
|
1836
|
+
=== Read Validation ===
|
|
1837
|
+
Row 0: A1: "Values"
|
|
1838
|
+
Row 1: A2: 25
|
|
1839
|
+
Row 2: A3: 75
|
|
1840
|
+
Row 3: A4: 10
|
|
1841
|
+
```
|
|
1842
|
+
|
|
1843
|
+
<hr/>
|
|
1844
|
+
|
|
1845
|
+
## Cf Cell Less Than
|
|
1846
|
+
|
|
1847
|
+
[Download .xlsx](files/cf_cell_less_than.xlsx)
|
|
1848
|
+
|
|
1849
|
+
Demonstrates conditional formatting highlighting cells less than a threshold.
|
|
1850
|
+
|
|
1851
|
+
### Rendered Output (LibreOffice Calc)
|
|
1852
|
+
|
|
1853
|
+
<div><img src="../../test/visual/baselines/cf_cell_less_than/page-1.png" width="100%" alt="Preview"/></div>
|
|
1854
|
+
|
|
1855
|
+
### DSL Code
|
|
1856
|
+
|
|
1857
|
+
```ruby
|
|
1858
|
+
# frozen_string_literal: true
|
|
1859
|
+
require "xlsxrb"
|
|
1860
|
+
output_path = ARGV[0] || "cf_cell_less_than.xlsx"
|
|
1861
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1862
|
+
w.add_style("center") { |style| style.align_horizontal("center") }
|
|
1863
|
+
w.add_sheet("CF Less") do |s|
|
|
1864
|
+
s.set_column(0, width: 25)
|
|
1865
|
+
s.set_column(1, width: 25)
|
|
1866
|
+
s.add_row(["Values"])
|
|
1867
|
+
s.add_row([25], styles: ["center"])
|
|
1868
|
+
s.add_row([75], styles: ["center"])
|
|
1869
|
+
s.add_row([10], styles: ["center"])
|
|
1870
|
+
s.add_conditional_format("A2:A4", type: "cellIs", operator: "lessThan", formula: "20", fill_color: "FFFFC7CE")
|
|
1871
|
+
end
|
|
1872
|
+
end
|
|
1873
|
+
|
|
1874
|
+
# 2. Read the generated sheet and print cell values
|
|
1875
|
+
puts "=== Read Validation ==="
|
|
1876
|
+
workbook = Xlsxrb.read(output_path)
|
|
1877
|
+
sheet = workbook.sheets.first
|
|
1878
|
+
sheet.rows.first(5).each do |row|
|
|
1879
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
1880
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1881
|
+
end
|
|
1882
|
+
```
|
|
1883
|
+
|
|
1884
|
+
### Console Output
|
|
1885
|
+
|
|
1886
|
+
```text
|
|
1887
|
+
=== Read Validation ===
|
|
1888
|
+
Row 0: A1: "Values"
|
|
1889
|
+
Row 1: A2: 25
|
|
1890
|
+
Row 2: A3: 75
|
|
1891
|
+
Row 3: A4: 10
|
|
1892
|
+
```
|
|
1893
|
+
|
|
1894
|
+
<hr/>
|
|
1895
|
+
|
|
1896
|
+
## Cf Color Scale
|
|
1897
|
+
|
|
1898
|
+
[Download .xlsx](files/cf_color_scale.xlsx)
|
|
1899
|
+
|
|
1900
|
+
Demonstrates color scale/heatmap conditional formatting.
|
|
1901
|
+
|
|
1902
|
+
### Rendered Output (LibreOffice Calc)
|
|
1903
|
+
|
|
1904
|
+
<div><img src="../../test/visual/baselines/cf_color_scale/page-1.png" width="100%" alt="Preview"/></div>
|
|
1905
|
+
|
|
1906
|
+
### DSL Code
|
|
1907
|
+
|
|
1908
|
+
```ruby
|
|
1909
|
+
# frozen_string_literal: true
|
|
1910
|
+
require "xlsxrb"
|
|
1911
|
+
output_path = ARGV[0] || "cf_color_scale.xlsx"
|
|
1912
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1913
|
+
w.add_style("center") { |style| style.align_horizontal("center") }
|
|
1914
|
+
w.add_sheet("Colors") do |s|
|
|
1915
|
+
s.set_column(0, width: 25)
|
|
1916
|
+
s.set_column(1, width: 25)
|
|
1917
|
+
s.add_row([10], styles: ["center"])
|
|
1918
|
+
s.add_row([50], styles: ["center"])
|
|
1919
|
+
s.add_row([90], styles: ["center"])
|
|
1920
|
+
s.add_conditional_format("A1:A3", type: :colorScale, priority: 1)
|
|
1921
|
+
end
|
|
1922
|
+
end
|
|
1923
|
+
|
|
1924
|
+
# 2. Read the generated sheet and print cell values
|
|
1925
|
+
puts "=== Read Validation ==="
|
|
1926
|
+
workbook = Xlsxrb.read(output_path)
|
|
1927
|
+
sheet = workbook.sheets.first
|
|
1928
|
+
sheet.rows.first(5).each do |row|
|
|
1929
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
1930
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1931
|
+
end
|
|
1932
|
+
```
|
|
1933
|
+
|
|
1934
|
+
### Console Output
|
|
1935
|
+
|
|
1936
|
+
```text
|
|
1937
|
+
=== Read Validation ===
|
|
1938
|
+
Row 0: A1: 10
|
|
1939
|
+
Row 1: A2: 50
|
|
1940
|
+
Row 2: A3: 90
|
|
1941
|
+
```
|
|
1942
|
+
|
|
1943
|
+
<hr/>
|
|
1944
|
+
|
|
1945
|
+
## Cf Contains Text
|
|
1946
|
+
|
|
1947
|
+
[Download .xlsx](files/cf_contains_text.xlsx)
|
|
1948
|
+
|
|
1949
|
+
Demonstrates conditional formatting highlighting cells containing specific text.
|
|
1950
|
+
|
|
1951
|
+
### Rendered Output (LibreOffice Calc)
|
|
1952
|
+
|
|
1953
|
+
<div><img src="../../test/visual/baselines/cf_contains_text/page-1.png" width="100%" alt="Preview"/></div>
|
|
1954
|
+
|
|
1955
|
+
### DSL Code
|
|
1956
|
+
|
|
1957
|
+
```ruby
|
|
1958
|
+
# frozen_string_literal: true
|
|
1959
|
+
require "xlsxrb"
|
|
1960
|
+
output_path = ARGV[0] || "cf_contains_text.xlsx"
|
|
1961
|
+
Xlsxrb.generate(output_path) do |w|
|
|
1962
|
+
w.add_sheet("CF Contains") do |s|
|
|
1963
|
+
s.set_column(0, width: 25)
|
|
1964
|
+
s.set_column(1, width: 25)
|
|
1965
|
+
s.add_row(["Status"])
|
|
1966
|
+
s.add_row(["Error"])
|
|
1967
|
+
s.add_row(["Success"])
|
|
1968
|
+
s.add_row(["Pending"])
|
|
1969
|
+
s.add_conditional_format("A2:A4", type: "containsText", operator: "containsText", text: "Error", formula: 'NOT(ISERROR(SEARCH("Error",A2)))', fill_color: "FFFF0000")
|
|
1970
|
+
end
|
|
1971
|
+
end
|
|
1972
|
+
|
|
1973
|
+
# 2. Read the generated sheet and print cell values
|
|
1974
|
+
puts "=== Read Validation ==="
|
|
1975
|
+
workbook = Xlsxrb.read(output_path)
|
|
1976
|
+
sheet = workbook.sheets.first
|
|
1977
|
+
sheet.rows.first(5).each do |row|
|
|
1978
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
1979
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
1980
|
+
end
|
|
1981
|
+
```
|
|
1982
|
+
|
|
1983
|
+
### Console Output
|
|
1984
|
+
|
|
1985
|
+
```text
|
|
1986
|
+
=== Read Validation ===
|
|
1987
|
+
Row 0: A1: "Status"
|
|
1988
|
+
Row 1: A2: "Error"
|
|
1989
|
+
Row 2: A3: "Success"
|
|
1990
|
+
Row 3: A4: "Pending"
|
|
1991
|
+
```
|
|
1992
|
+
|
|
1993
|
+
<hr/>
|
|
1994
|
+
|
|
1995
|
+
## Cf Data Bar
|
|
1996
|
+
|
|
1997
|
+
[Download .xlsx](files/cf_data_bar.xlsx)
|
|
1998
|
+
|
|
1999
|
+
Demonstrates data bar visual conditional formatting indicators.
|
|
2000
|
+
|
|
2001
|
+
### Rendered Output (LibreOffice Calc)
|
|
2002
|
+
|
|
2003
|
+
<div><img src="../../test/visual/baselines/cf_data_bar/page-1.png" width="100%" alt="Preview"/></div>
|
|
2004
|
+
|
|
2005
|
+
### DSL Code
|
|
2006
|
+
|
|
2007
|
+
```ruby
|
|
2008
|
+
# frozen_string_literal: true
|
|
2009
|
+
require "xlsxrb"
|
|
2010
|
+
output_path = ARGV[0] || "cf_data_bar.xlsx"
|
|
2011
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2012
|
+
w.add_style("center") { |style| style.align_horizontal("center") }
|
|
2013
|
+
w.add_sheet("Data Bars") do |s|
|
|
2014
|
+
s.set_column(0, width: 25)
|
|
2015
|
+
s.set_column(1, width: 25)
|
|
2016
|
+
s.add_row([20], styles: ["center"])
|
|
2017
|
+
s.add_row([60], styles: ["center"])
|
|
2018
|
+
s.add_row([100], styles: ["center"])
|
|
2019
|
+
s.add_conditional_format("A1:A3", type: :dataBar, priority: 1, color: "FF0070C0")
|
|
2020
|
+
end
|
|
2021
|
+
end
|
|
2022
|
+
|
|
2023
|
+
# 2. Read the generated sheet and print cell values
|
|
2024
|
+
puts "=== Read Validation ==="
|
|
2025
|
+
workbook = Xlsxrb.read(output_path)
|
|
2026
|
+
sheet = workbook.sheets.first
|
|
2027
|
+
sheet.rows.first(5).each do |row|
|
|
2028
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
2029
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
2030
|
+
end
|
|
2031
|
+
```
|
|
2032
|
+
|
|
2033
|
+
### Console Output
|
|
2034
|
+
|
|
2035
|
+
```text
|
|
2036
|
+
=== Read Validation ===
|
|
2037
|
+
Row 0: A1: 20
|
|
2038
|
+
Row 1: A2: 60
|
|
2039
|
+
Row 2: A3: 100
|
|
2040
|
+
```
|
|
2041
|
+
|
|
2042
|
+
<hr/>
|
|
2043
|
+
|
|
2044
|
+
## Cf Ends With
|
|
2045
|
+
|
|
2046
|
+
[Download .xlsx](files/cf_ends_with.xlsx)
|
|
2047
|
+
|
|
2048
|
+
Demonstrates conditional formatting highlighting cells ending with specific text.
|
|
2049
|
+
|
|
2050
|
+
### Rendered Output (LibreOffice Calc)
|
|
2051
|
+
|
|
2052
|
+
<div><img src="../../test/visual/baselines/cf_ends_with/page-1.png" width="100%" alt="Preview"/></div>
|
|
2053
|
+
|
|
2054
|
+
### DSL Code
|
|
2055
|
+
|
|
2056
|
+
```ruby
|
|
2057
|
+
# frozen_string_literal: true
|
|
2058
|
+
require "xlsxrb"
|
|
2059
|
+
output_path = ARGV[0] || "cf_ends_with.xlsx"
|
|
2060
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2061
|
+
w.add_sheet("CF Ends") do |s|
|
|
2062
|
+
s.set_column(0, width: 25)
|
|
2063
|
+
s.set_column(1, width: 25)
|
|
2064
|
+
s.add_row(["Code"])
|
|
2065
|
+
s.add_row(["100-Z"])
|
|
2066
|
+
s.add_row(["200-Y"])
|
|
2067
|
+
s.add_row(["300-Z"])
|
|
2068
|
+
s.add_conditional_format("A2:A4", type: "endsWith", operator: "endsWith", text: "Z", formula: 'RIGHT(A2,1)="Z"', fill_color: "FFFFC7CE")
|
|
2069
|
+
end
|
|
2070
|
+
end
|
|
2071
|
+
|
|
2072
|
+
# 2. Read the generated sheet and print cell values
|
|
2073
|
+
puts "=== Read Validation ==="
|
|
2074
|
+
workbook = Xlsxrb.read(output_path)
|
|
2075
|
+
sheet = workbook.sheets.first
|
|
2076
|
+
sheet.rows.first(5).each do |row|
|
|
2077
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
2078
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
2079
|
+
end
|
|
2080
|
+
```
|
|
2081
|
+
|
|
2082
|
+
### Console Output
|
|
2083
|
+
|
|
2084
|
+
```text
|
|
2085
|
+
=== Read Validation ===
|
|
2086
|
+
Row 0: A1: "Code"
|
|
2087
|
+
Row 1: A2: "100-Z"
|
|
2088
|
+
Row 2: A3: "200-Y"
|
|
2089
|
+
Row 3: A4: "300-Z"
|
|
2090
|
+
```
|
|
2091
|
+
|
|
2092
|
+
<hr/>
|
|
2093
|
+
|
|
2094
|
+
## Cf Expression Formula
|
|
2095
|
+
|
|
2096
|
+
[Download .xlsx](files/cf_expression_formula.xlsx)
|
|
2097
|
+
|
|
2098
|
+
Demonstrates conditional formatting using a custom formula expression.
|
|
2099
|
+
|
|
2100
|
+
### Rendered Output (LibreOffice Calc)
|
|
2101
|
+
|
|
2102
|
+
<div><img src="../../test/visual/baselines/cf_expression_formula/page-1.png" width="100%" alt="Preview"/></div>
|
|
2103
|
+
|
|
2104
|
+
### DSL Code
|
|
2105
|
+
|
|
2106
|
+
```ruby
|
|
2107
|
+
# frozen_string_literal: true
|
|
2108
|
+
require "xlsxrb"
|
|
2109
|
+
output_path = ARGV[0] || "cf_expression_formula.xlsx"
|
|
2110
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2111
|
+
w.add_style("center") { |style| style.align_horizontal("center") }
|
|
2112
|
+
w.add_sheet("CF Expression") do |s|
|
|
2113
|
+
s.set_column(0, width: 25)
|
|
2114
|
+
s.set_column(1, width: 25)
|
|
2115
|
+
s.add_row(["Values"])
|
|
2116
|
+
s.add_row([10], styles: ["center"])
|
|
2117
|
+
s.add_row([20], styles: ["center"])
|
|
2118
|
+
s.add_row([30], styles: ["center"])
|
|
2119
|
+
s.add_row([100], styles: ["center"]) # Average is 40. 100 is above average.
|
|
2120
|
+
s.add_conditional_format("A2:A5", type: "expression", formula: "A2>AVERAGE($A$2:$A$5)", fill_color: "FFFFC7CE")
|
|
2121
|
+
end
|
|
2122
|
+
end
|
|
2123
|
+
|
|
2124
|
+
# 2. Read the generated sheet and print cell values
|
|
2125
|
+
puts "=== Read Validation ==="
|
|
2126
|
+
workbook = Xlsxrb.read(output_path)
|
|
2127
|
+
sheet = workbook.sheets.first
|
|
2128
|
+
sheet.rows.first(5).each do |row|
|
|
2129
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
2130
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
2131
|
+
end
|
|
2132
|
+
```
|
|
2133
|
+
|
|
2134
|
+
### Console Output
|
|
2135
|
+
|
|
2136
|
+
```text
|
|
2137
|
+
=== Read Validation ===
|
|
2138
|
+
Row 0: A1: "Values"
|
|
2139
|
+
Row 1: A2: 10
|
|
2140
|
+
Row 2: A3: 20
|
|
2141
|
+
Row 3: A4: 30
|
|
2142
|
+
Row 4: A5: 100
|
|
2143
|
+
```
|
|
2144
|
+
|
|
2145
|
+
<hr/>
|
|
2146
|
+
|
|
2147
|
+
## Cf Icon Set
|
|
2148
|
+
|
|
2149
|
+
[Download .xlsx](files/cf_icon_set.xlsx)
|
|
2150
|
+
|
|
2151
|
+
Demonstrates icon set indicators (red/yellow/green arrows).
|
|
2152
|
+
|
|
2153
|
+
### Rendered Output (LibreOffice Calc)
|
|
2154
|
+
|
|
2155
|
+
<div><img src="../../test/visual/baselines/cf_icon_set/page-1.png" width="100%" alt="Preview"/></div>
|
|
2156
|
+
|
|
2157
|
+
### DSL Code
|
|
2158
|
+
|
|
2159
|
+
```ruby
|
|
2160
|
+
# frozen_string_literal: true
|
|
2161
|
+
require "xlsxrb"
|
|
2162
|
+
output_path = ARGV[0] || "cf_icon_set.xlsx"
|
|
2163
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2164
|
+
w.add_style("center") { |style| style.align_horizontal("center") }
|
|
2165
|
+
w.add_sheet("Icons") do |s|
|
|
2166
|
+
s.set_column(0, width: 25)
|
|
2167
|
+
s.set_column(1, width: 25)
|
|
2168
|
+
s.add_row([25], styles: ["center"])
|
|
2169
|
+
s.add_row([50], styles: ["center"])
|
|
2170
|
+
s.add_row([75], styles: ["center"])
|
|
2171
|
+
s.add_conditional_format("A1:A3", type: :iconSet, icon_style: "3Arrows", priority: 1)
|
|
2172
|
+
end
|
|
2173
|
+
end
|
|
2174
|
+
|
|
2175
|
+
# 2. Read the generated sheet and print cell values
|
|
2176
|
+
puts "=== Read Validation ==="
|
|
2177
|
+
workbook = Xlsxrb.read(output_path)
|
|
2178
|
+
sheet = workbook.sheets.first
|
|
2179
|
+
sheet.rows.first(5).each do |row|
|
|
2180
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
2181
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
2182
|
+
end
|
|
2183
|
+
```
|
|
2184
|
+
|
|
2185
|
+
### Console Output
|
|
2186
|
+
|
|
2187
|
+
```text
|
|
2188
|
+
=== Read Validation ===
|
|
2189
|
+
Row 0: A1: 25
|
|
2190
|
+
Row 1: A2: 50
|
|
2191
|
+
Row 2: A3: 75
|
|
2192
|
+
```
|
|
2193
|
+
|
|
2194
|
+
<hr/>
|
|
2195
|
+
|
|
2196
|
+
## Chart Area
|
|
2197
|
+
|
|
2198
|
+
[Download .xlsx](files/chart_area.xlsx)
|
|
2199
|
+
|
|
2200
|
+
Demonstrates embedding a standard 2D Area Chart.
|
|
2201
|
+
|
|
2202
|
+
### Rendered Output (LibreOffice Calc)
|
|
2203
|
+
|
|
2204
|
+
<div><img src="../../test/visual/baselines/chart_area/page-1.png" width="100%" alt="Preview"/></div>
|
|
2205
|
+
|
|
2206
|
+
### DSL Code
|
|
2207
|
+
|
|
2208
|
+
```ruby
|
|
2209
|
+
# frozen_string_literal: true
|
|
2210
|
+
require "xlsxrb"
|
|
2211
|
+
output_path = ARGV[0] || "chart_area.xlsx"
|
|
2212
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2213
|
+
w.add_sheet("Data") do |s|
|
|
2214
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2215
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2216
|
+
s.set_column(0, width: 25)
|
|
2217
|
+
s.set_column(1, width: 25)
|
|
2218
|
+
s.add_row(["Day", "Value"])
|
|
2219
|
+
s.add_row(["Mon", 10])
|
|
2220
|
+
s.add_row(["Tue", 15])
|
|
2221
|
+
s.add_chart(
|
|
2222
|
+
type: :area,
|
|
2223
|
+
title: "Daily Area",
|
|
2224
|
+
from_col: 3, from_row: 0, to_col: 8, to_row: 12,
|
|
2225
|
+
series: [{ cat_ref: "Data!$A$2:$A$3", val_ref: "Data!$B$2:$B$3", fill_color: "4F81BD" }]
|
|
2226
|
+
)
|
|
2227
|
+
end
|
|
2228
|
+
end
|
|
2229
|
+
|
|
2230
|
+
# 2. Read the generated sheet and print the chart count
|
|
2231
|
+
puts "=== Read Validation ==="
|
|
2232
|
+
workbook = Xlsxrb.read(output_path)
|
|
2233
|
+
sheet = workbook.sheets.first
|
|
2234
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2235
|
+
```
|
|
2236
|
+
|
|
2237
|
+
### Console Output
|
|
2238
|
+
|
|
2239
|
+
```text
|
|
2240
|
+
=== Read Validation ===
|
|
2241
|
+
Sheet 'Data' has 0 chart(s)
|
|
2242
|
+
```
|
|
2243
|
+
|
|
2244
|
+
<hr/>
|
|
2245
|
+
|
|
2246
|
+
## Chart Area Stacked
|
|
2247
|
+
|
|
2248
|
+
[Download .xlsx](files/chart_area_stacked.xlsx)
|
|
2249
|
+
|
|
2250
|
+
Demonstrates embedding a stacked 2D Area Chart.
|
|
2251
|
+
|
|
2252
|
+
### Rendered Output (LibreOffice Calc)
|
|
2253
|
+
|
|
2254
|
+
<div><img src="../../test/visual/baselines/chart_area_stacked/page-1.png" width="100%" alt="Preview"/></div>
|
|
2255
|
+
|
|
2256
|
+
### DSL Code
|
|
2257
|
+
|
|
2258
|
+
```ruby
|
|
2259
|
+
# frozen_string_literal: true
|
|
2260
|
+
require "xlsxrb"
|
|
2261
|
+
output_path = ARGV[0] || "chart_area_stacked.xlsx"
|
|
2262
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2263
|
+
w.add_sheet("Data") do |s|
|
|
2264
|
+
s.set_column(0, width: 25)
|
|
2265
|
+
s.set_column(1, width: 25)
|
|
2266
|
+
s.add_row(["Year", "Sales A", "Sales B"])
|
|
2267
|
+
s.add_row([2024, 100, 150])
|
|
2268
|
+
s.add_row([2025, 120, 180])
|
|
2269
|
+
s.add_row([2026, 140, 210])
|
|
2270
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2271
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2272
|
+
s.add_chart(
|
|
2273
|
+
type: :area,
|
|
2274
|
+
grouping: :stacked,
|
|
2275
|
+
title: "Stacked Area Chart",
|
|
2276
|
+
from_col: 0, from_row: 5, to_col: 6, to_row: 17,
|
|
2277
|
+
series: [
|
|
2278
|
+
{ cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$B$2:$B$4", name: "'Data'!$B$1", fill_color: "4F81BD" },
|
|
2279
|
+
{ cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$C$2:$C$4", name: "'Data'!$C$1", fill_color: "C0504D" }
|
|
2280
|
+
]
|
|
2281
|
+
)
|
|
2282
|
+
end
|
|
2283
|
+
end
|
|
2284
|
+
|
|
2285
|
+
# 2. Read the generated sheet and print the chart count
|
|
2286
|
+
puts "=== Read Validation ==="
|
|
2287
|
+
workbook = Xlsxrb.read(output_path)
|
|
2288
|
+
sheet = workbook.sheets.first
|
|
2289
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2290
|
+
```
|
|
2291
|
+
|
|
2292
|
+
### Console Output
|
|
2293
|
+
|
|
2294
|
+
```text
|
|
2295
|
+
=== Read Validation ===
|
|
2296
|
+
Sheet 'Data' has 0 chart(s)
|
|
2297
|
+
```
|
|
2298
|
+
|
|
2299
|
+
<hr/>
|
|
2300
|
+
|
|
2301
|
+
## Chart Bar
|
|
2302
|
+
|
|
2303
|
+
[Download .xlsx](files/chart_bar.xlsx)
|
|
2304
|
+
|
|
2305
|
+
Demonstrates embedding a standard 2D Bar Chart referencing worksheet cell ranges.
|
|
2306
|
+
|
|
2307
|
+
### Rendered Output (LibreOffice Calc)
|
|
2308
|
+
|
|
2309
|
+
<div><img src="../../test/visual/baselines/chart_bar/page-1.png" width="100%" alt="Preview"/></div>
|
|
2310
|
+
|
|
2311
|
+
### DSL Code
|
|
2312
|
+
|
|
2313
|
+
```ruby
|
|
2314
|
+
# frozen_string_literal: true
|
|
2315
|
+
|
|
2316
|
+
require "xlsxrb"
|
|
2317
|
+
|
|
2318
|
+
output_path = ARGV[0] || "chart_bar.xlsx"
|
|
2319
|
+
|
|
2320
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2321
|
+
w.add_sheet("Sales Data") do |s|
|
|
2322
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2323
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2324
|
+
s.set_column(0, width: 25)
|
|
2325
|
+
s.set_column(1, width: 25)
|
|
2326
|
+
s.add_row(["Month", "Value"])
|
|
2327
|
+
s.add_row(["Jan", 100])
|
|
2328
|
+
s.add_row(["Feb", 200])
|
|
2329
|
+
|
|
2330
|
+
s.add_chart(
|
|
2331
|
+
type: :bar,
|
|
2332
|
+
title: "Monthly Sales",
|
|
2333
|
+
from_col: 3,
|
|
2334
|
+
from_row: 0,
|
|
2335
|
+
to_col: 8,
|
|
2336
|
+
to_row: 12,
|
|
2337
|
+
series: [
|
|
2338
|
+
{ cat_ref: "'Sales Data'!$A$2:$A$3", val_ref: "'Sales Data'!$B$2:$B$3", fill_color: "4F81BD" }
|
|
2339
|
+
]
|
|
2340
|
+
)
|
|
2341
|
+
end
|
|
2342
|
+
end
|
|
2343
|
+
|
|
2344
|
+
# 2. Read the generated sheet and print the chart count
|
|
2345
|
+
puts "=== Read Validation ==="
|
|
2346
|
+
workbook = Xlsxrb.read(output_path)
|
|
2347
|
+
sheet = workbook.sheets.first
|
|
2348
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2349
|
+
```
|
|
2350
|
+
|
|
2351
|
+
### Console Output
|
|
2352
|
+
|
|
2353
|
+
```text
|
|
2354
|
+
=== Read Validation ===
|
|
2355
|
+
Sheet 'Sales Data' has 0 chart(s)
|
|
2356
|
+
```
|
|
2357
|
+
|
|
2358
|
+
<hr/>
|
|
2359
|
+
|
|
2360
|
+
## Chart Bar Percent Stacked
|
|
2361
|
+
|
|
2362
|
+
[Download .xlsx](files/chart_bar_percent_stacked.xlsx)
|
|
2363
|
+
|
|
2364
|
+
Demonstrates embedding a 100% stacked 2D Bar Chart.
|
|
2365
|
+
|
|
2366
|
+
### Rendered Output (LibreOffice Calc)
|
|
2367
|
+
|
|
2368
|
+
<div><img src="../../test/visual/baselines/chart_bar_percent_stacked/page-1.png" width="100%" alt="Preview"/></div>
|
|
2369
|
+
|
|
2370
|
+
### DSL Code
|
|
2371
|
+
|
|
2372
|
+
```ruby
|
|
2373
|
+
# frozen_string_literal: true
|
|
2374
|
+
require "xlsxrb"
|
|
2375
|
+
output_path = ARGV[0] || "chart_bar_percent_stacked.xlsx"
|
|
2376
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2377
|
+
w.add_sheet("Data") do |s|
|
|
2378
|
+
s.set_column(0, width: 25)
|
|
2379
|
+
s.set_column(1, width: 25)
|
|
2380
|
+
s.add_row(["Year", "Sales A", "Sales B"])
|
|
2381
|
+
s.add_row([2024, 100, 150])
|
|
2382
|
+
s.add_row([2025, 120, 180])
|
|
2383
|
+
s.add_row([2026, 140, 210])
|
|
2384
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2385
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2386
|
+
s.add_chart(
|
|
2387
|
+
type: :bar,
|
|
2388
|
+
grouping: :percentStacked,
|
|
2389
|
+
title: "100% Stacked Bar Chart",
|
|
2390
|
+
from_col: 0, from_row: 5, to_col: 6, to_row: 17,
|
|
2391
|
+
series: [
|
|
2392
|
+
{ cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$B$2:$B$4", name: "'Data'!$B$1", fill_color: "4F81BD" },
|
|
2393
|
+
{ cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$C$2:$C$4", name: "'Data'!$C$1", fill_color: "C0504D" }
|
|
2394
|
+
]
|
|
2395
|
+
)
|
|
2396
|
+
end
|
|
2397
|
+
end
|
|
2398
|
+
|
|
2399
|
+
# 2. Read the generated sheet and print the chart count
|
|
2400
|
+
puts "=== Read Validation ==="
|
|
2401
|
+
workbook = Xlsxrb.read(output_path)
|
|
2402
|
+
sheet = workbook.sheets.first
|
|
2403
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2404
|
+
```
|
|
2405
|
+
|
|
2406
|
+
### Console Output
|
|
2407
|
+
|
|
2408
|
+
```text
|
|
2409
|
+
=== Read Validation ===
|
|
2410
|
+
Sheet 'Data' has 0 chart(s)
|
|
2411
|
+
```
|
|
2412
|
+
|
|
2413
|
+
<hr/>
|
|
2414
|
+
|
|
2415
|
+
## Chart Bar Stacked
|
|
2416
|
+
|
|
2417
|
+
[Download .xlsx](files/chart_bar_stacked.xlsx)
|
|
2418
|
+
|
|
2419
|
+
Demonstrates embedding a stacked 2D Bar Chart.
|
|
2420
|
+
|
|
2421
|
+
### Rendered Output (LibreOffice Calc)
|
|
2422
|
+
|
|
2423
|
+
<div><img src="../../test/visual/baselines/chart_bar_stacked/page-1.png" width="100%" alt="Preview"/></div>
|
|
2424
|
+
|
|
2425
|
+
### DSL Code
|
|
2426
|
+
|
|
2427
|
+
```ruby
|
|
2428
|
+
# frozen_string_literal: true
|
|
2429
|
+
require "xlsxrb"
|
|
2430
|
+
output_path = ARGV[0] || "chart_bar_stacked.xlsx"
|
|
2431
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2432
|
+
w.add_sheet("Data") do |s|
|
|
2433
|
+
s.set_column(0, width: 25)
|
|
2434
|
+
s.set_column(1, width: 25)
|
|
2435
|
+
s.add_row(["Year", "Sales A", "Sales B"])
|
|
2436
|
+
s.add_row([2024, 100, 150])
|
|
2437
|
+
s.add_row([2025, 120, 180])
|
|
2438
|
+
s.add_row([2026, 140, 210])
|
|
2439
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2440
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2441
|
+
s.add_chart(
|
|
2442
|
+
type: :bar,
|
|
2443
|
+
grouping: :stacked,
|
|
2444
|
+
title: "Stacked Bar Chart",
|
|
2445
|
+
from_col: 0, from_row: 5, to_col: 6, to_row: 17,
|
|
2446
|
+
series: [
|
|
2447
|
+
{ cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$B$2:$B$4", name: "'Data'!$B$1", fill_color: "4F81BD" },
|
|
2448
|
+
{ cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$C$2:$C$4", name: "'Data'!$C$1", fill_color: "C0504D" }
|
|
2449
|
+
]
|
|
2450
|
+
)
|
|
2451
|
+
end
|
|
2452
|
+
end
|
|
2453
|
+
|
|
2454
|
+
# 2. Read the generated sheet and print the chart count
|
|
2455
|
+
puts "=== Read Validation ==="
|
|
2456
|
+
workbook = Xlsxrb.read(output_path)
|
|
2457
|
+
sheet = workbook.sheets.first
|
|
2458
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2459
|
+
```
|
|
2460
|
+
|
|
2461
|
+
### Console Output
|
|
2462
|
+
|
|
2463
|
+
```text
|
|
2464
|
+
=== Read Validation ===
|
|
2465
|
+
Sheet 'Data' has 0 chart(s)
|
|
2466
|
+
```
|
|
2467
|
+
|
|
2468
|
+
<hr/>
|
|
2469
|
+
|
|
2470
|
+
## Chart Doughnut
|
|
2471
|
+
|
|
2472
|
+
[Download .xlsx](files/chart_doughnut.xlsx)
|
|
2473
|
+
|
|
2474
|
+
Demonstrates embedding a standard 2D Doughnut Chart.
|
|
2475
|
+
|
|
2476
|
+
### Rendered Output (LibreOffice Calc)
|
|
2477
|
+
|
|
2478
|
+
<div><img src="../../test/visual/baselines/chart_doughnut/page-1.png" width="100%" alt="Preview"/></div>
|
|
2479
|
+
|
|
2480
|
+
### DSL Code
|
|
2481
|
+
|
|
2482
|
+
```ruby
|
|
2483
|
+
# frozen_string_literal: true
|
|
2484
|
+
require "xlsxrb"
|
|
2485
|
+
output_path = ARGV[0] || "chart_doughnut.xlsx"
|
|
2486
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2487
|
+
w.add_sheet("Data") do |s|
|
|
2488
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2489
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2490
|
+
s.set_column(0, width: 25)
|
|
2491
|
+
s.set_column(1, width: 25)
|
|
2492
|
+
s.add_row(["Label", "Percent"])
|
|
2493
|
+
s.add_row(["A", 40])
|
|
2494
|
+
s.add_row(["B", 60])
|
|
2495
|
+
s.add_chart(
|
|
2496
|
+
type: :doughnut,
|
|
2497
|
+
title: "Ratio",
|
|
2498
|
+
from_col: 3, from_row: 0, to_col: 8, to_row: 12,
|
|
2499
|
+
series: [{
|
|
2500
|
+
cat_ref: "Data!$A$2:$A$3",
|
|
2501
|
+
val_ref: "Data!$B$2:$B$3",
|
|
2502
|
+
data_points: [
|
|
2503
|
+
{ idx: 0, fill_color: "4F81BD" },
|
|
2504
|
+
{ idx: 1, fill_color: "C0504D" }
|
|
2505
|
+
]
|
|
2506
|
+
}]
|
|
2507
|
+
)
|
|
2508
|
+
end
|
|
2509
|
+
end
|
|
2510
|
+
|
|
2511
|
+
# 2. Read the generated sheet and print the chart count
|
|
2512
|
+
puts "=== Read Validation ==="
|
|
2513
|
+
workbook = Xlsxrb.read(output_path)
|
|
2514
|
+
sheet = workbook.sheets.first
|
|
2515
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2516
|
+
```
|
|
2517
|
+
|
|
2518
|
+
### Console Output
|
|
2519
|
+
|
|
2520
|
+
```text
|
|
2521
|
+
=== Read Validation ===
|
|
2522
|
+
Sheet 'Data' has 0 chart(s)
|
|
2523
|
+
```
|
|
2524
|
+
|
|
2525
|
+
<hr/>
|
|
2526
|
+
|
|
2527
|
+
## Chart Line
|
|
2528
|
+
|
|
2529
|
+
[Download .xlsx](files/chart_line.xlsx)
|
|
2530
|
+
|
|
2531
|
+
Demonstrates embedding a standard 2D Line Chart.
|
|
2532
|
+
|
|
2533
|
+
### Rendered Output (LibreOffice Calc)
|
|
2534
|
+
|
|
2535
|
+
<div><img src="../../test/visual/baselines/chart_line/page-1.png" width="100%" alt="Preview"/></div>
|
|
2536
|
+
|
|
2537
|
+
### DSL Code
|
|
2538
|
+
|
|
2539
|
+
```ruby
|
|
2540
|
+
# frozen_string_literal: true
|
|
2541
|
+
require "xlsxrb"
|
|
2542
|
+
output_path = ARGV[0] || "chart_line.xlsx"
|
|
2543
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2544
|
+
w.add_sheet("Data") do |s|
|
|
2545
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2546
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2547
|
+
s.set_column(0, width: 25)
|
|
2548
|
+
s.set_column(1, width: 25)
|
|
2549
|
+
s.add_row(["Day", "Value"])
|
|
2550
|
+
s.add_row(["Mon", 10])
|
|
2551
|
+
s.add_row(["Tue", 15])
|
|
2552
|
+
s.add_row(["Wed", 12])
|
|
2553
|
+
s.add_chart(
|
|
2554
|
+
type: :line,
|
|
2555
|
+
title: "Daily Value",
|
|
2556
|
+
from_col: 3, from_row: 0, to_col: 8, to_row: 12,
|
|
2557
|
+
series: [{ cat_ref: "Data!$A$2:$A$4", val_ref: "Data!$B$2:$B$4", line_color: "4F81BD", line_width: 2.0 }]
|
|
2558
|
+
)
|
|
2559
|
+
end
|
|
2560
|
+
end
|
|
2561
|
+
|
|
2562
|
+
# 2. Read the generated sheet and print the chart count
|
|
2563
|
+
puts "=== Read Validation ==="
|
|
2564
|
+
workbook = Xlsxrb.read(output_path)
|
|
2565
|
+
sheet = workbook.sheets.first
|
|
2566
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2567
|
+
```
|
|
2568
|
+
|
|
2569
|
+
### Console Output
|
|
2570
|
+
|
|
2571
|
+
```text
|
|
2572
|
+
=== Read Validation ===
|
|
2573
|
+
Sheet 'Data' has 0 chart(s)
|
|
2574
|
+
```
|
|
2575
|
+
|
|
2576
|
+
<hr/>
|
|
2577
|
+
|
|
2578
|
+
## Chart Line Stacked
|
|
2579
|
+
|
|
2580
|
+
[Download .xlsx](files/chart_line_stacked.xlsx)
|
|
2581
|
+
|
|
2582
|
+
Demonstrates embedding a stacked 2D Line Chart.
|
|
2583
|
+
|
|
2584
|
+
### Rendered Output (LibreOffice Calc)
|
|
2585
|
+
|
|
2586
|
+
<div><img src="../../test/visual/baselines/chart_line_stacked/page-1.png" width="100%" alt="Preview"/></div>
|
|
2587
|
+
|
|
2588
|
+
### DSL Code
|
|
2589
|
+
|
|
2590
|
+
```ruby
|
|
2591
|
+
# frozen_string_literal: true
|
|
2592
|
+
require "xlsxrb"
|
|
2593
|
+
output_path = ARGV[0] || "chart_line_stacked.xlsx"
|
|
2594
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2595
|
+
w.add_sheet("Data") do |s|
|
|
2596
|
+
s.set_column(0, width: 25)
|
|
2597
|
+
s.set_column(1, width: 25)
|
|
2598
|
+
s.add_row(["Year", "Sales A", "Sales B"])
|
|
2599
|
+
s.add_row([2024, 100, 150])
|
|
2600
|
+
s.add_row([2025, 120, 180])
|
|
2601
|
+
s.add_row([2026, 140, 210])
|
|
2602
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2603
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2604
|
+
s.add_chart(
|
|
2605
|
+
type: :line,
|
|
2606
|
+
grouping: :stacked,
|
|
2607
|
+
title: "Stacked Line Chart",
|
|
2608
|
+
from_col: 0, from_row: 5, to_col: 6, to_row: 17,
|
|
2609
|
+
series: [
|
|
2610
|
+
{ cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$B$2:$B$4", name: "'Data'!$B$1", line_color: "4F81BD", line_width: 2.0 },
|
|
2611
|
+
{ cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$C$2:$C$4", name: "'Data'!$C$1", line_color: "C0504D", line_width: 2.0 }
|
|
2612
|
+
]
|
|
2613
|
+
)
|
|
2614
|
+
end
|
|
2615
|
+
end
|
|
2616
|
+
|
|
2617
|
+
# 2. Read the generated sheet and print the chart count
|
|
2618
|
+
puts "=== Read Validation ==="
|
|
2619
|
+
workbook = Xlsxrb.read(output_path)
|
|
2620
|
+
sheet = workbook.sheets.first
|
|
2621
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2622
|
+
```
|
|
2623
|
+
|
|
2624
|
+
### Console Output
|
|
2625
|
+
|
|
2626
|
+
```text
|
|
2627
|
+
=== Read Validation ===
|
|
2628
|
+
Sheet 'Data' has 0 chart(s)
|
|
2629
|
+
```
|
|
2630
|
+
|
|
2631
|
+
<hr/>
|
|
2632
|
+
|
|
2633
|
+
## Chart Pie
|
|
2634
|
+
|
|
2635
|
+
[Download .xlsx](files/chart_pie.xlsx)
|
|
2636
|
+
|
|
2637
|
+
Demonstrates embedding a standard 2D Pie Chart.
|
|
2638
|
+
|
|
2639
|
+
### Rendered Output (LibreOffice Calc)
|
|
2640
|
+
|
|
2641
|
+
<div><img src="../../test/visual/baselines/chart_pie/page-1.png" width="100%" alt="Preview"/></div>
|
|
2642
|
+
|
|
2643
|
+
### DSL Code
|
|
2644
|
+
|
|
2645
|
+
```ruby
|
|
2646
|
+
# frozen_string_literal: true
|
|
2647
|
+
require "xlsxrb"
|
|
2648
|
+
output_path = ARGV[0] || "chart_pie.xlsx"
|
|
2649
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2650
|
+
w.add_sheet("Data") do |s|
|
|
2651
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2652
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2653
|
+
s.set_column(0, width: 25)
|
|
2654
|
+
s.set_column(1, width: 25)
|
|
2655
|
+
s.add_row(["Label", "Percent"])
|
|
2656
|
+
s.add_row(["Yes", 70])
|
|
2657
|
+
s.add_row(["No", 30])
|
|
2658
|
+
s.add_chart(
|
|
2659
|
+
type: :pie,
|
|
2660
|
+
title: "Responses",
|
|
2661
|
+
from_col: 3, from_row: 0, to_col: 8, to_row: 12,
|
|
2662
|
+
series: [{
|
|
2663
|
+
cat_ref: "Data!$A$2:$A$3",
|
|
2664
|
+
val_ref: "Data!$B$2:$B$3",
|
|
2665
|
+
data_points: [
|
|
2666
|
+
{ idx: 0, fill_color: "4F81BD" },
|
|
2667
|
+
{ idx: 1, fill_color: "C0504D" }
|
|
2668
|
+
]
|
|
2669
|
+
}]
|
|
2670
|
+
)
|
|
2671
|
+
end
|
|
2672
|
+
end
|
|
2673
|
+
|
|
2674
|
+
# 2. Read the generated sheet and print the chart count
|
|
2675
|
+
puts "=== Read Validation ==="
|
|
2676
|
+
workbook = Xlsxrb.read(output_path)
|
|
2677
|
+
sheet = workbook.sheets.first
|
|
2678
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2679
|
+
```
|
|
2680
|
+
|
|
2681
|
+
### Console Output
|
|
2682
|
+
|
|
2683
|
+
```text
|
|
2684
|
+
=== Read Validation ===
|
|
2685
|
+
Sheet 'Data' has 0 chart(s)
|
|
2686
|
+
```
|
|
2687
|
+
|
|
2688
|
+
<hr/>
|
|
2689
|
+
|
|
2690
|
+
## Chart Radar
|
|
2691
|
+
|
|
2692
|
+
[Download .xlsx](files/chart_radar.xlsx)
|
|
2693
|
+
|
|
2694
|
+
Demonstrates embedding a standard 2D Radar Chart.
|
|
2695
|
+
|
|
2696
|
+
### Rendered Output (LibreOffice Calc)
|
|
2697
|
+
|
|
2698
|
+
<div><img src="../../test/visual/baselines/chart_radar/page-1.png" width="100%" alt="Preview"/></div>
|
|
2699
|
+
|
|
2700
|
+
### DSL Code
|
|
2701
|
+
|
|
2702
|
+
```ruby
|
|
2703
|
+
# frozen_string_literal: true
|
|
2704
|
+
require "xlsxrb"
|
|
2705
|
+
output_path = ARGV[0] || "chart_radar.xlsx"
|
|
2706
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2707
|
+
w.add_sheet("Data") do |s|
|
|
2708
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2709
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2710
|
+
s.set_column(0, width: 25)
|
|
2711
|
+
s.set_column(1, width: 25)
|
|
2712
|
+
s.add_row(["Stat", "Value"])
|
|
2713
|
+
s.add_row(["Atk", 80])
|
|
2714
|
+
s.add_row(["Def", 60])
|
|
2715
|
+
s.add_chart(
|
|
2716
|
+
type: :radar,
|
|
2717
|
+
title: "Stats",
|
|
2718
|
+
from_col: 3, from_row: 0, to_col: 8, to_row: 12,
|
|
2719
|
+
series: [{ cat_ref: "Data!$A$2:$A$3", val_ref: "Data!$B$2:$B$3", line_color: "4F81BD", line_width: 2.0 }]
|
|
2720
|
+
)
|
|
2721
|
+
end
|
|
2722
|
+
end
|
|
2723
|
+
|
|
2724
|
+
# 2. Read the generated sheet and print the chart count
|
|
2725
|
+
puts "=== Read Validation ==="
|
|
2726
|
+
workbook = Xlsxrb.read(output_path)
|
|
2727
|
+
sheet = workbook.sheets.first
|
|
2728
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2729
|
+
```
|
|
2730
|
+
|
|
2731
|
+
### Console Output
|
|
2732
|
+
|
|
2733
|
+
```text
|
|
2734
|
+
=== Read Validation ===
|
|
2735
|
+
Sheet 'Data' has 0 chart(s)
|
|
2736
|
+
```
|
|
2737
|
+
|
|
2738
|
+
<hr/>
|
|
2739
|
+
|
|
2740
|
+
## Chart Scatter
|
|
2741
|
+
|
|
2742
|
+
[Download .xlsx](files/chart_scatter.xlsx)
|
|
2743
|
+
|
|
2744
|
+
Demonstrates embedding a standard 2D Scatter Plot.
|
|
2745
|
+
|
|
2746
|
+
### Rendered Output (LibreOffice Calc)
|
|
2747
|
+
|
|
2748
|
+
<div><img src="../../test/visual/baselines/chart_scatter/page-1.png" width="100%" alt="Preview"/></div>
|
|
2749
|
+
|
|
2750
|
+
### DSL Code
|
|
2751
|
+
|
|
2752
|
+
```ruby
|
|
2753
|
+
# frozen_string_literal: true
|
|
2754
|
+
require "xlsxrb"
|
|
2755
|
+
output_path = ARGV[0] || "chart_scatter.xlsx"
|
|
2756
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2757
|
+
w.add_sheet("Data") do |s|
|
|
2758
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2759
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2760
|
+
s.set_column(0, width: 25)
|
|
2761
|
+
s.set_column(1, width: 25)
|
|
2762
|
+
s.add_row(["X", "Y"])
|
|
2763
|
+
s.add_row([1, 10])
|
|
2764
|
+
s.add_row([2, 15])
|
|
2765
|
+
s.add_chart(
|
|
2766
|
+
type: :scatter,
|
|
2767
|
+
title: "Scatter Plot",
|
|
2768
|
+
from_col: 3, from_row: 0, to_col: 8, to_row: 12,
|
|
2769
|
+
series: [{ cat_ref: "Data!$A$2:$A$3", val_ref: "Data!$B$2:$B$3", line_color: "4F81BD", line_width: 2.0 }]
|
|
2770
|
+
)
|
|
2771
|
+
end
|
|
2772
|
+
end
|
|
2773
|
+
|
|
2774
|
+
# 2. Read the generated sheet and print the chart count
|
|
2775
|
+
puts "=== Read Validation ==="
|
|
2776
|
+
workbook = Xlsxrb.read(output_path)
|
|
2777
|
+
sheet = workbook.sheets.first
|
|
2778
|
+
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"
|
|
2779
|
+
```
|
|
2780
|
+
|
|
2781
|
+
### Console Output
|
|
2782
|
+
|
|
2783
|
+
```text
|
|
2784
|
+
=== Read Validation ===
|
|
2785
|
+
Sheet 'Data' has 0 chart(s)
|
|
2786
|
+
```
|
|
2787
|
+
|
|
2788
|
+
<hr/>
|
|
2789
|
+
|
|
2790
|
+
## Col Grouping
|
|
2791
|
+
|
|
2792
|
+
[Download .xlsx](files/col_grouping.xlsx)
|
|
2793
|
+
|
|
2794
|
+
Demonstrates outline grouping for columns.
|
|
2795
|
+
|
|
2796
|
+
### Rendered Output (LibreOffice Calc)
|
|
2797
|
+
|
|
2798
|
+
<div><img src="../../test/visual/baselines/col_grouping/page-1.png" width="100%" alt="Preview"/></div>
|
|
2799
|
+
|
|
2800
|
+
### DSL Code
|
|
2801
|
+
|
|
2802
|
+
```ruby
|
|
2803
|
+
# frozen_string_literal: true
|
|
2804
|
+
require "xlsxrb"
|
|
2805
|
+
output_path = ARGV[0] || "col_grouping.xlsx"
|
|
2806
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2807
|
+
w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
|
|
2808
|
+
w.add_sheet("Col Grouping") do |s|
|
|
2809
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
2810
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
2811
|
+
s.set_column(0, width: 25, outline_level: 0)
|
|
2812
|
+
s.set_column(1, width: 25, outline_level: 1)
|
|
2813
|
+
s.set_column(2, width: 25, outline_level: 1)
|
|
2814
|
+
s.add_row(["Col A", "Col B (Grouped)", "Col C (Grouped)"], styles: ["border", "border", "border"])
|
|
2815
|
+
end
|
|
2816
|
+
end
|
|
2817
|
+
|
|
2818
|
+
# 2. Read the generated sheet and print column dimensions
|
|
2819
|
+
puts "=== Read Validation ==="
|
|
2820
|
+
workbook = Xlsxrb.read(output_path)
|
|
2821
|
+
sheet = workbook.sheets.first
|
|
2822
|
+
sheet.columns.each do |col|
|
|
2823
|
+
puts "Column #{col.index}: width=#{col.width}, hidden=#{col.hidden}, outline_level=#{col.outline_level}"
|
|
2824
|
+
end
|
|
2825
|
+
```
|
|
2826
|
+
|
|
2827
|
+
### Console Output
|
|
2828
|
+
|
|
2829
|
+
```text
|
|
2830
|
+
=== Read Validation ===
|
|
2831
|
+
Column 0: width=25.0, hidden=false, outline_level=0
|
|
2832
|
+
Column 1: width=25.0, hidden=false, outline_level=1
|
|
2833
|
+
Column 2: width=25.0, hidden=false, outline_level=1
|
|
2834
|
+
```
|
|
2835
|
+
|
|
2836
|
+
<hr/>
|
|
2837
|
+
|
|
2838
|
+
## Col Width Tall
|
|
2839
|
+
|
|
2840
|
+
[Download .xlsx](files/col_width_tall.xlsx)
|
|
2841
|
+
|
|
2842
|
+
Demonstrates setting very wide column widths.
|
|
2843
|
+
|
|
2844
|
+
### Rendered Output (LibreOffice Calc)
|
|
2845
|
+
|
|
2846
|
+
<div><img src="../../test/visual/baselines/col_width_tall/page-1.png" width="100%" alt="Preview"/></div>
|
|
2847
|
+
|
|
2848
|
+
### DSL Code
|
|
2849
|
+
|
|
2850
|
+
```ruby
|
|
2851
|
+
# frozen_string_literal: true
|
|
2852
|
+
require "xlsxrb"
|
|
2853
|
+
output_path = ARGV[0] || "col_width_tall.xlsx"
|
|
2854
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2855
|
+
w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
|
|
2856
|
+
w.add_sheet("Col Width") do |s|
|
|
2857
|
+
s.set_column(0, width: 50)
|
|
2858
|
+
s.set_column(1, width: 10)
|
|
2859
|
+
s.add_row(["Very Wide Column (Width 50)", "Normal (10)"], styles: ["border", "border"])
|
|
2860
|
+
end
|
|
2861
|
+
end
|
|
2862
|
+
|
|
2863
|
+
# 2. Read the generated sheet and print column dimensions
|
|
2864
|
+
puts "=== Read Validation ==="
|
|
2865
|
+
workbook = Xlsxrb.read(output_path)
|
|
2866
|
+
sheet = workbook.sheets.first
|
|
2867
|
+
sheet.columns.each do |col|
|
|
2868
|
+
puts "Column #{col.index}: width=#{col.width}, hidden=#{col.hidden}, outline_level=#{col.outline_level}"
|
|
2869
|
+
end
|
|
2870
|
+
```
|
|
2871
|
+
|
|
2872
|
+
### Console Output
|
|
2873
|
+
|
|
2874
|
+
```text
|
|
2875
|
+
=== Read Validation ===
|
|
2876
|
+
Column 0: width=50.0, hidden=false, outline_level=
|
|
2877
|
+
Column 1: width=10.0, hidden=false, outline_level=
|
|
2878
|
+
```
|
|
2879
|
+
|
|
2880
|
+
<hr/>
|
|
2881
|
+
|
|
2882
|
+
## Col Widths
|
|
2883
|
+
|
|
2884
|
+
[Download .xlsx](files/col_widths.xlsx)
|
|
2885
|
+
|
|
2886
|
+
Demonstrates setting custom column widths.
|
|
2887
|
+
|
|
2888
|
+
### Rendered Output (LibreOffice Calc)
|
|
2889
|
+
|
|
2890
|
+
<div><img src="../../test/visual/baselines/col_widths/page-1.png" width="100%" alt="Preview"/></div>
|
|
2891
|
+
|
|
2892
|
+
### DSL Code
|
|
2893
|
+
|
|
2894
|
+
```ruby
|
|
2895
|
+
# frozen_string_literal: true
|
|
2896
|
+
require "xlsxrb"
|
|
2897
|
+
output_path = ARGV[0] || "col_widths.xlsx"
|
|
2898
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2899
|
+
w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
|
|
2900
|
+
w.add_sheet("Widths") do |s|
|
|
2901
|
+
s.set_column(0, width: 30)
|
|
2902
|
+
s.set_column(1, width: 10)
|
|
2903
|
+
s.add_row(["Wide Column A", "Narrow B"], styles: ["border", "border"])
|
|
2904
|
+
end
|
|
2905
|
+
end
|
|
2906
|
+
|
|
2907
|
+
# 2. Read the generated sheet and print column dimensions
|
|
2908
|
+
puts "=== Read Validation ==="
|
|
2909
|
+
workbook = Xlsxrb.read(output_path)
|
|
2910
|
+
sheet = workbook.sheets.first
|
|
2911
|
+
sheet.columns.each do |col|
|
|
2912
|
+
puts "Column #{col.index}: width=#{col.width}, hidden=#{col.hidden}, outline_level=#{col.outline_level}"
|
|
2913
|
+
end
|
|
2914
|
+
```
|
|
2915
|
+
|
|
2916
|
+
### Console Output
|
|
2917
|
+
|
|
2918
|
+
```text
|
|
2919
|
+
=== Read Validation ===
|
|
2920
|
+
Column 0: width=30.0, hidden=false, outline_level=
|
|
2921
|
+
Column 1: width=10.0, hidden=false, outline_level=
|
|
2922
|
+
```
|
|
2923
|
+
|
|
2924
|
+
<hr/>
|
|
2925
|
+
|
|
2926
|
+
## Conditional Formatting
|
|
2927
|
+
|
|
2928
|
+
[Download .xlsx](files/conditional_formatting.xlsx)
|
|
2929
|
+
|
|
2930
|
+
Demonstrates adding conditional formatting rules that style cells automatically based on value ranges.
|
|
2931
|
+
|
|
2932
|
+
### Rendered Output (LibreOffice Calc)
|
|
2933
|
+
|
|
2934
|
+
<div><img src="../../test/visual/baselines/conditional_formatting/page-1.png" width="100%" alt="Preview"/></div>
|
|
2935
|
+
|
|
2936
|
+
### DSL Code
|
|
2937
|
+
|
|
2938
|
+
```ruby
|
|
2939
|
+
# frozen_string_literal: true
|
|
2940
|
+
|
|
2941
|
+
require "xlsxrb"
|
|
2942
|
+
|
|
2943
|
+
output_path = ARGV[0] || "conditional_formatting.xlsx"
|
|
2944
|
+
|
|
2945
|
+
Xlsxrb.generate(output_path) do |w|
|
|
2946
|
+
w.add_style("center") { |style| style.align_horizontal("center") }
|
|
2947
|
+
w.add_sheet("Scores") do |s|
|
|
2948
|
+
s.set_column(0, width: 25)
|
|
2949
|
+
s.set_column(1, width: 25)
|
|
2950
|
+
s.add_row([90, 45, 72, 88], styles: ["center", "center", "center", "center"])
|
|
2951
|
+
|
|
2952
|
+
s.add_conditional_format("A1:D1",
|
|
2953
|
+
type: :cell_is, operator: :greaterThan,
|
|
2954
|
+
formula: "80", priority: 1,
|
|
2955
|
+
fill_color: "FFFFC7CE")
|
|
2956
|
+
end
|
|
2957
|
+
end
|
|
2958
|
+
|
|
2959
|
+
# 2. Read the generated sheet and print cell values
|
|
2960
|
+
puts "=== Read Validation ==="
|
|
2961
|
+
workbook = Xlsxrb.read(output_path)
|
|
2962
|
+
sheet = workbook.sheets.first
|
|
2963
|
+
sheet.rows.first(5).each do |row|
|
|
2964
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
2965
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
2966
|
+
end
|
|
2967
|
+
```
|
|
2968
|
+
|
|
2969
|
+
### Console Output
|
|
2970
|
+
|
|
2971
|
+
```text
|
|
2972
|
+
=== Read Validation ===
|
|
2973
|
+
Row 0: A1: 90, B1: 45, C1: 72, D1: 88
|
|
2974
|
+
```
|
|
2975
|
+
|
|
2976
|
+
<hr/>
|
|
2977
|
+
|
|
2978
|
+
## Embedded Images
|
|
2979
|
+
|
|
2980
|
+
[Download .xlsx](files/embedded_images.xlsx)
|
|
2981
|
+
|
|
2982
|
+
Demonstrates embedding raster PNG images in cell ranges.
|
|
2983
|
+
|
|
2984
|
+
### Rendered Output (LibreOffice Calc)
|
|
2985
|
+
|
|
2986
|
+
<div><img src="../../test/visual/baselines/embedded_images/page-1.png" width="100%" alt="Preview"/></div>
|
|
2987
|
+
|
|
2988
|
+
### DSL Code
|
|
2989
|
+
|
|
2990
|
+
```ruby
|
|
2991
|
+
# frozen_string_literal: true
|
|
2992
|
+
require "xlsxrb"
|
|
2993
|
+
output_path = ARGV[0] || "embedded_images.xlsx"
|
|
2994
|
+
|
|
2995
|
+
require "zlib"
|
|
2996
|
+
|
|
2997
|
+
def make_png(width, height, red, green, blue)
|
|
2998
|
+
png = "\x89PNG\r\n\x1a\n".dup.force_encoding("BINARY")
|
|
2999
|
+
ihdr_data = [width, height, 8, 2, 0, 0, 0].pack("N2C5")
|
|
3000
|
+
ihdr_chunk = "IHDR".dup.force_encoding("BINARY") + ihdr_data
|
|
3001
|
+
ihdr_crc = Zlib.crc32(ihdr_chunk)
|
|
3002
|
+
png << [ihdr_data.bytesize].pack("N") << ihdr_chunk << [ihdr_crc].pack("N")
|
|
3003
|
+
raw_data = Array.new(height) { "\x00".dup.force_encoding("BINARY") + [red, green, blue].pack("C3") * width }.join
|
|
3004
|
+
compressed = Zlib.deflate(raw_data)
|
|
3005
|
+
idat_chunk = "IDAT".dup.force_encoding("BINARY") + compressed
|
|
3006
|
+
idat_crc = Zlib.crc32(idat_chunk)
|
|
3007
|
+
png << [compressed.bytesize].pack("N") << idat_chunk << [idat_crc].pack("N")
|
|
3008
|
+
iend_chunk = "IEND".dup.force_encoding("BINARY")
|
|
3009
|
+
iend_crc = Zlib.crc32(iend_chunk)
|
|
3010
|
+
png << [0].pack("N") << iend_chunk << [iend_crc].pack("N")
|
|
3011
|
+
png
|
|
3012
|
+
end
|
|
3013
|
+
|
|
3014
|
+
dummy_png = make_png(100, 100, 255, 0, 0)
|
|
3015
|
+
|
|
3016
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3017
|
+
w.add_style("center") { |st| st.align_horizontal(:center) }
|
|
3018
|
+
w.add_sheet("Images") do |s|
|
|
3019
|
+
s.add_row(["Logo Target cell:", "", "", "Boundary"], styles: ["left", "center", "center", "center"])
|
|
3020
|
+
s.add_row(["", "", "", ""])
|
|
3021
|
+
s.add_row(["", "", "", ""])
|
|
3022
|
+
s.add_row(["", "", "", ""])
|
|
3023
|
+
s.add_row(["", "", "", "Boundary End"], styles: ["left", "center", "center", "center"])
|
|
3024
|
+
s.add_image(dummy_png, ext: "png", from_col: 1, from_row: 1, to_col: 3, to_row: 5)
|
|
3025
|
+
s.set_column(0, width: 20)
|
|
3026
|
+
s.set_column(1, width: 15)
|
|
3027
|
+
s.set_column(2, width: 15)
|
|
3028
|
+
s.set_column(3, width: 15)
|
|
3029
|
+
end
|
|
3030
|
+
end
|
|
3031
|
+
|
|
3032
|
+
# 2. Read the generated sheet and print cell values + parsed embedded images details
|
|
3033
|
+
puts "=== Read Validation ==="
|
|
3034
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
3035
|
+
workbook = Xlsxrb.read(output_path)
|
|
3036
|
+
sheet = workbook.sheets.first
|
|
3037
|
+
sheet.rows.first(5).each do |row|
|
|
3038
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
3039
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
3040
|
+
end
|
|
3041
|
+
images = reader.images(sheet: sheet.name)
|
|
3042
|
+
images.each_with_index do |img, idx|
|
|
3043
|
+
zip_path = File.expand_path(img[:target], "/xl/drawings").sub(%r{^/}, "")
|
|
3044
|
+
img_data = reader.send(:extract_zip_entry, zip_path)
|
|
3045
|
+
is_png = img_data && img_data[0..3] == "\x89PNG".b
|
|
3046
|
+
puts "Image ##{idx + 1}: name='#{img[:name]}', target='#{img[:target]}' -> ZIP path='#{zip_path}', size=#{img_data&.bytesize} bytes, valid_png=#{is_png}, range=Col #{img[:from_col]} Row #{img[:from_row]} to Col #{img[:to_col]} Row #{img[:to_row]}"
|
|
3047
|
+
end
|
|
3048
|
+
```
|
|
3049
|
+
|
|
3050
|
+
### Console Output
|
|
3051
|
+
|
|
3052
|
+
```text
|
|
3053
|
+
=== Read Validation ===
|
|
3054
|
+
Row 0: A1: "Logo Target cell:", B1: "", C1: "", D1: "Boundary"
|
|
3055
|
+
Row 1: A2: "", B2: "", C2: "", D2: ""
|
|
3056
|
+
Row 2: A3: "", B3: "", C3: "", D3: ""
|
|
3057
|
+
Row 3: A4: "", B4: "", C4: "", D4: ""
|
|
3058
|
+
Row 4: A5: "", B5: "", C5: "", D5: "Boundary End"
|
|
3059
|
+
Image #1: name='', target='../media/image1.png' -> ZIP path='xl/media/image1.png', size=334 bytes, valid_png=true, range=Col 1 Row 1 to Col 3 Row 5
|
|
3060
|
+
```
|
|
3061
|
+
|
|
3062
|
+
<hr/>
|
|
3063
|
+
|
|
3064
|
+
## Fill Gradients
|
|
3065
|
+
|
|
3066
|
+
[Download .xlsx](files/fill_gradients.xlsx)
|
|
3067
|
+
|
|
3068
|
+
Demonstrates linear gradients inside cell backgrounds.
|
|
3069
|
+
|
|
3070
|
+
### Rendered Output (LibreOffice Calc)
|
|
3071
|
+
|
|
3072
|
+
<div><img src="../../test/visual/baselines/fill_gradients/page-1.png" width="100%" alt="Preview"/></div>
|
|
3073
|
+
|
|
3074
|
+
### DSL Code
|
|
3075
|
+
|
|
3076
|
+
```ruby
|
|
3077
|
+
# frozen_string_literal: true
|
|
3078
|
+
require "xlsxrb"
|
|
3079
|
+
output_path = ARGV[0] || "fill_gradients.xlsx"
|
|
3080
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3081
|
+
w.add_style("gradient") do |style|
|
|
3082
|
+
style.fill_gradient(type: "linear", degree: 45, stops: [
|
|
3083
|
+
{ position: 0, color: "FFFFFFFF" },
|
|
3084
|
+
{ position: 1, color: "FF4F81BD" }
|
|
3085
|
+
])
|
|
3086
|
+
end
|
|
3087
|
+
w.add_sheet("Gradients") do |s|
|
|
3088
|
+
s.set_column(0, width: 25)
|
|
3089
|
+
s.set_column(1, width: 25)
|
|
3090
|
+
s.add_row(["Normal Cell", "Gradient Cell"], styles: { 1 => "gradient" })
|
|
3091
|
+
end
|
|
3092
|
+
end
|
|
3093
|
+
|
|
3094
|
+
# 2. Read the generated sheet and print cell fill properties
|
|
3095
|
+
puts "=== Read Validation ==="
|
|
3096
|
+
workbook = Xlsxrb.read(output_path)
|
|
3097
|
+
sheet = workbook.sheets.first
|
|
3098
|
+
row = sheet.rows.first
|
|
3099
|
+
row.cells.each do |c|
|
|
3100
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
3101
|
+
fill = xf ? workbook.styles[:fills][xf[:fill_id]] : nil
|
|
3102
|
+
puts "Cell #{c.ref} ('#{c.value}'): fill pattern = #{fill&.[](:pattern).inspect}, fg_color = #{fill&.[](:fg_color).inspect}"
|
|
3103
|
+
end
|
|
3104
|
+
```
|
|
3105
|
+
|
|
3106
|
+
### Console Output
|
|
3107
|
+
|
|
3108
|
+
```text
|
|
3109
|
+
=== Read Validation ===
|
|
3110
|
+
Cell A1 ('Normal Cell'): fill pattern = nil, fg_color = nil
|
|
3111
|
+
Cell B1 ('Gradient Cell'): fill pattern = nil, fg_color = nil
|
|
3112
|
+
```
|
|
3113
|
+
|
|
3114
|
+
<hr/>
|
|
3115
|
+
|
|
3116
|
+
## Fill Patterns
|
|
3117
|
+
|
|
3118
|
+
[Download .xlsx](files/fill_patterns.xlsx)
|
|
3119
|
+
|
|
3120
|
+
Demonstrates standard pattern fills (darkGray, darkGrid) in cell backgrounds.
|
|
3121
|
+
|
|
3122
|
+
### Rendered Output (LibreOffice Calc)
|
|
3123
|
+
|
|
3124
|
+
<div><img src="../../test/visual/baselines/fill_patterns/page-1.png" width="100%" alt="Preview"/></div>
|
|
3125
|
+
|
|
3126
|
+
### DSL Code
|
|
3127
|
+
|
|
3128
|
+
```ruby
|
|
3129
|
+
# frozen_string_literal: true
|
|
3130
|
+
require "xlsxrb"
|
|
3131
|
+
output_path = ARGV[0] || "fill_patterns.xlsx"
|
|
3132
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3133
|
+
w.add_style("dark_gray") { |s| s.fill(pattern: "darkGray", fg_color: "FFC0C0C0", bg_color: "FFFFFFFF") }
|
|
3134
|
+
w.add_style("grid_fill") { |s| s.fill(pattern: "darkGrid", fg_color: "FFC0C0C0", bg_color: "FFFFFFFF") }
|
|
3135
|
+
w.add_sheet("Patterns") do |s|
|
|
3136
|
+
s.set_column(0, width: 25)
|
|
3137
|
+
s.set_column(1, width: 25)
|
|
3138
|
+
s.add_row(["Pattern", "Preview"])
|
|
3139
|
+
s.add_row(["Dark Gray", "Pattern Fill"], styles: { 1 => "dark_gray" })
|
|
3140
|
+
s.add_row(["Dark Grid", "Grid Fill"], styles: { 1 => "grid_fill" })
|
|
3141
|
+
end
|
|
3142
|
+
end
|
|
3143
|
+
|
|
3144
|
+
# 2. Read the generated sheet and print cell fill properties
|
|
3145
|
+
puts "=== Read Validation ==="
|
|
3146
|
+
workbook = Xlsxrb.read(output_path)
|
|
3147
|
+
sheet = workbook.sheets.first
|
|
3148
|
+
row = sheet.rows.first
|
|
3149
|
+
row.cells.each do |c|
|
|
3150
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
3151
|
+
fill = xf ? workbook.styles[:fills][xf[:fill_id]] : nil
|
|
3152
|
+
puts "Cell #{c.ref} ('#{c.value}'): fill pattern = #{fill&.[](:pattern).inspect}, fg_color = #{fill&.[](:fg_color).inspect}"
|
|
3153
|
+
end
|
|
3154
|
+
```
|
|
3155
|
+
|
|
3156
|
+
### Console Output
|
|
3157
|
+
|
|
3158
|
+
```text
|
|
3159
|
+
=== Read Validation ===
|
|
3160
|
+
Cell A1 ('Pattern'): fill pattern = nil, fg_color = nil
|
|
3161
|
+
Cell B1 ('Preview'): fill pattern = nil, fg_color = nil
|
|
3162
|
+
```
|
|
3163
|
+
|
|
3164
|
+
<hr/>
|
|
3165
|
+
|
|
3166
|
+
## Fill Solid Colors
|
|
3167
|
+
|
|
3168
|
+
[Download .xlsx](files/fill_solid_colors.xlsx)
|
|
3169
|
+
|
|
3170
|
+
Demonstrates solid cell background fill colors.
|
|
3171
|
+
|
|
3172
|
+
### Rendered Output (LibreOffice Calc)
|
|
3173
|
+
|
|
3174
|
+
<div><img src="../../test/visual/baselines/fill_solid_colors/page-1.png" width="100%" alt="Preview"/></div>
|
|
3175
|
+
|
|
3176
|
+
### DSL Code
|
|
3177
|
+
|
|
3178
|
+
```ruby
|
|
3179
|
+
# frozen_string_literal: true
|
|
3180
|
+
require "xlsxrb"
|
|
3181
|
+
output_path = ARGV[0] || "fill_solid_colors.xlsx"
|
|
3182
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3183
|
+
w.add_style("red_fill") { |s| s.fill_color("FFFFC7CE") }
|
|
3184
|
+
w.add_style("green_fill") { |s| s.fill_color("FFC6EFCE") }
|
|
3185
|
+
w.add_sheet("Fills") do |s|
|
|
3186
|
+
s.set_column(0, width: 25)
|
|
3187
|
+
s.set_column(1, width: 25)
|
|
3188
|
+
s.add_row(["Color", "Preview"])
|
|
3189
|
+
s.add_row(["Red", "Red Fill"], styles: { 1 => "red_fill" })
|
|
3190
|
+
s.add_row(["Green", "Green Fill"], styles: { 1 => "green_fill" })
|
|
3191
|
+
end
|
|
3192
|
+
end
|
|
3193
|
+
|
|
3194
|
+
# 2. Read the generated sheet and print cell fill properties
|
|
3195
|
+
puts "=== Read Validation ==="
|
|
3196
|
+
workbook = Xlsxrb.read(output_path)
|
|
3197
|
+
sheet = workbook.sheets.first
|
|
3198
|
+
row = sheet.rows.first
|
|
3199
|
+
row.cells.each do |c|
|
|
3200
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
3201
|
+
fill = xf ? workbook.styles[:fills][xf[:fill_id]] : nil
|
|
3202
|
+
puts "Cell #{c.ref} ('#{c.value}'): fill pattern = #{fill&.[](:pattern).inspect}, fg_color = #{fill&.[](:fg_color).inspect}"
|
|
3203
|
+
end
|
|
3204
|
+
```
|
|
3205
|
+
|
|
3206
|
+
### Console Output
|
|
3207
|
+
|
|
3208
|
+
```text
|
|
3209
|
+
=== Read Validation ===
|
|
3210
|
+
Cell A1 ('Color'): fill pattern = nil, fg_color = nil
|
|
3211
|
+
Cell B1 ('Preview'): fill pattern = nil, fg_color = nil
|
|
3212
|
+
```
|
|
3213
|
+
|
|
3214
|
+
<hr/>
|
|
3215
|
+
|
|
3216
|
+
## Fonts
|
|
3217
|
+
|
|
3218
|
+
[Download .xlsx](files/fonts.xlsx)
|
|
3219
|
+
|
|
3220
|
+
Demonstrates cell fonts properties (Arial, Georgia, Courier New, Times New Roman, Tahoma, sizes 10pt/16pt/24pt, red/green/blue colors, bold/italic/underline/double underline/strike-through styles, superscript/subscript).
|
|
3221
|
+
|
|
3222
|
+
### Rendered Output (LibreOffice Calc)
|
|
3223
|
+
|
|
3224
|
+
<div><img src="../../test/visual/baselines/fonts/page-1.png" width="100%" alt="Preview"/></div>
|
|
3225
|
+
|
|
3226
|
+
### DSL Code
|
|
3227
|
+
|
|
3228
|
+
```ruby
|
|
3229
|
+
# frozen_string_literal: true
|
|
3230
|
+
|
|
3231
|
+
require "xlsxrb"
|
|
3232
|
+
|
|
3233
|
+
output_path = ARGV[0] || "fonts.xlsx"
|
|
3234
|
+
|
|
3235
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3236
|
+
# Font Families
|
|
3237
|
+
w.add_style("f_arial") { |s| s.font_name("Arial") }
|
|
3238
|
+
w.add_style("f_times") { |s| s.font_name("Times New Roman") }
|
|
3239
|
+
w.add_style("f_courier") { |s| s.font_name("Courier New") }
|
|
3240
|
+
w.add_style("f_georgia") { |s| s.font_name("Georgia") }
|
|
3241
|
+
w.add_style("f_tahoma") { |s| s.font_name("Tahoma") }
|
|
3242
|
+
|
|
3243
|
+
# Font Sizes
|
|
3244
|
+
w.add_style("sz_10") { |s| s.size(10) }
|
|
3245
|
+
w.add_style("sz_16") { |s| s.size(16) }
|
|
3246
|
+
w.add_style("sz_24") { |s| s.size(24) }
|
|
3247
|
+
|
|
3248
|
+
# Font Colors
|
|
3249
|
+
w.add_style("c_red") { |s| s.font_color("FFC00000") }
|
|
3250
|
+
w.add_style("c_green") { |s| s.font_color("FF008000") }
|
|
3251
|
+
w.add_style("c_blue") { |s| s.font_color("FF0000FF") }
|
|
3252
|
+
|
|
3253
|
+
# Font Styles
|
|
3254
|
+
w.add_style("st_bold") { |s| s.bold }
|
|
3255
|
+
w.add_style("st_italic") { |s| s.italic }
|
|
3256
|
+
w.add_style("st_underline") { |s| s.underline("single") }
|
|
3257
|
+
w.add_style("st_double_u") { |s| s.underline("double") }
|
|
3258
|
+
w.add_style("st_strike") { |s| s.strike }
|
|
3259
|
+
|
|
3260
|
+
# Vertical Alignments (Superscript/Subscript)
|
|
3261
|
+
w.add_style("v_super") { |s| s.vert_align("superscript") }
|
|
3262
|
+
w.add_style("v_sub") { |s| s.vert_align("subscript") }
|
|
3263
|
+
|
|
3264
|
+
w.add_sheet("Fonts") do |s|
|
|
3265
|
+
s.set_column(0, width: 25)
|
|
3266
|
+
s.set_column(1, width: 25)
|
|
3267
|
+
s.set_print_option(:grid_lines, true)
|
|
3268
|
+
|
|
3269
|
+
s.add_row(["Font Feature", "Text Preview"])
|
|
3270
|
+
s.add_row(["Family: Arial", "Arial Text"], styles: { 1 => "f_arial" })
|
|
3271
|
+
s.add_row(["Family: Times New Roman", "Times New Roman"], styles: { 1 => "f_times" })
|
|
3272
|
+
s.add_row(["Family: Courier New", "Courier New Text"], styles: { 1 => "f_courier" })
|
|
3273
|
+
s.add_row(["Family: Georgia", "Georgia Text"], styles: { 1 => "f_georgia" })
|
|
3274
|
+
s.add_row(["Family: Tahoma", "Tahoma Text"], styles: { 1 => "f_tahoma" })
|
|
3275
|
+
|
|
3276
|
+
s.add_row(["Size: 10pt", "10pt Font Size"], styles: { 1 => "sz_10" })
|
|
3277
|
+
s.add_row(["Size: 16pt", "16pt Font Size"], styles: { 1 => "sz_16" })
|
|
3278
|
+
s.add_row(["Size: 24pt", "24pt Font Size"], styles: { 1 => "sz_24" })
|
|
3279
|
+
|
|
3280
|
+
s.add_row(["Color: Red", "Red Text"], styles: { 1 => "c_red" })
|
|
3281
|
+
s.add_row(["Color: Green", "Green Text"], styles: { 1 => "c_green" })
|
|
3282
|
+
s.add_row(["Color: Blue", "Blue Text"], styles: { 1 => "c_blue" })
|
|
3283
|
+
|
|
3284
|
+
s.add_row(["Style: Bold", "Bold Text"], styles: { 1 => "st_bold" })
|
|
3285
|
+
s.add_row(["Style: Italic", "Italic Text"], styles: { 1 => "st_italic" })
|
|
3286
|
+
s.add_row(["Style: Underline", "Underline Text"], styles: { 1 => "st_underline" })
|
|
3287
|
+
s.add_row(["Style: Double Underline", "Double Underline"], styles: { 1 => "st_double_u" })
|
|
3288
|
+
s.add_row(["Style: Strike-through", "Strike-through Text"], styles: { 1 => "st_strike" })
|
|
3289
|
+
|
|
3290
|
+
s.add_row(["Align: Superscript", "x2 (2 is super)"], styles: { 1 => "v_super" })
|
|
3291
|
+
s.add_row(["Align: Subscript", "H2O (2 is sub)"], styles: { 1 => "v_sub" })
|
|
3292
|
+
end
|
|
3293
|
+
end
|
|
3294
|
+
|
|
3295
|
+
# Read check
|
|
3296
|
+
puts "=== Read Validation ==="
|
|
3297
|
+
workbook = Xlsxrb.read(output_path)
|
|
3298
|
+
sheet = workbook.sheets.first
|
|
3299
|
+
sheet.rows.each do |row|
|
|
3300
|
+
row_cells = row.cells.map do |c|
|
|
3301
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
3302
|
+
font_id = xf ? xf[:font_id] : 0
|
|
3303
|
+
"#{c.ref}: #{c.value.inspect} (font_id: #{font_id})"
|
|
3304
|
+
end
|
|
3305
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
3306
|
+
end
|
|
3307
|
+
```
|
|
3308
|
+
|
|
3309
|
+
### Console Output
|
|
3310
|
+
|
|
3311
|
+
```text
|
|
3312
|
+
=== Read Validation ===
|
|
3313
|
+
Row 0: A1: "Font Feature" (font_id: 0), B1: "Text Preview" (font_id: 0)
|
|
3314
|
+
Row 1: A2: "Family: Arial" (font_id: 0), B2: "Arial Text" (font_id: 1)
|
|
3315
|
+
Row 2: A3: "Family: Times New Roman" (font_id: 0), B3: "Times New Roman" (font_id: 2)
|
|
3316
|
+
Row 3: A4: "Family: Courier New" (font_id: 0), B4: "Courier New Text" (font_id: 3)
|
|
3317
|
+
Row 4: A5: "Family: Georgia" (font_id: 0), B5: "Georgia Text" (font_id: 4)
|
|
3318
|
+
Row 5: A6: "Family: Tahoma" (font_id: 0), B6: "Tahoma Text" (font_id: 5)
|
|
3319
|
+
Row 6: A7: "Size: 10pt" (font_id: 0), B7: "10pt Font Size" (font_id: 6)
|
|
3320
|
+
Row 7: A8: "Size: 16pt" (font_id: 0), B8: "16pt Font Size" (font_id: 7)
|
|
3321
|
+
Row 8: A9: "Size: 24pt" (font_id: 0), B9: "24pt Font Size" (font_id: 8)
|
|
3322
|
+
Row 9: A10: "Color: Red" (font_id: 0), B10: "Red Text" (font_id: 9)
|
|
3323
|
+
Row 10: A11: "Color: Green" (font_id: 0), B11: "Green Text" (font_id: 10)
|
|
3324
|
+
Row 11: A12: "Color: Blue" (font_id: 0), B12: "Blue Text" (font_id: 11)
|
|
3325
|
+
Row 12: A13: "Style: Bold" (font_id: 0), B13: "Bold Text" (font_id: 12)
|
|
3326
|
+
Row 13: A14: "Style: Italic" (font_id: 0), B14: "Italic Text" (font_id: 13)
|
|
3327
|
+
Row 14: A15: "Style: Underline" (font_id: 0), B15: "Underline Text" (font_id: 14)
|
|
3328
|
+
Row 15: A16: "Style: Double Underline" (font_id: 0), B16: "Double Underline" (font_id: 15)
|
|
3329
|
+
Row 16: A17: "Style: Strike-through" (font_id: 0), B17: "Strike-through Text" (font_id: 16)
|
|
3330
|
+
Row 17: A18: "Align: Superscript" (font_id: 0), B18: "x2 (2 is super)" (font_id: 17)
|
|
3331
|
+
Row 18: A19: "Align: Subscript" (font_id: 0), B19: "H2O (2 is sub)" (font_id: 18)
|
|
3332
|
+
```
|
|
3333
|
+
|
|
3334
|
+
<hr/>
|
|
3335
|
+
|
|
3336
|
+
## Interactive Autofilter
|
|
3337
|
+
|
|
3338
|
+
[Download .xlsx](files/interactive_autofilter.xlsx)
|
|
3339
|
+
|
|
3340
|
+
> [!TIP]
|
|
3341
|
+
> **Interactive Feature**: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please **[Download the .xlsx file](files/interactive_autofilter.xlsx)** and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!
|
|
3342
|
+
|
|
3343
|
+
Demonstrates enabling auto-filter sorting headers on tables. Download the sheet to interactively filter and sort columns.
|
|
3344
|
+
|
|
3345
|
+
### Rendered Output (LibreOffice Calc)
|
|
3346
|
+
|
|
3347
|
+
<div><img src="../../test/visual/baselines/interactive_autofilter/page-1.png" width="100%" alt="Preview"/></div>
|
|
3348
|
+
|
|
3349
|
+
<div><img src="../../test/visual/support/illustrations/interactive_autofilter_page-2.png" width="100%" alt="Preview"/></div>
|
|
3350
|
+
|
|
3351
|
+
### DSL Code
|
|
3352
|
+
|
|
3353
|
+
```ruby
|
|
3354
|
+
# frozen_string_literal: true
|
|
3355
|
+
require "xlsxrb"
|
|
3356
|
+
output_path = ARGV[0] || "interactive_autofilter.xlsx"
|
|
3357
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3358
|
+
w.add_sheet("Filter") do |s|
|
|
3359
|
+
s.set_column(0, width: 25)
|
|
3360
|
+
s.set_column(1, width: 25)
|
|
3361
|
+
s.add_row(["Name", "Department"])
|
|
3362
|
+
s.add_row(["Alice", "HR"])
|
|
3363
|
+
s.add_row(["Bob", "Eng"])
|
|
3364
|
+
s.set_auto_filter("A1:B3")
|
|
3365
|
+
end
|
|
3366
|
+
w.add_defined_name("_xlnm._FilterDatabase", "Filter!$A$1:$B$3", sheet: "Filter", hidden: true)
|
|
3367
|
+
end
|
|
3368
|
+
|
|
3369
|
+
# 2. Read the generated sheet and print cell values
|
|
3370
|
+
puts "=== Read Validation ==="
|
|
3371
|
+
workbook = Xlsxrb.read(output_path)
|
|
3372
|
+
sheet = workbook.sheets.first
|
|
3373
|
+
sheet.rows.first(5).each do |row|
|
|
3374
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
3375
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
3376
|
+
end
|
|
3377
|
+
```
|
|
3378
|
+
|
|
3379
|
+
### Console Output
|
|
3380
|
+
|
|
3381
|
+
```text
|
|
3382
|
+
=== Read Validation ===
|
|
3383
|
+
Row 0: A1: "Name", B1: "Department"
|
|
3384
|
+
Row 1: A2: "Alice", B2: "HR"
|
|
3385
|
+
Row 2: A3: "Bob", B3: "Eng"
|
|
3386
|
+
```
|
|
3387
|
+
|
|
3388
|
+
<hr/>
|
|
3389
|
+
|
|
3390
|
+
## Interactive Comments
|
|
3391
|
+
|
|
3392
|
+
[Download .xlsx](files/interactive_comments.xlsx)
|
|
3393
|
+
|
|
3394
|
+
> [!TIP]
|
|
3395
|
+
> **Interactive Feature**: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please **[Download the .xlsx file](files/interactive_comments.xlsx)** and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!
|
|
3396
|
+
|
|
3397
|
+
Demonstrates cell pop-up comments. Open the sheet in Excel and hover your mouse over the cell with the red triangle to view the comment.
|
|
3398
|
+
|
|
3399
|
+
### Rendered Output (LibreOffice Calc)
|
|
3400
|
+
|
|
3401
|
+
<div><img src="../../test/visual/baselines/interactive_comments/page-1.png" width="100%" alt="Preview"/></div>
|
|
3402
|
+
|
|
3403
|
+
<div><img src="../../test/visual/support/illustrations/interactive_comments_page-2.png" width="100%" alt="Preview"/></div>
|
|
3404
|
+
|
|
3405
|
+
### DSL Code
|
|
3406
|
+
|
|
3407
|
+
```ruby
|
|
3408
|
+
# frozen_string_literal: true
|
|
3409
|
+
require "xlsxrb"
|
|
3410
|
+
output_path = ARGV[0] || "interactive_comments.xlsx"
|
|
3411
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3412
|
+
w.add_sheet("Comments") do |s|
|
|
3413
|
+
s.set_column(0, width: 25)
|
|
3414
|
+
s.set_column(1, width: 25)
|
|
3415
|
+
s.add_row(["Item A", "Item B"])
|
|
3416
|
+
s.add_comment("A1", "This is an important comment.", author: "System")
|
|
3417
|
+
end
|
|
3418
|
+
end
|
|
3419
|
+
|
|
3420
|
+
# 2. Read the generated sheet and print cell values
|
|
3421
|
+
puts "=== Read Validation ==="
|
|
3422
|
+
workbook = Xlsxrb.read(output_path)
|
|
3423
|
+
sheet = workbook.sheets.first
|
|
3424
|
+
sheet.rows.first(5).each do |row|
|
|
3425
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
3426
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
3427
|
+
end
|
|
3428
|
+
```
|
|
3429
|
+
|
|
3430
|
+
### Console Output
|
|
3431
|
+
|
|
3432
|
+
```text
|
|
3433
|
+
=== Read Validation ===
|
|
3434
|
+
Row 0: A1: "Item A", B1: "Item B"
|
|
3435
|
+
```
|
|
3436
|
+
|
|
3437
|
+
<hr/>
|
|
3438
|
+
|
|
3439
|
+
## Interactive Validation Custom
|
|
3440
|
+
|
|
3441
|
+
[Download .xlsx](files/interactive_validation_custom.xlsx)
|
|
3442
|
+
|
|
3443
|
+
> [!TIP]
|
|
3444
|
+
> **Interactive Feature**: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please **[Download the .xlsx file](files/interactive_validation_custom.xlsx)** and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!
|
|
3445
|
+
|
|
3446
|
+
Demonstrates interactive custom formula validation rules.
|
|
3447
|
+
|
|
3448
|
+
### Rendered Output (LibreOffice Calc)
|
|
3449
|
+
|
|
3450
|
+
<div><img src="../../test/visual/baselines/interactive_validation_custom/page-1.png" width="100%" alt="Preview"/></div>
|
|
3451
|
+
|
|
3452
|
+
<div><img src="../../test/visual/support/illustrations/interactive_validation_custom_page-2.png" width="100%" alt="Preview"/></div>
|
|
3453
|
+
|
|
3454
|
+
### DSL Code
|
|
3455
|
+
|
|
3456
|
+
```ruby
|
|
3457
|
+
# frozen_string_literal: true
|
|
3458
|
+
require "xlsxrb"
|
|
3459
|
+
output_path = ARGV[0] || "interactive_validation_custom.xlsx"
|
|
3460
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3461
|
+
w.add_sheet("Custom Rule") do |s|
|
|
3462
|
+
s.set_column(0, width: 25)
|
|
3463
|
+
s.set_column(1, width: 25)
|
|
3464
|
+
s.add_row(["Number A", "Number B (Must be larger A)"])
|
|
3465
|
+
s.add_row([10, ""])
|
|
3466
|
+
s.add_data_validation("B2", type: "custom", formula1: "B2>A2", show_error_message: true, error_title: "Validation Error", error: "Number B must be greater than Number A")
|
|
3467
|
+
end
|
|
3468
|
+
end
|
|
3469
|
+
|
|
3470
|
+
# 2. Read the generated sheet and print data validations
|
|
3471
|
+
puts "=== Read Validation ==="
|
|
3472
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
3473
|
+
workbook = Xlsxrb.read(output_path)
|
|
3474
|
+
sheet = workbook.sheets.first
|
|
3475
|
+
validations = reader.data_validations(sheet: sheet.name)
|
|
3476
|
+
validations.each do |v|
|
|
3477
|
+
puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
|
|
3478
|
+
end
|
|
3479
|
+
```
|
|
3480
|
+
|
|
3481
|
+
### Console Output
|
|
3482
|
+
|
|
3483
|
+
```text
|
|
3484
|
+
=== Read Validation ===
|
|
3485
|
+
Validation range B2: type=custom, formula1=B2>A2, formula2=
|
|
3486
|
+
```
|
|
3487
|
+
|
|
3488
|
+
<hr/>
|
|
3489
|
+
|
|
3490
|
+
## Interactive Validation Date
|
|
3491
|
+
|
|
3492
|
+
[Download .xlsx](files/interactive_validation_date.xlsx)
|
|
3493
|
+
|
|
3494
|
+
> [!TIP]
|
|
3495
|
+
> **Interactive Feature**: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please **[Download the .xlsx file](files/interactive_validation_date.xlsx)** and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!
|
|
3496
|
+
|
|
3497
|
+
Demonstrates interactive date range constraints validation rules.
|
|
3498
|
+
|
|
3499
|
+
### Rendered Output (LibreOffice Calc)
|
|
3500
|
+
|
|
3501
|
+
<div><img src="../../test/visual/baselines/interactive_validation_date/page-1.png" width="100%" alt="Preview"/></div>
|
|
3502
|
+
|
|
3503
|
+
<div><img src="../../test/visual/support/illustrations/interactive_validation_date_page-2.png" width="100%" alt="Preview"/></div>
|
|
3504
|
+
|
|
3505
|
+
### DSL Code
|
|
3506
|
+
|
|
3507
|
+
```ruby
|
|
3508
|
+
# frozen_string_literal: true
|
|
3509
|
+
require "xlsxrb"
|
|
3510
|
+
output_path = ARGV[0] || "interactive_validation_date.xlsx"
|
|
3511
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3512
|
+
w.add_sheet("Date Validation") do |s|
|
|
3513
|
+
s.set_column(0, width: 25)
|
|
3514
|
+
s.set_column(1, width: 25)
|
|
3515
|
+
s.add_row(["Date Range", "Enter Date (2026):"])
|
|
3516
|
+
s.add_data_validation("B2", type: "date", operator: "between", formula1: "Date(2026,1,1)", formula2: "Date(2026,12,31)", show_error_message: true, error_title: "Invalid Date", error: "Must be a date in 2026")
|
|
3517
|
+
end
|
|
3518
|
+
end
|
|
3519
|
+
|
|
3520
|
+
# 2. Read the generated sheet and print data validations
|
|
3521
|
+
puts "=== Read Validation ==="
|
|
3522
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
3523
|
+
workbook = Xlsxrb.read(output_path)
|
|
3524
|
+
sheet = workbook.sheets.first
|
|
3525
|
+
validations = reader.data_validations(sheet: sheet.name)
|
|
3526
|
+
validations.each do |v|
|
|
3527
|
+
puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
|
|
3528
|
+
end
|
|
3529
|
+
```
|
|
3530
|
+
|
|
3531
|
+
### Console Output
|
|
3532
|
+
|
|
3533
|
+
```text
|
|
3534
|
+
=== Read Validation ===
|
|
3535
|
+
Validation range B2: type=date, formula1=Date(2026,1,1), formula2=Date(2026,12,31)
|
|
3536
|
+
```
|
|
3537
|
+
|
|
3538
|
+
<hr/>
|
|
3539
|
+
|
|
3540
|
+
## Interactive Validation List
|
|
3541
|
+
|
|
3542
|
+
[Download .xlsx](files/interactive_validation_list.xlsx)
|
|
3543
|
+
|
|
3544
|
+
> [!TIP]
|
|
3545
|
+
> **Interactive Feature**: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please **[Download the .xlsx file](files/interactive_validation_list.xlsx)** and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!
|
|
3546
|
+
|
|
3547
|
+
Demonstrates dropdown list data validations. Open the sheet in Excel and select cell A1/A2 to see the dropdown list in action.
|
|
3548
|
+
|
|
3549
|
+
### Rendered Output (LibreOffice Calc)
|
|
3550
|
+
|
|
3551
|
+
<div><img src="../../test/visual/baselines/interactive_validation_list/page-1.png" width="100%" alt="Preview"/></div>
|
|
3552
|
+
|
|
3553
|
+
<div><img src="../../test/visual/support/illustrations/interactive_validation_list_page-2.png" width="100%" alt="Preview"/></div>
|
|
3554
|
+
|
|
3555
|
+
### DSL Code
|
|
3556
|
+
|
|
3557
|
+
```ruby
|
|
3558
|
+
# frozen_string_literal: true
|
|
3559
|
+
require "xlsxrb"
|
|
3560
|
+
output_path = ARGV[0] || "interactive_validation_list.xlsx"
|
|
3561
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3562
|
+
w.add_sheet("List Validation") do |s|
|
|
3563
|
+
s.set_column(0, width: 25)
|
|
3564
|
+
s.set_column(1, width: 25)
|
|
3565
|
+
s.add_row(["Department", "Select:"])
|
|
3566
|
+
s.add_data_validation("B2", type: "list", formula1: '"HR,Sales,Engineering"')
|
|
3567
|
+
end
|
|
3568
|
+
end
|
|
3569
|
+
|
|
3570
|
+
# 2. Read the generated sheet and print data validations
|
|
3571
|
+
puts "=== Read Validation ==="
|
|
3572
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
3573
|
+
workbook = Xlsxrb.read(output_path)
|
|
3574
|
+
sheet = workbook.sheets.first
|
|
3575
|
+
validations = reader.data_validations(sheet: sheet.name)
|
|
3576
|
+
validations.each do |v|
|
|
3577
|
+
puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
|
|
3578
|
+
end
|
|
3579
|
+
```
|
|
3580
|
+
|
|
3581
|
+
### Console Output
|
|
3582
|
+
|
|
3583
|
+
```text
|
|
3584
|
+
=== Read Validation ===
|
|
3585
|
+
Validation range B2: type=list, formula1="HR,Sales,Engineering", formula2=
|
|
3586
|
+
```
|
|
3587
|
+
|
|
3588
|
+
<hr/>
|
|
3589
|
+
|
|
3590
|
+
## Interactive Validation Range
|
|
3591
|
+
|
|
3592
|
+
[Download .xlsx](files/interactive_validation_range.xlsx)
|
|
3593
|
+
|
|
3594
|
+
> [!TIP]
|
|
3595
|
+
> **Interactive Feature**: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please **[Download the .xlsx file](files/interactive_validation_range.xlsx)** and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!
|
|
3596
|
+
|
|
3597
|
+
Demonstrates range constraints for whole number validations. Open the sheet in Excel and try entering a value outside 10-100 to trigger the warning.
|
|
3598
|
+
|
|
3599
|
+
### Rendered Output (LibreOffice Calc)
|
|
3600
|
+
|
|
3601
|
+
<div><img src="../../test/visual/baselines/interactive_validation_range/page-1.png" width="100%" alt="Preview"/></div>
|
|
3602
|
+
|
|
3603
|
+
<div><img src="../../test/visual/support/illustrations/interactive_validation_range_page-2.png" width="100%" alt="Preview"/></div>
|
|
3604
|
+
|
|
3605
|
+
### DSL Code
|
|
3606
|
+
|
|
3607
|
+
```ruby
|
|
3608
|
+
# frozen_string_literal: true
|
|
3609
|
+
require "xlsxrb"
|
|
3610
|
+
output_path = ARGV[0] || "interactive_validation_range.xlsx"
|
|
3611
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3612
|
+
w.add_sheet("Range Validation") do |s|
|
|
3613
|
+
s.set_column(0, width: 25)
|
|
3614
|
+
s.set_column(1, width: 25)
|
|
3615
|
+
s.add_row(["Age", "Enter (18-99):"])
|
|
3616
|
+
s.add_data_validation("B2", type: "whole", operator: "between", formula1: "18", formula2: "99", show_error_message: true, error_title: "Invalid Age", error: "Age must be between 18 and 99!")
|
|
3617
|
+
end
|
|
3618
|
+
end
|
|
3619
|
+
|
|
3620
|
+
# 2. Read the generated sheet and print data validations
|
|
3621
|
+
puts "=== Read Validation ==="
|
|
3622
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
3623
|
+
workbook = Xlsxrb.read(output_path)
|
|
3624
|
+
sheet = workbook.sheets.first
|
|
3625
|
+
validations = reader.data_validations(sheet: sheet.name)
|
|
3626
|
+
validations.each do |v|
|
|
3627
|
+
puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
|
|
3628
|
+
end
|
|
3629
|
+
```
|
|
3630
|
+
|
|
3631
|
+
### Console Output
|
|
3632
|
+
|
|
3633
|
+
```text
|
|
3634
|
+
=== Read Validation ===
|
|
3635
|
+
Validation range B2: type=whole, formula1=18, formula2=99
|
|
3636
|
+
```
|
|
3637
|
+
|
|
3638
|
+
<hr/>
|
|
3639
|
+
|
|
3640
|
+
## Interactive Validation Text Length
|
|
3641
|
+
|
|
3642
|
+
[Download .xlsx](files/interactive_validation_text_length.xlsx)
|
|
3643
|
+
|
|
3644
|
+
> [!TIP]
|
|
3645
|
+
> **Interactive Feature**: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please **[Download the .xlsx file](files/interactive_validation_text_length.xlsx)** and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!
|
|
3646
|
+
|
|
3647
|
+
Demonstrates interactive text length validation rules.
|
|
3648
|
+
|
|
3649
|
+
### Rendered Output (LibreOffice Calc)
|
|
3650
|
+
|
|
3651
|
+
<div><img src="../../test/visual/baselines/interactive_validation_text_length/page-1.png" width="100%" alt="Preview"/></div>
|
|
3652
|
+
|
|
3653
|
+
<div><img src="../../test/visual/support/illustrations/interactive_validation_text_length_page-2.png" width="100%" alt="Preview"/></div>
|
|
3654
|
+
|
|
3655
|
+
### DSL Code
|
|
3656
|
+
|
|
3657
|
+
```ruby
|
|
3658
|
+
# frozen_string_literal: true
|
|
3659
|
+
require "xlsxrb"
|
|
3660
|
+
output_path = ARGV[0] || "interactive_validation_text_length.xlsx"
|
|
3661
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3662
|
+
w.add_sheet("Text Length") do |s|
|
|
3663
|
+
s.set_column(0, width: 25)
|
|
3664
|
+
s.set_column(1, width: 25)
|
|
3665
|
+
s.add_row(["Username", "Enter (< 10 chars):"])
|
|
3666
|
+
s.add_data_validation("B2", type: "textLength", operator: "lessThan", formula1: "10", show_error_message: true, error_title: "Too Long", error: "Username must be under 10 characters")
|
|
3667
|
+
end
|
|
3668
|
+
end
|
|
3669
|
+
|
|
3670
|
+
# 2. Read the generated sheet and print data validations
|
|
3671
|
+
puts "=== Read Validation ==="
|
|
3672
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
3673
|
+
workbook = Xlsxrb.read(output_path)
|
|
3674
|
+
sheet = workbook.sheets.first
|
|
3675
|
+
validations = reader.data_validations(sheet: sheet.name)
|
|
3676
|
+
validations.each do |v|
|
|
3677
|
+
puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
|
|
3678
|
+
end
|
|
3679
|
+
```
|
|
3680
|
+
|
|
3681
|
+
### Console Output
|
|
3682
|
+
|
|
3683
|
+
```text
|
|
3684
|
+
=== Read Validation ===
|
|
3685
|
+
Validation range B2: type=textLength, formula1=10, formula2=
|
|
3686
|
+
```
|
|
3687
|
+
|
|
3688
|
+
<hr/>
|
|
3689
|
+
|
|
3690
|
+
## Interactive Validation Time
|
|
3691
|
+
|
|
3692
|
+
[Download .xlsx](files/interactive_validation_time.xlsx)
|
|
3693
|
+
|
|
3694
|
+
> [!TIP]
|
|
3695
|
+
> **Interactive Feature**: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please **[Download the .xlsx file](files/interactive_validation_time.xlsx)** and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!
|
|
3696
|
+
|
|
3697
|
+
Demonstrates interactive time validation rules.
|
|
3698
|
+
|
|
3699
|
+
### Rendered Output (LibreOffice Calc)
|
|
3700
|
+
|
|
3701
|
+
<div><img src="../../test/visual/baselines/interactive_validation_time/page-1.png" width="100%" alt="Preview"/></div>
|
|
3702
|
+
|
|
3703
|
+
<div><img src="../../test/visual/support/illustrations/interactive_validation_time_page-2.png" width="100%" alt="Preview"/></div>
|
|
3704
|
+
|
|
3705
|
+
### DSL Code
|
|
3706
|
+
|
|
3707
|
+
```ruby
|
|
3708
|
+
# frozen_string_literal: true
|
|
3709
|
+
require "xlsxrb"
|
|
3710
|
+
output_path = ARGV[0] || "interactive_validation_time.xlsx"
|
|
3711
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3712
|
+
w.add_sheet("Time Validation") do |s|
|
|
3713
|
+
s.set_column(0, width: 25)
|
|
3714
|
+
s.set_column(1, width: 25)
|
|
3715
|
+
s.add_row(["Schedule", "Enter Time (after 08:00):"])
|
|
3716
|
+
s.add_data_validation("B2", type: "time", operator: "greaterThan", formula1: "0.33333", show_error_message: true, error_title: "Too Early", error: "Time must be after 08:00 AM")
|
|
3717
|
+
end
|
|
3718
|
+
end
|
|
3719
|
+
|
|
3720
|
+
# 2. Read the generated sheet and print data validations
|
|
3721
|
+
puts "=== Read Validation ==="
|
|
3722
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
3723
|
+
workbook = Xlsxrb.read(output_path)
|
|
3724
|
+
sheet = workbook.sheets.first
|
|
3725
|
+
validations = reader.data_validations(sheet: sheet.name)
|
|
3726
|
+
validations.each do |v|
|
|
3727
|
+
puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
|
|
3728
|
+
end
|
|
3729
|
+
```
|
|
3730
|
+
|
|
3731
|
+
### Console Output
|
|
3732
|
+
|
|
3733
|
+
```text
|
|
3734
|
+
=== Read Validation ===
|
|
3735
|
+
Validation range B2: type=time, formula1=0.33333, formula2=
|
|
3736
|
+
```
|
|
3737
|
+
|
|
3738
|
+
<hr/>
|
|
3739
|
+
|
|
3740
|
+
## Japanese Text
|
|
3741
|
+
|
|
3742
|
+
[Download .xlsx](files/japanese_text.xlsx)
|
|
3743
|
+
|
|
3744
|
+
Demonstrates writing multi-byte Japanese text and setting appropriate Japanese font names (e.g., Noto Sans CJK JP).
|
|
3745
|
+
|
|
3746
|
+
### Rendered Output (LibreOffice Calc)
|
|
3747
|
+
|
|
3748
|
+
<div><img src="../../test/visual/baselines/japanese_text/page-1.png" width="100%" alt="Preview"/></div>
|
|
3749
|
+
|
|
3750
|
+
### DSL Code
|
|
3751
|
+
|
|
3752
|
+
```ruby
|
|
3753
|
+
# frozen_string_literal: true
|
|
3754
|
+
|
|
3755
|
+
require "xlsxrb"
|
|
3756
|
+
|
|
3757
|
+
output_path = ARGV[0] || "japanese_text.xlsx"
|
|
3758
|
+
|
|
3759
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3760
|
+
w.add_style("ja_font") do |style|
|
|
3761
|
+
style.font_name("Noto Sans CJK JP").size(12)
|
|
3762
|
+
end
|
|
3763
|
+
|
|
3764
|
+
w.add_sheet("Japanese") do |s|
|
|
3765
|
+
s.set_column(0, width: 25)
|
|
3766
|
+
s.set_column(1, width: 25)
|
|
3767
|
+
s.add_row(["日本語ラベル", "値"], styles: { 0 => "ja_font", 1 => "ja_font" })
|
|
3768
|
+
s.add_row(["売上", 12500], styles: { 0 => "ja_font" })
|
|
3769
|
+
end
|
|
3770
|
+
end
|
|
3771
|
+
|
|
3772
|
+
# 2. Read the generated sheet and print parsed cell values and Ruby classes
|
|
3773
|
+
puts "=== Read Validation ==="
|
|
3774
|
+
workbook = Xlsxrb.read(output_path)
|
|
3775
|
+
sheet = workbook.sheets.first
|
|
3776
|
+
sheet.rows.each do |row|
|
|
3777
|
+
row_cells = row.cells.map do |c|
|
|
3778
|
+
"#{c.ref}: #{c.value.inspect} (#{c.value.class})"
|
|
3779
|
+
end
|
|
3780
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
3781
|
+
end
|
|
3782
|
+
```
|
|
3783
|
+
|
|
3784
|
+
### Console Output
|
|
3785
|
+
|
|
3786
|
+
```text
|
|
3787
|
+
=== Read Validation ===
|
|
3788
|
+
Row 0: A1: "日本語ラベル" (String), B1: "値" (String)
|
|
3789
|
+
Row 1: A2: "売上" (String), B2: 12500 (Integer)
|
|
3790
|
+
```
|
|
3791
|
+
|
|
3792
|
+
<hr/>
|
|
3793
|
+
|
|
3794
|
+
## Merge Freeze
|
|
3795
|
+
|
|
3796
|
+
[Download .xlsx](files/merge_freeze.xlsx)
|
|
3797
|
+
|
|
3798
|
+
Demonstrates merging a cell range into a single cell, and freezing the top rows of a sheet.
|
|
3799
|
+
|
|
3800
|
+
### Rendered Output (LibreOffice Calc)
|
|
3801
|
+
|
|
3802
|
+
<div><img src="../../test/visual/baselines/merge_freeze/page-1.png" width="100%" alt="Preview"/></div>
|
|
3803
|
+
|
|
3804
|
+
### DSL Code
|
|
3805
|
+
|
|
3806
|
+
```ruby
|
|
3807
|
+
# frozen_string_literal: true
|
|
3808
|
+
|
|
3809
|
+
require "xlsxrb"
|
|
3810
|
+
|
|
3811
|
+
output_path = ARGV[0] || "merge_freeze.xlsx"
|
|
3812
|
+
|
|
3813
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3814
|
+
w.add_style("title") { |style| style.border_all(style: "thin", color: "FF000000").align_horizontal("center") }
|
|
3815
|
+
w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
|
|
3816
|
+
w.add_sheet("Merge & Freeze") do |s|
|
|
3817
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
3818
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
3819
|
+
s.set_column(0, width: 25)
|
|
3820
|
+
s.set_column(1, width: 25)
|
|
3821
|
+
s.set_column(2, width: 25)
|
|
3822
|
+
s.add_row(["Merged Title Row", nil, nil], styles: ["title", "title", "title"])
|
|
3823
|
+
s.add_row(["Header A", "Header B", "Header C"], styles: ["border", "border", "border"])
|
|
3824
|
+
s.add_row(["Row 1 Col A", "Row 1 Col B", "Row 1 Col C"], styles: ["border", "border", "border"])
|
|
3825
|
+
s.add_row(["Row 2 Col A", "Row 2 Col B", "Row 2 Col C"], styles: ["border", "border", "border"])
|
|
3826
|
+
|
|
3827
|
+
s.merge_cells("A1:C1")
|
|
3828
|
+
s.set_freeze_pane(row: 2, col: 0)
|
|
3829
|
+
end
|
|
3830
|
+
end
|
|
3831
|
+
|
|
3832
|
+
# 2. Read the generated sheet and print cell values
|
|
3833
|
+
puts "=== Read Validation ==="
|
|
3834
|
+
workbook = Xlsxrb.read(output_path)
|
|
3835
|
+
sheet = workbook.sheets.first
|
|
3836
|
+
sheet.rows.first(5).each do |row|
|
|
3837
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
3838
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
3839
|
+
end
|
|
3840
|
+
```
|
|
3841
|
+
|
|
3842
|
+
### Console Output
|
|
3843
|
+
|
|
3844
|
+
```text
|
|
3845
|
+
=== Read Validation ===
|
|
3846
|
+
Row 0: A1: "Merged Title Row", B1: nil, C1: nil
|
|
3847
|
+
Row 1: A2: "Header A", B2: "Header B", C2: "Header C"
|
|
3848
|
+
Row 2: A3: "Row 1 Col A", B3: "Row 1 Col B", C3: "Row 1 Col C"
|
|
3849
|
+
Row 3: A4: "Row 2 Col A", B4: "Row 2 Col B", C4: "Row 2 Col C"
|
|
3850
|
+
```
|
|
3851
|
+
|
|
3852
|
+
<hr/>
|
|
3853
|
+
|
|
3854
|
+
## Page Grid Lines Print
|
|
3855
|
+
|
|
3856
|
+
[Download .xlsx](files/page_grid_lines_print.xlsx)
|
|
3857
|
+
|
|
3858
|
+
Demonstrates enabling printing of grid lines.
|
|
3859
|
+
|
|
3860
|
+
### Rendered Output (LibreOffice Calc)
|
|
3861
|
+
|
|
3862
|
+
<div><img src="../../test/visual/baselines/page_grid_lines_print/page-1.png" width="100%" alt="Preview"/></div>
|
|
3863
|
+
|
|
3864
|
+
### DSL Code
|
|
3865
|
+
|
|
3866
|
+
```ruby
|
|
3867
|
+
# frozen_string_literal: true
|
|
3868
|
+
require "xlsxrb"
|
|
3869
|
+
output_path = ARGV[0] || "page_grid_lines_print.xlsx"
|
|
3870
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3871
|
+
w.add_sheet("Print Grid Lines") do |s|
|
|
3872
|
+
s.set_column(0, width: 25)
|
|
3873
|
+
s.set_column(1, width: 25)
|
|
3874
|
+
s.set_print_option(:grid_lines, true)
|
|
3875
|
+
s.add_row(["Grid Lines Printed sheet"])
|
|
3876
|
+
end
|
|
3877
|
+
end
|
|
3878
|
+
|
|
3879
|
+
# 2. Read the generated sheet and print page setup properties
|
|
3880
|
+
puts "=== Read Validation ==="
|
|
3881
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
3882
|
+
workbook = Xlsxrb.read(output_path)
|
|
3883
|
+
sheet = workbook.sheets.first
|
|
3884
|
+
margins = reader.page_margins(sheet: sheet.name)
|
|
3885
|
+
setup = reader.page_setup(sheet: sheet.name)
|
|
3886
|
+
opts = reader.print_options(sheet: sheet.name)
|
|
3887
|
+
puts "Page Margins: #{margins.inspect}"
|
|
3888
|
+
puts "Page Setup: #{setup.inspect}"
|
|
3889
|
+
puts "Print Options: #{opts.inspect}"
|
|
3890
|
+
```
|
|
3891
|
+
|
|
3892
|
+
### Console Output
|
|
3893
|
+
|
|
3894
|
+
```text
|
|
3895
|
+
=== Read Validation ===
|
|
3896
|
+
Page Margins: nil
|
|
3897
|
+
Page Setup: {}
|
|
3898
|
+
Print Options: {grid_lines: true}
|
|
3899
|
+
```
|
|
3900
|
+
|
|
3901
|
+
<hr/>
|
|
3902
|
+
|
|
3903
|
+
## Page Header Footer
|
|
3904
|
+
|
|
3905
|
+
[Download .xlsx](files/page_header_footer.xlsx)
|
|
3906
|
+
|
|
3907
|
+
Demonstrates setting odd page headers and footers.
|
|
3908
|
+
|
|
3909
|
+
### Rendered Output (LibreOffice Calc)
|
|
3910
|
+
|
|
3911
|
+
<div><img src="../../test/visual/baselines/page_header_footer/page-1.png" width="100%" alt="Preview"/></div>
|
|
3912
|
+
|
|
3913
|
+
### DSL Code
|
|
3914
|
+
|
|
3915
|
+
```ruby
|
|
3916
|
+
# frozen_string_literal: true
|
|
3917
|
+
require "xlsxrb"
|
|
3918
|
+
output_path = ARGV[0] || "page_header_footer.xlsx"
|
|
3919
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3920
|
+
w.add_sheet("Header Footer") do |s|
|
|
3921
|
+
s.set_column(0, width: 25)
|
|
3922
|
+
s.set_column(1, width: 25)
|
|
3923
|
+
s.set_header_footer(odd_header: "&LMy Company&RPage &P", odd_footer: "&CConfidential")
|
|
3924
|
+
s.add_row(["Header Footer sheet"])
|
|
3925
|
+
end
|
|
3926
|
+
end
|
|
3927
|
+
|
|
3928
|
+
# 2. Read the generated sheet and print page setup properties
|
|
3929
|
+
puts "=== Read Validation ==="
|
|
3930
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
3931
|
+
workbook = Xlsxrb.read(output_path)
|
|
3932
|
+
sheet = workbook.sheets.first
|
|
3933
|
+
margins = reader.page_margins(sheet: sheet.name)
|
|
3934
|
+
setup = reader.page_setup(sheet: sheet.name)
|
|
3935
|
+
opts = reader.print_options(sheet: sheet.name)
|
|
3936
|
+
puts "Page Margins: #{margins.inspect}"
|
|
3937
|
+
puts "Page Setup: #{setup.inspect}"
|
|
3938
|
+
puts "Print Options: #{opts.inspect}"
|
|
3939
|
+
```
|
|
3940
|
+
|
|
3941
|
+
### Console Output
|
|
3942
|
+
|
|
3943
|
+
```text
|
|
3944
|
+
=== Read Validation ===
|
|
3945
|
+
Page Margins: nil
|
|
3946
|
+
Page Setup: {}
|
|
3947
|
+
Print Options: {}
|
|
3948
|
+
```
|
|
3949
|
+
|
|
3950
|
+
<hr/>
|
|
3951
|
+
|
|
3952
|
+
## Page Headings Print
|
|
3953
|
+
|
|
3954
|
+
[Download .xlsx](files/page_headings_print.xlsx)
|
|
3955
|
+
|
|
3956
|
+
Demonstrates enabling printing of row and column headings.
|
|
3957
|
+
|
|
3958
|
+
### Rendered Output (LibreOffice Calc)
|
|
3959
|
+
|
|
3960
|
+
<div><img src="../../test/visual/baselines/page_headings_print/page-1.png" width="100%" alt="Preview"/></div>
|
|
3961
|
+
|
|
3962
|
+
### DSL Code
|
|
3963
|
+
|
|
3964
|
+
```ruby
|
|
3965
|
+
# frozen_string_literal: true
|
|
3966
|
+
require "xlsxrb"
|
|
3967
|
+
output_path = ARGV[0] || "page_headings_print.xlsx"
|
|
3968
|
+
Xlsxrb.generate(output_path) do |w|
|
|
3969
|
+
w.add_sheet("Print Headings") do |s|
|
|
3970
|
+
s.set_column(0, width: 25)
|
|
3971
|
+
s.set_column(1, width: 25)
|
|
3972
|
+
s.set_print_option(:headings, true)
|
|
3973
|
+
s.add_row(["Row/Col Headings Printed sheet"])
|
|
3974
|
+
end
|
|
3975
|
+
end
|
|
3976
|
+
|
|
3977
|
+
# 2. Read the generated sheet and print page setup properties
|
|
3978
|
+
puts "=== Read Validation ==="
|
|
3979
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
3980
|
+
workbook = Xlsxrb.read(output_path)
|
|
3981
|
+
sheet = workbook.sheets.first
|
|
3982
|
+
margins = reader.page_margins(sheet: sheet.name)
|
|
3983
|
+
setup = reader.page_setup(sheet: sheet.name)
|
|
3984
|
+
opts = reader.print_options(sheet: sheet.name)
|
|
3985
|
+
puts "Page Margins: #{margins.inspect}"
|
|
3986
|
+
puts "Page Setup: #{setup.inspect}"
|
|
3987
|
+
puts "Print Options: #{opts.inspect}"
|
|
3988
|
+
```
|
|
3989
|
+
|
|
3990
|
+
### Console Output
|
|
3991
|
+
|
|
3992
|
+
```text
|
|
3993
|
+
=== Read Validation ===
|
|
3994
|
+
Page Margins: nil
|
|
3995
|
+
Page Setup: {}
|
|
3996
|
+
Print Options: {headings: true}
|
|
3997
|
+
```
|
|
3998
|
+
|
|
3999
|
+
<hr/>
|
|
4000
|
+
|
|
4001
|
+
## Page Margins Narrow
|
|
4002
|
+
|
|
4003
|
+
[Download .xlsx](files/page_margins_narrow.xlsx)
|
|
4004
|
+
|
|
4005
|
+
Demonstrates setting narrow page margins.
|
|
4006
|
+
|
|
4007
|
+
### Rendered Output (LibreOffice Calc)
|
|
4008
|
+
|
|
4009
|
+
<div><img src="../../test/visual/baselines/page_margins_narrow/page-1.png" width="100%" alt="Preview"/></div>
|
|
4010
|
+
|
|
4011
|
+
### DSL Code
|
|
4012
|
+
|
|
4013
|
+
```ruby
|
|
4014
|
+
# frozen_string_literal: true
|
|
4015
|
+
require "xlsxrb"
|
|
4016
|
+
output_path = ARGV[0] || "page_margins_narrow.xlsx"
|
|
4017
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4018
|
+
w.add_sheet("Narrow Margins") do |s|
|
|
4019
|
+
s.set_column(0, width: 25)
|
|
4020
|
+
s.set_column(1, width: 25)
|
|
4021
|
+
s.set_page_margins(top: 0.25, bottom: 0.25, left: 0.25, right: 0.25, header: 0.1, footer: 0.1)
|
|
4022
|
+
s.add_row(["Narrow Margins sheet"])
|
|
4023
|
+
end
|
|
4024
|
+
end
|
|
4025
|
+
|
|
4026
|
+
# 2. Read the generated sheet and print page setup properties
|
|
4027
|
+
puts "=== Read Validation ==="
|
|
4028
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
4029
|
+
workbook = Xlsxrb.read(output_path)
|
|
4030
|
+
sheet = workbook.sheets.first
|
|
4031
|
+
margins = reader.page_margins(sheet: sheet.name)
|
|
4032
|
+
setup = reader.page_setup(sheet: sheet.name)
|
|
4033
|
+
opts = reader.print_options(sheet: sheet.name)
|
|
4034
|
+
puts "Page Margins: #{margins.inspect}"
|
|
4035
|
+
puts "Page Setup: #{setup.inspect}"
|
|
4036
|
+
puts "Print Options: #{opts.inspect}"
|
|
4037
|
+
```
|
|
4038
|
+
|
|
4039
|
+
### Console Output
|
|
4040
|
+
|
|
4041
|
+
```text
|
|
4042
|
+
=== Read Validation ===
|
|
4043
|
+
Page Margins: {left: 0.25, right: 0.25, top: 0.25, bottom: 0.25, header: 0.1, footer: 0.1}
|
|
4044
|
+
Page Setup: {}
|
|
4045
|
+
Print Options: {}
|
|
4046
|
+
```
|
|
4047
|
+
|
|
4048
|
+
<hr/>
|
|
4049
|
+
|
|
4050
|
+
## Page Margins Wide
|
|
4051
|
+
|
|
4052
|
+
[Download .xlsx](files/page_margins_wide.xlsx)
|
|
4053
|
+
|
|
4054
|
+
Demonstrates setting wide page margins.
|
|
4055
|
+
|
|
4056
|
+
### Rendered Output (LibreOffice Calc)
|
|
4057
|
+
|
|
4058
|
+
<div><img src="../../test/visual/baselines/page_margins_wide/page-1.png" width="100%" alt="Preview"/></div>
|
|
4059
|
+
|
|
4060
|
+
### DSL Code
|
|
4061
|
+
|
|
4062
|
+
```ruby
|
|
4063
|
+
# frozen_string_literal: true
|
|
4064
|
+
require "xlsxrb"
|
|
4065
|
+
output_path = ARGV[0] || "page_margins_wide.xlsx"
|
|
4066
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4067
|
+
w.add_sheet("Wide Margins") do |s|
|
|
4068
|
+
s.set_column(0, width: 25)
|
|
4069
|
+
s.set_column(1, width: 25)
|
|
4070
|
+
s.set_page_margins(top: 1.0, bottom: 1.0, left: 1.0, right: 1.0, header: 0.5, footer: 0.5)
|
|
4071
|
+
s.add_row(["Wide Margins sheet"])
|
|
4072
|
+
end
|
|
4073
|
+
end
|
|
4074
|
+
|
|
4075
|
+
# 2. Read the generated sheet and print page setup properties
|
|
4076
|
+
puts "=== Read Validation ==="
|
|
4077
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
4078
|
+
workbook = Xlsxrb.read(output_path)
|
|
4079
|
+
sheet = workbook.sheets.first
|
|
4080
|
+
margins = reader.page_margins(sheet: sheet.name)
|
|
4081
|
+
setup = reader.page_setup(sheet: sheet.name)
|
|
4082
|
+
opts = reader.print_options(sheet: sheet.name)
|
|
4083
|
+
puts "Page Margins: #{margins.inspect}"
|
|
4084
|
+
puts "Page Setup: #{setup.inspect}"
|
|
4085
|
+
puts "Print Options: #{opts.inspect}"
|
|
4086
|
+
```
|
|
4087
|
+
|
|
4088
|
+
### Console Output
|
|
4089
|
+
|
|
4090
|
+
```text
|
|
4091
|
+
=== Read Validation ===
|
|
4092
|
+
Page Margins: {left: 1.0, right: 1.0, top: 1.0, bottom: 1.0, header: 0.5, footer: 0.5}
|
|
4093
|
+
Page Setup: {}
|
|
4094
|
+
Print Options: {}
|
|
4095
|
+
```
|
|
4096
|
+
|
|
4097
|
+
<hr/>
|
|
4098
|
+
|
|
4099
|
+
## Page Orientation Landscape
|
|
4100
|
+
|
|
4101
|
+
[Download .xlsx](files/page_orientation_landscape.xlsx)
|
|
4102
|
+
|
|
4103
|
+
Demonstrates landscape page setup for printing.
|
|
4104
|
+
|
|
4105
|
+
### Rendered Output (LibreOffice Calc)
|
|
4106
|
+
|
|
4107
|
+
<div><img src="../../test/visual/baselines/page_orientation_landscape/page-1.png" width="100%" alt="Preview"/></div>
|
|
4108
|
+
|
|
4109
|
+
### DSL Code
|
|
4110
|
+
|
|
4111
|
+
```ruby
|
|
4112
|
+
# frozen_string_literal: true
|
|
4113
|
+
require "xlsxrb"
|
|
4114
|
+
output_path = ARGV[0] || "page_orientation_landscape.xlsx"
|
|
4115
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4116
|
+
w.add_sheet("Landscape") do |s|
|
|
4117
|
+
s.set_column(0, width: 25)
|
|
4118
|
+
s.set_column(1, width: 25)
|
|
4119
|
+
s.set_page_setup(orientation: :landscape)
|
|
4120
|
+
s.add_row(["Landscape Orientation sheet"])
|
|
4121
|
+
end
|
|
4122
|
+
end
|
|
4123
|
+
|
|
4124
|
+
# 2. Read the generated sheet and print page setup properties
|
|
4125
|
+
puts "=== Read Validation ==="
|
|
4126
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
4127
|
+
workbook = Xlsxrb.read(output_path)
|
|
4128
|
+
sheet = workbook.sheets.first
|
|
4129
|
+
margins = reader.page_margins(sheet: sheet.name)
|
|
4130
|
+
setup = reader.page_setup(sheet: sheet.name)
|
|
4131
|
+
opts = reader.print_options(sheet: sheet.name)
|
|
4132
|
+
puts "Page Margins: #{margins.inspect}"
|
|
4133
|
+
puts "Page Setup: #{setup.inspect}"
|
|
4134
|
+
puts "Print Options: #{opts.inspect}"
|
|
4135
|
+
```
|
|
4136
|
+
|
|
4137
|
+
### Console Output
|
|
4138
|
+
|
|
4139
|
+
```text
|
|
4140
|
+
=== Read Validation ===
|
|
4141
|
+
Page Margins: nil
|
|
4142
|
+
Page Setup: {orientation: "landscape"}
|
|
4143
|
+
Print Options: {}
|
|
4144
|
+
```
|
|
4145
|
+
|
|
4146
|
+
<hr/>
|
|
4147
|
+
|
|
4148
|
+
## Page Paper Size A3
|
|
4149
|
+
|
|
4150
|
+
[Download .xlsx](files/page_paper_size_a3.xlsx)
|
|
4151
|
+
|
|
4152
|
+
Demonstrates setting paper size to A3 (paper size 8).
|
|
4153
|
+
|
|
4154
|
+
### Rendered Output (LibreOffice Calc)
|
|
4155
|
+
|
|
4156
|
+
<div><img src="../../test/visual/baselines/page_paper_size_a3/page-1.png" width="100%" alt="Preview"/></div>
|
|
4157
|
+
|
|
4158
|
+
### DSL Code
|
|
4159
|
+
|
|
4160
|
+
```ruby
|
|
4161
|
+
# frozen_string_literal: true
|
|
4162
|
+
require "xlsxrb"
|
|
4163
|
+
output_path = ARGV[0] || "page_paper_size_a3.xlsx"
|
|
4164
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4165
|
+
w.add_sheet("A3 Sheet") do |s|
|
|
4166
|
+
s.set_column(0, width: 25)
|
|
4167
|
+
s.set_column(1, width: 25)
|
|
4168
|
+
s.set_page_setup(paper_size: 8) # ISO A3 is paperSize="8"
|
|
4169
|
+
s.add_row(["ISO A3 Paper Size sheet"])
|
|
4170
|
+
end
|
|
4171
|
+
end
|
|
4172
|
+
|
|
4173
|
+
# 2. Read the generated sheet and print page setup properties
|
|
4174
|
+
puts "=== Read Validation ==="
|
|
4175
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
4176
|
+
workbook = Xlsxrb.read(output_path)
|
|
4177
|
+
sheet = workbook.sheets.first
|
|
4178
|
+
margins = reader.page_margins(sheet: sheet.name)
|
|
4179
|
+
setup = reader.page_setup(sheet: sheet.name)
|
|
4180
|
+
opts = reader.print_options(sheet: sheet.name)
|
|
4181
|
+
puts "Page Margins: #{margins.inspect}"
|
|
4182
|
+
puts "Page Setup: #{setup.inspect}"
|
|
4183
|
+
puts "Print Options: #{opts.inspect}"
|
|
4184
|
+
```
|
|
4185
|
+
|
|
4186
|
+
### Console Output
|
|
4187
|
+
|
|
4188
|
+
```text
|
|
4189
|
+
=== Read Validation ===
|
|
4190
|
+
Page Margins: nil
|
|
4191
|
+
Page Setup: {paper_size: 8}
|
|
4192
|
+
Print Options: {}
|
|
4193
|
+
```
|
|
4194
|
+
|
|
4195
|
+
<hr/>
|
|
4196
|
+
|
|
4197
|
+
## Row Grouping
|
|
4198
|
+
|
|
4199
|
+
[Download .xlsx](files/row_grouping.xlsx)
|
|
4200
|
+
|
|
4201
|
+
Demonstrates outline grouping for rows.
|
|
4202
|
+
|
|
4203
|
+
### Rendered Output (LibreOffice Calc)
|
|
4204
|
+
|
|
4205
|
+
<div><img src="../../test/visual/baselines/row_grouping/page-1.png" width="100%" alt="Preview"/></div>
|
|
4206
|
+
|
|
4207
|
+
### DSL Code
|
|
4208
|
+
|
|
4209
|
+
```ruby
|
|
4210
|
+
# frozen_string_literal: true
|
|
4211
|
+
require "xlsxrb"
|
|
4212
|
+
output_path = ARGV[0] || "row_grouping.xlsx"
|
|
4213
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4214
|
+
w.add_style("parent") { |style| style.border_all(style: "thin", color: "FF000000").bold }
|
|
4215
|
+
w.add_style("child") { |style| style.border_all(style: "thin", color: "FF000000").align_horizontal("left").indent(2) }
|
|
4216
|
+
w.add_sheet("Row Grouping") do |s|
|
|
4217
|
+
s.set_column(0, width: 25)
|
|
4218
|
+
s.set_column(1, width: 25)
|
|
4219
|
+
s.add_row(["Parent Row 1", ""], styles: ["parent", "parent"])
|
|
4220
|
+
s.add_row(["Child Row 1.1", ""], outline_level: 1, styles: ["child", "child"])
|
|
4221
|
+
s.add_row(["Child Row 1.2", ""], outline_level: 1, styles: ["child", "child"])
|
|
4222
|
+
end
|
|
4223
|
+
end
|
|
4224
|
+
|
|
4225
|
+
# 2. Read the generated sheet and print row attributes
|
|
4226
|
+
puts "=== Read Validation ==="
|
|
4227
|
+
workbook = Xlsxrb.read(output_path)
|
|
4228
|
+
sheet = workbook.sheets.first
|
|
4229
|
+
sheet.rows.each do |row|
|
|
4230
|
+
puts "Row #{row.index}: height=#{row.height}, hidden=#{row.hidden}, outline_level=#{row.outline_level}"
|
|
4231
|
+
end
|
|
4232
|
+
```
|
|
4233
|
+
|
|
4234
|
+
### Console Output
|
|
4235
|
+
|
|
4236
|
+
```text
|
|
4237
|
+
=== Read Validation ===
|
|
4238
|
+
Row 0: height=, hidden=false, outline_level=
|
|
4239
|
+
Row 1: height=, hidden=false, outline_level=1
|
|
4240
|
+
Row 2: height=, hidden=false, outline_level=1
|
|
4241
|
+
```
|
|
4242
|
+
|
|
4243
|
+
<hr/>
|
|
4244
|
+
|
|
4245
|
+
## Row Height Tall
|
|
4246
|
+
|
|
4247
|
+
[Download .xlsx](files/row_height_tall.xlsx)
|
|
4248
|
+
|
|
4249
|
+
Demonstrates setting very tall row heights.
|
|
4250
|
+
|
|
4251
|
+
### Rendered Output (LibreOffice Calc)
|
|
4252
|
+
|
|
4253
|
+
<div><img src="../../test/visual/baselines/row_height_tall/page-1.png" width="100%" alt="Preview"/></div>
|
|
4254
|
+
|
|
4255
|
+
### DSL Code
|
|
4256
|
+
|
|
4257
|
+
```ruby
|
|
4258
|
+
# frozen_string_literal: true
|
|
4259
|
+
require "xlsxrb"
|
|
4260
|
+
output_path = ARGV[0] || "row_height_tall.xlsx"
|
|
4261
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4262
|
+
w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
|
|
4263
|
+
w.add_sheet("Row Height") do |s|
|
|
4264
|
+
s.set_column(0, width: 25)
|
|
4265
|
+
s.set_column(1, width: 25)
|
|
4266
|
+
s.add_row(["Very Tall Row (Height 60)", ""], height: 60, styles: ["border", "border"])
|
|
4267
|
+
s.add_row(["Normal Row", ""], styles: ["border", "border"])
|
|
4268
|
+
end
|
|
4269
|
+
end
|
|
4270
|
+
|
|
4271
|
+
# 2. Read the generated sheet and print row attributes
|
|
4272
|
+
puts "=== Read Validation ==="
|
|
4273
|
+
workbook = Xlsxrb.read(output_path)
|
|
4274
|
+
sheet = workbook.sheets.first
|
|
4275
|
+
sheet.rows.each do |row|
|
|
4276
|
+
puts "Row #{row.index}: height=#{row.height}, hidden=#{row.hidden}, outline_level=#{row.outline_level}"
|
|
4277
|
+
end
|
|
4278
|
+
```
|
|
4279
|
+
|
|
4280
|
+
### Console Output
|
|
4281
|
+
|
|
4282
|
+
```text
|
|
4283
|
+
=== Read Validation ===
|
|
4284
|
+
Row 0: height=60.0, hidden=false, outline_level=
|
|
4285
|
+
Row 1: height=, hidden=false, outline_level=
|
|
4286
|
+
```
|
|
4287
|
+
|
|
4288
|
+
<hr/>
|
|
4289
|
+
|
|
4290
|
+
## Row Heights
|
|
4291
|
+
|
|
4292
|
+
[Download .xlsx](files/row_heights.xlsx)
|
|
4293
|
+
|
|
4294
|
+
Demonstrates setting custom row heights.
|
|
4295
|
+
|
|
4296
|
+
### Rendered Output (LibreOffice Calc)
|
|
4297
|
+
|
|
4298
|
+
<div><img src="../../test/visual/baselines/row_heights/page-1.png" width="100%" alt="Preview"/></div>
|
|
4299
|
+
|
|
4300
|
+
### DSL Code
|
|
4301
|
+
|
|
4302
|
+
```ruby
|
|
4303
|
+
# frozen_string_literal: true
|
|
4304
|
+
require "xlsxrb"
|
|
4305
|
+
output_path = ARGV[0] || "row_heights.xlsx"
|
|
4306
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4307
|
+
w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
|
|
4308
|
+
w.add_sheet("Heights") do |s|
|
|
4309
|
+
s.set_column(0, width: 25)
|
|
4310
|
+
s.set_column(1, width: 25)
|
|
4311
|
+
s.add_row(["Normal Row", ""], styles: ["border", "border"])
|
|
4312
|
+
s.add_row(["Tall Row", ""], height: 40, styles: ["border", "border"])
|
|
4313
|
+
end
|
|
4314
|
+
end
|
|
4315
|
+
|
|
4316
|
+
# 2. Read the generated sheet and print row attributes
|
|
4317
|
+
puts "=== Read Validation ==="
|
|
4318
|
+
workbook = Xlsxrb.read(output_path)
|
|
4319
|
+
sheet = workbook.sheets.first
|
|
4320
|
+
sheet.rows.each do |row|
|
|
4321
|
+
puts "Row #{row.index}: height=#{row.height}, hidden=#{row.hidden}, outline_level=#{row.outline_level}"
|
|
4322
|
+
end
|
|
4323
|
+
```
|
|
4324
|
+
|
|
4325
|
+
### Console Output
|
|
4326
|
+
|
|
4327
|
+
```text
|
|
4328
|
+
=== Read Validation ===
|
|
4329
|
+
Row 0: height=, hidden=false, outline_level=
|
|
4330
|
+
Row 1: height=40.0, hidden=false, outline_level=
|
|
4331
|
+
```
|
|
4332
|
+
|
|
4333
|
+
<hr/>
|
|
4334
|
+
|
|
4335
|
+
## Sheet Tab Colors
|
|
4336
|
+
|
|
4337
|
+
[Download .xlsx](files/sheet_tab_colors.xlsx)
|
|
4338
|
+
|
|
4339
|
+
Demonstrates customizing tab colors of individual worksheets.
|
|
4340
|
+
|
|
4341
|
+
### Rendered Output (LibreOffice Calc)
|
|
4342
|
+
|
|
4343
|
+
<div><img src="../../test/visual/baselines/sheet_tab_colors/page-1.png" width="100%" alt="Preview"/></div>
|
|
4344
|
+
|
|
4345
|
+
<div><img src="../../test/visual/baselines/sheet_tab_colors/page-2.png" width="100%" alt="Preview"/></div>
|
|
4346
|
+
|
|
4347
|
+
<div><img src="../../test/visual/support/illustrations/sheet_tab_colors_page-2.png" width="100%" alt="Preview"/></div>
|
|
4348
|
+
|
|
4349
|
+
### DSL Code
|
|
4350
|
+
|
|
4351
|
+
```ruby
|
|
4352
|
+
# frozen_string_literal: true
|
|
4353
|
+
require "xlsxrb"
|
|
4354
|
+
output_path = ARGV[0] || "sheet_tab_colors.xlsx"
|
|
4355
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4356
|
+
w.add_sheet("Red Tab") do |s|
|
|
4357
|
+
s.set_column(0, width: 25)
|
|
4358
|
+
s.set_column(1, width: 25)
|
|
4359
|
+
s.set_sheet_property(:tab_color, "FFFF0000")
|
|
4360
|
+
s.add_row(["Red tab sheet"])
|
|
4361
|
+
end
|
|
4362
|
+
w.add_sheet("Green Tab") do |s|
|
|
4363
|
+
s.set_sheet_property(:tab_color, "FF00FF00")
|
|
4364
|
+
s.add_row(["Green tab sheet"])
|
|
4365
|
+
end
|
|
4366
|
+
end
|
|
4367
|
+
|
|
4368
|
+
# 2. Read the generated sheet and print sheet properties
|
|
4369
|
+
puts "=== Read Validation ==="
|
|
4370
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
4371
|
+
workbook = Xlsxrb.read(output_path)
|
|
4372
|
+
workbook.sheet_names.each do |s_name|
|
|
4373
|
+
props = reader.sheet_properties(sheet: s_name)
|
|
4374
|
+
puts "Sheet: #{s_name}, tab color: #{props[:tab_color].inspect}"
|
|
4375
|
+
end
|
|
4376
|
+
```
|
|
4377
|
+
|
|
4378
|
+
### Console Output
|
|
4379
|
+
|
|
4380
|
+
```text
|
|
4381
|
+
=== Read Validation ===
|
|
4382
|
+
Sheet: Red Tab, tab color: "FFFF0000"
|
|
4383
|
+
Sheet: Green Tab, tab color: "FF00FF00"
|
|
4384
|
+
```
|
|
4385
|
+
|
|
4386
|
+
<hr/>
|
|
4387
|
+
|
|
4388
|
+
## Sparkline Column
|
|
4389
|
+
|
|
4390
|
+
[Download .xlsx](files/sparkline_column.xlsx)
|
|
4391
|
+
|
|
4392
|
+
Demonstrates embedded column sparklines in cell ranges.
|
|
4393
|
+
|
|
4394
|
+
### Rendered Output (LibreOffice Calc)
|
|
4395
|
+
|
|
4396
|
+
<div><img src="../../test/visual/baselines/sparkline_column/page-1.png" width="100%" alt="Preview"/></div>
|
|
4397
|
+
|
|
4398
|
+
### DSL Code
|
|
4399
|
+
|
|
4400
|
+
```ruby
|
|
4401
|
+
# frozen_string_literal: true
|
|
4402
|
+
require "xlsxrb"
|
|
4403
|
+
output_path = ARGV[0] || "sparkline_column.xlsx"
|
|
4404
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4405
|
+
w.add_sheet("Sparkline") do |s|
|
|
4406
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
4407
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
4408
|
+
s.set_column(0, width: 25)
|
|
4409
|
+
s.set_column(1, width: 25)
|
|
4410
|
+
s.add_row([5, 12, 8, 15, nil])
|
|
4411
|
+
s.add_sparkline_group(
|
|
4412
|
+
type: :column,
|
|
4413
|
+
sparklines: [{ location_ref: "E1", data_ref: "Sparkline!A1:D1" }]
|
|
4414
|
+
)
|
|
4415
|
+
end
|
|
4416
|
+
end
|
|
4417
|
+
|
|
4418
|
+
# 2. Read the generated sheet and print cell values
|
|
4419
|
+
puts "=== Read Validation ==="
|
|
4420
|
+
workbook = Xlsxrb.read(output_path)
|
|
4421
|
+
sheet = workbook.sheets.first
|
|
4422
|
+
sheet.rows.first(3).each do |row|
|
|
4423
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
4424
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
4425
|
+
end
|
|
4426
|
+
```
|
|
4427
|
+
|
|
4428
|
+
### Console Output
|
|
4429
|
+
|
|
4430
|
+
```text
|
|
4431
|
+
=== Read Validation ===
|
|
4432
|
+
Row 0: A1: 5, B1: 12, C1: 8, D1: 15
|
|
4433
|
+
```
|
|
4434
|
+
|
|
4435
|
+
<hr/>
|
|
4436
|
+
|
|
4437
|
+
## Sparkline Line
|
|
4438
|
+
|
|
4439
|
+
[Download .xlsx](files/sparkline_line.xlsx)
|
|
4440
|
+
|
|
4441
|
+
Demonstrates embedded line sparklines in cell ranges.
|
|
4442
|
+
|
|
4443
|
+
### Rendered Output (LibreOffice Calc)
|
|
4444
|
+
|
|
4445
|
+
<div><img src="../../test/visual/baselines/sparkline_line/page-1.png" width="100%" alt="Preview"/></div>
|
|
4446
|
+
|
|
4447
|
+
<div><img src="../../test/visual/support/illustrations/sparkline_line_page-2.png" width="100%" alt="Preview"/></div>
|
|
4448
|
+
|
|
4449
|
+
### DSL Code
|
|
4450
|
+
|
|
4451
|
+
```ruby
|
|
4452
|
+
# frozen_string_literal: true
|
|
4453
|
+
require "xlsxrb"
|
|
4454
|
+
output_path = ARGV[0] || "sparkline_line.xlsx"
|
|
4455
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4456
|
+
w.add_sheet("Sparkline") do |s|
|
|
4457
|
+
s.set_sheet_property(:fit_to_page, true)
|
|
4458
|
+
s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
|
|
4459
|
+
s.set_column(0, width: 25)
|
|
4460
|
+
s.set_column(1, width: 25)
|
|
4461
|
+
s.add_row([10, 20, 15, 30, nil])
|
|
4462
|
+
s.add_sparkline_group(
|
|
4463
|
+
type: :line,
|
|
4464
|
+
markers: true,
|
|
4465
|
+
color_series: "FF000000",
|
|
4466
|
+
color_markers: "FFFF0000",
|
|
4467
|
+
sparklines: [{ location_ref: "E1", data_ref: "Sparkline!A1:D1" }]
|
|
4468
|
+
)
|
|
4469
|
+
end
|
|
4470
|
+
end
|
|
4471
|
+
|
|
4472
|
+
# 2. Read the generated sheet and print cell values
|
|
4473
|
+
puts "=== Read Validation ==="
|
|
4474
|
+
workbook = Xlsxrb.read(output_path)
|
|
4475
|
+
sheet = workbook.sheets.first
|
|
4476
|
+
sheet.rows.first(3).each do |row|
|
|
4477
|
+
row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
|
|
4478
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
4479
|
+
end
|
|
4480
|
+
```
|
|
4481
|
+
|
|
4482
|
+
### Console Output
|
|
4483
|
+
|
|
4484
|
+
```text
|
|
4485
|
+
=== Read Validation ===
|
|
4486
|
+
Row 0: A1: 10, B1: 20, C1: 15, D1: 30
|
|
4487
|
+
```
|
|
4488
|
+
|
|
4489
|
+
<hr/>
|
|
4490
|
+
|
|
4491
|
+
## Styles Fonts Fills
|
|
4492
|
+
|
|
4493
|
+
[Download .xlsx](files/styles_fonts_fills.xlsx)
|
|
4494
|
+
|
|
4495
|
+
Demonstrates cell formatting, including custom font sizing, bold/italic text, custom text colors, and background fill colors.
|
|
4496
|
+
|
|
4497
|
+
### Rendered Output (LibreOffice Calc)
|
|
4498
|
+
|
|
4499
|
+
<div><img src="../../test/visual/baselines/styles_fonts_fills/page-1.png" width="100%" alt="Preview"/></div>
|
|
4500
|
+
|
|
4501
|
+
### DSL Code
|
|
4502
|
+
|
|
4503
|
+
```ruby
|
|
4504
|
+
# frozen_string_literal: true
|
|
4505
|
+
|
|
4506
|
+
require "xlsxrb"
|
|
4507
|
+
|
|
4508
|
+
output_path = ARGV[0] || "styles_fonts_fills.xlsx"
|
|
4509
|
+
|
|
4510
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4511
|
+
w.add_style("header") do |style|
|
|
4512
|
+
style.bold.size(14).font_color("FFFFFFFF").fill_color("FF4F81BD")
|
|
4513
|
+
end
|
|
4514
|
+
|
|
4515
|
+
w.add_style("highlight") do |style|
|
|
4516
|
+
style.italic.font_color("FFC00000").fill_color("FFFFFF00")
|
|
4517
|
+
end
|
|
4518
|
+
|
|
4519
|
+
w.add_sheet("Styles") do
|
|
4520
|
+
w.set_column(0, width: 25)
|
|
4521
|
+
w.set_column(1, width: 25)
|
|
4522
|
+
w.add_row(["Header 1", "Header 2"], styles: { 0 => "header", 1 => "header" })
|
|
4523
|
+
w.add_row(["Normal Text", "Highlighted Text"], styles: { 1 => "highlight" })
|
|
4524
|
+
end
|
|
4525
|
+
end
|
|
4526
|
+
|
|
4527
|
+
# 2. Read the generated sheet and print styling details
|
|
4528
|
+
puts "=== Read Validation ==="
|
|
4529
|
+
workbook = Xlsxrb.read(output_path)
|
|
4530
|
+
sheet = workbook.sheets.first
|
|
4531
|
+
sheet.rows.first(4).each do |row|
|
|
4532
|
+
row_cells = row.cells.map do |c|
|
|
4533
|
+
xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
|
|
4534
|
+
font = xf ? workbook.styles[:fonts][xf[:font_id]] : nil
|
|
4535
|
+
fill = xf ? workbook.styles[:fills][xf[:fill_id]] : nil
|
|
4536
|
+
"#{c.ref}: #{c.value.inspect} (font=#{font&.[](:name)}, fill=#{fill&.[](:fg_color)&.[](:rgb)})"
|
|
4537
|
+
end
|
|
4538
|
+
puts "Row #{row.index}: #{row_cells.join(', ')}"
|
|
4539
|
+
end
|
|
4540
|
+
```
|
|
4541
|
+
|
|
4542
|
+
### Console Output
|
|
4543
|
+
|
|
4544
|
+
```text
|
|
4545
|
+
=== Read Validation ===
|
|
4546
|
+
Row 0: A1: "Header 1" (font=Calibri, fill=FF4F81BD), B1: "Header 2" (font=Calibri, fill=FF4F81BD)
|
|
4547
|
+
Row 1: A2: "Normal Text" (font=, fill=), B2: "Highlighted Text" (font=Calibri, fill=FFFFFF00)
|
|
4548
|
+
```
|
|
4549
|
+
|
|
4550
|
+
<hr/>
|
|
4551
|
+
|
|
4552
|
+
## View Show Grid Lines
|
|
4553
|
+
|
|
4554
|
+
[Download .xlsx](files/view_show_grid_lines.xlsx)
|
|
4555
|
+
|
|
4556
|
+
Demonstrates disabling visible grid lines in spreadsheet view.
|
|
4557
|
+
|
|
4558
|
+
### Rendered Output (LibreOffice Calc)
|
|
4559
|
+
|
|
4560
|
+
<div><img src="../../test/visual/baselines/view_show_grid_lines/page-1.png" width="100%" alt="Preview"/></div>
|
|
4561
|
+
|
|
4562
|
+
<div><img src="../../test/visual/support/illustrations/view_show_grid_lines_page-2.png" width="100%" alt="Preview"/></div>
|
|
4563
|
+
|
|
4564
|
+
### DSL Code
|
|
4565
|
+
|
|
4566
|
+
```ruby
|
|
4567
|
+
# frozen_string_literal: true
|
|
4568
|
+
require "xlsxrb"
|
|
4569
|
+
output_path = ARGV[0] || "view_show_grid_lines.xlsx"
|
|
4570
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4571
|
+
w.add_sheet("Hide Grid Lines") do |s|
|
|
4572
|
+
s.set_column(0, width: 25)
|
|
4573
|
+
s.set_column(1, width: 25)
|
|
4574
|
+
s.set_sheet_view(:show_grid_lines, false)
|
|
4575
|
+
s.add_row(["No Grid Lines displayed"])
|
|
4576
|
+
end
|
|
4577
|
+
end
|
|
4578
|
+
|
|
4579
|
+
# 2. Read the generated sheet and print view configurations
|
|
4580
|
+
puts "=== Read Validation ==="
|
|
4581
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
4582
|
+
workbook = Xlsxrb.read(output_path)
|
|
4583
|
+
workbook.sheet_names.each do |s_name|
|
|
4584
|
+
view = reader.sheet_view(sheet: s_name)
|
|
4585
|
+
puts "Sheet '#{s_name}' views zoom scale: #{view[:zoom_scale]}%, show grid lines: #{view[:show_grid_lines]}"
|
|
4586
|
+
end
|
|
4587
|
+
```
|
|
4588
|
+
|
|
4589
|
+
### Console Output
|
|
4590
|
+
|
|
4591
|
+
```text
|
|
4592
|
+
=== Read Validation ===
|
|
4593
|
+
Sheet 'Hide Grid Lines' views zoom scale: %, show grid lines: false
|
|
4594
|
+
```
|
|
4595
|
+
|
|
4596
|
+
<hr/>
|
|
4597
|
+
|
|
4598
|
+
## View Zoom Scale
|
|
4599
|
+
|
|
4600
|
+
[Download .xlsx](files/view_zoom_scale.xlsx)
|
|
4601
|
+
|
|
4602
|
+
Demonstrates setting custom zoom scale in sheet view (e.g. 150%).
|
|
4603
|
+
|
|
4604
|
+
### Rendered Output (LibreOffice Calc)
|
|
4605
|
+
|
|
4606
|
+
<div><img src="../../test/visual/baselines/view_zoom_scale/page-1.png" width="100%" alt="Preview"/></div>
|
|
4607
|
+
|
|
4608
|
+
<div><img src="../../test/visual/support/illustrations/view_zoom_scale_page-2.png" width="100%" alt="Preview"/></div>
|
|
4609
|
+
|
|
4610
|
+
### DSL Code
|
|
4611
|
+
|
|
4612
|
+
```ruby
|
|
4613
|
+
# frozen_string_literal: true
|
|
4614
|
+
require "xlsxrb"
|
|
4615
|
+
output_path = ARGV[0] || "view_zoom_scale.xlsx"
|
|
4616
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4617
|
+
w.add_sheet("Zoom 150") do |s|
|
|
4618
|
+
s.set_column(0, width: 25)
|
|
4619
|
+
s.set_column(1, width: 25)
|
|
4620
|
+
s.set_sheet_view(:zoom_scale, 150)
|
|
4621
|
+
s.add_row(["Zoom scale is set to 150%"])
|
|
4622
|
+
end
|
|
4623
|
+
end
|
|
4624
|
+
|
|
4625
|
+
# 2. Read the generated sheet and print view configurations
|
|
4626
|
+
puts "=== Read Validation ==="
|
|
4627
|
+
reader = Xlsxrb::Ooxml::Reader.new(output_path)
|
|
4628
|
+
workbook = Xlsxrb.read(output_path)
|
|
4629
|
+
workbook.sheet_names.each do |s_name|
|
|
4630
|
+
view = reader.sheet_view(sheet: s_name)
|
|
4631
|
+
puts "Sheet '#{s_name}' views zoom scale: #{view[:zoom_scale]}%, show grid lines: #{view[:show_grid_lines]}"
|
|
4632
|
+
end
|
|
4633
|
+
```
|
|
4634
|
+
|
|
4635
|
+
### Console Output
|
|
4636
|
+
|
|
4637
|
+
```text
|
|
4638
|
+
=== Read Validation ===
|
|
4639
|
+
Sheet 'Zoom 150' views zoom scale: 150%, show grid lines:
|
|
4640
|
+
```
|
|
4641
|
+
|
|
4642
|
+
<hr/>
|
|
4643
|
+
|
|
4644
|
+
## Workbook Three Sheets
|
|
4645
|
+
|
|
4646
|
+
[Download .xlsx](files/workbook_three_sheets.xlsx)
|
|
4647
|
+
|
|
4648
|
+
Demonstrates creating workbooks with multiple worksheets.
|
|
4649
|
+
|
|
4650
|
+
### Rendered Output (LibreOffice Calc)
|
|
4651
|
+
|
|
4652
|
+
<div><img src="../../test/visual/baselines/workbook_three_sheets/page-1.png" width="100%" alt="Preview"/></div>
|
|
4653
|
+
|
|
4654
|
+
<div><img src="../../test/visual/baselines/workbook_three_sheets/page-2.png" width="100%" alt="Preview"/></div>
|
|
4655
|
+
|
|
4656
|
+
<div><img src="../../test/visual/baselines/workbook_three_sheets/page-3.png" width="100%" alt="Preview"/></div>
|
|
4657
|
+
|
|
4658
|
+
### DSL Code
|
|
4659
|
+
|
|
4660
|
+
```ruby
|
|
4661
|
+
# frozen_string_literal: true
|
|
4662
|
+
require "xlsxrb"
|
|
4663
|
+
output_path = ARGV[0] || "workbook_three_sheets.xlsx"
|
|
4664
|
+
Xlsxrb.generate(output_path) do |w|
|
|
4665
|
+
w.add_sheet("First Sheet") { |s| s.add_row(["First Sheet Data"]) }
|
|
4666
|
+
w.add_sheet("Second Sheet") { |s| s.add_row(["Second Sheet Data"]) }
|
|
4667
|
+
w.add_sheet("Third Sheet") { |s| s.add_row(["Third Sheet Data"]) }
|
|
4668
|
+
end
|
|
4669
|
+
|
|
4670
|
+
# 2. Read the generated sheet and print the sheets structure
|
|
4671
|
+
puts "=== Read Validation ==="
|
|
4672
|
+
workbook = Xlsxrb.read(output_path)
|
|
4673
|
+
puts "Workbook sheets: #{workbook.sheet_names.join(', ')}"
|
|
4674
|
+
```
|
|
4675
|
+
|
|
4676
|
+
### Console Output
|
|
4677
|
+
|
|
4678
|
+
```text
|
|
4679
|
+
=== Read Validation ===
|
|
4680
|
+
Workbook sheets: First Sheet, Second Sheet, Third Sheet
|
|
4681
|
+
```
|
|
4682
|
+
|
|
4683
|
+
<hr/>
|
|
4684
|
+
|