write_xlsx 1.12.0 → 1.12.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/.rubocop.yml +12 -0
- data/Changes +33 -0
- data/LICENSE.txt +1 -1
- data/examples/autofilter.rb +1 -2
- data/examples/colors.rb +4 -4
- data/examples/formats.rb +14 -14
- data/lib/write_xlsx/chart/area.rb +1 -1
- data/lib/write_xlsx/chart/axis.rb +4 -4
- data/lib/write_xlsx/chart/bar.rb +1 -1
- data/lib/write_xlsx/chart/caption.rb +8 -4
- data/lib/write_xlsx/chart/column.rb +1 -1
- data/lib/write_xlsx/chart/doughnut.rb +2 -2
- data/lib/write_xlsx/chart/line.rb +1 -1
- data/lib/write_xlsx/chart/pie.rb +2 -2
- data/lib/write_xlsx/chart/radar.rb +1 -1
- data/lib/write_xlsx/chart/scatter.rb +1 -1
- data/lib/write_xlsx/chart/series.rb +10 -20
- data/lib/write_xlsx/chart/stock.rb +1 -1
- data/lib/write_xlsx/chart.rb +14 -21
- data/lib/write_xlsx/chartsheet.rb +3 -3
- data/lib/write_xlsx/drawing.rb +108 -114
- data/lib/write_xlsx/format.rb +20 -24
- data/lib/write_xlsx/image.rb +89 -0
- data/lib/write_xlsx/image_property.rb +163 -0
- data/lib/write_xlsx/inserted_chart.rb +42 -0
- data/lib/write_xlsx/package/button.rb +58 -5
- data/lib/write_xlsx/package/conditional_format.rb +4 -4
- data/lib/write_xlsx/package/packager.rb +22 -27
- data/lib/write_xlsx/package/rich_value.rb +1 -1
- data/lib/write_xlsx/package/styles.rb +1 -1
- data/lib/write_xlsx/package/vml.rb +10 -19
- data/lib/write_xlsx/shape.rb +3 -2
- data/lib/write_xlsx/sparkline.rb +1 -1
- data/lib/write_xlsx/utility.rb +8 -203
- data/lib/write_xlsx/version.rb +1 -1
- data/lib/write_xlsx/workbook.rb +87 -175
- data/lib/write_xlsx/worksheet/data_validation.rb +1 -1
- data/lib/write_xlsx/worksheet/hyperlink.rb +2 -2
- data/lib/write_xlsx/worksheet.rb +478 -484
- data/lib/write_xlsx/zip_file_utils.rb +1 -1
- data/write_xlsx.gemspec +3 -3
- metadata +11 -11
data/lib/write_xlsx/workbook.rb
CHANGED
@@ -1,30 +1,33 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require 'write_xlsx/
|
5
|
-
require 'write_xlsx/package/packager'
|
6
|
-
require 'write_xlsx/sheets'
|
7
|
-
require 'write_xlsx/worksheet'
|
4
|
+
require 'write_xlsx/chart'
|
8
5
|
require 'write_xlsx/chartsheet'
|
9
|
-
require 'write_xlsx/formats'
|
10
6
|
require 'write_xlsx/format'
|
7
|
+
require 'write_xlsx/formats'
|
8
|
+
require 'write_xlsx/image_property'
|
11
9
|
require 'write_xlsx/shape'
|
10
|
+
require 'write_xlsx/sheets'
|
12
11
|
require 'write_xlsx/utility'
|
13
|
-
require 'write_xlsx/
|
12
|
+
require 'write_xlsx/worksheet'
|
14
13
|
require 'write_xlsx/zip_file_utils'
|
14
|
+
require 'write_xlsx/package/xml_writer_simple'
|
15
|
+
require 'write_xlsx/package/packager'
|
15
16
|
require 'tmpdir'
|
16
17
|
require 'tempfile'
|
17
18
|
require 'digest/md5'
|
18
19
|
|
19
20
|
module Writexlsx
|
20
|
-
OFFICE_URL
|
21
|
+
OFFICE_URL = 'http://schemas.microsoft.com/office/' # :nodoc:
|
22
|
+
MAX_URL_LENGTH = 2_079
|
21
23
|
|
22
24
|
class Workbook
|
23
25
|
include Writexlsx::Utility
|
24
26
|
|
25
27
|
attr_writer :firstsheet # :nodoc:
|
26
28
|
attr_reader :palette # :nodoc:
|
27
|
-
attr_reader :worksheets
|
29
|
+
attr_reader :worksheets # :nodoc:
|
30
|
+
attr_accessor :drawings # :nodoc:
|
28
31
|
attr_reader :named_ranges # :nodoc:
|
29
32
|
attr_reader :doc_properties # :nodoc:
|
30
33
|
attr_reader :custom_properties # :nodoc:
|
@@ -38,9 +41,13 @@ module Writexlsx
|
|
38
41
|
attr_reader :embedded_image_indexes # :nodec:
|
39
42
|
attr_reader :embedded_images # :nodoc:
|
40
43
|
attr_reader :embedded_descriptions # :nodoc:
|
44
|
+
attr_writer :has_embedded_descriptions # :nodoc:
|
45
|
+
attr_accessor :charts # :nodoc:
|
41
46
|
|
42
47
|
def initialize(file, *option_params)
|
43
48
|
options, default_formats = process_workbook_options(*option_params)
|
49
|
+
@options = options.dup # for test
|
50
|
+
@default_formats = default_formats.dup # for test
|
44
51
|
@writer = Package::XMLWriterSimple.new
|
45
52
|
|
46
53
|
@file = file
|
@@ -60,7 +67,6 @@ module Writexlsx
|
|
60
67
|
@formats = Formats.new
|
61
68
|
@xf_formats = []
|
62
69
|
@dxf_formats = []
|
63
|
-
@font_count = 0
|
64
70
|
@num_formats = []
|
65
71
|
@defined_names = []
|
66
72
|
@named_ranges = []
|
@@ -70,16 +76,15 @@ module Writexlsx
|
|
70
76
|
@optimization = options[:optimization] || 0
|
71
77
|
@x_window = 240
|
72
78
|
@y_window = 15
|
73
|
-
@window_width =
|
74
|
-
@window_height =
|
79
|
+
@window_width = 16_095
|
80
|
+
@window_height = 9_660
|
75
81
|
@tab_ratio = 600
|
76
82
|
@excel2003_style = options[:excel2003_style] || false
|
77
|
-
@table_count = 0
|
78
83
|
@image_types = {}
|
79
84
|
@images = []
|
80
85
|
@strings_to_urls = options[:strings_to_urls].nil? || options[:strings_to_urls] ? true : false
|
81
86
|
|
82
|
-
@max_url_length =
|
87
|
+
@max_url_length = MAX_URL_LENGTH
|
83
88
|
@has_comments = false
|
84
89
|
@read_only = 0
|
85
90
|
@has_metadata = false
|
@@ -87,10 +92,11 @@ module Writexlsx
|
|
87
92
|
@has_embedded_descriptions = false
|
88
93
|
|
89
94
|
if options[:max_url_length]
|
90
|
-
@max_url_length = options[:max_url_length]
|
95
|
+
@max_url_length = options[:max_url_length].to_i
|
91
96
|
|
92
|
-
@max_url_length =
|
97
|
+
@max_url_length = MAX_URL_LENGTH if @max_url_length < 255
|
93
98
|
end
|
99
|
+
|
94
100
|
# Structures for the shared strings data.
|
95
101
|
@shared_strings = Package::SharedStrings.new
|
96
102
|
|
@@ -619,8 +625,51 @@ module Writexlsx
|
|
619
625
|
@has_embedded_descriptions
|
620
626
|
end
|
621
627
|
|
628
|
+
#
|
629
|
+
# Store the image types (PNG/JPEG/etc) used in the workbook to use in these
|
630
|
+
# Content_Types file.
|
631
|
+
#
|
632
|
+
def store_image_types(type)
|
633
|
+
case type
|
634
|
+
when 'png'
|
635
|
+
@image_types[:png] = 1
|
636
|
+
when 'jpeg'
|
637
|
+
@image_types[:jpeg] = 1
|
638
|
+
when 'gif'
|
639
|
+
@image_types[:gif] = 1
|
640
|
+
when 'bmp'
|
641
|
+
@image_types[:bmp] = 1
|
642
|
+
end
|
643
|
+
end
|
644
|
+
|
622
645
|
private
|
623
646
|
|
647
|
+
#
|
648
|
+
# Workbook の生成時のオプションハッシュを解析する
|
649
|
+
#
|
650
|
+
def process_workbook_options(*params)
|
651
|
+
case params.size
|
652
|
+
when 0
|
653
|
+
[{}, {}]
|
654
|
+
when 1 # one hash
|
655
|
+
options_keys = %i[tempdir date_1904 optimization excel2003_style strings_to_urls max_url_length]
|
656
|
+
|
657
|
+
hash = params.first
|
658
|
+
options = hash.reject { |k, _v| !options_keys.include?(k) }
|
659
|
+
|
660
|
+
default_format_properties =
|
661
|
+
hash[:default_format_properties] ||
|
662
|
+
hash.reject { |k, _v| options_keys.include?(k) }
|
663
|
+
|
664
|
+
[options, default_format_properties.dup]
|
665
|
+
when 2 # array which includes options and default_format_properties
|
666
|
+
options, default_format_properties = params
|
667
|
+
default_format_properties ||= {}
|
668
|
+
|
669
|
+
[options.dup, default_format_properties.dup]
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
624
673
|
def filename
|
625
674
|
setup_filename unless @filename
|
626
675
|
@filename
|
@@ -732,7 +781,7 @@ module Writexlsx
|
|
732
781
|
|
733
782
|
if pos > 0
|
734
783
|
sheetname = range[0, pos]
|
735
|
-
cells = range[pos + 1..-1]
|
784
|
+
cells = range[(pos + 1)..-1]
|
736
785
|
end
|
737
786
|
|
738
787
|
# Split the cell range into 2 cells or else use single cell for both.
|
@@ -924,24 +973,10 @@ module Writexlsx
|
|
924
973
|
Writexlsx::Utility.delete_files(tempdir)
|
925
974
|
end
|
926
975
|
|
927
|
-
def write_parts(zip)
|
928
|
-
parts.each do |part|
|
929
|
-
zip.put_next_entry(zip_entry_for_part(part.sub(Regexp.new("#{tempdir}/?"), '')))
|
930
|
-
zip.puts(File.read(part))
|
931
|
-
end
|
932
|
-
end
|
933
|
-
|
934
976
|
def zip_entry_for_part(part)
|
935
977
|
Zip::Entry.new("", part)
|
936
978
|
end
|
937
979
|
|
938
|
-
#
|
939
|
-
# files
|
940
|
-
#
|
941
|
-
def parts
|
942
|
-
Dir.glob(File.join(tempdir, "**", "*"), File::FNM_DOTMATCH).select { |f| File.file?(f) }
|
943
|
-
end
|
944
|
-
|
945
980
|
#
|
946
981
|
# prepare_sst_string_data
|
947
982
|
#
|
@@ -1188,7 +1223,6 @@ module Writexlsx
|
|
1188
1223
|
vml_data_id = 1
|
1189
1224
|
vml_header_id = 0
|
1190
1225
|
vml_shape_id = 1024
|
1191
|
-
comment_files = 0
|
1192
1226
|
has_button = false
|
1193
1227
|
|
1194
1228
|
@worksheets.each do |sheet|
|
@@ -1196,8 +1230,7 @@ module Writexlsx
|
|
1196
1230
|
|
1197
1231
|
if sheet.has_vml?
|
1198
1232
|
if sheet.has_comments?
|
1199
|
-
|
1200
|
-
comment_id += 1
|
1233
|
+
comment_id += 1
|
1201
1234
|
@has_comments = true
|
1202
1235
|
end
|
1203
1236
|
vml_drawing_id += 1
|
@@ -1402,158 +1435,37 @@ module Writexlsx
|
|
1402
1435
|
# Iterate through the worksheets and set up any chart or image drawings.
|
1403
1436
|
#
|
1404
1437
|
def prepare_drawings # :nodoc:
|
1405
|
-
chart_ref_id = 0
|
1406
|
-
drawing_id = 0
|
1407
|
-
ref_id = 0
|
1408
|
-
image_ids = {}
|
1409
|
-
header_image_ids = {}
|
1410
|
-
background_ids = {}
|
1411
|
-
|
1412
1438
|
# Store the image types for any embedded images.
|
1413
|
-
@embedded_images.each do |
|
1414
|
-
store_image_types(
|
1439
|
+
@embedded_images.each do |image|
|
1440
|
+
store_image_types(image.type)
|
1415
1441
|
|
1416
|
-
@has_embedded_descriptions = true if ptrue?(
|
1442
|
+
@has_embedded_descriptions = true if ptrue?(image.description)
|
1417
1443
|
end
|
1418
1444
|
|
1419
|
-
|
1420
|
-
image_ref_id = @embedded_images.size
|
1421
|
-
|
1422
|
-
@worksheets.each do |sheet|
|
1423
|
-
chart_count = sheet.charts.size
|
1424
|
-
image_count = sheet.images.size
|
1425
|
-
shape_count = sheet.shapes.size
|
1426
|
-
header_image_count = sheet.header_images.size
|
1427
|
-
footer_image_count = sheet.footer_images.size
|
1428
|
-
has_background = sheet.background_image.size
|
1429
|
-
has_drawings = false
|
1430
|
-
|
1431
|
-
# Check that some image or drawing needs to be processed.
|
1432
|
-
next if chart_count + image_count + shape_count + header_image_count + footer_image_count + has_background == 0
|
1433
|
-
|
1434
|
-
# Don't increase the drawing_id header/footer images.
|
1435
|
-
if chart_count + image_count + shape_count > 0
|
1436
|
-
drawing_id += 1
|
1437
|
-
has_drawings = true
|
1438
|
-
end
|
1439
|
-
|
1440
|
-
# Prepare the background images.
|
1441
|
-
if ptrue?(has_background)
|
1442
|
-
filename = sheet.background_image
|
1443
|
-
type, width, height, name, x_dpi, y_dpi, md5 = get_image_properties(filename)
|
1444
|
-
|
1445
|
-
if background_ids[md5]
|
1446
|
-
ref_id = background_ids[md5]
|
1447
|
-
else
|
1448
|
-
image_ref_id += 1
|
1449
|
-
ref_id = image_ref_id
|
1450
|
-
background_ids[md5] = ref_id
|
1451
|
-
@images << [filename, type]
|
1452
|
-
end
|
1453
|
-
|
1454
|
-
sheet.prepare_background(ref_id, type)
|
1455
|
-
end
|
1456
|
-
|
1457
|
-
# Prepare the worksheet images.
|
1458
|
-
sheet.images.each_with_index do |image, index|
|
1459
|
-
filename = image[2]
|
1460
|
-
type, width, height, name, x_dpi, y_dpi, md5 = get_image_properties(image[2])
|
1461
|
-
if image_ids[md5]
|
1462
|
-
ref_id = image_ids[md5]
|
1463
|
-
else
|
1464
|
-
image_ref_id += 1
|
1465
|
-
image_ids[md5] = ref_id = image_ref_id
|
1466
|
-
@images << [filename, type]
|
1467
|
-
end
|
1468
|
-
sheet.prepare_image(
|
1469
|
-
index, ref_id, drawing_id, width, height,
|
1470
|
-
name, type, x_dpi, y_dpi, md5
|
1471
|
-
)
|
1472
|
-
end
|
1473
|
-
|
1474
|
-
# Prepare the worksheet charts.
|
1475
|
-
sheet.charts.each_with_index do |_chart, index|
|
1476
|
-
chart_ref_id += 1
|
1477
|
-
sheet.prepare_chart(index, chart_ref_id, drawing_id)
|
1478
|
-
end
|
1479
|
-
|
1480
|
-
# Prepare the worksheet shapes.
|
1481
|
-
sheet.shapes.each_with_index do |_shape, index|
|
1482
|
-
sheet.prepare_shape(index, drawing_id)
|
1483
|
-
end
|
1484
|
-
|
1485
|
-
# Prepare the header images.
|
1486
|
-
header_image_count.times do |index|
|
1487
|
-
filename = sheet.header_images[index][0]
|
1488
|
-
position = sheet.header_images[index][1]
|
1489
|
-
|
1490
|
-
type, width, height, name, x_dpi, y_dpi, md5 =
|
1491
|
-
get_image_properties(filename)
|
1492
|
-
|
1493
|
-
if header_image_ids[md5]
|
1494
|
-
ref_id = header_image_ids[md5]
|
1495
|
-
else
|
1496
|
-
image_ref_id += 1
|
1497
|
-
header_image_ids[md5] = ref_id = image_ref_id
|
1498
|
-
@images << [filename, type]
|
1499
|
-
end
|
1500
|
-
|
1501
|
-
sheet.prepare_header_image(
|
1502
|
-
ref_id, width, height, name, type,
|
1503
|
-
position, x_dpi, y_dpi, md5
|
1504
|
-
)
|
1505
|
-
end
|
1506
|
-
|
1507
|
-
# Prepare the footer images.
|
1508
|
-
footer_image_count.times do |index|
|
1509
|
-
filename = sheet.footer_images[index][0]
|
1510
|
-
position = sheet.footer_images[index][1]
|
1511
|
-
|
1512
|
-
type, width, height, name, x_dpi, y_dpi, md5 =
|
1513
|
-
get_image_properties(filename)
|
1514
|
-
|
1515
|
-
if header_image_ids[md5]
|
1516
|
-
ref_id = header_image_ids[md5]
|
1517
|
-
else
|
1518
|
-
image_ref_id += 1
|
1519
|
-
header_image_ids[md5] = ref_id = image_ref_id
|
1520
|
-
@images << [filename, type]
|
1521
|
-
end
|
1522
|
-
|
1523
|
-
sheet.prepare_header_image(
|
1524
|
-
ref_id, width, height, name, type,
|
1525
|
-
position, x_dpi, y_dpi, md5
|
1526
|
-
)
|
1527
|
-
end
|
1528
|
-
|
1529
|
-
if has_drawings
|
1530
|
-
drawings = sheet.drawings
|
1531
|
-
@drawings << drawings
|
1532
|
-
end
|
1533
|
-
end
|
1445
|
+
prepare_drawings_of_all_sheets
|
1534
1446
|
|
1535
1447
|
# Sort the workbook charts references into the order that the were
|
1536
1448
|
# written from the worksheets above.
|
1537
1449
|
@charts = @charts.select { |chart| chart.id != -1 }
|
1538
|
-
|
1539
|
-
|
1540
|
-
@drawing_count = drawing_id
|
1450
|
+
.sort_by { |chart| chart.id }
|
1541
1451
|
end
|
1542
1452
|
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1453
|
+
def prepare_drawings_of_all_sheets
|
1454
|
+
drawing_id = 0
|
1455
|
+
chart_ref_id = 0
|
1456
|
+
image_ids = {}
|
1457
|
+
header_image_ids = {}
|
1458
|
+
background_ids = {}
|
1459
|
+
|
1460
|
+
# The image IDs start from after the embedded images.
|
1461
|
+
image_ref_id = @embedded_images.size
|
1462
|
+
|
1463
|
+
@worksheets.each do |sheet|
|
1464
|
+
drawing_id, chart_ref_id, image_ref_id =
|
1465
|
+
sheet.prepare_drawings(
|
1466
|
+
drawing_id, chart_ref_id, image_ref_id, image_ids,
|
1467
|
+
header_image_ids, background_ids
|
1468
|
+
)
|
1557
1469
|
end
|
1558
1470
|
end
|
1559
1471
|
end
|
@@ -163,7 +163,7 @@ module Writexlsx
|
|
163
163
|
attributes << %w[errorStyle information] if @error_type == 2
|
164
164
|
end
|
165
165
|
attributes << ['allowBlank', 1] if @ignore_blank != 0
|
166
|
-
attributes << ['showDropDown', 1] if @dropdown
|
166
|
+
attributes << ['showDropDown', 1] if @dropdown == 0
|
167
167
|
attributes << ['showInputMessage', 1] if @show_input != 0
|
168
168
|
attributes << ['showErrorMessage', 1] if @show_error != 0
|
169
169
|
|
@@ -34,7 +34,7 @@ module Writexlsx
|
|
34
34
|
url = escape_url(url)
|
35
35
|
|
36
36
|
# Excel limits the escaped URL and location/anchor to 255 characters.
|
37
|
-
raise "Ignoring URL '#{url}' where link or anchor > #{max_url_length} characters since it exceeds Excel's limit for URLS. See LIMITATIONS section of the
|
37
|
+
raise "Ignoring URL '#{url}' where link or anchor > #{max_url_length} characters since it exceeds Excel's limit for URLS. See LIMITATIONS section of the WriteXLSX documentation." if url.bytesize > max_url_length || (!@url_str.nil? && @url_str.bytesize > max_url_length)
|
38
38
|
|
39
39
|
@url = url
|
40
40
|
@str = normalized_str
|
@@ -123,7 +123,7 @@ module Writexlsx
|
|
123
123
|
@url_str = url_str
|
124
124
|
|
125
125
|
# Excel limits the escaped URL and location/anchor to max_url_length characters.
|
126
|
-
raise "Ignoring URL '#{url}' where link or anchor > #{max_url_length} characters since it exceeds Excel's limit for URLS. See LIMITATIONS section of the
|
126
|
+
raise "Ignoring URL '#{url}' where link or anchor > #{max_url_length} characters since it exceeds Excel's limit for URLS. See LIMITATIONS section of the WriteXLSX documentation." if url.bytesize > max_url_length || (!@url_str.nil? && @url_str.bytesize > max_url_length)
|
127
127
|
|
128
128
|
@url = url
|
129
129
|
@str = str
|