write_xlsx 1.04.0 → 1.08.2
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/.travis.yml +0 -1
- data/Changes +50 -0
- data/README.md +1 -1
- data/examples/chart_data_labels.rb +320 -0
- data/examples/ignore_errors.rb +39 -0
- data/ignore_errors.xlsx +0 -0
- data/lib/write_xlsx/chart/series.rb +100 -0
- data/lib/write_xlsx/chart.rb +155 -33
- data/lib/write_xlsx/drawing.rb +80 -17
- data/lib/write_xlsx/package/app.rb +3 -3
- data/lib/write_xlsx/package/conditional_format.rb +2 -8
- data/lib/write_xlsx/package/packager.rb +1 -0
- data/lib/write_xlsx/package/styles.rb +16 -3
- data/lib/write_xlsx/package/table.rb +8 -0
- data/lib/write_xlsx/utility.rb +9 -3
- data/lib/write_xlsx/version.rb +1 -1
- data/lib/write_xlsx/workbook.rb +23 -0
- data/lib/write_xlsx/worksheet/data_validation.rb +1 -6
- data/lib/write_xlsx/worksheet.rb +160 -37
- data/test/drawing/{test_write_ext.rb → test_write_xdr_ext.rb} +2 -2
- data/test/perl_output/chart_data_labels.xlsx +0 -0
- data/test/perl_output/ignore_errors.xlsx +0 -0
- data/test/regression/test_array_formula04.rb +31 -0
- data/test/regression/test_chart_crossing01.rb +1 -1
- data/test/regression/test_chart_crossing05.rb +46 -0
- data/test/regression/test_chart_crossing06.rb +46 -0
- data/test/regression/test_chart_data_labels26.rb +44 -0
- data/test/regression/test_chart_data_labels27.rb +44 -0
- data/test/regression/test_chart_data_labels28.rb +52 -0
- data/test/regression/test_chart_data_labels29.rb +43 -0
- data/test/regression/test_chart_data_labels30.rb +46 -0
- data/test/regression/test_chart_data_labels31.rb +49 -0
- data/test/regression/test_chart_data_labels32.rb +54 -0
- data/test/regression/test_chart_data_labels33.rb +52 -0
- data/test/regression/test_chart_data_labels34.rb +54 -0
- data/test/regression/test_chart_data_labels35.rb +46 -0
- data/test/regression/test_chart_data_labels36.rb +54 -0
- data/test/regression/test_chart_data_labels37.rb +51 -0
- data/test/regression/test_chart_data_labels38.rb +54 -0
- data/test/regression/test_chart_data_labels39.rb +53 -0
- data/test/regression/test_chart_data_labels40.rb +53 -0
- data/test/regression/test_chart_data_labels41.rb +54 -0
- data/test/regression/test_chart_data_labels42.rb +58 -0
- data/test/regression/test_chart_data_labels43.rb +58 -0
- data/test/regression/test_chart_data_labels44.rb +56 -0
- data/test/regression/test_chart_data_labels45.rb +57 -0
- data/test/regression/test_chart_data_labels46.rb +61 -0
- data/test/regression/test_chart_data_labels47.rb +61 -0
- data/test/regression/test_chart_data_labels48.rb +55 -0
- data/test/regression/test_chart_data_labels49.rb +55 -0
- data/test/regression/test_chart_data_labels50.rb +57 -0
- data/test/regression/test_format16.rb +24 -0
- data/test/regression/test_format17.rb +24 -0
- data/test/regression/test_header04.rb +30 -0
- data/test/regression/test_hyperlink50.rb +27 -0
- data/test/regression/test_hyperlink51.rb +27 -0
- data/test/regression/test_ignore_error01.rb +23 -0
- data/test/regression/test_ignore_error02.rb +24 -0
- data/test/regression/test_ignore_error03.rb +26 -0
- data/test/regression/test_ignore_error04.rb +26 -0
- data/test/regression/test_ignore_error05.rb +32 -0
- data/test/regression/test_ignore_error06.rb +32 -0
- data/test/regression/test_image52.rb +26 -0
- data/test/regression/test_image53.rb +26 -0
- data/test/regression/test_image54.rb +26 -0
- data/test/regression/test_image55.rb +27 -0
- data/test/regression/test_protect04.rb +32 -0
- data/test/regression/test_protect05.rb +35 -0
- data/test/regression/test_protect06.rb +35 -0
- data/test/regression/test_protect07.rb +23 -0
- data/test/regression/test_table26.rb +38 -0
- data/test/regression/xlsx_files/array_formula04.xlsx +0 -0
- data/test/regression/xlsx_files/chart_crossing05.xlsx +0 -0
- data/test/regression/xlsx_files/chart_crossing06.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels26.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels27.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels28.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels29.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels30.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels31.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels32.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels33.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels34.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels35.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels36.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels37.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels38.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels39.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels40.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels41.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels42.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels43.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels44.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels45.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels46.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels47.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels48.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels49.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels50.xlsx +0 -0
- data/test/regression/xlsx_files/format16.xlsx +0 -0
- data/test/regression/xlsx_files/format17.xlsx +0 -0
- data/test/regression/xlsx_files/header04.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink50.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink51.xlsx +0 -0
- data/test/regression/xlsx_files/ignore_error01.xlsx +0 -0
- data/test/regression/xlsx_files/ignore_error02.xlsx +0 -0
- data/test/regression/xlsx_files/ignore_error03.xlsx +0 -0
- data/test/regression/xlsx_files/ignore_error04.xlsx +0 -0
- data/test/regression/xlsx_files/ignore_error05.xlsx +0 -0
- data/test/regression/xlsx_files/ignore_error06.xlsx +0 -0
- data/test/regression/xlsx_files/image52.xlsx +0 -0
- data/test/regression/xlsx_files/image53.xlsx +0 -0
- data/test/regression/xlsx_files/image54.xlsx +0 -0
- data/test/regression/xlsx_files/image55.xlsx +0 -0
- data/test/regression/xlsx_files/protect04.xlsx +0 -0
- data/test/regression/xlsx_files/protect05.xlsx +0 -0
- data/test/regression/xlsx_files/protect06.xlsx +0 -0
- data/test/regression/xlsx_files/protect07.xlsx +0 -0
- data/test/regression/xlsx_files/table26.xlsx +0 -0
- data/test/test_example_match.rb +345 -1
- data/test/utility/test_range.rb +20 -0
- metadata +209 -8
data/lib/write_xlsx/chart.rb
CHANGED
|
@@ -34,7 +34,7 @@ module Writexlsx
|
|
|
34
34
|
@writer.empty_tag('c:showOutline', attributes) if ptrue?(outline)
|
|
35
35
|
@writer.empty_tag('c:showKeys', attributes) if ptrue?(show_keys)
|
|
36
36
|
# Write the table font.
|
|
37
|
-
write_tx_pr(
|
|
37
|
+
write_tx_pr(font) if ptrue?(font)
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -783,7 +783,7 @@ module Writexlsx
|
|
|
783
783
|
elsif @title.formula
|
|
784
784
|
write_title_formula(@title, nil, nil, @title.layout, @title.overlay)
|
|
785
785
|
elsif @title.name
|
|
786
|
-
write_title_rich(@title, nil, @title.layout, @title.overlay)
|
|
786
|
+
write_title_rich(@title, nil, @title.name_font, @title.layout, @title.overlay)
|
|
787
787
|
end
|
|
788
788
|
|
|
789
789
|
# Write the c:plotArea element.
|
|
@@ -1204,7 +1204,7 @@ module Writexlsx
|
|
|
1204
1204
|
if x_axis.formula
|
|
1205
1205
|
write_title_formula(x_axis, is_y_axis, @x_axis, x_axis.layout)
|
|
1206
1206
|
elsif x_axis.name
|
|
1207
|
-
write_title_rich(x_axis, is_y_axis, x_axis.layout)
|
|
1207
|
+
write_title_rich(x_axis, is_y_axis, x_axis.name_font, x_axis.layout)
|
|
1208
1208
|
end
|
|
1209
1209
|
|
|
1210
1210
|
# Write the c:numFmt element.
|
|
@@ -1281,7 +1281,7 @@ module Writexlsx
|
|
|
1281
1281
|
if y_axis.formula
|
|
1282
1282
|
write_title_formula(y_axis, @horiz_val_axis, nil, y_axis.layout)
|
|
1283
1283
|
elsif y_axis.name
|
|
1284
|
-
write_title_rich(y_axis, @horiz_val_axis, y_axis.layout)
|
|
1284
|
+
write_title_rich(y_axis, @horiz_val_axis, y_axis.name_font, y_axis.layout)
|
|
1285
1285
|
end
|
|
1286
1286
|
|
|
1287
1287
|
# Write the c:numberFormat element.
|
|
@@ -1356,7 +1356,7 @@ module Writexlsx
|
|
|
1356
1356
|
if x_axis.formula
|
|
1357
1357
|
write_title_formula(x_axis, nil, nil, x_axis.layout)
|
|
1358
1358
|
elsif x_axis.name
|
|
1359
|
-
write_title_rich(x_axis, nil, x_axis.layout)
|
|
1359
|
+
write_title_rich(x_axis, nil, x_axis.name_font, x_axis.layout)
|
|
1360
1360
|
end
|
|
1361
1361
|
# Write the c:numFmt element.
|
|
1362
1362
|
write_number_format(x_axis)
|
|
@@ -1397,7 +1397,7 @@ module Writexlsx
|
|
|
1397
1397
|
|
|
1398
1398
|
def write_crossing(crossing)
|
|
1399
1399
|
# Note, the category crossing comes from the value axis.
|
|
1400
|
-
if
|
|
1400
|
+
if [nil, 'max', 'min'].include?(crossing)
|
|
1401
1401
|
# Write the c:crosses element.
|
|
1402
1402
|
write_crosses(crossing)
|
|
1403
1403
|
else
|
|
@@ -1693,7 +1693,7 @@ module Writexlsx
|
|
|
1693
1693
|
# Write the c:spPr element.
|
|
1694
1694
|
write_sp_pr(@legend)
|
|
1695
1695
|
# Write the c:txPr element.
|
|
1696
|
-
write_tx_pr(
|
|
1696
|
+
write_tx_pr(@legend.font) if ptrue?(@legend.font)
|
|
1697
1697
|
end
|
|
1698
1698
|
end
|
|
1699
1699
|
|
|
@@ -1808,10 +1808,10 @@ module Writexlsx
|
|
|
1808
1808
|
#
|
|
1809
1809
|
# Write the <c:title> element for a rich string.
|
|
1810
1810
|
#
|
|
1811
|
-
def write_title_rich(title, is_y_axis
|
|
1811
|
+
def write_title_rich(title, is_y_axis, font, layout, overlay = nil) # :nodoc:
|
|
1812
1812
|
@writer.tag_elements('c:title') do
|
|
1813
1813
|
# Write the c:tx element.
|
|
1814
|
-
write_tx_rich(title, is_y_axis)
|
|
1814
|
+
write_tx_rich(title, is_y_axis, font)
|
|
1815
1815
|
# Write the c:layout element.
|
|
1816
1816
|
write_layout(layout, 'text')
|
|
1817
1817
|
# Write the c:overlay element.
|
|
@@ -1831,15 +1831,17 @@ module Writexlsx
|
|
|
1831
1831
|
# Write the c:overlay element.
|
|
1832
1832
|
write_overlay if overlay
|
|
1833
1833
|
# Write the c:txPr element.
|
|
1834
|
-
write_tx_pr(
|
|
1834
|
+
write_tx_pr(axis ? axis.name_font : title.name_font, is_y_axis)
|
|
1835
1835
|
end
|
|
1836
1836
|
end
|
|
1837
1837
|
|
|
1838
1838
|
#
|
|
1839
1839
|
# Write the <c:tx> element.
|
|
1840
1840
|
#
|
|
1841
|
-
def write_tx_rich(title, is_y_axis) # :nodoc:
|
|
1842
|
-
@writer.tag_elements('c:tx')
|
|
1841
|
+
def write_tx_rich(title, is_y_axis, font) # :nodoc:
|
|
1842
|
+
@writer.tag_elements('c:tx') do
|
|
1843
|
+
write_rich(title, font, is_y_axis)
|
|
1844
|
+
end
|
|
1843
1845
|
end
|
|
1844
1846
|
|
|
1845
1847
|
#
|
|
@@ -1861,10 +1863,11 @@ module Writexlsx
|
|
|
1861
1863
|
#
|
|
1862
1864
|
# Write the <c:rich> element.
|
|
1863
1865
|
#
|
|
1864
|
-
def write_rich(title, is_y_axis) # :nodoc:
|
|
1866
|
+
def write_rich(title, font, is_y_axis, ignore_rich_pr = false) # :nodoc:
|
|
1865
1867
|
rotation = nil
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
+
|
|
1869
|
+
if font && font[:_rotation]
|
|
1870
|
+
rotation = font[:_rotation]
|
|
1868
1871
|
end
|
|
1869
1872
|
@writer.tag_elements('c:rich') do
|
|
1870
1873
|
# Write the a:bodyPr element.
|
|
@@ -1872,18 +1875,18 @@ module Writexlsx
|
|
|
1872
1875
|
# Write the a:lstStyle element.
|
|
1873
1876
|
write_a_lst_style
|
|
1874
1877
|
# Write the a:p element.
|
|
1875
|
-
write_a_p_rich(title)
|
|
1878
|
+
write_a_p_rich(title, font, ignore_rich_pr)
|
|
1876
1879
|
end
|
|
1877
1880
|
end
|
|
1878
1881
|
#
|
|
1879
1882
|
# Write the <a:p> element for rich string titles.
|
|
1880
1883
|
#
|
|
1881
|
-
def write_a_p_rich(title) # :nodoc:
|
|
1884
|
+
def write_a_p_rich(title, font, ignore_rich_pr) # :nodoc:
|
|
1882
1885
|
@writer.tag_elements('a:p') do
|
|
1883
1886
|
# Write the a:pPr element.
|
|
1884
|
-
write_a_p_pr_rich(
|
|
1887
|
+
write_a_p_pr_rich(font) if !ignore_rich_pr
|
|
1885
1888
|
# Write the a:r element.
|
|
1886
|
-
write_a_r(title)
|
|
1889
|
+
write_a_r(title, font)
|
|
1887
1890
|
end
|
|
1888
1891
|
end
|
|
1889
1892
|
|
|
@@ -1897,12 +1900,12 @@ module Writexlsx
|
|
|
1897
1900
|
#
|
|
1898
1901
|
# Write the <a:r> element.
|
|
1899
1902
|
#
|
|
1900
|
-
def write_a_r(title) # :nodoc:
|
|
1903
|
+
def write_a_r(title, font) # :nodoc:
|
|
1901
1904
|
@writer.tag_elements('a:r') do
|
|
1902
1905
|
# Write the a:rPr element.
|
|
1903
|
-
write_a_r_pr(
|
|
1906
|
+
write_a_r_pr(font)
|
|
1904
1907
|
# Write the a:t element.
|
|
1905
|
-
write_a_t(title.name)
|
|
1908
|
+
write_a_t(title.respond_to?(:name) ? title.name : title)
|
|
1906
1909
|
end
|
|
1907
1910
|
end
|
|
1908
1911
|
|
|
@@ -1967,17 +1970,27 @@ module Writexlsx
|
|
|
1967
1970
|
@writer.empty_tag('c:symbol', [ ['val', val] ])
|
|
1968
1971
|
end
|
|
1969
1972
|
|
|
1973
|
+
def has_fill_formatting(element)
|
|
1974
|
+
line = series_property(element, :line)
|
|
1975
|
+
fill = series_property(element, :fill)
|
|
1976
|
+
pattern = series_property(element, :pattern)
|
|
1977
|
+
gradient = series_property(element, :gradient)
|
|
1978
|
+
|
|
1979
|
+
(line && ptrue?(line[:_defined])) ||
|
|
1980
|
+
(fill && ptrue?(fill[:_defined])) || pattern || gradient
|
|
1981
|
+
end
|
|
1982
|
+
|
|
1983
|
+
|
|
1970
1984
|
#
|
|
1971
1985
|
# Write the <c:spPr> element.
|
|
1972
1986
|
#
|
|
1973
1987
|
def write_sp_pr(series) # :nodoc:
|
|
1974
|
-
|
|
1975
|
-
fill = series.fill
|
|
1976
|
-
pattern = series.pattern if series.respond_to?(:pattern)
|
|
1977
|
-
gradient = series.gradient if series.respond_to?(:gradient)
|
|
1988
|
+
return if !has_fill_formatting(series)
|
|
1978
1989
|
|
|
1979
|
-
|
|
1980
|
-
|
|
1990
|
+
line = series_property(series, :line)
|
|
1991
|
+
fill = series_property(series, :fill)
|
|
1992
|
+
pattern = series_property(series, :pattern)
|
|
1993
|
+
gradient = series_property(series, :gradient)
|
|
1981
1994
|
|
|
1982
1995
|
@writer.tag_elements('c:spPr') do
|
|
1983
1996
|
# Write the fill elements for solid charts such as pie/doughnut and bar.
|
|
@@ -2002,6 +2015,14 @@ module Writexlsx
|
|
|
2002
2015
|
end
|
|
2003
2016
|
end
|
|
2004
2017
|
|
|
2018
|
+
def series_property(object, property)
|
|
2019
|
+
if object.respond_to?(property)
|
|
2020
|
+
object.send(property)
|
|
2021
|
+
elsif object.respond_to?(:[])
|
|
2022
|
+
object[property]
|
|
2023
|
+
end
|
|
2024
|
+
end
|
|
2025
|
+
|
|
2005
2026
|
#
|
|
2006
2027
|
# Write the <a:ln> element.
|
|
2007
2028
|
#
|
|
@@ -2349,8 +2370,14 @@ module Writexlsx
|
|
|
2349
2370
|
return unless labels
|
|
2350
2371
|
|
|
2351
2372
|
@writer.tag_elements('c:dLbls') do
|
|
2373
|
+
# Write the custom c:dLbl elements.
|
|
2374
|
+
if labels[:custom]
|
|
2375
|
+
write_custom_labels(labels, labels[:custom])
|
|
2376
|
+
end
|
|
2352
2377
|
# Write the c:numFmt element.
|
|
2353
2378
|
write_data_label_number_format(labels[:num_format]) if labels[:num_format]
|
|
2379
|
+
# Write the c:spPr element.
|
|
2380
|
+
write_sp_pr(labels)
|
|
2354
2381
|
# Write the data label font elements.
|
|
2355
2382
|
write_axis_font(labels[:font]) if labels[:font]
|
|
2356
2383
|
# Write the c:dLblPos element.
|
|
@@ -2372,6 +2399,105 @@ module Writexlsx
|
|
|
2372
2399
|
end
|
|
2373
2400
|
end
|
|
2374
2401
|
|
|
2402
|
+
#
|
|
2403
|
+
# Write the <c:dLbl> element.
|
|
2404
|
+
#
|
|
2405
|
+
def write_custom_labels(parent, labels)
|
|
2406
|
+
index = 0
|
|
2407
|
+
|
|
2408
|
+
labels.each do |label|
|
|
2409
|
+
index += 1
|
|
2410
|
+
next if !ptrue?(label)
|
|
2411
|
+
|
|
2412
|
+
@writer.tag_elements('c:dLbl') do
|
|
2413
|
+
# Write the c:idx element.
|
|
2414
|
+
write_idx(index - 1)
|
|
2415
|
+
|
|
2416
|
+
if label[:delete] && label[:delete]
|
|
2417
|
+
write_delete(1)
|
|
2418
|
+
elsif label[:formula]
|
|
2419
|
+
write_custom_label_formula(label)
|
|
2420
|
+
|
|
2421
|
+
write_d_lbl_pos(parent[:position]) if parent[:position]
|
|
2422
|
+
write_show_val if parent[:value]
|
|
2423
|
+
write_show_cat_name if parent[:category]
|
|
2424
|
+
write_show_ser_name if parent[:series_name]
|
|
2425
|
+
elsif label[:value]
|
|
2426
|
+
write_custom_label_str(label)
|
|
2427
|
+
|
|
2428
|
+
write_d_lbl_pos(parent[:position]) if parent[:position]
|
|
2429
|
+
write_show_val if parent[:value]
|
|
2430
|
+
write_show_cat_name if parent[:category]
|
|
2431
|
+
write_show_ser_name if parent[:series_name]
|
|
2432
|
+
else
|
|
2433
|
+
write_custom_label_format_only(label)
|
|
2434
|
+
end
|
|
2435
|
+
end
|
|
2436
|
+
end
|
|
2437
|
+
end
|
|
2438
|
+
|
|
2439
|
+
#
|
|
2440
|
+
# Write parts of the <c:dLbl> element for strings.
|
|
2441
|
+
#
|
|
2442
|
+
def write_custom_label_str(label)
|
|
2443
|
+
value = label[:value]
|
|
2444
|
+
font = label[:font]
|
|
2445
|
+
is_y_axis = 0
|
|
2446
|
+
has_formatting = has_fill_formatting(label)
|
|
2447
|
+
|
|
2448
|
+
# Write the c:layout element.
|
|
2449
|
+
write_layout()
|
|
2450
|
+
|
|
2451
|
+
@writer.tag_elements('c:tx') do
|
|
2452
|
+
# Write the c:rich element.
|
|
2453
|
+
write_rich(value, font, is_y_axis, !has_formatting)
|
|
2454
|
+
end
|
|
2455
|
+
|
|
2456
|
+
# Write the c:cpPr element.
|
|
2457
|
+
write_sp_pr(label)
|
|
2458
|
+
end
|
|
2459
|
+
|
|
2460
|
+
#
|
|
2461
|
+
# Write parts of the <c:dLbl> element for formulas.
|
|
2462
|
+
#
|
|
2463
|
+
def write_custom_label_formula(label)
|
|
2464
|
+
formula = label[:formula]
|
|
2465
|
+
data_id = label[:data_id]
|
|
2466
|
+
|
|
2467
|
+
if data_id
|
|
2468
|
+
data = @formula_data[data_id]
|
|
2469
|
+
end
|
|
2470
|
+
|
|
2471
|
+
# Write the c:layout element.
|
|
2472
|
+
write_layout
|
|
2473
|
+
|
|
2474
|
+
@writer.tag_elements('c:tx') do
|
|
2475
|
+
# Write the c:strRef element.
|
|
2476
|
+
write_str_ref(formula, data, 'str')
|
|
2477
|
+
end
|
|
2478
|
+
|
|
2479
|
+
# Write the data label formatting, if any.
|
|
2480
|
+
write_custom_label_format_only(label)
|
|
2481
|
+
end
|
|
2482
|
+
|
|
2483
|
+
#
|
|
2484
|
+
# Write parts of the <c:dLbl> element for labels where only the formatting has
|
|
2485
|
+
# changed.
|
|
2486
|
+
#
|
|
2487
|
+
def write_custom_label_format_only(label)
|
|
2488
|
+
font = label[:font]
|
|
2489
|
+
has_formatting = has_fill_formatting(label)
|
|
2490
|
+
|
|
2491
|
+
if has_formatting
|
|
2492
|
+
# Write the c:spPr element.
|
|
2493
|
+
write_sp_pr(label)
|
|
2494
|
+
write_tx_pr(font)
|
|
2495
|
+
elsif font
|
|
2496
|
+
@writer.empty_tag('c:spPr')
|
|
2497
|
+
write_tx_pr(font)
|
|
2498
|
+
end
|
|
2499
|
+
end
|
|
2500
|
+
|
|
2375
2501
|
#
|
|
2376
2502
|
# Write the <c:showLegendKey> element.
|
|
2377
2503
|
#
|
|
@@ -2700,7 +2826,7 @@ module Writexlsx
|
|
|
2700
2826
|
|
|
2701
2827
|
# Write the a:srgbClr element.
|
|
2702
2828
|
# TODO: Wait for a feature request to support transparency.
|
|
2703
|
-
write_a_srgb_clr( color )
|
|
2829
|
+
write_a_srgb_clr( color )
|
|
2704
2830
|
end
|
|
2705
2831
|
end
|
|
2706
2832
|
end
|
|
@@ -2802,9 +2928,5 @@ module Writexlsx
|
|
|
2802
2928
|
@writer.empty_tag(tag)
|
|
2803
2929
|
end
|
|
2804
2930
|
end
|
|
2805
|
-
|
|
2806
|
-
def nil_or_max?(val) # :nodoc:
|
|
2807
|
-
val.nil? || val == 'max'
|
|
2808
|
-
end
|
|
2809
2931
|
end
|
|
2810
2932
|
end
|
data/lib/write_xlsx/drawing.rb
CHANGED
|
@@ -5,11 +5,11 @@ require 'write_xlsx/utility'
|
|
|
5
5
|
module Writexlsx
|
|
6
6
|
class Drawing
|
|
7
7
|
attr_accessor :type, :dimensions, :width, :height, :description, :shape, :anchor, :rel_index, :url_rel_index
|
|
8
|
-
attr_reader :tip
|
|
8
|
+
attr_reader :tip, :decorative
|
|
9
9
|
|
|
10
|
-
def initialize(type, dimensions, width, height, description, shape, anchor, rel_index = nil, url_rel_index = nil, tip = nil)
|
|
11
|
-
@type, @dimensions, @width, @height, @description, @shape, @anchor, @rel_index, @url_rel_index, @tip =
|
|
12
|
-
type, dimensions, width, height, description, shape, anchor, rel_index, url_rel_index, tip
|
|
10
|
+
def initialize(type, dimensions, width, height, description, shape, anchor, rel_index = nil, url_rel_index = nil, tip = nil, decorative = nil)
|
|
11
|
+
@type, @dimensions, @width, @height, @description, @shape, @anchor, @rel_index, @url_rel_index, @tip, @decorative =
|
|
12
|
+
type, dimensions, width, height, description, shape, anchor, rel_index, url_rel_index, tip, decorative
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -92,6 +92,7 @@ module Writexlsx
|
|
|
92
92
|
rel_index = drawing.rel_index
|
|
93
93
|
url_rel_index = drawing.url_rel_index
|
|
94
94
|
tip = drawing.tip
|
|
95
|
+
decorative = drawing.decorative
|
|
95
96
|
|
|
96
97
|
col_from, row_from, col_from_offset, row_from_offset,
|
|
97
98
|
col_to, row_to, col_to_offset, row_to_offset, col_absolute, row_absolute = drawing.dimensions
|
|
@@ -124,7 +125,7 @@ module Writexlsx
|
|
|
124
125
|
write_pic(
|
|
125
126
|
index, rel_index, col_absolute,
|
|
126
127
|
row_absolute, width, height,
|
|
127
|
-
description, url_rel_index , tip
|
|
128
|
+
description, url_rel_index , tip, decorative
|
|
128
129
|
)
|
|
129
130
|
else
|
|
130
131
|
# Write the xdr:sp element for shapes.
|
|
@@ -148,13 +149,13 @@ module Writexlsx
|
|
|
148
149
|
write_pos(0, 0)
|
|
149
150
|
|
|
150
151
|
# Write the xdr:ext element.
|
|
151
|
-
|
|
152
|
+
write_xdr_ext(9308969, 6078325)
|
|
152
153
|
else
|
|
153
154
|
# Write the xdr:pos element.
|
|
154
155
|
write_pos(0, -47625)
|
|
155
156
|
|
|
156
157
|
# Write the xdr:ext element.
|
|
157
|
-
|
|
158
|
+
write_xdr_ext(6162675, 6124575)
|
|
158
159
|
end
|
|
159
160
|
|
|
160
161
|
# Write the xdr:graphicFrame element.
|
|
@@ -242,7 +243,7 @@ module Writexlsx
|
|
|
242
243
|
#
|
|
243
244
|
# Write the <xdr:ext> element.
|
|
244
245
|
#
|
|
245
|
-
def
|
|
246
|
+
def write_xdr_ext(cx, cy)
|
|
246
247
|
attributes = [
|
|
247
248
|
['cx', cx],
|
|
248
249
|
['cy', cy]
|
|
@@ -286,19 +287,25 @@ module Writexlsx
|
|
|
286
287
|
#
|
|
287
288
|
# Write the <xdr:cNvPr> element.
|
|
288
289
|
#
|
|
289
|
-
def write_c_nv_pr(index, name, description = nil, url_rel_index = nil, tip = nil)
|
|
290
|
+
def write_c_nv_pr(index, name, description = nil, url_rel_index = nil, tip = nil, decorative = nil)
|
|
290
291
|
attributes = [
|
|
291
292
|
['id', index],
|
|
292
293
|
['name', name]
|
|
293
294
|
]
|
|
294
295
|
|
|
295
296
|
# Add description attribute for images.
|
|
296
|
-
attributes << ['descr', description] if description
|
|
297
|
+
attributes << ['descr', description] if ptrue?(description) && !ptrue?(decorative)
|
|
297
298
|
|
|
298
|
-
if ptrue?(url_rel_index)
|
|
299
|
+
if ptrue?(url_rel_index) || ptrue?(decorative)
|
|
299
300
|
@writer.tag_elements('xdr:cNvPr', attributes) do
|
|
300
|
-
|
|
301
|
-
|
|
301
|
+
if ptrue?(url_rel_index)
|
|
302
|
+
# Write the a:hlinkClick element.
|
|
303
|
+
write_a_hlink_click(url_rel_index, tip)
|
|
304
|
+
end
|
|
305
|
+
if ptrue?(decorative)
|
|
306
|
+
# Write the adec:decorative element.
|
|
307
|
+
write_decorative
|
|
308
|
+
end
|
|
302
309
|
end
|
|
303
310
|
else
|
|
304
311
|
@writer.empty_tag('xdr:cNvPr', attributes)
|
|
@@ -323,6 +330,62 @@ module Writexlsx
|
|
|
323
330
|
@writer.empty_tag('a:hlinkClick', attributes)
|
|
324
331
|
end
|
|
325
332
|
|
|
333
|
+
#
|
|
334
|
+
# Write the <adec:decorative> element.
|
|
335
|
+
#
|
|
336
|
+
def write_decorative
|
|
337
|
+
@writer.tag_elements('a:extLst') do
|
|
338
|
+
write_a_uri_ext('{FF2B5EF4-FFF2-40B4-BE49-F238E27FC236}')
|
|
339
|
+
write_a16_creation_id
|
|
340
|
+
@writer.end_tag('a:ext')
|
|
341
|
+
|
|
342
|
+
write_a_uri_ext('{C183D7F6-B498-43B3-948B-1728B52AA6E4}')
|
|
343
|
+
write_adec_decorative
|
|
344
|
+
@writer.end_tag('a:ext')
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
#
|
|
349
|
+
# Write the <a:ext> element.
|
|
350
|
+
#
|
|
351
|
+
def write_a_uri_ext(uri)
|
|
352
|
+
attributes = [
|
|
353
|
+
['uri', uri]
|
|
354
|
+
]
|
|
355
|
+
|
|
356
|
+
@writer.start_tag('a:ext', attributes)
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
#
|
|
360
|
+
# Write the <adec:decorative> element.
|
|
361
|
+
#
|
|
362
|
+
def write_adec_decorative
|
|
363
|
+
xmlns_adec = 'http://schemas.microsoft.com/office/drawing/2017/decorative'
|
|
364
|
+
val = 1
|
|
365
|
+
|
|
366
|
+
attributes = [
|
|
367
|
+
['xmlns:adec', xmlns_adec],
|
|
368
|
+
['val', val]
|
|
369
|
+
]
|
|
370
|
+
|
|
371
|
+
@writer.empty_tag('adec:decorative', attributes)
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
#
|
|
375
|
+
# Write the <a16:creationId> element.
|
|
376
|
+
#
|
|
377
|
+
def write_a16_creation_id
|
|
378
|
+
xmlns_a_16 = 'http://schemas.microsoft.com/office/drawing/2014/main'
|
|
379
|
+
id = '{00000000-0008-0000-0000-000002000000}'
|
|
380
|
+
|
|
381
|
+
attributes = [
|
|
382
|
+
['xmlns:a16', xmlns_a_16],
|
|
383
|
+
['id', id]
|
|
384
|
+
]
|
|
385
|
+
|
|
386
|
+
@writer.empty_tag('a16:creationId', attributes)
|
|
387
|
+
end
|
|
388
|
+
|
|
326
389
|
#
|
|
327
390
|
# Write the <xdr:cNvGraphicFramePr> element.
|
|
328
391
|
#
|
|
@@ -527,10 +590,10 @@ module Writexlsx
|
|
|
527
590
|
#
|
|
528
591
|
# Write the <xdr:pic> element.
|
|
529
592
|
#
|
|
530
|
-
def write_pic(index, rel_index, col_absolute, row_absolute, width, height, description, url_rel_index, tip)
|
|
593
|
+
def write_pic(index, rel_index, col_absolute, row_absolute, width, height, description, url_rel_index, tip, decorative)
|
|
531
594
|
@writer.tag_elements('xdr:pic') do
|
|
532
595
|
# Write the xdr:nvPicPr element.
|
|
533
|
-
write_nv_pic_pr(index, rel_index, description, url_rel_index, tip)
|
|
596
|
+
write_nv_pic_pr(index, rel_index, description, url_rel_index, tip, decorative)
|
|
534
597
|
# Write the xdr:blipFill element.
|
|
535
598
|
write_blip_fill(rel_index)
|
|
536
599
|
|
|
@@ -546,12 +609,12 @@ module Writexlsx
|
|
|
546
609
|
#
|
|
547
610
|
# Write the <xdr:nvPicPr> element.
|
|
548
611
|
#
|
|
549
|
-
def write_nv_pic_pr(index, rel_index, description, url_rel_index, tip)
|
|
612
|
+
def write_nv_pic_pr(index, rel_index, description, url_rel_index, tip, decorative)
|
|
550
613
|
@writer.tag_elements('xdr:nvPicPr') do
|
|
551
614
|
# Write the xdr:cNvPr element.
|
|
552
615
|
write_c_nv_pr(
|
|
553
616
|
index + 1, "Picture #{index}", description,
|
|
554
|
-
url_rel_index, tip
|
|
617
|
+
url_rel_index, tip, decorative
|
|
555
618
|
)
|
|
556
619
|
# Write the xdr:cNvPicPr element.
|
|
557
620
|
write_c_nv_pic_pr
|
|
@@ -7,6 +7,7 @@ module Writexlsx
|
|
|
7
7
|
class App
|
|
8
8
|
|
|
9
9
|
include Writexlsx::Utility
|
|
10
|
+
attr_writer :doc_security
|
|
10
11
|
|
|
11
12
|
def initialize(workbook)
|
|
12
13
|
@writer = Package::XMLWriterSimple.new
|
|
@@ -14,6 +15,7 @@ module Writexlsx
|
|
|
14
15
|
@part_names = []
|
|
15
16
|
@heading_pairs = []
|
|
16
17
|
@properties = {}
|
|
18
|
+
@doc_security = 0
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def set_xml_writer(filename)
|
|
@@ -123,9 +125,7 @@ module Writexlsx
|
|
|
123
125
|
# Write the <DocSecurity> element.
|
|
124
126
|
#
|
|
125
127
|
def write_doc_security
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
@writer.data_element('DocSecurity', data)
|
|
128
|
+
@writer.data_element('DocSecurity', @doc_security)
|
|
129
129
|
end
|
|
130
130
|
|
|
131
131
|
#
|
|
@@ -397,14 +397,8 @@ module Writexlsx
|
|
|
397
397
|
def range_start_cell_for_conditional_formatting(*args) # :nodoc:
|
|
398
398
|
row1, row2, col1, col2, user_range, param =
|
|
399
399
|
row_col_param_for_conditional_formatting(*args)
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
range = xl_rowcol_to_cell(row1, col1)
|
|
403
|
-
@start_cell = range
|
|
404
|
-
else
|
|
405
|
-
range = xl_range(row1, row2, col1, col2)
|
|
406
|
-
@start_cell = xl_rowcol_to_cell(row1, col1)
|
|
407
|
-
end
|
|
400
|
+
range = xl_range(row1, row2, col1, col2)
|
|
401
|
+
@start_cell = xl_rowcol_to_cell(row1, col1)
|
|
408
402
|
|
|
409
403
|
# Override with user defined multiple range if provided.
|
|
410
404
|
range = user_range if user_range
|
|
@@ -155,6 +155,7 @@ module Writexlsx
|
|
|
155
155
|
app.add_named_ranges_parts
|
|
156
156
|
|
|
157
157
|
app.set_properties(@workbook.doc_properties)
|
|
158
|
+
app.doc_security = @workbook.read_only
|
|
158
159
|
|
|
159
160
|
FileUtils.mkdir_p("#{@package_dir}/docProps")
|
|
160
161
|
app.set_xml_writer("#{@package_dir}/docProps/app.xml")
|
|
@@ -253,11 +253,22 @@ module Writexlsx
|
|
|
253
253
|
# Write the <fill> element.
|
|
254
254
|
#
|
|
255
255
|
def write_fill(format, dxf_format = nil)
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
# Special handling for pattern only case.
|
|
257
|
+
if pattern_only_case?(format, dxf_format)
|
|
258
|
+
write_default_fill(PATTERNS[format.pattern])
|
|
259
|
+
else
|
|
260
|
+
@writer.tag_elements('fill' ) do
|
|
261
|
+
write_fill_base(format, dxf_format)
|
|
262
|
+
end
|
|
258
263
|
end
|
|
259
264
|
end
|
|
260
265
|
|
|
266
|
+
def pattern_only_case?(format, dxf_format)
|
|
267
|
+
bg_color, fg_color = bg_and_fg_color(format, dxf_format)
|
|
268
|
+
|
|
269
|
+
!ptrue?(fg_color) && !ptrue?(bg_color) && ptrue?(format.pattern)
|
|
270
|
+
end
|
|
271
|
+
|
|
261
272
|
def write_fill_base(format, dxf_format)
|
|
262
273
|
# The "none" pattern is handled differently for dxf formats.
|
|
263
274
|
if dxf_format && format.pattern <= 1
|
|
@@ -281,7 +292,9 @@ module Writexlsx
|
|
|
281
292
|
if bg_color && bg_color != 0
|
|
282
293
|
@writer.empty_tag('bgColor', [ ['rgb', palette_color(bg_color)] ])
|
|
283
294
|
else
|
|
284
|
-
|
|
295
|
+
if !dxf_format && format.pattern <= 1
|
|
296
|
+
@writer.empty_tag('bgColor', [ ['indexed', 64] ])
|
|
297
|
+
end
|
|
285
298
|
end
|
|
286
299
|
end
|
|
287
300
|
|
|
@@ -189,6 +189,14 @@ module Writexlsx
|
|
|
189
189
|
param[:header_row] ||= 1
|
|
190
190
|
param[:autofilter] ||= 1
|
|
191
191
|
|
|
192
|
+
# Check that there are enough rows.
|
|
193
|
+
num_rows = row2 - row1
|
|
194
|
+
num_rows -= 1 if ptrue?(param[:header_row])
|
|
195
|
+
|
|
196
|
+
if num_rows < 0
|
|
197
|
+
raise "Must have at least one data row in in add_table()"
|
|
198
|
+
end
|
|
199
|
+
|
|
192
200
|
# If the header row if off the default is to turn autofilter off.
|
|
193
201
|
param[:autofilter] = 0 if param[:header_row] == 0
|
|
194
202
|
|
data/lib/write_xlsx/utility.rb
CHANGED
|
@@ -60,7 +60,11 @@ module Writexlsx
|
|
|
60
60
|
range1 = xl_rowcol_to_cell(row_1, col_1, row_abs_1, col_abs_1)
|
|
61
61
|
range2 = xl_rowcol_to_cell(row_2, col_2, row_abs_2, col_abs_2)
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
if range1 == range2
|
|
64
|
+
range1
|
|
65
|
+
else
|
|
66
|
+
"#{range1}:#{range2}"
|
|
67
|
+
end
|
|
64
68
|
end
|
|
65
69
|
|
|
66
70
|
def xl_range_formula(sheetname, row_1, row_2, col_1, col_2)
|
|
@@ -804,9 +808,9 @@ module Writexlsx
|
|
|
804
808
|
#
|
|
805
809
|
# Write the <c:txPr> element.
|
|
806
810
|
#
|
|
807
|
-
def write_tx_pr(
|
|
811
|
+
def write_tx_pr(font, is_y_axis = nil) # :nodoc:
|
|
808
812
|
rotation = nil
|
|
809
|
-
if font && font[:_rotation]
|
|
813
|
+
if font && font.respond_to?(:[]) && font[:_rotation]
|
|
810
814
|
rotation = font[:_rotation]
|
|
811
815
|
end
|
|
812
816
|
@writer.tag_elements('c:txPr') do
|
|
@@ -903,6 +907,7 @@ module Writexlsx
|
|
|
903
907
|
#
|
|
904
908
|
def get_font_latin_attributes(font)
|
|
905
909
|
return [] unless font
|
|
910
|
+
return [] unless font.respond_to?(:[])
|
|
906
911
|
|
|
907
912
|
attributes = []
|
|
908
913
|
attributes << ['typeface', font[:_name]] if ptrue?(font[:_name])
|
|
@@ -959,6 +964,7 @@ module Writexlsx
|
|
|
959
964
|
#
|
|
960
965
|
def get_font_style_attributes(font)
|
|
961
966
|
return [] unless font
|
|
967
|
+
return [] unless font.respond_to?(:[])
|
|
962
968
|
|
|
963
969
|
attributes = []
|
|
964
970
|
attributes << ['sz', font[:_size]] if ptrue?(font[:_size])
|
data/lib/write_xlsx/version.rb
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
WriteXLSX_VERSION = "1.
|
|
1
|
+
WriteXLSX_VERSION = "1.08.2"
|