xlsxrb 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +125 -0
- data/README.md +24 -5
- data/benchmark/micro_ips.rb +70 -0
- data/lib/xlsxrb/chart_builder.rb +41 -2
- data/lib/xlsxrb/dsl_helpers.rb +522 -6
- data/lib/xlsxrb/elements/cell.rb +34 -9
- data/lib/xlsxrb/elements/column.rb +2 -2
- data/lib/xlsxrb/elements/styles.rb +427 -15
- data/lib/xlsxrb/elements/types.rb +1 -0
- data/lib/xlsxrb/elements/workbook.rb +79 -4
- data/lib/xlsxrb/elements/worksheet.rb +173 -11
- data/lib/xlsxrb/ooxml/cfb.rb +10 -0
- data/lib/xlsxrb/ooxml/reader/listeners/core_listeners.rb +77 -38
- data/lib/xlsxrb/ooxml/reader/listeners/drawing_listeners.rb +187 -24
- data/lib/xlsxrb/ooxml/reader/listeners/feature_listeners.rb +115 -2
- data/lib/xlsxrb/ooxml/reader/listeners/style_listeners.rb +28 -18
- data/lib/xlsxrb/ooxml/reader.rb +253 -136
- data/lib/xlsxrb/ooxml/shared_strings_parser.rb +83 -28
- data/lib/xlsxrb/ooxml/styles_parser.rb +76 -25
- data/lib/xlsxrb/ooxml/utils.rb +59 -2
- data/lib/xlsxrb/ooxml/workbook_parser.rb +57 -3
- data/lib/xlsxrb/ooxml/workbook_writer.rb +471 -86
- data/lib/xlsxrb/ooxml/worksheet_parser.rb +210 -127
- data/lib/xlsxrb/ooxml/worksheet_writer.rb +515 -184
- data/lib/xlsxrb/ooxml/writer/drawing_xml.rb +595 -453
- data/lib/xlsxrb/ooxml/writer/features_xml.rb +26 -9
- data/lib/xlsxrb/ooxml/writer/styles_xml.rb +87 -24
- data/lib/xlsxrb/ooxml/writer.rb +299 -59
- data/lib/xlsxrb/ooxml/xml_builder.rb +12 -4
- data/lib/xlsxrb/ooxml/xml_parser.rb +45 -0
- data/lib/xlsxrb/ooxml/zip_reader.rb +48 -29
- data/lib/xlsxrb/ooxml/zip_writer.rb +15 -5
- data/lib/xlsxrb/stream_row.rb +4 -3
- data/lib/xlsxrb/stream_sheet.rb +182 -8
- data/lib/xlsxrb/stream_writer.rb +977 -84
- data/lib/xlsxrb/style_builder.rb +59 -6
- data/lib/xlsxrb/utils.rb +80 -0
- data/lib/xlsxrb/version.rb +1 -1
- data/lib/xlsxrb/workbook_builder.rb +307 -24
- data/lib/xlsxrb/worksheet_builder.rb +1150 -49
- data/lib/xlsxrb.rb +705 -142
- data/sig/generated/xlsxrb/chart_builder.rbs +31 -3
- data/sig/generated/xlsxrb/dsl_helpers.rbs +119 -4
- data/sig/generated/xlsxrb/elements/cell.rbs +20 -3
- data/sig/generated/xlsxrb/elements/column.rbs +3 -3
- data/sig/generated/xlsxrb/elements/styles.rbs +271 -5
- data/sig/generated/xlsxrb/elements/types.rbs +2 -0
- data/sig/generated/xlsxrb/elements/workbook.rbs +63 -3
- data/sig/generated/xlsxrb/elements/worksheet.rbs +92 -2
- data/sig/generated/xlsxrb/ooxml/reader/listeners/core_listeners.rbs +2 -0
- data/sig/generated/xlsxrb/ooxml/reader/listeners/drawing_listeners.rbs +74 -2
- data/sig/generated/xlsxrb/ooxml/reader/listeners/feature_listeners.rbs +36 -0
- data/sig/generated/xlsxrb/ooxml/reader/listeners/style_listeners.rbs +5 -0
- data/sig/generated/xlsxrb/ooxml/reader.rbs +29 -0
- data/sig/generated/xlsxrb/ooxml/shared_strings_parser.rbs +3 -1
- data/sig/generated/xlsxrb/ooxml/styles_parser.rbs +5 -0
- data/sig/generated/xlsxrb/ooxml/utils.rbs +22 -0
- data/sig/generated/xlsxrb/ooxml/workbook_parser.rbs +15 -0
- data/sig/generated/xlsxrb/ooxml/workbook_writer.rbs +20 -4
- data/sig/generated/xlsxrb/ooxml/worksheet_parser.rbs +19 -3
- data/sig/generated/xlsxrb/ooxml/worksheet_writer.rbs +15 -2
- data/sig/generated/xlsxrb/ooxml/writer/drawing_xml.rbs +16 -0
- data/sig/generated/xlsxrb/ooxml/writer/styles_xml.rbs +5 -2
- data/sig/generated/xlsxrb/ooxml/writer.rbs +42 -8
- data/sig/generated/xlsxrb/ooxml/xml_builder.rbs +4 -1
- data/sig/generated/xlsxrb/ooxml/zip_reader.rbs +6 -6
- data/sig/generated/xlsxrb/ooxml/zip_writer.rbs +8 -2
- data/sig/generated/xlsxrb/stream_row.rbs +3 -2
- data/sig/generated/xlsxrb/stream_sheet.rbs +122 -6
- data/sig/generated/xlsxrb/stream_writer.rbs +606 -30
- data/sig/generated/xlsxrb/style_builder.rbs +24 -6
- data/sig/generated/xlsxrb/utils.rbs +33 -0
- data/sig/generated/xlsxrb/workbook_builder.rbs +87 -5
- data/sig/generated/xlsxrb/worksheet_builder.rbs +557 -12
- data/sig/generated/xlsxrb.rbs +118 -20
- metadata +2 -1
|
@@ -1075,9 +1075,22 @@ module Xlsxrb
|
|
|
1075
1075
|
class ChartTypeListener
|
|
1076
1076
|
include REXML::SAX2Listener
|
|
1077
1077
|
|
|
1078
|
-
attr_reader :
|
|
1078
|
+
attr_reader :title, :title_overlay, :title_font,
|
|
1079
1079
|
:title_fill_color, :title_no_fill, :title_line_color, :title_line_width, :title_line_dash,
|
|
1080
1080
|
:series, :legend, :data_labels, :cat_axis_title, :val_axis_title,
|
|
1081
|
+
:secondary_value_axis, :sec_val_axis_title, :chart_types,
|
|
1082
|
+
:sec_val_axis_major_gridlines, :sec_val_axis_minor_gridlines,
|
|
1083
|
+
:sec_val_axis_delete, :sec_val_axis_orientation, :sec_val_axis_num_fmt,
|
|
1084
|
+
:sec_val_axis_major_tick_mark, :sec_val_axis_minor_tick_mark, :sec_val_axis_crosses,
|
|
1085
|
+
:sec_val_axis_crosses_at, :sec_val_axis_cross_between, :sec_val_axis_major_unit,
|
|
1086
|
+
:sec_val_axis_minor_unit, :sec_val_axis_disp_units, :sec_val_axis_scaling_max,
|
|
1087
|
+
:sec_val_axis_scaling_min, :sec_val_axis_log_base, :sec_val_axis_pos,
|
|
1088
|
+
:sec_val_axis_label_rotation, :sec_val_axis_font, :sec_val_axis_fill,
|
|
1089
|
+
:sec_val_axis_no_fill, :sec_val_axis_line_color, :sec_val_axis_line_width,
|
|
1090
|
+
:sec_val_axis_line_dash, :sec_val_axis_tick_lbl_pos,
|
|
1091
|
+
:sec_val_axis_title_font, :sec_val_axis_title_fill, :sec_val_axis_title_no_fill,
|
|
1092
|
+
:sec_val_axis_title_line_color, :sec_val_axis_title_line_width, :sec_val_axis_title_line_dash,
|
|
1093
|
+
:sec_val_axis_title_layout, :sec_val_axis_title_rotation,
|
|
1081
1094
|
:grouping, :bar_dir, :vary_colors, :plot_vis_only, :disp_blanks_as, :style, :auto_title_deleted,
|
|
1082
1095
|
:rounded_corners, :cat_axis_tick_lbl_pos, :val_axis_tick_lbl_pos,
|
|
1083
1096
|
:cat_axis_major_gridlines, :val_axis_major_gridlines,
|
|
@@ -1134,8 +1147,54 @@ module Xlsxrb
|
|
|
1134
1147
|
bar3DChart line3DChart pie3DChart area3DChart surfaceChart surface3DChart stockChart bubbleChart
|
|
1135
1148
|
ofPieChart].freeze
|
|
1136
1149
|
|
|
1150
|
+
def chart_type
|
|
1151
|
+
return "comboChart" if @chart_types && @chart_types.uniq.size > 1
|
|
1152
|
+
|
|
1153
|
+
@chart_types&.first || @chart_type
|
|
1154
|
+
end
|
|
1155
|
+
|
|
1137
1156
|
def initialize
|
|
1138
1157
|
@chart_type = nil
|
|
1158
|
+
@chart_types = []
|
|
1159
|
+
@current_chart_type = nil
|
|
1160
|
+
@current_chart_series = []
|
|
1161
|
+
@val_ax_count = 0
|
|
1162
|
+
@is_secondary_val_ax = false
|
|
1163
|
+
@secondary_value_axis = nil
|
|
1164
|
+
@sec_val_axis_title = nil
|
|
1165
|
+
@sec_val_axis_major_gridlines = false
|
|
1166
|
+
@sec_val_axis_minor_gridlines = false
|
|
1167
|
+
@sec_val_axis_delete = nil
|
|
1168
|
+
@sec_val_axis_orientation = nil
|
|
1169
|
+
@sec_val_axis_num_fmt = nil
|
|
1170
|
+
@sec_val_axis_major_tick_mark = nil
|
|
1171
|
+
@sec_val_axis_minor_tick_mark = nil
|
|
1172
|
+
@sec_val_axis_crosses = nil
|
|
1173
|
+
@sec_val_axis_crosses_at = nil
|
|
1174
|
+
@sec_val_axis_cross_between = nil
|
|
1175
|
+
@sec_val_axis_major_unit = nil
|
|
1176
|
+
@sec_val_axis_minor_unit = nil
|
|
1177
|
+
@sec_val_axis_disp_units = nil
|
|
1178
|
+
@sec_val_axis_scaling_max = nil
|
|
1179
|
+
@sec_val_axis_scaling_min = nil
|
|
1180
|
+
@sec_val_axis_log_base = nil
|
|
1181
|
+
@sec_val_axis_pos = nil
|
|
1182
|
+
@sec_val_axis_label_rotation = nil
|
|
1183
|
+
@sec_val_axis_font = nil
|
|
1184
|
+
@sec_val_axis_fill = nil
|
|
1185
|
+
@sec_val_axis_no_fill = nil
|
|
1186
|
+
@sec_val_axis_line_color = nil
|
|
1187
|
+
@sec_val_axis_line_width = nil
|
|
1188
|
+
@sec_val_axis_line_dash = nil
|
|
1189
|
+
@sec_val_axis_tick_lbl_pos = nil
|
|
1190
|
+
@sec_val_axis_title_font = nil
|
|
1191
|
+
@sec_val_axis_title_fill = nil
|
|
1192
|
+
@sec_val_axis_title_no_fill = nil
|
|
1193
|
+
@sec_val_axis_title_line_color = nil
|
|
1194
|
+
@sec_val_axis_title_line_width = nil
|
|
1195
|
+
@sec_val_axis_title_line_dash = nil
|
|
1196
|
+
@sec_val_axis_title_layout = nil
|
|
1197
|
+
@sec_val_axis_title_rotation = nil
|
|
1139
1198
|
@title = nil
|
|
1140
1199
|
@title_overlay = nil
|
|
1141
1200
|
@title_font = nil
|
|
@@ -1441,13 +1500,25 @@ module Xlsxrb
|
|
|
1441
1500
|
|
|
1442
1501
|
def start_element(_uri, local_name, qname, attributes)
|
|
1443
1502
|
name = element_name(local_name, qname)
|
|
1444
|
-
|
|
1503
|
+
if CHART_TYPES.include?(name)
|
|
1504
|
+
@chart_type ||= name
|
|
1505
|
+
@chart_types << name
|
|
1506
|
+
@current_chart_type = name
|
|
1507
|
+
@current_chart_series = []
|
|
1508
|
+
end
|
|
1445
1509
|
|
|
1446
1510
|
case name
|
|
1447
1511
|
when "chart"
|
|
1448
1512
|
@inside_chart = true
|
|
1449
1513
|
when "plotArea"
|
|
1450
1514
|
@inside_plot_area = true
|
|
1515
|
+
when "axId"
|
|
1516
|
+
val = attributes["val"]
|
|
1517
|
+
if @inside_val_ax
|
|
1518
|
+
@is_secondary_val_ax = val == "3" || @val_ax_count > 1
|
|
1519
|
+
elsif @current_chart_series && val == "3"
|
|
1520
|
+
@current_chart_series.each { |s| s[:secondary_axis] = true }
|
|
1521
|
+
end
|
|
1451
1522
|
when "grouping"
|
|
1452
1523
|
@grouping = attributes["val"] if attributes["val"]
|
|
1453
1524
|
when "barDir"
|
|
@@ -2191,7 +2262,11 @@ module Xlsxrb
|
|
|
2191
2262
|
if @inside_cat_ax
|
|
2192
2263
|
@cat_axis_delete = attributes["val"] == "1"
|
|
2193
2264
|
elsif @inside_val_ax
|
|
2194
|
-
@
|
|
2265
|
+
if @is_secondary_val_ax
|
|
2266
|
+
@sec_val_axis_delete = attributes["val"] == "1"
|
|
2267
|
+
else
|
|
2268
|
+
@val_axis_delete = attributes["val"] == "1"
|
|
2269
|
+
end
|
|
2195
2270
|
end
|
|
2196
2271
|
end
|
|
2197
2272
|
when "overlay"
|
|
@@ -2285,6 +2360,8 @@ module Xlsxrb
|
|
|
2285
2360
|
@cat_axis_type = :date
|
|
2286
2361
|
when "valAx"
|
|
2287
2362
|
@inside_val_ax = true
|
|
2363
|
+
@val_ax_count += 1
|
|
2364
|
+
@is_secondary_val_ax = (@val_ax_count > 1)
|
|
2288
2365
|
when "scaling"
|
|
2289
2366
|
@inside_scaling = true if @inside_cat_ax || @inside_val_ax
|
|
2290
2367
|
when "logBase"
|
|
@@ -2292,7 +2369,11 @@ module Xlsxrb
|
|
|
2292
2369
|
if @inside_cat_ax
|
|
2293
2370
|
@cat_axis_log_base = attributes["val"].to_f
|
|
2294
2371
|
elsif @inside_val_ax
|
|
2295
|
-
@
|
|
2372
|
+
if @is_secondary_val_ax
|
|
2373
|
+
@sec_val_axis_log_base = attributes["val"].to_f
|
|
2374
|
+
else
|
|
2375
|
+
@val_axis_log_base = attributes["val"].to_f
|
|
2376
|
+
end
|
|
2296
2377
|
end
|
|
2297
2378
|
end
|
|
2298
2379
|
when "max"
|
|
@@ -2300,7 +2381,11 @@ module Xlsxrb
|
|
|
2300
2381
|
if @inside_cat_ax
|
|
2301
2382
|
@cat_axis_scaling_max = attributes["val"].to_f
|
|
2302
2383
|
elsif @inside_val_ax
|
|
2303
|
-
@
|
|
2384
|
+
if @is_secondary_val_ax
|
|
2385
|
+
@sec_val_axis_scaling_max = attributes["val"].to_f
|
|
2386
|
+
else
|
|
2387
|
+
@val_axis_scaling_max = attributes["val"].to_f
|
|
2388
|
+
end
|
|
2304
2389
|
end
|
|
2305
2390
|
end
|
|
2306
2391
|
when "min"
|
|
@@ -2308,7 +2393,11 @@ module Xlsxrb
|
|
|
2308
2393
|
if @inside_cat_ax
|
|
2309
2394
|
@cat_axis_scaling_min = attributes["val"].to_f
|
|
2310
2395
|
elsif @inside_val_ax
|
|
2311
|
-
@
|
|
2396
|
+
if @is_secondary_val_ax
|
|
2397
|
+
@sec_val_axis_scaling_min = attributes["val"].to_f
|
|
2398
|
+
else
|
|
2399
|
+
@val_axis_scaling_min = attributes["val"].to_f
|
|
2400
|
+
end
|
|
2312
2401
|
end
|
|
2313
2402
|
end
|
|
2314
2403
|
when "orientation"
|
|
@@ -2316,7 +2405,11 @@ module Xlsxrb
|
|
|
2316
2405
|
if @inside_cat_ax
|
|
2317
2406
|
@cat_axis_orientation = attributes["val"]
|
|
2318
2407
|
elsif @inside_val_ax
|
|
2319
|
-
@
|
|
2408
|
+
if @is_secondary_val_ax
|
|
2409
|
+
@sec_val_axis_orientation = attributes["val"]
|
|
2410
|
+
else
|
|
2411
|
+
@val_axis_orientation = attributes["val"]
|
|
2412
|
+
end
|
|
2320
2413
|
end
|
|
2321
2414
|
end
|
|
2322
2415
|
when "numFmt"
|
|
@@ -2339,7 +2432,11 @@ module Xlsxrb
|
|
|
2339
2432
|
if @inside_cat_ax
|
|
2340
2433
|
@cat_axis_num_fmt = nf
|
|
2341
2434
|
elsif @inside_val_ax
|
|
2342
|
-
@
|
|
2435
|
+
if @is_secondary_val_ax
|
|
2436
|
+
@sec_val_axis_num_fmt = nf
|
|
2437
|
+
else
|
|
2438
|
+
@val_axis_num_fmt = nf
|
|
2439
|
+
end
|
|
2343
2440
|
end
|
|
2344
2441
|
elsif @inside_dlbl && @current_dlbl && attributes["formatCode"]
|
|
2345
2442
|
nf = { format_code: attributes["formatCode"] }
|
|
@@ -2356,7 +2453,11 @@ module Xlsxrb
|
|
|
2356
2453
|
if @inside_cat_ax
|
|
2357
2454
|
@cat_axis_major_tick_mark = attributes["val"]
|
|
2358
2455
|
elsif @inside_val_ax
|
|
2359
|
-
@
|
|
2456
|
+
if @is_secondary_val_ax
|
|
2457
|
+
@sec_val_axis_major_tick_mark = attributes["val"]
|
|
2458
|
+
else
|
|
2459
|
+
@val_axis_major_tick_mark = attributes["val"]
|
|
2460
|
+
end
|
|
2360
2461
|
end
|
|
2361
2462
|
end
|
|
2362
2463
|
when "minorTickMark"
|
|
@@ -2364,7 +2465,11 @@ module Xlsxrb
|
|
|
2364
2465
|
if @inside_cat_ax
|
|
2365
2466
|
@cat_axis_minor_tick_mark = attributes["val"]
|
|
2366
2467
|
elsif @inside_val_ax
|
|
2367
|
-
@
|
|
2468
|
+
if @is_secondary_val_ax
|
|
2469
|
+
@sec_val_axis_minor_tick_mark = attributes["val"]
|
|
2470
|
+
else
|
|
2471
|
+
@val_axis_minor_tick_mark = attributes["val"]
|
|
2472
|
+
end
|
|
2368
2473
|
end
|
|
2369
2474
|
end
|
|
2370
2475
|
when "crosses"
|
|
@@ -2372,7 +2477,11 @@ module Xlsxrb
|
|
|
2372
2477
|
if @inside_cat_ax
|
|
2373
2478
|
@cat_axis_crosses = attributes["val"]
|
|
2374
2479
|
elsif @inside_val_ax
|
|
2375
|
-
@
|
|
2480
|
+
if @is_secondary_val_ax
|
|
2481
|
+
@sec_val_axis_crosses = attributes["val"]
|
|
2482
|
+
else
|
|
2483
|
+
@val_axis_crosses = attributes["val"]
|
|
2484
|
+
end
|
|
2376
2485
|
end
|
|
2377
2486
|
end
|
|
2378
2487
|
when "crossesAt"
|
|
@@ -2380,7 +2489,11 @@ module Xlsxrb
|
|
|
2380
2489
|
if @inside_cat_ax
|
|
2381
2490
|
@cat_axis_crosses_at = attributes["val"]&.to_f
|
|
2382
2491
|
elsif @inside_val_ax
|
|
2383
|
-
@
|
|
2492
|
+
if @is_secondary_val_ax
|
|
2493
|
+
@sec_val_axis_crosses_at = attributes["val"]&.to_f
|
|
2494
|
+
else
|
|
2495
|
+
@val_axis_crosses_at = attributes["val"]&.to_f
|
|
2496
|
+
end
|
|
2384
2497
|
end
|
|
2385
2498
|
end
|
|
2386
2499
|
when "tickLblSkip"
|
|
@@ -2400,22 +2513,40 @@ module Xlsxrb
|
|
|
2400
2513
|
if @inside_cat_ax
|
|
2401
2514
|
@cat_axis_pos = attributes["val"]
|
|
2402
2515
|
elsif @inside_val_ax
|
|
2403
|
-
@
|
|
2516
|
+
if @is_secondary_val_ax
|
|
2517
|
+
@sec_val_axis_pos = attributes["val"]
|
|
2518
|
+
else
|
|
2519
|
+
@val_axis_pos = attributes["val"]
|
|
2520
|
+
end
|
|
2404
2521
|
end
|
|
2405
2522
|
end
|
|
2406
2523
|
when "crossBetween"
|
|
2407
|
-
|
|
2524
|
+
if @inside_val_ax && attributes["val"]
|
|
2525
|
+
if @is_secondary_val_ax
|
|
2526
|
+
@sec_val_axis_cross_between = attributes["val"]
|
|
2527
|
+
else
|
|
2528
|
+
@val_axis_cross_between = attributes["val"]
|
|
2529
|
+
end
|
|
2530
|
+
end
|
|
2408
2531
|
when "majorUnit"
|
|
2409
2532
|
if @inside_cat_ax && @cat_axis_type == :date && attributes["val"]
|
|
2410
2533
|
@cat_axis_major_unit = attributes["val"].to_f
|
|
2411
2534
|
elsif @inside_val_ax && attributes["val"]
|
|
2412
|
-
@
|
|
2535
|
+
if @is_secondary_val_ax
|
|
2536
|
+
@sec_val_axis_major_unit = attributes["val"].to_f
|
|
2537
|
+
else
|
|
2538
|
+
@val_axis_major_unit = attributes["val"].to_f
|
|
2539
|
+
end
|
|
2413
2540
|
end
|
|
2414
2541
|
when "minorUnit"
|
|
2415
2542
|
if @inside_cat_ax && @cat_axis_type == :date && attributes["val"]
|
|
2416
2543
|
@cat_axis_minor_unit = attributes["val"].to_f
|
|
2417
2544
|
elsif @inside_val_ax && attributes["val"]
|
|
2418
|
-
@
|
|
2545
|
+
if @is_secondary_val_ax
|
|
2546
|
+
@sec_val_axis_minor_unit = attributes["val"].to_f
|
|
2547
|
+
else
|
|
2548
|
+
@val_axis_minor_unit = attributes["val"].to_f
|
|
2549
|
+
end
|
|
2419
2550
|
end
|
|
2420
2551
|
when "baseTimeUnit"
|
|
2421
2552
|
@cat_axis_base_time_unit = attributes["val"] if @inside_cat_ax && attributes["val"]
|
|
@@ -2490,7 +2621,11 @@ module Xlsxrb
|
|
|
2490
2621
|
if @inside_cat_ax
|
|
2491
2622
|
@cat_axis_tick_lbl_pos = attributes["val"]
|
|
2492
2623
|
elsif @inside_val_ax
|
|
2493
|
-
@
|
|
2624
|
+
if @is_secondary_val_ax
|
|
2625
|
+
@sec_val_axis_tick_lbl_pos = attributes["val"]
|
|
2626
|
+
else
|
|
2627
|
+
@val_axis_tick_lbl_pos = attributes["val"]
|
|
2628
|
+
end
|
|
2494
2629
|
end
|
|
2495
2630
|
end
|
|
2496
2631
|
when "majorGridlines"
|
|
@@ -2499,8 +2634,13 @@ module Xlsxrb
|
|
|
2499
2634
|
@cat_axis_major_gridlines = true
|
|
2500
2635
|
@gridlines_target = :cat_axis_major_gridlines
|
|
2501
2636
|
elsif @inside_val_ax
|
|
2502
|
-
@
|
|
2503
|
-
|
|
2637
|
+
if @is_secondary_val_ax
|
|
2638
|
+
@sec_val_axis_major_gridlines = true
|
|
2639
|
+
@gridlines_target = :sec_val_axis_major_gridlines
|
|
2640
|
+
else
|
|
2641
|
+
@val_axis_major_gridlines = true
|
|
2642
|
+
@gridlines_target = :val_axis_major_gridlines
|
|
2643
|
+
end
|
|
2504
2644
|
end
|
|
2505
2645
|
when "minorGridlines"
|
|
2506
2646
|
@inside_gridlines = true
|
|
@@ -2508,8 +2648,13 @@ module Xlsxrb
|
|
|
2508
2648
|
@cat_axis_minor_gridlines = true
|
|
2509
2649
|
@gridlines_target = :cat_axis_minor_gridlines
|
|
2510
2650
|
elsif @inside_val_ax
|
|
2511
|
-
@
|
|
2512
|
-
|
|
2651
|
+
if @is_secondary_val_ax
|
|
2652
|
+
@sec_val_axis_minor_gridlines = true
|
|
2653
|
+
@gridlines_target = :sec_val_axis_minor_gridlines
|
|
2654
|
+
else
|
|
2655
|
+
@val_axis_minor_gridlines = true
|
|
2656
|
+
@gridlines_target = :val_axis_minor_gridlines
|
|
2657
|
+
end
|
|
2513
2658
|
end
|
|
2514
2659
|
when "plotVisOnly"
|
|
2515
2660
|
@plot_vis_only = attributes["val"] == "1" if attributes["val"]
|
|
@@ -2616,7 +2761,11 @@ module Xlsxrb
|
|
|
2616
2761
|
if @inside_cat_ax
|
|
2617
2762
|
@cat_axis_title = @text_buffer.dup
|
|
2618
2763
|
elsif @inside_val_ax
|
|
2619
|
-
|
|
2764
|
+
if @is_secondary_val_ax
|
|
2765
|
+
@sec_val_axis_title = @text_buffer.dup
|
|
2766
|
+
else
|
|
2767
|
+
@val_axis_title = @text_buffer.dup
|
|
2768
|
+
end
|
|
2620
2769
|
end
|
|
2621
2770
|
elsif @inside_title && @title_depth == 1
|
|
2622
2771
|
@title = @text_buffer.dup
|
|
@@ -2737,7 +2886,11 @@ module Xlsxrb
|
|
|
2737
2886
|
@current_trendline[:name] = @text_buffer.dup if @inside_trendline_name && @current_trendline
|
|
2738
2887
|
@inside_trendline_name = false
|
|
2739
2888
|
when "ser"
|
|
2740
|
-
|
|
2889
|
+
if @current_ser
|
|
2890
|
+
@current_ser[:chart_type] = @current_chart_type if @current_chart_type
|
|
2891
|
+
@current_chart_series << @current_ser if @current_chart_series
|
|
2892
|
+
@series << @current_ser
|
|
2893
|
+
end
|
|
2741
2894
|
@current_ser = nil
|
|
2742
2895
|
@inside_ser = false
|
|
2743
2896
|
@inside_ser_sp_pr = false
|
|
@@ -3007,6 +3160,7 @@ module Xlsxrb
|
|
|
3007
3160
|
@inside_axis_def_rpr = false
|
|
3008
3161
|
when "valAx"
|
|
3009
3162
|
@inside_val_ax = false
|
|
3163
|
+
@is_secondary_val_ax = false
|
|
3010
3164
|
@inside_axis_tx_pr = false
|
|
3011
3165
|
@inside_axis_def_rpr = false
|
|
3012
3166
|
@inside_disp_units = false
|
|
@@ -3145,6 +3299,11 @@ module Xlsxrb
|
|
|
3145
3299
|
@inside_leader_lines_ln = false
|
|
3146
3300
|
@inside_leader_lines_solid_fill = false
|
|
3147
3301
|
end
|
|
3302
|
+
|
|
3303
|
+
return unless CHART_TYPES.include?(name)
|
|
3304
|
+
|
|
3305
|
+
@current_chart_type = nil
|
|
3306
|
+
@current_chart_series = nil
|
|
3148
3307
|
end
|
|
3149
3308
|
|
|
3150
3309
|
private
|
|
@@ -3154,7 +3313,11 @@ module Xlsxrb
|
|
|
3154
3313
|
if @inside_cat_ax
|
|
3155
3314
|
(@cat_axis_title_layout ||= {})[key] = value
|
|
3156
3315
|
elsif @inside_val_ax
|
|
3157
|
-
|
|
3316
|
+
if @is_secondary_val_ax
|
|
3317
|
+
(@sec_val_axis_title_layout ||= {})[key] = value
|
|
3318
|
+
else
|
|
3319
|
+
(@val_axis_title_layout ||= {})[key] = value
|
|
3320
|
+
end
|
|
3158
3321
|
end
|
|
3159
3322
|
elsif @inside_title && @title_depth == 1
|
|
3160
3323
|
(@title_layout ||= {})[key] = value
|
|
@@ -449,6 +449,12 @@ module Xlsxrb
|
|
|
449
449
|
@properties[:summary_right] = %w[1 true].include?(sr) unless sr.nil?
|
|
450
450
|
sos = attributes["showOutlineSymbols"]
|
|
451
451
|
@properties[:show_outline_symbols] = %w[1 true].include?(sos) unless sos.nil?
|
|
452
|
+
@properties[:outline_properties] = {
|
|
453
|
+
apply_styles: @properties[:apply_styles],
|
|
454
|
+
summary_below: @properties[:summary_below],
|
|
455
|
+
summary_right: @properties[:summary_right],
|
|
456
|
+
show_outline_symbols: @properties[:show_outline_symbols]
|
|
457
|
+
}.compact
|
|
452
458
|
end
|
|
453
459
|
when "pageSetUpPr"
|
|
454
460
|
if @inside_sheet_pr
|
|
@@ -962,11 +968,14 @@ module Xlsxrb
|
|
|
962
968
|
when "formula2"
|
|
963
969
|
@inside_formula2 = true
|
|
964
970
|
@text_buffer = +""
|
|
971
|
+
when "sqref"
|
|
972
|
+
@inside_sqref = true
|
|
973
|
+
@text_buffer = +""
|
|
965
974
|
end
|
|
966
975
|
end
|
|
967
976
|
|
|
968
977
|
def characters(text)
|
|
969
|
-
@text_buffer << text if @inside_formula1 || @inside_formula2
|
|
978
|
+
@text_buffer << text if @inside_formula1 || @inside_formula2 || @inside_sqref
|
|
970
979
|
end
|
|
971
980
|
|
|
972
981
|
def end_element(_uri, local_name, qname)
|
|
@@ -978,6 +987,9 @@ module Xlsxrb
|
|
|
978
987
|
when "formula2"
|
|
979
988
|
@current_dv[:formula2] = @text_buffer.dup if @current_dv
|
|
980
989
|
@inside_formula2 = false
|
|
990
|
+
when "sqref"
|
|
991
|
+
@current_dv[:sqref] = @text_buffer.strip if @current_dv && (@current_dv[:sqref].nil? || @current_dv[:sqref].empty?)
|
|
992
|
+
@inside_sqref = false
|
|
981
993
|
when "dataValidation"
|
|
982
994
|
@validations << @current_dv if @current_dv
|
|
983
995
|
@current_dv = nil
|
|
@@ -1388,7 +1400,11 @@ module Xlsxrb
|
|
|
1388
1400
|
name = element_name(local_name, qname)
|
|
1389
1401
|
case name
|
|
1390
1402
|
when "calculatedColumnFormula"
|
|
1391
|
-
|
|
1403
|
+
if @current_column
|
|
1404
|
+
val = @text_buffer.dup
|
|
1405
|
+
@current_column[:calculated_column_formula] = val
|
|
1406
|
+
@current_column[:data_formula] = val
|
|
1407
|
+
end
|
|
1392
1408
|
@inside_calc_formula = false
|
|
1393
1409
|
when "totalsRowFormula"
|
|
1394
1410
|
@current_column[:totals_row_formula] = @text_buffer.dup if @current_column
|
|
@@ -1797,6 +1813,103 @@ module Xlsxrb
|
|
|
1797
1813
|
end
|
|
1798
1814
|
end
|
|
1799
1815
|
end
|
|
1816
|
+
|
|
1817
|
+
# SAX2 listener for parsing <personList> element in xl/persons/person.xml.
|
|
1818
|
+
class PersonListListener
|
|
1819
|
+
include REXML::SAX2Listener
|
|
1820
|
+
|
|
1821
|
+
attr_reader :persons
|
|
1822
|
+
|
|
1823
|
+
def initialize
|
|
1824
|
+
@persons = []
|
|
1825
|
+
end
|
|
1826
|
+
|
|
1827
|
+
def start_element(_uri, local_name, qname, attributes)
|
|
1828
|
+
name = element_name(local_name, qname)
|
|
1829
|
+
return unless name == "person"
|
|
1830
|
+
|
|
1831
|
+
@persons << {
|
|
1832
|
+
id: attributes["id"],
|
|
1833
|
+
display_name: attributes["displayName"],
|
|
1834
|
+
user_id: attributes["userId"],
|
|
1835
|
+
provider_id: attributes["providerId"]
|
|
1836
|
+
}.compact
|
|
1837
|
+
end
|
|
1838
|
+
|
|
1839
|
+
def end_element(_uri, _local_name, _qname); end
|
|
1840
|
+
|
|
1841
|
+
private
|
|
1842
|
+
|
|
1843
|
+
def element_name(local_name, qname)
|
|
1844
|
+
if local_name.nil? || local_name.empty?
|
|
1845
|
+
qname.to_s.split(":").last
|
|
1846
|
+
else
|
|
1847
|
+
local_name
|
|
1848
|
+
end
|
|
1849
|
+
end
|
|
1850
|
+
end
|
|
1851
|
+
|
|
1852
|
+
# SAX2 listener for parsing <ThreadedComments> element in xl/threadedComments/threadedComment{N}.xml.
|
|
1853
|
+
class ThreadedCommentsListener
|
|
1854
|
+
include REXML::SAX2Listener
|
|
1855
|
+
|
|
1856
|
+
attr_reader :threaded_comments
|
|
1857
|
+
|
|
1858
|
+
def initialize
|
|
1859
|
+
@threaded_comments = []
|
|
1860
|
+
@current_comment = nil
|
|
1861
|
+
@inside_text = false
|
|
1862
|
+
@text_buffer = +""
|
|
1863
|
+
end
|
|
1864
|
+
|
|
1865
|
+
def start_element(_uri, local_name, qname, attributes)
|
|
1866
|
+
name = element_name(local_name, qname)
|
|
1867
|
+
case name
|
|
1868
|
+
when "threadedComment"
|
|
1869
|
+
@current_comment = {
|
|
1870
|
+
ref: attributes["ref"],
|
|
1871
|
+
dt: attributes["dT"] || attributes["dt"],
|
|
1872
|
+
person_id: attributes["personId"],
|
|
1873
|
+
id: attributes["id"]
|
|
1874
|
+
}
|
|
1875
|
+
@current_comment[:parent_id] = attributes["parentId"] if attributes["parentId"]
|
|
1876
|
+
@current_comment[:done] = %w[1 true].include?(attributes["done"]) if attributes.key?("done")
|
|
1877
|
+
when "text"
|
|
1878
|
+
if @current_comment
|
|
1879
|
+
@inside_text = true
|
|
1880
|
+
@text_buffer = +""
|
|
1881
|
+
end
|
|
1882
|
+
end
|
|
1883
|
+
end
|
|
1884
|
+
|
|
1885
|
+
def characters(text)
|
|
1886
|
+
@text_buffer << text if @inside_text
|
|
1887
|
+
end
|
|
1888
|
+
|
|
1889
|
+
def end_element(_uri, local_name, qname)
|
|
1890
|
+
name = element_name(local_name, qname)
|
|
1891
|
+
case name
|
|
1892
|
+
when "text"
|
|
1893
|
+
if @current_comment && @inside_text
|
|
1894
|
+
@current_comment[:text] = @text_buffer.dup
|
|
1895
|
+
@inside_text = false
|
|
1896
|
+
end
|
|
1897
|
+
when "threadedComment"
|
|
1898
|
+
@threaded_comments << @current_comment if @current_comment
|
|
1899
|
+
@current_comment = nil
|
|
1900
|
+
end
|
|
1901
|
+
end
|
|
1902
|
+
|
|
1903
|
+
private
|
|
1904
|
+
|
|
1905
|
+
def element_name(local_name, qname)
|
|
1906
|
+
if local_name.nil? || local_name.empty?
|
|
1907
|
+
qname.to_s.split(":").last
|
|
1908
|
+
else
|
|
1909
|
+
local_name
|
|
1910
|
+
end
|
|
1911
|
+
end
|
|
1912
|
+
end
|
|
1800
1913
|
end
|
|
1801
1914
|
end
|
|
1802
1915
|
end
|
|
@@ -85,12 +85,12 @@ module Xlsxrb
|
|
|
85
85
|
}
|
|
86
86
|
%w[applyNumberFormat applyFont applyFill applyBorder applyAlignment applyProtection].each do |attr|
|
|
87
87
|
key = attr.gsub(/[A-Z]/) { |m| "_#{m.downcase}" }.to_sym
|
|
88
|
-
xf_entry[key] = attributes[attr]
|
|
88
|
+
xf_entry[key] = boolean_val(attributes[attr]) unless attributes[attr].nil?
|
|
89
89
|
end
|
|
90
90
|
if @inside_cell_xfs
|
|
91
91
|
xf_entry[:xf_id] = attributes["xfId"]&.to_i
|
|
92
|
-
xf_entry[:quote_prefix] = true if attributes["quotePrefix"]
|
|
93
|
-
xf_entry[:pivot_button] = true if attributes["pivotButton"]
|
|
92
|
+
xf_entry[:quote_prefix] = true if boolean_val(attributes["quotePrefix"])
|
|
93
|
+
xf_entry[:pivot_button] = true if boolean_val(attributes["pivotButton"])
|
|
94
94
|
@cell_xfs << xf_entry
|
|
95
95
|
@current_xf = xf_entry
|
|
96
96
|
elsif @inside_cell_style_xfs
|
|
@@ -103,15 +103,15 @@ module Xlsxrb
|
|
|
103
103
|
alignment = {}
|
|
104
104
|
alignment[:horizontal] = attributes["horizontal"] if attributes["horizontal"]
|
|
105
105
|
alignment[:vertical] = attributes["vertical"] if attributes["vertical"]
|
|
106
|
-
alignment[:wrap_text] = true if attributes["wrapText"]
|
|
106
|
+
alignment[:wrap_text] = true if boolean_val(attributes["wrapText"])
|
|
107
107
|
alignment[:text_rotation] = attributes["textRotation"].to_i if attributes["textRotation"]
|
|
108
108
|
alignment[:indent] = attributes["indent"].to_i if attributes["indent"]
|
|
109
109
|
ri = attributes["relativeIndent"]
|
|
110
110
|
alignment[:relative_indent] = ri.to_i if ri
|
|
111
|
-
alignment[:shrink_to_fit] = true if attributes["shrinkToFit"]
|
|
111
|
+
alignment[:shrink_to_fit] = true if boolean_val(attributes["shrinkToFit"])
|
|
112
112
|
ro = attributes["readingOrder"]
|
|
113
113
|
alignment[:reading_order] = ro.to_i if ro
|
|
114
|
-
alignment[:justify_last_line] = true if attributes["justifyLastLine"]
|
|
114
|
+
alignment[:justify_last_line] = true if boolean_val(attributes["justifyLastLine"])
|
|
115
115
|
unless alignment.empty?
|
|
116
116
|
if @inside_dxfs && @current_dxf
|
|
117
117
|
@current_dxf[:alignment] = alignment
|
|
@@ -121,8 +121,8 @@ module Xlsxrb
|
|
|
121
121
|
end
|
|
122
122
|
when "protection"
|
|
123
123
|
protection = {}
|
|
124
|
-
protection[:locked] = attributes["locked"]
|
|
125
|
-
protection[:hidden] = attributes["hidden"]
|
|
124
|
+
protection[:locked] = !%w[0 false].include?(attributes["locked"]&.downcase) if attributes.key?("locked")
|
|
125
|
+
protection[:hidden] = boolean_val(attributes["hidden"]) if attributes.key?("hidden")
|
|
126
126
|
unless protection.empty?
|
|
127
127
|
if @inside_dxfs && @current_dxf
|
|
128
128
|
@current_dxf[:protection] = protection
|
|
@@ -135,19 +135,19 @@ module Xlsxrb
|
|
|
135
135
|
when "font"
|
|
136
136
|
@current_font = {} if @inside_fonts || @inside_dxfs
|
|
137
137
|
when "b"
|
|
138
|
-
@current_font[:bold] =
|
|
138
|
+
@current_font[:bold] = truthy_val?(attributes) if @current_font
|
|
139
139
|
when "i"
|
|
140
|
-
@current_font[:italic] =
|
|
140
|
+
@current_font[:italic] = truthy_val?(attributes) if @current_font
|
|
141
141
|
when "strike"
|
|
142
|
-
@current_font[:strike] =
|
|
142
|
+
@current_font[:strike] = truthy_val?(attributes) if @current_font
|
|
143
143
|
when "shadow"
|
|
144
|
-
@current_font[:shadow] =
|
|
144
|
+
@current_font[:shadow] = truthy_val?(attributes) if @current_font
|
|
145
145
|
when "outline"
|
|
146
|
-
@current_font[:outline] =
|
|
146
|
+
@current_font[:outline] = truthy_val?(attributes) if @current_font
|
|
147
147
|
when "condense"
|
|
148
|
-
@current_font[:condense] =
|
|
148
|
+
@current_font[:condense] = truthy_val?(attributes) if @current_font
|
|
149
149
|
when "extend"
|
|
150
|
-
@current_font[:extend] =
|
|
150
|
+
@current_font[:extend] = truthy_val?(attributes) if @current_font
|
|
151
151
|
when "u"
|
|
152
152
|
if @current_font
|
|
153
153
|
val = attributes["val"]
|
|
@@ -194,10 +194,10 @@ module Xlsxrb
|
|
|
194
194
|
when "border"
|
|
195
195
|
if @inside_borders || @inside_dxfs
|
|
196
196
|
@current_border = {}
|
|
197
|
-
@current_border[:diagonal_up] = true if attributes["diagonalUp"]
|
|
198
|
-
@current_border[:diagonal_down] = true if attributes["diagonalDown"]
|
|
197
|
+
@current_border[:diagonal_up] = true if boolean_val(attributes["diagonalUp"])
|
|
198
|
+
@current_border[:diagonal_down] = true if boolean_val(attributes["diagonalDown"])
|
|
199
199
|
ol = attributes["outline"]
|
|
200
|
-
@current_border[:outline] =
|
|
200
|
+
@current_border[:outline] = boolean_val(ol) unless ol.nil?
|
|
201
201
|
end
|
|
202
202
|
when "left", "right", "top", "bottom", "diagonal", "vertical", "horizontal", "start", "end"
|
|
203
203
|
if @current_border
|
|
@@ -303,6 +303,16 @@ module Xlsxrb
|
|
|
303
303
|
|
|
304
304
|
private
|
|
305
305
|
|
|
306
|
+
#: (untyped val) -> bool
|
|
307
|
+
def boolean_val(val)
|
|
308
|
+
val == "1" || (val&.casecmp?("true") || false)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def truthy_val?(attributes)
|
|
312
|
+
val = attributes["val"]
|
|
313
|
+
val.nil? || (val != "0" && val.downcase != "false")
|
|
314
|
+
end
|
|
315
|
+
|
|
306
316
|
def parse_color(attributes)
|
|
307
317
|
if @inside_mru_colors
|
|
308
318
|
c = {}
|