write_xlsx 1.11.1 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/Changes +9 -0
- data/README.md +1 -1
- data/examples/shape_all.rb +1 -1
- data/lib/write_xlsx/chart/pie.rb +14 -2
- data/lib/write_xlsx/chart/series.rb +48 -0
- data/lib/write_xlsx/chart.rb +65 -12
- data/lib/write_xlsx/chartsheet.rb +10 -1
- data/lib/write_xlsx/col_name.rb +7 -3
- data/lib/write_xlsx/format.rb +6 -6
- data/lib/write_xlsx/package/app.rb +9 -5
- data/lib/write_xlsx/package/conditional_format.rb +2 -2
- data/lib/write_xlsx/package/content_types.rb +22 -0
- data/lib/write_xlsx/package/metadata.rb +139 -22
- data/lib/write_xlsx/package/packager.rb +122 -6
- data/lib/write_xlsx/package/relationships.rb +25 -0
- data/lib/write_xlsx/package/rich_value.rb +70 -0
- data/lib/write_xlsx/package/rich_value_rel.rb +70 -0
- data/lib/write_xlsx/package/rich_value_structure.rb +83 -0
- data/lib/write_xlsx/package/rich_value_types.rb +103 -0
- data/lib/write_xlsx/package/table.rb +74 -20
- data/lib/write_xlsx/package/xml_writer_simple.rb +32 -44
- data/lib/write_xlsx/sheets.rb +6 -2
- data/lib/write_xlsx/sparkline.rb +2 -2
- data/lib/write_xlsx/utility.rb +183 -9
- data/lib/write_xlsx/version.rb +1 -1
- data/lib/write_xlsx/workbook.rb +48 -168
- data/lib/write_xlsx/worksheet/cell_data.rb +35 -16
- data/lib/write_xlsx/worksheet/hyperlink.rb +4 -3
- data/lib/write_xlsx/worksheet.rb +180 -57
- data/write_xlsx.gemspec +2 -0
- metadata +35 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8f704b9674f7d6de467d512cea780114dccc51ed88d99ad4d57727fdafd32b4
|
4
|
+
data.tar.gz: 54df4aec8346b1935bb3b0ba283c11b04f415b3b644308ab8f4cce2f0595d14d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ecbd4957e8b5ee4d9c77e46da68ddfa0f877dd94166551a20c1b76a782209db761a43a86bae340657181ec8993bdc277ee67b66c4c889bc5ad418e6fe2b953c5
|
7
|
+
data.tar.gz: c2a9f0b209de183bbb87ddceb0897dca8708b372d7bb8a5fb7953595440fdaceac60fe4500dafe2ed74585208c6f17b03c554e20c4b5d05af2ec019854b0a259
|
data/.rubocop.yml
CHANGED
data/Changes
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
Change history of write_xlsx rubygem.
|
2
2
|
|
3
|
+
2023-12-26 v1.11.2
|
4
|
+
Fix issue where header images in chartsheets weren't displayed.
|
5
|
+
Add support for custom table total functions.
|
6
|
+
Add chart option to display N/A as empty cells.
|
7
|
+
Add support for leader lines to all chart types.
|
8
|
+
Fix issue where column formulas were overwritten by table data
|
9
|
+
add Worksheet#very_hidden method.
|
10
|
+
Add add trendline equation formatting for chart.
|
11
|
+
|
3
12
|
2023-08-09 v1.11.1
|
4
13
|
Fixed issue #110. Redefining costant Struct::ColInfo
|
5
14
|
|
data/README.md
CHANGED
@@ -85,7 +85,7 @@ the first worksheet in an Excel XML spreadsheet called ruby.xlsx:
|
|
85
85
|
Original Perl module was written by John McNamara(jmcnamara@cpan.org).
|
86
86
|
|
87
87
|
Converted to ruby by Hideo NAKAMURA(nakamrua.hideo@gmail.com)
|
88
|
-
Copyright (c) 2012-
|
88
|
+
Copyright (c) 2012-2024 Hideo NAKAMURA.
|
89
89
|
|
90
90
|
See LICENSE.txt for further details.
|
91
91
|
|
data/examples/shape_all.rb
CHANGED
@@ -218,7 +218,7 @@ shapes_list.each_line do |line|
|
|
218
218
|
line = line.chomp
|
219
219
|
next unless line =~ /^\w/ # Skip blank lines and comments.
|
220
220
|
|
221
|
-
sheet, name = line.split(
|
221
|
+
sheet, name = line.split("\t")
|
222
222
|
if last_sheet != sheet
|
223
223
|
worksheet = workbook.add_worksheet(sheet)
|
224
224
|
row = 2
|
data/lib/write_xlsx/chart/pie.rb
CHANGED
@@ -123,8 +123,7 @@ module Writexlsx
|
|
123
123
|
# Write the <c:legend> element.
|
124
124
|
#
|
125
125
|
def write_legend
|
126
|
-
|
127
|
-
allowed = %w[right left top bottom]
|
126
|
+
allowed = %w[right left top bottom]
|
128
127
|
delete_series = @legend.delete_series || []
|
129
128
|
|
130
129
|
if @legend.position =~ /^overlay_/
|
@@ -207,6 +206,19 @@ module Writexlsx
|
|
207
206
|
def write_first_slice_ang
|
208
207
|
@writer.empty_tag('c:firstSliceAng', [['val', @rotation]])
|
209
208
|
end
|
209
|
+
|
210
|
+
#
|
211
|
+
# Write the <c:showLeaderLines> element. This is for Pie/Doughnut charts.
|
212
|
+
# Other chart types only supported leader lines after Excel 2015 via an
|
213
|
+
# extension element.
|
214
|
+
#
|
215
|
+
def write_show_leader_lines
|
216
|
+
val = 1
|
217
|
+
|
218
|
+
attributes = [['val', val]]
|
219
|
+
|
220
|
+
@writer.empty_tag('c:showLeaderLines', attributes)
|
221
|
+
end
|
210
222
|
end
|
211
223
|
end
|
212
224
|
end
|
@@ -59,10 +59,13 @@ module Writexlsx
|
|
59
59
|
class Trendline < Chartline
|
60
60
|
attr_reader :name, :forward, :backward, :order, :period
|
61
61
|
attr_reader :intercept, :display_equation, :display_r_squared
|
62
|
+
attr_reader :label
|
62
63
|
|
63
64
|
def initialize(params)
|
64
65
|
super(params)
|
65
66
|
|
67
|
+
@label = trendline_label_properties(params[:label])
|
68
|
+
|
66
69
|
@name = params[:name]
|
67
70
|
@forward = params[:forward]
|
68
71
|
@backward = params[:backward]
|
@@ -76,6 +79,51 @@ module Writexlsx
|
|
76
79
|
|
77
80
|
private
|
78
81
|
|
82
|
+
#
|
83
|
+
# Convert user defined trendline label properties to the structure required
|
84
|
+
# internally.
|
85
|
+
#
|
86
|
+
def trendline_label_properties(_label)
|
87
|
+
return unless _label || _label.is_a?(Hash)
|
88
|
+
|
89
|
+
# Copy the user supplied properties.
|
90
|
+
label = {}
|
91
|
+
|
92
|
+
# Set the font properties for the label.
|
93
|
+
label[:font] = convert_font_args(_label[:font]) if ptrue?(_label[:font])
|
94
|
+
|
95
|
+
# Set the line properties for the label.
|
96
|
+
line = line_properties(_label[:line])
|
97
|
+
|
98
|
+
# Allow 'border' as a synonym for 'line'.
|
99
|
+
line = line_properties(_label[:border]) if ptrue?(_label[:border])
|
100
|
+
|
101
|
+
# Set the fill properties for the label.
|
102
|
+
fill = fill_properties(_label[:fill])
|
103
|
+
|
104
|
+
# Set the pattern properties for the label.
|
105
|
+
pattern = pattern_properties(_label[:pattern])
|
106
|
+
|
107
|
+
# Set the gradient fill properties for the label.
|
108
|
+
gradient = gradient_properties(_label[:gradient])
|
109
|
+
|
110
|
+
# Pattern fill overrides solid fill.
|
111
|
+
fill = nil if ptrue?(pattern)
|
112
|
+
|
113
|
+
# Gradient fill overrides solid and pattern fills.
|
114
|
+
if ptrue?(gradient)
|
115
|
+
pattern = nil
|
116
|
+
fill = nil
|
117
|
+
end
|
118
|
+
|
119
|
+
label[:line] = line
|
120
|
+
label[:fill] = fill
|
121
|
+
label[:pattern] = pattern
|
122
|
+
label[:gradient] = gradient
|
123
|
+
|
124
|
+
label
|
125
|
+
end
|
126
|
+
|
79
127
|
def types
|
80
128
|
{
|
81
129
|
exponential: 'exp',
|
data/lib/write_xlsx/chart.rb
CHANGED
@@ -568,6 +568,13 @@ module Writexlsx
|
|
568
568
|
@is_secondary
|
569
569
|
end
|
570
570
|
|
571
|
+
#
|
572
|
+
# Set the option for displaying #N/A as an empty cell in a chart.
|
573
|
+
#
|
574
|
+
def show_na_as_empty_cell
|
575
|
+
@show_na_as_empty = true
|
576
|
+
end
|
577
|
+
|
571
578
|
private
|
572
579
|
|
573
580
|
def axis_setup
|
@@ -598,6 +605,7 @@ module Writexlsx
|
|
598
605
|
@cross_between = 'between'
|
599
606
|
@date_category = false
|
600
607
|
@show_blanks = 'gap'
|
608
|
+
@show_na_as_empty = false
|
601
609
|
@show_hidden_data = false
|
602
610
|
@show_crosses = true
|
603
611
|
end
|
@@ -782,6 +790,9 @@ module Writexlsx
|
|
782
790
|
|
783
791
|
# Write the c:dispBlanksAs element.
|
784
792
|
write_disp_blanks_as
|
793
|
+
|
794
|
+
# Write the c:extLst element.
|
795
|
+
write_ext_lst_display_na if @show_na_as_empty
|
785
796
|
end
|
786
797
|
end
|
787
798
|
|
@@ -950,12 +961,13 @@ module Writexlsx
|
|
950
961
|
write_val(series)
|
951
962
|
# Write the c:smooth element.
|
952
963
|
write_c_smooth(series.smooth) if ptrue?(@smooth_allowed)
|
953
|
-
|
964
|
+
# Write the c:extLst element.
|
965
|
+
write_ext_lst_inverted_fill(series.inverted_color) if series.inverted_color
|
954
966
|
end
|
955
967
|
@series_index += 1
|
956
968
|
end
|
957
969
|
|
958
|
-
def
|
970
|
+
def write_ext_lst_inverted_fill(color)
|
959
971
|
uri = '{6F2FDCE9-48DA-4B69-8628-5D25D57E5C99}'
|
960
972
|
xmlns_c_14 =
|
961
973
|
'http://schemas.microsoft.com/office/drawing/2007/8/2/chart'
|
@@ -980,6 +992,31 @@ module Writexlsx
|
|
980
992
|
end
|
981
993
|
end
|
982
994
|
|
995
|
+
#
|
996
|
+
# Write the <c:extLst> element for the display N/A as empty cell option.
|
997
|
+
#
|
998
|
+
def write_ext_lst_display_na
|
999
|
+
uri = '{56B9EC1D-385E-4148-901F-78D8002777C0}'
|
1000
|
+
xmlns_c_16 = 'http://schemas.microsoft.com/office/drawing/2017/03/chart'
|
1001
|
+
|
1002
|
+
attributes1 = [
|
1003
|
+
['uri', uri],
|
1004
|
+
['xmlns:c16r3', xmlns_c_16]
|
1005
|
+
]
|
1006
|
+
|
1007
|
+
attributes2 = [
|
1008
|
+
['val', 1]
|
1009
|
+
]
|
1010
|
+
|
1011
|
+
@writer.tag_elements('c:extLst') do
|
1012
|
+
@writer.tag_elements('c:ext', attributes1) do
|
1013
|
+
@writer.tag_elements('c16r3:dataDisplayOptions16') do
|
1014
|
+
@writer.empty_tag('c16r3:dispNaAsBlank', attributes2)
|
1015
|
+
end
|
1016
|
+
end
|
1017
|
+
end
|
1018
|
+
end
|
1019
|
+
|
983
1020
|
def write_ser_base(series)
|
984
1021
|
# Write the c:idx element.
|
985
1022
|
write_idx(@series_index)
|
@@ -2122,7 +2159,7 @@ module Writexlsx
|
|
2122
2159
|
# Write the c:dispEq element.
|
2123
2160
|
write_disp_eq
|
2124
2161
|
# Write the c:trendlineLbl element.
|
2125
|
-
write_trendline_lbl
|
2162
|
+
write_trendline_lbl(trendline)
|
2126
2163
|
end
|
2127
2164
|
end
|
2128
2165
|
end
|
@@ -2199,12 +2236,18 @@ module Writexlsx
|
|
2199
2236
|
#
|
2200
2237
|
# Write the <c:trendlineLbl> element.
|
2201
2238
|
#
|
2202
|
-
def write_trendline_lbl
|
2239
|
+
def write_trendline_lbl(trendline)
|
2203
2240
|
@writer.tag_elements('c:trendlineLbl') do
|
2204
2241
|
# Write the c:layout element.
|
2205
2242
|
write_layout
|
2206
2243
|
# Write the c:numFmt element.
|
2207
2244
|
write_trendline_num_fmt
|
2245
|
+
# Write the c:spPr element for the label formatting.
|
2246
|
+
write_sp_pr(trendline.label)
|
2247
|
+
# Write the data label font elements.
|
2248
|
+
if trendline.label && ptrue?(trendline.label[:font])
|
2249
|
+
write_axis_font(trendline.label[:font])
|
2250
|
+
end
|
2208
2251
|
end
|
2209
2252
|
end
|
2210
2253
|
|
@@ -2544,11 +2587,25 @@ module Writexlsx
|
|
2544
2587
|
@writer.data_element('c:separator', data)
|
2545
2588
|
end
|
2546
2589
|
|
2547
|
-
#
|
2548
|
-
#
|
2549
|
-
#
|
2590
|
+
# Write the <c:showLeaderLines> element. This is different for Pie/Doughnut
|
2591
|
+
# charts. Other chart types only supported leader lines after Excel 2015 via
|
2592
|
+
# an extension element.
|
2550
2593
|
def write_show_leader_lines
|
2551
|
-
|
2594
|
+
uri = '{CE6537A1-D6FC-4f65-9D91-7224C49458BB}'
|
2595
|
+
xmlns_c_15 = 'http://schemas.microsoft.com/office/drawing/2012/chart'
|
2596
|
+
|
2597
|
+
attributes1 = [
|
2598
|
+
['uri', uri],
|
2599
|
+
['xmlns:c15', xmlns_c_15]
|
2600
|
+
]
|
2601
|
+
|
2602
|
+
attributes2 = [['val', 1]]
|
2603
|
+
|
2604
|
+
@writer.tag_elements('c:extLst') do
|
2605
|
+
@writer.tag_elements('c:ext', attributes1) do
|
2606
|
+
@writer.empty_tag('c15:showLeaderLines', attributes2)
|
2607
|
+
end
|
2608
|
+
end
|
2552
2609
|
end
|
2553
2610
|
|
2554
2611
|
#
|
@@ -2862,8 +2919,6 @@ module Writexlsx
|
|
2862
2919
|
# Write the <a:fillToRect> element.
|
2863
2920
|
#
|
2864
2921
|
def write_a_fill_to_rect(type)
|
2865
|
-
attributes = []
|
2866
|
-
|
2867
2922
|
attributes = if type == 'shape'
|
2868
2923
|
[
|
2869
2924
|
['l', 50000],
|
@@ -2885,8 +2940,6 @@ module Writexlsx
|
|
2885
2940
|
# Write the <a:tileRect> element.
|
2886
2941
|
#
|
2887
2942
|
def write_a_tile_rect(type)
|
2888
|
-
attributes = []
|
2889
|
-
|
2890
2943
|
attributes = if type == 'shape'
|
2891
2944
|
[]
|
2892
2945
|
else
|
@@ -54,6 +54,8 @@ module Writexlsx
|
|
54
54
|
write_header_footer
|
55
55
|
# Write the drawing element.
|
56
56
|
write_drawings
|
57
|
+
# Write the legaacyDrawingHF element.
|
58
|
+
write_legacy_drawing_hf
|
57
59
|
# Close the worksheet tag.
|
58
60
|
end
|
59
61
|
end
|
@@ -145,6 +147,10 @@ module Writexlsx
|
|
145
147
|
@chart.show_blanks_as(*args)
|
146
148
|
end
|
147
149
|
|
150
|
+
def show_na_as_empty_cell
|
151
|
+
@chart.show_na_as_empty_cell(*args)
|
152
|
+
end
|
153
|
+
|
148
154
|
def show_hidden_data(*args)
|
149
155
|
@chart.show_hidden_data(*args)
|
150
156
|
end
|
@@ -185,7 +191,10 @@ module Writexlsx
|
|
185
191
|
end
|
186
192
|
|
187
193
|
def external_links
|
188
|
-
[
|
194
|
+
[
|
195
|
+
@external_drawing_links,
|
196
|
+
@external_vml_links
|
197
|
+
]
|
189
198
|
end
|
190
199
|
|
191
200
|
private
|
data/lib/write_xlsx/col_name.rb
CHANGED
@@ -7,12 +7,16 @@ class ColName
|
|
7
7
|
include Singleton
|
8
8
|
|
9
9
|
def initialize
|
10
|
-
@col_str_table =
|
10
|
+
@col_str_table = []
|
11
|
+
@row_str_table = []
|
11
12
|
end
|
12
13
|
|
13
14
|
def col_str(col)
|
14
|
-
@col_str_table[col]
|
15
|
-
|
15
|
+
@col_str_table[col] ||= col_str_build(col)
|
16
|
+
end
|
17
|
+
|
18
|
+
def row_str(row)
|
19
|
+
@row_str_table[row] ||= row.to_s
|
16
20
|
end
|
17
21
|
|
18
22
|
private
|
data/lib/write_xlsx/format.rb
CHANGED
@@ -146,10 +146,10 @@ module Writexlsx
|
|
146
146
|
return
|
147
147
|
end
|
148
148
|
|
149
|
-
# Indent is only allowed for
|
150
|
-
#
|
151
|
-
#
|
152
|
-
@text_h_align = 1 if @indent != 0 && ![1, 3, 7].include?(@text_h_align)
|
149
|
+
# Indent is only allowed for some alignment properties. If it is defined
|
150
|
+
# for any other alignment or no alignment has been set then default to
|
151
|
+
# left alignment.
|
152
|
+
@text_h_align = 1 if @indent != 0 && ![1, 3, 7].include?(@text_h_align) && ![1, 3, 5].include?(@text_v_align)
|
153
153
|
|
154
154
|
# Check for properties that are mutually exclusive.
|
155
155
|
@shrink = 0 if @text_wrap != 0
|
@@ -178,8 +178,8 @@ module Writexlsx
|
|
178
178
|
align << %w[vertical justify] if @text_v_align == 4
|
179
179
|
align << %w[vertical distributed] if @text_v_align == 5
|
180
180
|
|
181
|
-
align << ['indent', @indent] if @indent != 0
|
182
181
|
align << ['textRotation', @rotation] if @rotation != 0
|
182
|
+
align << ['indent', @indent] if @indent != 0
|
183
183
|
|
184
184
|
align << ['wrapText', 1] if @text_wrap != 0
|
185
185
|
align << ['shrinkToFit', 1] if @shrink != 0
|
@@ -324,7 +324,7 @@ module Writexlsx
|
|
324
324
|
return colors[color_code.downcase.to_sym] if colors[color_code.downcase.to_sym]
|
325
325
|
|
326
326
|
# or the default color if string is unrecognised,
|
327
|
-
|
327
|
+
0x00 if color_code =~ /\D/
|
328
328
|
else
|
329
329
|
# or an index < 8 mapped into the correct range,
|
330
330
|
return color_code + 8 if color_code < 8
|
@@ -46,7 +46,9 @@ module Writexlsx
|
|
46
46
|
add_heading_pair(
|
47
47
|
[
|
48
48
|
'Worksheets',
|
49
|
-
@workbook.worksheets.reject
|
49
|
+
@workbook.worksheets.reject do |s|
|
50
|
+
s.is_chartsheet? || s.very_hidden?
|
51
|
+
end.count
|
50
52
|
]
|
51
53
|
)
|
52
54
|
end
|
@@ -57,14 +59,16 @@ module Writexlsx
|
|
57
59
|
|
58
60
|
def add_worksheet_part_names
|
59
61
|
@workbook.worksheets
|
60
|
-
|
61
|
-
|
62
|
+
.reject { |sheet| sheet.is_chartsheet? || sheet.very_hidden? }
|
63
|
+
.each do |sheet|
|
64
|
+
add_part_name(sheet.name)
|
65
|
+
end
|
62
66
|
end
|
63
67
|
|
64
68
|
def add_chartsheet_part_names
|
65
69
|
@workbook.worksheets
|
66
|
-
|
67
|
-
|
70
|
+
.select { |sheet| sheet.is_chartsheet? }
|
71
|
+
.each { |sheet| add_part_name(sheet.name) }
|
68
72
|
end
|
69
73
|
|
70
74
|
def add_part_name(part_name)
|
@@ -411,7 +411,7 @@ module Writexlsx
|
|
411
411
|
# Check for a cell reference in A1 notation and substitute row and column
|
412
412
|
user_range = if args[0].to_s =~ (/^\D/) && (args[0] =~ /,/)
|
413
413
|
# Check for a user defined multiple range like B3:K6,B8:K11.
|
414
|
-
args[0].sub(/^=/, '').gsub(/\s*,\s*/, ' ').gsub(
|
414
|
+
args[0].sub(/^=/, '').gsub(/\s*,\s*/, ' ').gsub("$", '')
|
415
415
|
end
|
416
416
|
|
417
417
|
if (row_col_array = row_col_notation(args.first))
|
@@ -769,7 +769,7 @@ module Writexlsx
|
|
769
769
|
attr = super
|
770
770
|
attr << ['percent', 1] if criteria == '%'
|
771
771
|
attr << ['bottom', 1] if direction
|
772
|
-
attr << ['rank',
|
772
|
+
attr << ['rank', value || 10]
|
773
773
|
attr
|
774
774
|
end
|
775
775
|
end
|
@@ -199,6 +199,28 @@ module Writexlsx
|
|
199
199
|
)
|
200
200
|
end
|
201
201
|
|
202
|
+
def add_richvalue
|
203
|
+
add_override(
|
204
|
+
'/xl/richData/rdRichValueTypes.xml',
|
205
|
+
'application/vnd.ms-excel.rdrichvaluetypes+xml'
|
206
|
+
)
|
207
|
+
|
208
|
+
add_override(
|
209
|
+
'/xl/richData/rdrichvalue.xml',
|
210
|
+
'application/vnd.ms-excel.rdrichvalue+xml'
|
211
|
+
)
|
212
|
+
|
213
|
+
add_override(
|
214
|
+
'/xl/richData/rdrichvaluestructure.xml',
|
215
|
+
'application/vnd.ms-excel.rdrichvaluestructure+xml'
|
216
|
+
)
|
217
|
+
|
218
|
+
add_override(
|
219
|
+
'/xl/richData/richValueRel.xml',
|
220
|
+
'application/vnd.ms-excel.richvaluerel+xml'
|
221
|
+
)
|
222
|
+
end
|
223
|
+
|
202
224
|
private
|
203
225
|
|
204
226
|
def change_the_workbook_xml_content_type_from_xlsx_to_xlsm
|