write_xlsx 1.11.2 → 1.12.1
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 +30 -0
- data/README.md +1 -1
- data/lib/write_xlsx/format.rb +5 -5
- 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 +120 -3
- 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/utility.rb +172 -0
- data/lib/write_xlsx/version.rb +1 -1
- data/lib/write_xlsx/workbook.rb +46 -166
- data/lib/write_xlsx/worksheet/cell_data.rb +19 -0
- data/lib/write_xlsx/worksheet/hyperlink.rb +2 -1
- data/lib/write_xlsx/worksheet.rb +93 -22
- metadata +7 -3
data/lib/write_xlsx/workbook.rb
CHANGED
@@ -35,6 +35,9 @@ module Writexlsx
|
|
35
35
|
attr_reader :max_url_length # :nodoc:
|
36
36
|
attr_reader :strings_to_urls # :nodoc:
|
37
37
|
attr_reader :read_only # :nodoc:
|
38
|
+
attr_reader :embedded_image_indexes # :nodec:
|
39
|
+
attr_reader :embedded_images # :nodoc:
|
40
|
+
attr_reader :embedded_descriptions # :nodoc:
|
38
41
|
|
39
42
|
def initialize(file, *option_params)
|
40
43
|
options, default_formats = process_workbook_options(*option_params)
|
@@ -80,6 +83,9 @@ module Writexlsx
|
|
80
83
|
@has_comments = false
|
81
84
|
@read_only = 0
|
82
85
|
@has_metadata = false
|
86
|
+
@has_embedded_images = false
|
87
|
+
@has_embedded_descriptions = false
|
88
|
+
|
83
89
|
if options[:max_url_length]
|
84
90
|
@max_url_length = options[:max_url_length]
|
85
91
|
|
@@ -88,6 +94,10 @@ module Writexlsx
|
|
88
94
|
# Structures for the shared strings data.
|
89
95
|
@shared_strings = Package::SharedStrings.new
|
90
96
|
|
97
|
+
# Structures for embedded images.
|
98
|
+
@embedded_image_indexes = {}
|
99
|
+
@embedded_images = []
|
100
|
+
|
91
101
|
# Formula calculation default settings.
|
92
102
|
@calc_id = 124519
|
93
103
|
@calc_mode = 'auto'
|
@@ -530,6 +540,10 @@ module Writexlsx
|
|
530
540
|
!!@date_1904
|
531
541
|
end
|
532
542
|
|
543
|
+
def has_dynamic_functions?
|
544
|
+
@has_dynamic_functions
|
545
|
+
end
|
546
|
+
|
533
547
|
#
|
534
548
|
# Add a string to the shared string table, if it isn't already there, and
|
535
549
|
# return the string index.
|
@@ -597,6 +611,14 @@ module Writexlsx
|
|
597
611
|
@has_metadata
|
598
612
|
end
|
599
613
|
|
614
|
+
def has_embedded_images?
|
615
|
+
@has_embedded_images
|
616
|
+
end
|
617
|
+
|
618
|
+
def has_embedded_descriptions?
|
619
|
+
@has_embedded_descriptions
|
620
|
+
end
|
621
|
+
|
600
622
|
private
|
601
623
|
|
602
624
|
def filename
|
@@ -1226,10 +1248,11 @@ module Writexlsx
|
|
1226
1248
|
#
|
1227
1249
|
def prepare_metadata
|
1228
1250
|
@worksheets.each do |sheet|
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1251
|
+
next unless sheet.has_dynamic_functions? || sheet.has_embedded_images?
|
1252
|
+
|
1253
|
+
@has_metadata = true
|
1254
|
+
@has_dynamic_functions ||= sheet.has_dynamic_functions?
|
1255
|
+
@has_embedded_images ||= sheet.has_embedded_images?
|
1233
1256
|
end
|
1234
1257
|
end
|
1235
1258
|
|
@@ -1380,12 +1403,22 @@ module Writexlsx
|
|
1380
1403
|
#
|
1381
1404
|
def prepare_drawings # :nodoc:
|
1382
1405
|
chart_ref_id = 0
|
1383
|
-
image_ref_id = 0
|
1384
1406
|
drawing_id = 0
|
1385
1407
|
ref_id = 0
|
1386
1408
|
image_ids = {}
|
1387
1409
|
header_image_ids = {}
|
1388
1410
|
background_ids = {}
|
1411
|
+
|
1412
|
+
# Store the image types for any embedded images.
|
1413
|
+
@embedded_images.each do |image_data|
|
1414
|
+
store_image_types(image_data[1])
|
1415
|
+
|
1416
|
+
@has_embedded_descriptions = true if ptrue?(image_data[2])
|
1417
|
+
end
|
1418
|
+
|
1419
|
+
# The image IDs start from after the embedded images.
|
1420
|
+
image_ref_id = @embedded_images.size
|
1421
|
+
|
1389
1422
|
@worksheets.each do |sheet|
|
1390
1423
|
chart_count = sheet.charts.size
|
1391
1424
|
image_count = sheet.images.size
|
@@ -1508,173 +1541,20 @@ module Writexlsx
|
|
1508
1541
|
end
|
1509
1542
|
|
1510
1543
|
#
|
1511
|
-
#
|
1512
|
-
#
|
1513
|
-
# any duplicates.
|
1544
|
+
# Store the image types (PNG/JPEG/etc) used in the workbook to use in these
|
1545
|
+
# Content_Types file.
|
1514
1546
|
#
|
1515
|
-
def
|
1516
|
-
|
1517
|
-
|
1518
|
-
y_dpi = 96
|
1519
|
-
|
1520
|
-
# Open the image file and import the data.
|
1521
|
-
data = File.binread(filename)
|
1522
|
-
md5 = Digest::MD5.hexdigest(data)
|
1523
|
-
if data.unpack1('x A3') == 'PNG'
|
1524
|
-
# Test for PNGs.
|
1525
|
-
type, width, height, x_dpi, y_dpi = process_png(data)
|
1547
|
+
def store_image_types(type)
|
1548
|
+
case type
|
1549
|
+
when 'png'
|
1526
1550
|
@image_types[:png] = 1
|
1527
|
-
|
1528
|
-
# Test for JPEG files.
|
1529
|
-
type, width, height, x_dpi, y_dpi = process_jpg(data, filename)
|
1551
|
+
when 'jpeg'
|
1530
1552
|
@image_types[:jpeg] = 1
|
1531
|
-
|
1532
|
-
# Test for GIFs.
|
1533
|
-
type, width, height, x_dpi, y_dpi = process_gif(data, filename)
|
1553
|
+
when 'gif'
|
1534
1554
|
@image_types[:gif] = 1
|
1535
|
-
|
1536
|
-
# Test for BMPs.
|
1537
|
-
type, width, height = process_bmp(data, filename)
|
1555
|
+
when 'bmp'
|
1538
1556
|
@image_types[:bmp] = 1
|
1539
|
-
else
|
1540
|
-
# TODO. Add Image::Size to support other types.
|
1541
|
-
raise "Unsupported image format for file: #{filename}\n"
|
1542
1557
|
end
|
1543
|
-
|
1544
|
-
# Set a default dpi for images with 0 dpi.
|
1545
|
-
x_dpi = 96 if x_dpi == 0
|
1546
|
-
y_dpi = 96 if y_dpi == 0
|
1547
|
-
|
1548
|
-
[type, width, height, File.basename(filename), x_dpi, y_dpi, md5]
|
1549
|
-
end
|
1550
|
-
|
1551
|
-
#
|
1552
|
-
# Extract width and height information from a PNG file.
|
1553
|
-
#
|
1554
|
-
def process_png(data)
|
1555
|
-
type = 'png'
|
1556
|
-
width = 0
|
1557
|
-
height = 0
|
1558
|
-
x_dpi = 96
|
1559
|
-
y_dpi = 96
|
1560
|
-
|
1561
|
-
offset = 8
|
1562
|
-
data_length = data.size
|
1563
|
-
|
1564
|
-
# Search through the image data to read the height and width in th the
|
1565
|
-
# IHDR element. Also read the DPI in the pHYs element.
|
1566
|
-
while offset < data_length
|
1567
|
-
|
1568
|
-
length = data[offset + 0, 4].unpack1("N")
|
1569
|
-
png_type = data[offset + 4, 4].unpack1("A4")
|
1570
|
-
|
1571
|
-
case png_type
|
1572
|
-
when "IHDR"
|
1573
|
-
width = data[offset + 8, 4].unpack1("N")
|
1574
|
-
height = data[offset + 12, 4].unpack1("N")
|
1575
|
-
when "pHYs"
|
1576
|
-
x_ppu = data[offset + 8, 4].unpack1("N")
|
1577
|
-
y_ppu = data[offset + 12, 4].unpack1("N")
|
1578
|
-
units = data[offset + 16, 1].unpack1("C")
|
1579
|
-
|
1580
|
-
if units == 1
|
1581
|
-
x_dpi = x_ppu * 0.0254
|
1582
|
-
y_dpi = y_ppu * 0.0254
|
1583
|
-
end
|
1584
|
-
end
|
1585
|
-
|
1586
|
-
offset = offset + length + 12
|
1587
|
-
|
1588
|
-
break if png_type == "IEND"
|
1589
|
-
end
|
1590
|
-
raise "#{filename}: no size data found in png image.\n" unless height
|
1591
|
-
|
1592
|
-
[type, width, height, x_dpi, y_dpi]
|
1593
|
-
end
|
1594
|
-
|
1595
|
-
def process_jpg(data, filename)
|
1596
|
-
type = 'jpeg'
|
1597
|
-
x_dpi = 96
|
1598
|
-
y_dpi = 96
|
1599
|
-
|
1600
|
-
offset = 2
|
1601
|
-
data_length = data.bytesize
|
1602
|
-
|
1603
|
-
# Search through the image data to read the JPEG markers.
|
1604
|
-
while offset < data_length
|
1605
|
-
marker = data[offset + 0, 2].unpack1("n")
|
1606
|
-
length = data[offset + 2, 2].unpack1("n")
|
1607
|
-
|
1608
|
-
# Read the height and width in the 0xFFCn elements
|
1609
|
-
# (Except C4, C8 and CC which aren't SOF markers).
|
1610
|
-
if (marker & 0xFFF0) == 0xFFC0 &&
|
1611
|
-
marker != 0xFFC4 && marker != 0xFFCC
|
1612
|
-
height = data[offset + 5, 2].unpack1("n")
|
1613
|
-
width = data[offset + 7, 2].unpack1("n")
|
1614
|
-
end
|
1615
|
-
|
1616
|
-
# Read the DPI in the 0xFFE0 element.
|
1617
|
-
if marker == 0xFFE0
|
1618
|
-
units = data[offset + 11, 1].unpack1("C")
|
1619
|
-
x_density = data[offset + 12, 2].unpack1("n")
|
1620
|
-
y_density = data[offset + 14, 2].unpack1("n")
|
1621
|
-
|
1622
|
-
if units == 1
|
1623
|
-
x_dpi = x_density
|
1624
|
-
y_dpi = y_density
|
1625
|
-
elsif units == 2
|
1626
|
-
x_dpi = x_density * 2.54
|
1627
|
-
y_dpi = y_density * 2.54
|
1628
|
-
end
|
1629
|
-
end
|
1630
|
-
|
1631
|
-
offset += length + 2
|
1632
|
-
break if marker == 0xFFDA
|
1633
|
-
end
|
1634
|
-
|
1635
|
-
raise "#{filename}: no size data found in jpeg image.\n" unless height
|
1636
|
-
|
1637
|
-
[type, width, height, x_dpi, y_dpi]
|
1638
|
-
end
|
1639
|
-
|
1640
|
-
#
|
1641
|
-
# Extract width and height information from a GIF file.
|
1642
|
-
#
|
1643
|
-
def process_gif(data, filename)
|
1644
|
-
type = 'gif'
|
1645
|
-
x_dpi = 96
|
1646
|
-
y_dpi = 96
|
1647
|
-
|
1648
|
-
width = data[6, 2].unpack1("v")
|
1649
|
-
height = data[8, 2].unpack1("v")
|
1650
|
-
|
1651
|
-
raise "#{filename}: no size data found in gif image.\n" if height.nil?
|
1652
|
-
|
1653
|
-
[type, width, height, x_dpi, y_dpi]
|
1654
|
-
end
|
1655
|
-
|
1656
|
-
# Extract width and height information from a BMP file.
|
1657
|
-
def process_bmp(data, filename) # :nodoc:
|
1658
|
-
type = 'bmp'
|
1659
|
-
|
1660
|
-
# Check that the file is big enough to be a bitmap.
|
1661
|
-
raise "#{filename} doesn't contain enough data." if data.bytesize <= 0x36
|
1662
|
-
|
1663
|
-
# Read the bitmap width and height. Verify the sizes.
|
1664
|
-
width, height = data.unpack("x18 V2")
|
1665
|
-
raise "#{filename}: largest image width #{width} supported is 65k." if width > 0xFFFF
|
1666
|
-
raise "#{filename}: largest image height supported is 65k." if height > 0xFFFF
|
1667
|
-
|
1668
|
-
# Read the bitmap planes and bpp data. Verify them.
|
1669
|
-
planes, bitcount = data.unpack("x26 v2")
|
1670
|
-
raise "#{filename} isn't a 24bit true color bitmap." unless bitcount == 24
|
1671
|
-
raise "#{filename}: only 1 plane supported in bitmap image." unless planes == 1
|
1672
|
-
|
1673
|
-
# Read the bitmap compression. Verify compression.
|
1674
|
-
compression = data.unpack1("x30 V")
|
1675
|
-
raise "#{filename}: compression not supported in bitmap image." unless compression == 0
|
1676
|
-
|
1677
|
-
[type, width, height]
|
1678
1558
|
end
|
1679
1559
|
end
|
1680
1560
|
end
|
@@ -206,5 +206,24 @@ module Writexlsx
|
|
206
206
|
worksheet.writer.empty_tag('c', cell_attributes(worksheet, row, row_name, col))
|
207
207
|
end
|
208
208
|
end
|
209
|
+
|
210
|
+
class EmbedImageCellData < CellData # :nodoc:
|
211
|
+
def initialize(image_index, xf)
|
212
|
+
@image_index = image_index
|
213
|
+
@xf = xf
|
214
|
+
end
|
215
|
+
|
216
|
+
def write_cell(worksheet, row, row_name, col)
|
217
|
+
attributes = cell_attributes(worksheet, row, row_name, col)
|
218
|
+
|
219
|
+
# Write a error value (mainly for embedded images).
|
220
|
+
attributes << %w[t e]
|
221
|
+
attributes << ['vm', @image_index]
|
222
|
+
|
223
|
+
worksheet.writer.tag_elements('c', attributes) do
|
224
|
+
worksheet.write_cell_value('#VALUE!')
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
209
228
|
end
|
210
229
|
end
|
data/lib/write_xlsx/worksheet.rb
CHANGED
@@ -113,7 +113,8 @@ module Writexlsx
|
|
113
113
|
@drawing_rels_id = 0
|
114
114
|
@vml_drawing_rels = {}
|
115
115
|
@vml_drawing_rels_id = 0
|
116
|
-
@
|
116
|
+
@has_dynamic_functions = false
|
117
|
+
@has_embedded_images = false
|
117
118
|
|
118
119
|
@use_future_functions = false
|
119
120
|
|
@@ -160,6 +161,8 @@ module Writexlsx
|
|
160
161
|
@page_setup.margin_footer = 0.5
|
161
162
|
@page_setup.header_footer_aligns = false
|
162
163
|
end
|
164
|
+
|
165
|
+
@embedded_image_indexes = @workbook.embedded_image_indexes
|
163
166
|
end
|
164
167
|
|
165
168
|
def set_xml_writer(filename) # :nodoc:
|
@@ -1446,6 +1449,7 @@ module Writexlsx
|
|
1446
1449
|
formula = expand_formula(formula, 'HYPGEOM.DIST\(')
|
1447
1450
|
formula = expand_formula(formula, 'IFNA\(')
|
1448
1451
|
formula = expand_formula(formula, 'IFS\(')
|
1452
|
+
formula = expand_formula(formula, 'IMAGE\(')
|
1449
1453
|
formula = expand_formula(formula, 'IMCOSH\(')
|
1450
1454
|
formula = expand_formula(formula, 'IMCOT\(')
|
1451
1455
|
formula = expand_formula(formula, 'IMCSCH\(')
|
@@ -1536,7 +1540,7 @@ module Writexlsx
|
|
1536
1540
|
raise WriteXLSXInsufficientArgumentError if [_row, _col, _formula].include?(nil)
|
1537
1541
|
|
1538
1542
|
# Check for dynamic array functions.
|
1539
|
-
regex = /\
|
1543
|
+
regex = /\bANCHORARRAY\(|\bBYCOL\(|\bBYROW\(|\bCHOOSECOLS\(|\bCHOOSEROWS\(|\bDROP\(|\bEXPAND\(|\bFILTER\(|\bHSTACK\(|\bLAMBDA\(|\bMAKEARRAY\(|\bMAP\(|\bRANDARRAY\(|\bREDUCE\(|\bSCAN\(|\bSEQUENCE\(|\bSINGLE\(|\bSORT\(|\bSORTBY\(|\bSWITCH\(|\bTAKE\(|\bTEXTSPLIT\(|\bTOCOL\(|\bTOROW\(|\bUNIQUE\(|\bVSTACK\(|\bWRAPCOLS\(|\bWRAPROWS\(|\bXLOOKUP\(/
|
1540
1544
|
if _formula =~ regex
|
1541
1545
|
return write_dynamic_array_formula(
|
1542
1546
|
_row, _col, _row, _col, _formula, _format, _value
|
@@ -1549,7 +1553,7 @@ module Writexlsx
|
|
1549
1553
|
else
|
1550
1554
|
check_dimensions(_row, _col)
|
1551
1555
|
store_row_col_max_min_values(_row, _col)
|
1552
|
-
_formula = _formula
|
1556
|
+
_formula = prepare_formula(_formula)
|
1553
1557
|
|
1554
1558
|
store_data_to_table(FormulaCellData.new(_formula, _format, _value), _row, _col)
|
1555
1559
|
end
|
@@ -1634,7 +1638,7 @@ module Writexlsx
|
|
1634
1638
|
#
|
1635
1639
|
def write_dynamic_array_formula(row1, col1, row2 = nil, col2 = nil, formula = nil, format = nil, value = nil)
|
1636
1640
|
write_array_formula_base('d', row1, col1, row2, col2, formula, format, value)
|
1637
|
-
@
|
1641
|
+
@has_dynamic_functions = true
|
1638
1642
|
end
|
1639
1643
|
|
1640
1644
|
#
|
@@ -1782,21 +1786,23 @@ module Writexlsx
|
|
1782
1786
|
# The label is written using the {#write()}[#method-i-write] method. Therefore it is
|
1783
1787
|
# possible to write strings, numbers or formulas as labels.
|
1784
1788
|
#
|
1785
|
-
def write_url(row, col, url = nil, format = nil, str = nil, tip = nil)
|
1789
|
+
def write_url(row, col, url = nil, format = nil, str = nil, tip = nil, ignore_write_string = false)
|
1786
1790
|
# Check for a cell reference in A1 notation and substitute row and column
|
1787
1791
|
if (row_col_array = row_col_notation(row))
|
1788
|
-
_row, _col
|
1789
|
-
_url
|
1790
|
-
_format
|
1791
|
-
_str
|
1792
|
-
_tip
|
1792
|
+
_row, _col = row_col_array
|
1793
|
+
_url = col
|
1794
|
+
_format = url
|
1795
|
+
_str = format
|
1796
|
+
_tip = str
|
1797
|
+
_ignore_write_string = tip
|
1793
1798
|
else
|
1794
|
-
_row
|
1795
|
-
_col
|
1796
|
-
_url
|
1797
|
-
_format
|
1798
|
-
_str
|
1799
|
-
_tip
|
1799
|
+
_row = row
|
1800
|
+
_col = col
|
1801
|
+
_url = url
|
1802
|
+
_format = format
|
1803
|
+
_str = str
|
1804
|
+
_tip = tip
|
1805
|
+
_ignore_write_string = ignore_write_string
|
1800
1806
|
end
|
1801
1807
|
_format, _str = _str, _format if _str.respond_to?(:xf_index) || !_format.respond_to?(:xf_index)
|
1802
1808
|
raise WriteXLSXInsufficientArgumentError if [_row, _col, _url].include?(nil)
|
@@ -1814,7 +1820,7 @@ module Writexlsx
|
|
1814
1820
|
_format ||= @default_url_format
|
1815
1821
|
|
1816
1822
|
# Write the hyperlink string.
|
1817
|
-
write_string(_row, _col, hyperlink.str, _format)
|
1823
|
+
write_string(_row, _col, hyperlink.str, _format) unless _ignore_write_string
|
1818
1824
|
end
|
1819
1825
|
|
1820
1826
|
#
|
@@ -1959,6 +1965,65 @@ module Writexlsx
|
|
1959
1965
|
]
|
1960
1966
|
end
|
1961
1967
|
|
1968
|
+
#
|
1969
|
+
# Embed an image into the worksheet.
|
1970
|
+
#
|
1971
|
+
def embed_image(row, col, filename, options = nil)
|
1972
|
+
# Check for a cell reference in A1 notation and substitute row and column.
|
1973
|
+
if (row_col_array = row_col_notation(row))
|
1974
|
+
_row, _col = row_col_array
|
1975
|
+
image = col
|
1976
|
+
_options = filename
|
1977
|
+
else
|
1978
|
+
_row = row
|
1979
|
+
_col = col
|
1980
|
+
image = filename
|
1981
|
+
_options = options
|
1982
|
+
end
|
1983
|
+
xf, url, tip, description, decorative = []
|
1984
|
+
|
1985
|
+
raise WriteXLSXInsufficientArgumentError if [_row, _col, image].include?(nil)
|
1986
|
+
raise "Couldn't locate #{image}" unless File.exist?(image)
|
1987
|
+
|
1988
|
+
# Check that row and col are valid and store max and min values
|
1989
|
+
check_dimensions(_row, _col)
|
1990
|
+
store_row_col_max_min_values(_row, _col)
|
1991
|
+
|
1992
|
+
if options
|
1993
|
+
xf = options[:cell_format]
|
1994
|
+
url = options[:url]
|
1995
|
+
tip = options[:tip]
|
1996
|
+
description = options[:description]
|
1997
|
+
decorative = options[:decorative]
|
1998
|
+
end
|
1999
|
+
|
2000
|
+
# Write the url without writing a string.
|
2001
|
+
if url
|
2002
|
+
xf ||= @default_url_format
|
2003
|
+
|
2004
|
+
write_url(row, col, url, xf, nil, tip, true)
|
2005
|
+
end
|
2006
|
+
|
2007
|
+
# Get the image properties, mainly for the type and checksum.
|
2008
|
+
image_properties = get_image_properties(image)
|
2009
|
+
type = image_properties[0]
|
2010
|
+
md5 = image_properties[6]
|
2011
|
+
|
2012
|
+
# Check for duplicate images.
|
2013
|
+
image_index = @embedded_image_indexes[md5]
|
2014
|
+
|
2015
|
+
unless ptrue?(image_index)
|
2016
|
+
@workbook.embedded_images << [image, type, description, decorative]
|
2017
|
+
|
2018
|
+
image_index = @workbook.embedded_images.size
|
2019
|
+
@embedded_image_indexes[md5] = image_index
|
2020
|
+
end
|
2021
|
+
|
2022
|
+
# Write the cell placeholder.
|
2023
|
+
store_data_to_table(EmbedImageCellData.new(image_index, xf), _row, _col)
|
2024
|
+
@has_embedded_images = true
|
2025
|
+
end
|
2026
|
+
|
1962
2027
|
#
|
1963
2028
|
# :call-seq:
|
1964
2029
|
# repeat_formula(row, column, formula [ , format ])
|
@@ -2799,8 +2864,12 @@ module Writexlsx
|
|
2799
2864
|
end
|
2800
2865
|
end
|
2801
2866
|
|
2802
|
-
def
|
2803
|
-
@
|
2867
|
+
def has_dynamic_functions?
|
2868
|
+
@has_dynamic_functions
|
2869
|
+
end
|
2870
|
+
|
2871
|
+
def has_embedded_images?
|
2872
|
+
@has_embedded_images
|
2804
2873
|
end
|
2805
2874
|
|
2806
2875
|
private
|
@@ -3278,6 +3347,7 @@ EOS
|
|
3278
3347
|
end
|
3279
3348
|
|
3280
3349
|
@drawing_links << ['/image', "../media/image#{image_id}.#{image_type}"] unless @drawing_rels[md5]
|
3350
|
+
|
3281
3351
|
drawing.rel_index = drawing_rel_index(md5)
|
3282
3352
|
end
|
3283
3353
|
public :prepare_image
|
@@ -4256,9 +4326,10 @@ EOS
|
|
4256
4326
|
|
4257
4327
|
# If the cell isn't a string then we have to add the url as
|
4258
4328
|
# the string to display
|
4259
|
-
if ptrue?(@cell_data_table)
|
4260
|
-
ptrue?(@cell_data_table[row_num])
|
4261
|
-
ptrue?(@cell_data_table[row_num][col_num]) &&
|
4329
|
+
if ptrue?(@cell_data_table) &&
|
4330
|
+
ptrue?(@cell_data_table[row_num]) &&
|
4331
|
+
ptrue?(@cell_data_table[row_num][col_num]) &&
|
4332
|
+
@cell_data_table[row_num][col_num].display_url_string?
|
4262
4333
|
link.display_on
|
4263
4334
|
end
|
4264
4335
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: write_xlsx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hideo NAKAMURA
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nkf
|
@@ -266,6 +266,10 @@ files:
|
|
266
266
|
- lib/write_xlsx/package/metadata.rb
|
267
267
|
- lib/write_xlsx/package/packager.rb
|
268
268
|
- lib/write_xlsx/package/relationships.rb
|
269
|
+
- lib/write_xlsx/package/rich_value.rb
|
270
|
+
- lib/write_xlsx/package/rich_value_rel.rb
|
271
|
+
- lib/write_xlsx/package/rich_value_structure.rb
|
272
|
+
- lib/write_xlsx/package/rich_value_types.rb
|
269
273
|
- lib/write_xlsx/package/shared_strings.rb
|
270
274
|
- lib/write_xlsx/package/styles.rb
|
271
275
|
- lib/write_xlsx/package/table.rb
|
@@ -304,7 +308,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
304
308
|
- !ruby/object:Gem::Version
|
305
309
|
version: '0'
|
306
310
|
requirements: []
|
307
|
-
rubygems_version: 3.
|
311
|
+
rubygems_version: 3.4.19
|
308
312
|
signing_key:
|
309
313
|
specification_version: 4
|
310
314
|
summary: write_xlsx is a gem to create a new file in the Excel 2007+ XLSX format.
|