write_xlsx 1.11.2 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,83 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'write_xlsx/package/xml_writer_simple'
5
+ require 'write_xlsx/utility'
6
+
7
+ module Writexlsx
8
+ module Package
9
+ #
10
+ # RichValueStructure - A class for writing the Excel XLSX rdrichvaluestructure.xml
11
+ # file.
12
+ #
13
+ # Used in conjunction with Excel::Writer::XLSX
14
+ #
15
+ # Copyright 2000-2024, John McNamara, jmcnamara@cpan.org
16
+ #
17
+ # Convert to Ruby by Hideo NAKAMURA, nakamura.hideo@gmail.com
18
+ #
19
+ class RichValueStructure
20
+ include Writexlsx::Utility
21
+
22
+ attr_writer :has_embedded_descriptions
23
+
24
+ def initialize
25
+ @writer = Package::XMLWriterSimple.new
26
+ @has_embedded_descriptions = false
27
+ end
28
+
29
+ def set_xml_writer(filename)
30
+ @writer.set_xml_writer(filename)
31
+ end
32
+
33
+ def assemble_xml_file
34
+ write_xml_declaration do
35
+ write_rv_structures
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ #
42
+ # Write the <rvStructures> element.
43
+ #
44
+ def write_rv_structures
45
+ xmlns = 'http://schemas.microsoft.com/office/spreadsheetml/2017/richdata'
46
+
47
+ attributes = [
48
+ ['xmlns', xmlns],
49
+ ['count', 1]
50
+ ]
51
+
52
+ @writer.tag_elements('rvStructures', attributes) do
53
+ write_s
54
+ end
55
+ end
56
+
57
+ #
58
+ # Write the <s> element.
59
+ #
60
+ def write_s
61
+ attributes = [%w[t _localImage]]
62
+
63
+ @writer.tag_elements('s', attributes) do
64
+ write_k('_rvRel:LocalImageIdentifier', 'i')
65
+ write_k('CalcOrigin', 'i')
66
+ write_k('Text', 's') if @has_embedded_descriptions
67
+ end
68
+ end
69
+
70
+ #
71
+ # Write the <k> element.
72
+ #
73
+ def write_k(n, t)
74
+ attributes = [
75
+ ['n', n],
76
+ ['t', t]
77
+ ]
78
+
79
+ @writer.empty_tag('k', attributes)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,103 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'write_xlsx/package/xml_writer_simple'
5
+ require 'write_xlsx/utility'
6
+
7
+ module Writexlsx
8
+ module Package
9
+ #
10
+ # RichValueTypes - A class for writing the Excel XLSX rdRichValueTypes.xml file.
11
+ #
12
+ # Used in conjunction with Excel::Writer::XLSX
13
+ #
14
+ # Copyright 2000-2024, John McNamara, jmcnamara@cpan.org
15
+ #
16
+ # Convert to Ruby by Hideo NAKAMURA, nakamura.hideo@gmail.com
17
+ #
18
+ class RichValueTypes
19
+ include Writexlsx::Utility
20
+
21
+ def initialize
22
+ @writer = Package::XMLWriterSimple.new
23
+ end
24
+
25
+ def set_xml_writer(filename)
26
+ @writer.set_xml_writer(filename)
27
+ end
28
+
29
+ def assemble_xml_file
30
+ write_xml_declaration do
31
+ write_rv_types_info
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ #
38
+ # Write the <rvTypesInfo> element.
39
+ #
40
+ def write_rv_types_info
41
+ xmlns = 'http://schemas.microsoft.com/office/spreadsheetml/2017/richdata2'
42
+ xmlns_mc = 'http://schemas.openxmlformats.org/markup-compatibility/2006'
43
+ xmlns_x = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'
44
+
45
+ attributes = [
46
+ ['xmlns', xmlns],
47
+ ['xmlns:mc', xmlns_mc],
48
+ ['mc:Ignorable', 'x'],
49
+ ['xmlns:x', xmlns_x]
50
+ ]
51
+
52
+ key_flags = [
53
+ ['_Self', %w[ExcludeFromFile ExcludeFromCalcComparison]],
54
+ ['_DisplayString', ['ExcludeFromCalcComparison']],
55
+ ['_Flags', ['ExcludeFromCalcComparison']],
56
+ ['_Format', ['ExcludeFromCalcComparison']],
57
+ ['_SubLabel', ['ExcludeFromCalcComparison']],
58
+ ['_Attribution', ['ExcludeFromCalcComparison']],
59
+ ['_Icon', ['ExcludeFromCalcComparison']],
60
+ ['_Display', ['ExcludeFromCalcComparison']],
61
+ ['_CanonicalPropertyNames', ['ExcludeFromCalcComparison']],
62
+ ['_ClassificationId', ['ExcludeFromCalcComparison']]
63
+ ]
64
+
65
+ @writer.tag_elements('rvTypesInfo', attributes) do
66
+ @writer.tag_elements('global') do
67
+ @writer.tag_elements('keyFlags') do
68
+ # Write the keyFlags element.
69
+ key_flags.each do |key_flag|
70
+ write_key(key_flag[0], key_flag[1])
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ #
78
+ # Write the <key> element.
79
+ #
80
+ def write_key(name, flags = [])
81
+ attributes = [['name', name]]
82
+
83
+ @writer.tag_elements('key', attributes) do
84
+ flags.each do |flag|
85
+ write_flag(flag)
86
+ end
87
+ end
88
+ end
89
+
90
+ #
91
+ # Write the <flag> element.
92
+ #
93
+ def write_flag(name)
94
+ attributes = [
95
+ ['name', name],
96
+ ['value', 1]
97
+ ]
98
+
99
+ @writer.empty_tag('flag', attributes)
100
+ end
101
+ end
102
+ end
103
+ end
@@ -988,6 +988,178 @@ module Writexlsx
988
988
  def write_a_end_para_rpr # :nodoc:
989
989
  @writer.empty_tag('a:endParaRPr', [%w[lang en-US]])
990
990
  end
991
+
992
+ #
993
+ # Extract information from the image file such as dimension, type, filename,
994
+ # and extension. Also keep track of previously seen images to optimise out
995
+ # any duplicates.
996
+ #
997
+ def get_image_properties(filename)
998
+ # Note the image_id, and previous_images mechanism isn't currently used.
999
+ x_dpi = 96
1000
+ y_dpi = 96
1001
+
1002
+ workbook = @workbook || self
1003
+
1004
+ # Open the image file and import the data.
1005
+ data = File.binread(filename)
1006
+ md5 = Digest::MD5.hexdigest(data)
1007
+ if data.unpack1('x A3') == 'PNG'
1008
+ # Test for PNGs.
1009
+ type, width, height, x_dpi, y_dpi = process_png(data)
1010
+ workbook.image_types[:png] = 1
1011
+ elsif data.unpack1('n') == 0xFFD8
1012
+ # Test for JPEG files.
1013
+ type, width, height, x_dpi, y_dpi = process_jpg(data, filename)
1014
+ workbook.image_types[:jpeg] = 1
1015
+ elsif data.unpack1('A4') == 'GIF8'
1016
+ # Test for GIFs.
1017
+ type, width, height, x_dpi, y_dpi = process_gif(data, filename)
1018
+ workbook.image_types[:gif] = 1
1019
+ elsif data.unpack1('A2') == 'BM'
1020
+ # Test for BMPs.
1021
+ type, width, height = process_bmp(data, filename)
1022
+ workbook.image_types[:bmp] = 1
1023
+ else
1024
+ # TODO. Add Image::Size to support other types.
1025
+ raise "Unsupported image format for file: #{filename}\n"
1026
+ end
1027
+
1028
+ # Set a default dpi for images with 0 dpi.
1029
+ x_dpi = 96 if x_dpi == 0
1030
+ y_dpi = 96 if y_dpi == 0
1031
+
1032
+ [type, width, height, File.basename(filename), x_dpi, y_dpi, md5]
1033
+ end
1034
+
1035
+ #
1036
+ # Extract width and height information from a PNG file.
1037
+ #
1038
+ def process_png(data)
1039
+ type = 'png'
1040
+ width = 0
1041
+ height = 0
1042
+ x_dpi = 96
1043
+ y_dpi = 96
1044
+
1045
+ offset = 8
1046
+ data_length = data.size
1047
+
1048
+ # Search through the image data to read the height and width in th the
1049
+ # IHDR element. Also read the DPI in the pHYs element.
1050
+ while offset < data_length
1051
+
1052
+ length = data[offset + 0, 4].unpack1("N")
1053
+ png_type = data[offset + 4, 4].unpack1("A4")
1054
+
1055
+ case png_type
1056
+ when "IHDR"
1057
+ width = data[offset + 8, 4].unpack1("N")
1058
+ height = data[offset + 12, 4].unpack1("N")
1059
+ when "pHYs"
1060
+ x_ppu = data[offset + 8, 4].unpack1("N")
1061
+ y_ppu = data[offset + 12, 4].unpack1("N")
1062
+ units = data[offset + 16, 1].unpack1("C")
1063
+
1064
+ if units == 1
1065
+ x_dpi = x_ppu * 0.0254
1066
+ y_dpi = y_ppu * 0.0254
1067
+ end
1068
+ end
1069
+
1070
+ offset = offset + length + 12
1071
+
1072
+ break if png_type == "IEND"
1073
+ end
1074
+ raise "#{filename}: no size data found in png image.\n" unless height
1075
+
1076
+ [type, width, height, x_dpi, y_dpi]
1077
+ end
1078
+
1079
+ def process_jpg(data, filename)
1080
+ type = 'jpeg'
1081
+ x_dpi = 96
1082
+ y_dpi = 96
1083
+
1084
+ offset = 2
1085
+ data_length = data.bytesize
1086
+
1087
+ # Search through the image data to read the JPEG markers.
1088
+ while offset < data_length
1089
+ marker = data[offset + 0, 2].unpack1("n")
1090
+ length = data[offset + 2, 2].unpack1("n")
1091
+
1092
+ # Read the height and width in the 0xFFCn elements
1093
+ # (Except C4, C8 and CC which aren't SOF markers).
1094
+ if (marker & 0xFFF0) == 0xFFC0 &&
1095
+ marker != 0xFFC4 && marker != 0xFFCC
1096
+ height = data[offset + 5, 2].unpack1("n")
1097
+ width = data[offset + 7, 2].unpack1("n")
1098
+ end
1099
+
1100
+ # Read the DPI in the 0xFFE0 element.
1101
+ if marker == 0xFFE0
1102
+ units = data[offset + 11, 1].unpack1("C")
1103
+ x_density = data[offset + 12, 2].unpack1("n")
1104
+ y_density = data[offset + 14, 2].unpack1("n")
1105
+
1106
+ if units == 1
1107
+ x_dpi = x_density
1108
+ y_dpi = y_density
1109
+ elsif units == 2
1110
+ x_dpi = x_density * 2.54
1111
+ y_dpi = y_density * 2.54
1112
+ end
1113
+ end
1114
+
1115
+ offset += length + 2
1116
+ break if marker == 0xFFDA
1117
+ end
1118
+
1119
+ raise "#{filename}: no size data found in jpeg image.\n" unless height
1120
+
1121
+ [type, width, height, x_dpi, y_dpi]
1122
+ end
1123
+
1124
+ #
1125
+ # Extract width and height information from a GIF file.
1126
+ #
1127
+ def process_gif(data, filename)
1128
+ type = 'gif'
1129
+ x_dpi = 96
1130
+ y_dpi = 96
1131
+
1132
+ width = data[6, 2].unpack1("v")
1133
+ height = data[8, 2].unpack1("v")
1134
+
1135
+ raise "#{filename}: no size data found in gif image.\n" if height.nil?
1136
+
1137
+ [type, width, height, x_dpi, y_dpi]
1138
+ end
1139
+
1140
+ # Extract width and height information from a BMP file.
1141
+ def process_bmp(data, filename) # :nodoc:
1142
+ type = 'bmp'
1143
+
1144
+ # Check that the file is big enough to be a bitmap.
1145
+ raise "#{filename} doesn't contain enough data." if data.bytesize <= 0x36
1146
+
1147
+ # Read the bitmap width and height. Verify the sizes.
1148
+ width, height = data.unpack("x18 V2")
1149
+ raise "#{filename}: largest image width #{width} supported is 65k." if width > 0xFFFF
1150
+ raise "#{filename}: largest image height supported is 65k." if height > 0xFFFF
1151
+
1152
+ # Read the bitmap planes and bpp data. Verify them.
1153
+ planes, bitcount = data.unpack("x26 v2")
1154
+ raise "#{filename} isn't a 24bit true color bitmap." unless bitcount == 24
1155
+ raise "#{filename}: only 1 plane supported in bitmap image." unless planes == 1
1156
+
1157
+ # Read the bitmap compression. Verify compression.
1158
+ compression = data.unpack1("x30 V")
1159
+ raise "#{filename}: compression not supported in bitmap image." unless compression == 0
1160
+
1161
+ [type, width, height]
1162
+ end
991
1163
  end
992
1164
 
993
1165
  module WriteDPtPoint
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- WriteXLSX_VERSION = "1.11.2"
3
+ WriteXLSX_VERSION = "1.12.0"
@@ -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
- if sheet.has_dynamic_arrays?
1230
- @has_metadata = true
1231
- break
1232
- end
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
- # Extract information from the image file such as dimension, type, filename,
1512
- # and extension. Also keep track of previously seen images to optimise out
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 get_image_properties(filename)
1516
- # Note the image_id, and previous_images mechanism isn't currently used.
1517
- x_dpi = 96
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
- elsif data.unpack1('n') == 0xFFD8
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
- elsif data.unpack1('A4') == 'GIF8'
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
- elsif data.unpack1('A2') == 'BM'
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
@@ -58,7 +58,8 @@ module Writexlsx
58
58
  end
59
59
 
60
60
  def display_on
61
- @display = @url_str
61
+ # @display = @url_str
62
+ @display = @str
62
63
  end
63
64
  end
64
65