write_xlsx 0.99.0 → 1.07.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +0 -1
- data/Changes +70 -0
- data/README.md +1 -1
- data/examples/a_simple.rb +1 -1
- data/examples/add_vba_project.rb +1 -1
- data/examples/array_formula.rb +1 -1
- data/examples/chart_area.rb +5 -2
- data/examples/chart_bar.rb +5 -2
- data/examples/chart_clustered.rb +1 -1
- data/examples/chart_column.rb +5 -2
- data/examples/chart_combined.rb +1 -1
- data/examples/chart_data_labels.rb +320 -0
- data/examples/chart_data_table.rb +9 -3
- data/examples/chart_data_tools.rb +25 -7
- data/examples/chart_doughnut.rb +17 -5
- data/examples/chart_gauge.rb +73 -0
- data/examples/chart_line.rb +90 -12
- data/examples/chart_pareto.rb +1 -1
- data/examples/chart_pie.rb +9 -3
- data/examples/chart_radar.rb +13 -4
- data/examples/chart_scatter.rb +5 -2
- data/examples/chart_secondary_axis.rb +5 -2
- data/examples/chart_stock.rb +1 -1
- data/examples/chart_styles.rb +1 -1
- data/examples/colors.rb +1 -1
- data/examples/data_validate.rb +1 -1
- data/examples/date_time.rb +1 -1
- data/examples/demo.rb +4 -1
- data/examples/formats.rb +1 -1
- data/examples/headers.rb +1 -1
- data/examples/hide_row_col.rb +1 -1
- data/examples/hide_sheet.rb +1 -1
- data/examples/hyperlink1.rb +1 -1
- data/examples/indent.rb +1 -1
- data/examples/macros.rb +1 -1
- data/examples/merge1.rb +1 -1
- data/examples/merge2.rb +1 -1
- data/examples/merge3.rb +1 -1
- data/examples/merge4.rb +1 -1
- data/examples/merge5.rb +1 -1
- data/examples/merge6.rb +1 -1
- data/examples/outline.rb +1 -1
- data/examples/outline_collapsed.rb +1 -1
- data/examples/panes.rb +1 -1
- data/examples/properties.rb +1 -1
- data/examples/regions.rb +1 -1
- data/examples/rich_strings.rb +1 -1
- data/examples/right_to_left.rb +1 -1
- data/examples/shape1.rb +1 -1
- data/examples/shape2.rb +1 -1
- data/examples/shape3.rb +1 -1
- data/examples/shape4.rb +1 -1
- data/examples/shape5.rb +1 -1
- data/examples/shape6.rb +1 -1
- data/examples/shape7.rb +1 -1
- data/examples/shape8.rb +1 -1
- data/examples/shape_all.rb +1 -1
- data/examples/sparklines1.rb +1 -1
- data/examples/sparklines2.rb +1 -1
- data/examples/stats.rb +1 -1
- data/examples/stats_ext.rb +1 -1
- data/examples/stocks.rb +1 -1
- data/examples/tab_colors.rb +1 -1
- data/examples/tables.rb +78 -43
- data/lib/write_xlsx/chart.rb +163 -34
- data/lib/write_xlsx/chart/area.rb +1 -1
- data/lib/write_xlsx/chart/bar.rb +1 -1
- data/lib/write_xlsx/chart/column.rb +1 -1
- data/lib/write_xlsx/chart/doughnut.rb +1 -1
- data/lib/write_xlsx/chart/line.rb +16 -2
- data/lib/write_xlsx/chart/pie.rb +21 -8
- 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 +100 -0
- data/lib/write_xlsx/chart/stock.rb +1 -1
- data/lib/write_xlsx/chartsheet.rb +5 -5
- data/lib/write_xlsx/drawing.rb +86 -30
- data/lib/write_xlsx/format.rb +5 -5
- data/lib/write_xlsx/package/comments.rb +11 -11
- data/lib/write_xlsx/package/relationships.rb +4 -4
- data/lib/write_xlsx/package/styles.rb +26 -8
- data/lib/write_xlsx/package/table.rb +8 -7
- data/lib/write_xlsx/package/vml.rb +20 -19
- data/lib/write_xlsx/shape.rb +4 -3
- data/lib/write_xlsx/sheets.rb +18 -16
- data/lib/write_xlsx/sparkline.rb +1 -1
- data/lib/write_xlsx/utility.rb +40 -7
- data/lib/write_xlsx/version.rb +1 -1
- data/lib/write_xlsx/workbook.rb +69 -44
- data/lib/write_xlsx/worksheet.rb +206 -138
- data/lib/write_xlsx/worksheet/hyperlink.rb +16 -37
- data/test/drawing/test_drawing_chart_01.rb +6 -2
- data/test/drawing/test_drawing_image_01.rb +12 -3
- data/test/drawing/test_drawing_shape_01.rb +8 -5
- data/test/drawing/test_drawing_shape_02.rb +12 -5
- data/test/drawing/test_drawing_shape_03.rb +8 -5
- data/test/drawing/test_drawing_shape_04.rb +8 -24
- data/test/drawing/test_drawing_shape_05.rb +8 -5
- data/test/drawing/test_drawing_shape_06.rb +11 -6
- data/test/drawing/test_drawing_shape_07.rb +11 -6
- data/test/drawing/test_write_a_graphic_frame_locks.rb +1 -1
- data/test/drawing/test_write_c_chart.rb +1 -1
- data/test/drawing/test_write_c_nv_graphic_frame_pr.rb +1 -1
- data/test/drawing/test_write_c_nv_pr.rb +1 -1
- data/test/drawing/test_write_col.rb +1 -1
- data/test/drawing/test_write_col_off.rb +1 -1
- data/test/drawing/test_write_ext.rb +1 -1
- data/test/drawing/test_write_pos.rb +1 -1
- data/test/drawing/test_write_row.rb +1 -1
- data/test/drawing/test_write_row_off.rb +1 -1
- data/test/drawing/test_write_xfrm_extension.rb +1 -1
- data/test/drawing/test_write_xfrm_offset.rb +1 -1
- data/test/perl_output/chart_data_labels.xlsx +0 -0
- data/test/perl_output/chart_gauge.xlsx +0 -0
- data/test/perl_output/chart_line.xlsx +0 -0
- data/test/perl_output/comments2.xlsx +0 -0
- data/test/perl_output/tables.xlsx +0 -0
- data/test/regression/images/red2.png +0 -0
- data/test/regression/test_array_formula04.rb +31 -0
- data/test/regression/test_chart_axis26.rb +10 -8
- data/test/regression/test_chart_axis27.rb +1 -1
- data/test/regression/test_chart_axis28.rb +1 -1
- data/test/regression/test_chart_axis29.rb +1 -1
- data/test/regression/test_chart_axis33.rb +1 -1
- data/test/regression/test_chart_axis44.rb +54 -0
- data/test/regression/test_chart_axis45.rb +54 -0
- data/test/regression/test_chart_axis46.rb +54 -0
- data/test/regression/test_chart_combined10.rb +43 -0
- data/test/regression/test_chart_combined11.rb +63 -0
- data/test/regression/test_chart_data_labels25.rb +1 -1
- 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_doughnut07.rb +37 -0
- data/test/regression/test_chart_font09.rb +1 -1
- data/test/regression/test_chart_line05.rb +43 -0
- data/test/regression/test_chart_line06.rb +43 -0
- data/test/regression/test_chart_size03.rb +4 -1
- data/test/regression/test_comment14.rb +29 -0
- data/test/regression/test_comment15.rb +28 -0
- data/test/regression/test_comment16.rb +34 -0
- data/test/regression/test_header_image15.rb +36 -0
- data/test/regression/test_header_image16.rb +42 -0
- data/test/regression/test_header_image17.rb +46 -0
- data/test/regression/test_header_image18.rb +48 -0
- data/test/regression/test_header_image19.rb +36 -0
- data/test/regression/test_hyperlink32.rb +27 -0
- data/test/regression/test_hyperlink33.rb +28 -0
- data/test/regression/test_hyperlink34.rb +33 -0
- data/test/regression/test_hyperlink35.rb +39 -0
- data/test/regression/test_hyperlink36.rb +34 -0
- data/test/regression/test_hyperlink37.rb +33 -0
- data/test/regression/test_hyperlink38.rb +27 -0
- data/test/regression/test_hyperlink39.rb +27 -0
- data/test/regression/test_hyperlink40.rb +27 -0
- data/test/regression/test_hyperlink41.rb +27 -0
- data/test/regression/test_hyperlink42.rb +27 -0
- data/test/regression/test_hyperlink43.rb +27 -0
- data/test/regression/test_hyperlink44.rb +27 -0
- data/test/regression/test_hyperlink45.rb +27 -0
- data/test/regression/test_hyperlink47.rb +27 -0
- data/test/regression/test_hyperlink48.rb +31 -0
- data/test/regression/test_hyperlink49.rb +29 -0
- data/test/regression/test_image06.rb +5 -5
- data/test/regression/test_image08.rb +5 -4
- data/test/regression/test_image15.rb +4 -2
- data/test/regression/test_image28.rb +1 -1
- data/test/regression/test_image44.rb +28 -0
- data/test/regression/test_image45.rb +29 -0
- data/test/regression/test_image46.rb +29 -0
- data/test/regression/test_image47.rb +28 -0
- data/test/regression/test_image48.rb +32 -0
- data/test/regression/test_image49.rb +38 -0
- data/test/regression/test_image50.rb +24 -0
- data/test/regression/test_image51.rb +30 -0
- data/test/regression/test_object_position01.rb +26 -0
- data/test/regression/test_object_position02.rb +26 -0
- data/test/regression/test_object_position03.rb +26 -0
- data/test/regression/test_object_position04.rb +44 -0
- data/test/regression/test_object_position06.rb +28 -0
- data/test/regression/test_object_position07.rb +28 -0
- data/test/regression/test_object_position08.rb +47 -0
- data/test/regression/test_object_position09.rb +50 -0
- data/test/regression/test_object_position10.rb +28 -0
- data/test/regression/test_object_position12.rb +25 -0
- data/test/regression/test_object_position13.rb +25 -0
- data/test/regression/test_object_position14.rb +25 -0
- data/test/regression/test_object_position15.rb +29 -0
- data/test/regression/test_object_position16.rb +29 -0
- data/test/regression/test_object_position17.rb +29 -0
- data/test/regression/test_object_position18.rb +29 -0
- data/test/regression/test_object_position19.rb +29 -0
- data/test/regression/test_object_position20.rb +29 -0
- data/test/regression/test_shape_connect01.rb +4 -2
- data/test/regression/test_table24.rb +27 -0
- data/test/regression/test_table25.rb +27 -0
- data/test/regression/xlsx_files/array_formula04.xlsx +0 -0
- data/test/regression/xlsx_files/chart_axis26.xlsx +0 -0
- data/test/regression/xlsx_files/chart_axis27.xlsx +0 -0
- data/test/regression/xlsx_files/chart_axis28.xlsx +0 -0
- data/test/regression/xlsx_files/chart_axis29.xlsx +0 -0
- data/test/regression/xlsx_files/chart_axis33.xlsx +0 -0
- data/test/regression/xlsx_files/chart_axis44.xlsx +0 -0
- data/test/regression/xlsx_files/chart_axis45.xlsx +0 -0
- data/test/regression/xlsx_files/chart_axis46.xlsx +0 -0
- data/test/regression/xlsx_files/chart_combined10.xlsx +0 -0
- data/test/regression/xlsx_files/chart_combined11.xlsx +0 -0
- data/test/regression/xlsx_files/chart_data_labels25.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_doughnut07.xlsx +0 -0
- data/test/regression/xlsx_files/chart_font09.xlsx +0 -0
- data/test/regression/xlsx_files/chart_line05.xlsx +0 -0
- data/test/regression/xlsx_files/chart_line06.xlsx +0 -0
- data/test/regression/xlsx_files/comment14.xlsx +0 -0
- data/test/regression/xlsx_files/comment15.xlsx +0 -0
- data/test/regression/xlsx_files/comment16.xlsx +0 -0
- data/test/regression/xlsx_files/header_image15.xlsx +0 -0
- data/test/regression/xlsx_files/header_image16.xlsx +0 -0
- data/test/regression/xlsx_files/header_image17.xlsx +0 -0
- data/test/regression/xlsx_files/header_image18.xlsx +0 -0
- data/test/regression/xlsx_files/header_image19.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink32.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink33.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink34.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink35.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink36.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink37.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink38.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink39.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink40.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink41.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink42.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink43.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink44.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink45.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink46.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink47.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink48.xlsx +0 -0
- data/test/regression/xlsx_files/hyperlink49.xlsx +0 -0
- data/test/regression/xlsx_files/image06.xlsx +0 -0
- data/test/regression/xlsx_files/image44.xlsx +0 -0
- data/test/regression/xlsx_files/image45.xlsx +0 -0
- data/test/regression/xlsx_files/image46.xlsx +0 -0
- data/test/regression/xlsx_files/image47.xlsx +0 -0
- data/test/regression/xlsx_files/image48.xlsx +0 -0
- data/test/regression/xlsx_files/image49.xlsx +0 -0
- data/test/regression/xlsx_files/image50.xlsx +0 -0
- data/test/regression/xlsx_files/image51.xlsx +0 -0
- data/test/regression/xlsx_files/object_position01.xlsx +0 -0
- data/test/regression/xlsx_files/object_position02.xlsx +0 -0
- data/test/regression/xlsx_files/object_position03.xlsx +0 -0
- data/test/regression/xlsx_files/object_position04.xlsx +0 -0
- data/test/regression/xlsx_files/object_position06.xlsx +0 -0
- data/test/regression/xlsx_files/object_position07.xlsx +0 -0
- data/test/regression/xlsx_files/object_position08.xlsx +0 -0
- data/test/regression/xlsx_files/object_position09.xlsx +0 -0
- data/test/regression/xlsx_files/object_position10.xlsx +0 -0
- data/test/regression/xlsx_files/object_position12.xlsx +0 -0
- data/test/regression/xlsx_files/object_position13.xlsx +0 -0
- data/test/regression/xlsx_files/object_position14.xlsx +0 -0
- data/test/regression/xlsx_files/object_position15.xlsx +0 -0
- data/test/regression/xlsx_files/object_position16.xlsx +0 -0
- data/test/regression/xlsx_files/object_position17.xlsx +0 -0
- data/test/regression/xlsx_files/object_position18.xlsx +0 -0
- data/test/regression/xlsx_files/object_position19.xlsx +0 -0
- data/test/regression/xlsx_files/object_position20.xlsx +0 -0
- data/test/regression/xlsx_files/table24.xlsx +0 -0
- data/test/regression/xlsx_files/table25.xlsx +0 -0
- data/test/test_example_match.rb +1268 -780
- data/test/workbook/test_check_sheetname.rb +51 -0
- data/write_xlsx.gemspec +1 -0
- metadata +367 -5
data/lib/write_xlsx/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
WriteXLSX_VERSION = "
|
1
|
+
WriteXLSX_VERSION = "1.07.0"
|
data/lib/write_xlsx/workbook.rb
CHANGED
@@ -49,6 +49,7 @@ class Workbook
|
|
49
49
|
attr_reader :shared_strings # :nodoc:
|
50
50
|
attr_reader :vba_project # :nodoc:
|
51
51
|
attr_reader :excel2003_style # :nodoc:
|
52
|
+
attr_reader :max_url_length # :nodoc:
|
52
53
|
attr_reader :strings_to_urls # :nodoc:
|
53
54
|
attr_reader :default_url_format # :nodoc:
|
54
55
|
|
@@ -130,6 +131,13 @@ def initialize(file, *option_params)
|
|
130
131
|
@images = []
|
131
132
|
@strings_to_urls = (options[:strings_to_urls].nil? || options[:strings_to_urls]) ? true : false
|
132
133
|
|
134
|
+
@max_url_length = 2079
|
135
|
+
@has_comments = false
|
136
|
+
if options[:max_url_length]
|
137
|
+
@max_url_length = options[:max_url_length]
|
138
|
+
|
139
|
+
@max_url_length = 2079 if @max_url_length < 250
|
140
|
+
end
|
133
141
|
# Structures for the shared strings data.
|
134
142
|
@shared_strings = Package::SharedStrings.new
|
135
143
|
|
@@ -1108,7 +1116,8 @@ def style_properties
|
|
1108
1116
|
@border_count,
|
1109
1117
|
@fill_count,
|
1110
1118
|
@custom_colors,
|
1111
|
-
@dxf_formats
|
1119
|
+
@dxf_formats,
|
1120
|
+
@has_comments
|
1112
1121
|
]
|
1113
1122
|
end
|
1114
1123
|
|
@@ -1704,11 +1713,14 @@ def prepare_vml_objects #:nodoc:
|
|
1704
1713
|
if sheet.has_comments?
|
1705
1714
|
comment_files += 1
|
1706
1715
|
comment_id += 1
|
1716
|
+
@has_comments = true
|
1707
1717
|
end
|
1708
1718
|
vml_drawing_id += 1
|
1709
1719
|
|
1710
|
-
sheet.prepare_vml_objects(
|
1711
|
-
|
1720
|
+
sheet.prepare_vml_objects(
|
1721
|
+
vml_data_id, vml_shape_id,
|
1722
|
+
vml_drawing_id, comment_id
|
1723
|
+
)
|
1712
1724
|
|
1713
1725
|
# Each VML file should start with a shape id incremented by 1024.
|
1714
1726
|
vml_data_id += 1 * ( 1 + sheet.num_comments_block )
|
@@ -1731,8 +1743,6 @@ def prepare_vml_objects #:nodoc:
|
|
1731
1743
|
end
|
1732
1744
|
end
|
1733
1745
|
|
1734
|
-
add_font_format_for_cell_comments if num_comment_files > 0
|
1735
|
-
|
1736
1746
|
# Set the workbook vba_codename if one of the sheets has a button and
|
1737
1747
|
# the workbook has a vbaProject binary.
|
1738
1748
|
if has_button && @vba_project && !@vba_codename
|
@@ -1752,19 +1762,6 @@ def prepare_tables
|
|
1752
1762
|
end
|
1753
1763
|
end
|
1754
1764
|
|
1755
|
-
def add_font_format_for_cell_comments
|
1756
|
-
format = Format.new(
|
1757
|
-
@formats,
|
1758
|
-
:font => 'Tahoma',
|
1759
|
-
:size => 8,
|
1760
|
-
:color_indexed => 81,
|
1761
|
-
:font_only => 1
|
1762
|
-
)
|
1763
|
-
|
1764
|
-
format.get_xf_index
|
1765
|
-
@formats.formats << format
|
1766
|
-
end
|
1767
|
-
|
1768
1765
|
#
|
1769
1766
|
# Add "cached" data to charts to provide the numCache and strCache data for
|
1770
1767
|
# series and title/axis ranges.
|
@@ -1915,16 +1912,19 @@ def extract_named_ranges(defined_names) #:nodoc:
|
|
1915
1912
|
# Iterate through the worksheets and set up any chart or image drawings.
|
1916
1913
|
#
|
1917
1914
|
def prepare_drawings #:nodoc:
|
1918
|
-
chart_ref_id
|
1919
|
-
image_ref_id
|
1920
|
-
drawing_id
|
1915
|
+
chart_ref_id = 0
|
1916
|
+
image_ref_id = 0
|
1917
|
+
drawing_id = 0
|
1918
|
+
ref_id = 0
|
1919
|
+
image_ids = {}
|
1920
|
+
header_image_ids = {}
|
1921
1921
|
@worksheets.each do |sheet|
|
1922
1922
|
chart_count = sheet.charts.size
|
1923
1923
|
image_count = sheet.images.size
|
1924
1924
|
shape_count = sheet.shapes.size
|
1925
1925
|
header_image_count = sheet.header_images.size
|
1926
1926
|
footer_image_count = sheet.footer_images.size
|
1927
|
-
|
1927
|
+
has_drawings = false
|
1928
1928
|
|
1929
1929
|
# Check that some image or drawing needs to be processed.
|
1930
1930
|
next if chart_count + image_count + shape_count + header_image_count + footer_image_count == 0
|
@@ -1932,7 +1932,24 @@ def prepare_drawings #:nodoc:
|
|
1932
1932
|
# Don't increase the drawing_id header/footer images.
|
1933
1933
|
if chart_count + image_count + shape_count > 0
|
1934
1934
|
drawing_id += 1
|
1935
|
-
|
1935
|
+
has_drawings = true
|
1936
|
+
end
|
1937
|
+
|
1938
|
+
# Prepare the worksheet images.
|
1939
|
+
sheet.images.each_with_index do |image, index|
|
1940
|
+
filename = image[2]
|
1941
|
+
type, width, height, name, x_dpi, y_dpi, md5 = get_image_properties(image[2])
|
1942
|
+
if image_ids[md5]
|
1943
|
+
ref_id = image_ids[md5]
|
1944
|
+
else
|
1945
|
+
image_ref_id += 1
|
1946
|
+
image_ids[md5] = ref_id = image_ref_id
|
1947
|
+
@images << [filename, type]
|
1948
|
+
end
|
1949
|
+
sheet.prepare_image(
|
1950
|
+
index, ref_id, drawing_id, width, height,
|
1951
|
+
name, type, x_dpi, y_dpi, md5
|
1952
|
+
)
|
1936
1953
|
end
|
1937
1954
|
|
1938
1955
|
# Prepare the worksheet charts.
|
@@ -1941,13 +1958,6 @@ def prepare_drawings #:nodoc:
|
|
1941
1958
|
sheet.prepare_chart(index, chart_ref_id, drawing_id)
|
1942
1959
|
end
|
1943
1960
|
|
1944
|
-
# Prepare the worksheet images.
|
1945
|
-
sheet.images.each_with_index do |image, index|
|
1946
|
-
type, width, height, name, x_dpi, y_dpi = get_image_properties(image[2])
|
1947
|
-
image_ref_id += 1
|
1948
|
-
sheet.prepare_image(index, image_ref_id, drawing_id, width, height, name, type, x_dpi, y_dpi)
|
1949
|
-
end
|
1950
|
-
|
1951
1961
|
# Prepare the worksheet shapes.
|
1952
1962
|
sheet.shapes.each_with_index do |shape, index|
|
1953
1963
|
sheet.prepare_shape(index, drawing_id)
|
@@ -1958,13 +1968,21 @@ def prepare_drawings #:nodoc:
|
|
1958
1968
|
filename = sheet.header_images[index][0]
|
1959
1969
|
position = sheet.header_images[index][1]
|
1960
1970
|
|
1961
|
-
type, width, height, name, x_dpi, y_dpi =
|
1971
|
+
type, width, height, name, x_dpi, y_dpi, md5 =
|
1962
1972
|
get_image_properties(filename)
|
1963
1973
|
|
1964
|
-
|
1974
|
+
if header_image_ids[md5]
|
1975
|
+
ref_id = header_image_ids[md5]
|
1976
|
+
else
|
1977
|
+
image_ref_id += 1
|
1978
|
+
header_image_ids[md5] = ref_id = image_ref_id
|
1979
|
+
@images << [filename, type]
|
1980
|
+
end
|
1965
1981
|
|
1966
|
-
sheet.prepare_header_image(
|
1967
|
-
|
1982
|
+
sheet.prepare_header_image(
|
1983
|
+
ref_id, width, height, name, type,
|
1984
|
+
position, x_dpi, y_dpi, md5
|
1985
|
+
)
|
1968
1986
|
end
|
1969
1987
|
|
1970
1988
|
# Prepare the footer images.
|
@@ -1972,18 +1990,26 @@ def prepare_drawings #:nodoc:
|
|
1972
1990
|
filename = sheet.footer_images[index][0]
|
1973
1991
|
position = sheet.footer_images[index][1]
|
1974
1992
|
|
1975
|
-
type, width, height, name, x_dpi, y_dpi =
|
1993
|
+
type, width, height, name, x_dpi, y_dpi, md5 =
|
1976
1994
|
get_image_properties(filename)
|
1977
1995
|
|
1978
|
-
|
1996
|
+
if header_image_ids[md5]
|
1997
|
+
ref_id = header_image_ids[md5]
|
1998
|
+
else
|
1999
|
+
image_ref_id += 1
|
2000
|
+
header_image_ids[md5] = ref_id = image_ref_id
|
2001
|
+
@images << [filename, type]
|
2002
|
+
end
|
1979
2003
|
|
1980
|
-
sheet.prepare_header_image(
|
1981
|
-
|
2004
|
+
sheet.prepare_header_image(
|
2005
|
+
ref_id, width, height, name, type,
|
2006
|
+
position, x_dpi, y_dpi, md5
|
2007
|
+
)
|
1982
2008
|
end
|
1983
2009
|
|
1984
|
-
if
|
1985
|
-
|
1986
|
-
@drawings <<
|
2010
|
+
if has_drawings
|
2011
|
+
drawings = sheet.drawings
|
2012
|
+
@drawings << drawings
|
1987
2013
|
end
|
1988
2014
|
end
|
1989
2015
|
|
@@ -2007,6 +2033,7 @@ def get_image_properties(filename)
|
|
2007
2033
|
|
2008
2034
|
# Open the image file and import the data.
|
2009
2035
|
data = File.binread(filename)
|
2036
|
+
md5 = Digest::MD5.hexdigest(data)
|
2010
2037
|
if data.unpack('x A3')[0] == 'PNG'
|
2011
2038
|
# Test for PNGs.
|
2012
2039
|
type, width, height, x_dpi, y_dpi = process_png(data)
|
@@ -2024,13 +2051,11 @@ def get_image_properties(filename)
|
|
2024
2051
|
raise "Unsupported image format for file: #{filename}\n"
|
2025
2052
|
end
|
2026
2053
|
|
2027
|
-
@images << [filename, type]
|
2028
|
-
|
2029
2054
|
# Set a default dpi for images with 0 dpi.
|
2030
2055
|
x_dpi = 96 if x_dpi == 0
|
2031
2056
|
y_dpi = 96 if y_dpi == 0
|
2032
2057
|
|
2033
|
-
[type, width, height, File.basename(filename), x_dpi, y_dpi]
|
2058
|
+
[type, width, height, File.basename(filename), x_dpi, y_dpi, md5]
|
2034
2059
|
end
|
2035
2060
|
|
2036
2061
|
#
|
data/lib/write_xlsx/worksheet.rb
CHANGED
@@ -285,7 +285,7 @@ class Worksheet
|
|
285
285
|
PADDING = 5 # :nodoc:
|
286
286
|
|
287
287
|
attr_reader :index # :nodoc:
|
288
|
-
attr_reader :charts, :images, :tables, :shapes, :
|
288
|
+
attr_reader :charts, :images, :tables, :shapes, :drawings # :nodoc:
|
289
289
|
attr_reader :header_images, :footer_images # :nodoc:
|
290
290
|
attr_reader :vml_drawing_links # :nodoc:
|
291
291
|
attr_reader :vml_data_id # :nodoc:
|
@@ -309,6 +309,7 @@ def initialize(workbook, index, name) #:nodoc:
|
|
309
309
|
@excel_version = 2007
|
310
310
|
@palette = workbook.palette
|
311
311
|
@default_url_format = workbook.default_url_format
|
312
|
+
@max_url_length = workbook.max_url_length
|
312
313
|
|
313
314
|
@page_setup = PageSetup.new
|
314
315
|
|
@@ -356,6 +357,10 @@ def initialize(workbook, index, name) #:nodoc:
|
|
356
357
|
@sparklines = []
|
357
358
|
@shapes = []
|
358
359
|
@shape_hash = {}
|
360
|
+
@drawing_rels = {}
|
361
|
+
@drawing_rels_id = 0
|
362
|
+
@vml_drawing_rels = {}
|
363
|
+
@vml_drawing_rels_id = 0
|
359
364
|
@header_images = []
|
360
365
|
@footer_images = []
|
361
366
|
|
@@ -365,6 +370,7 @@ def initialize(workbook, index, name) #:nodoc:
|
|
365
370
|
@original_row_height = 15
|
366
371
|
@default_row_height = 15
|
367
372
|
@default_row_pixels = 20
|
373
|
+
@default_col_width = 8.43
|
368
374
|
@default_col_pixels = 64
|
369
375
|
@default_row_rezoed = 0
|
370
376
|
|
@@ -768,10 +774,10 @@ def set_column(*args)
|
|
768
774
|
|
769
775
|
# Store the col sizes for use when calculating image vertices taking
|
770
776
|
# hidden columns into account. Also store the column formats.
|
771
|
-
width =
|
777
|
+
width = @default_col_width unless width
|
772
778
|
|
773
779
|
(firstcol .. lastcol).each do |col|
|
774
|
-
@col_sizes[col] = width
|
780
|
+
@col_sizes[col] = [width, hidden]
|
775
781
|
@col_formats[col] = format if format
|
776
782
|
end
|
777
783
|
end
|
@@ -2169,7 +2175,7 @@ def write_comment(*args)
|
|
2169
2175
|
@has_vml = true
|
2170
2176
|
|
2171
2177
|
# Process the properties of the cell comment.
|
2172
|
-
@comments.add(
|
2178
|
+
@comments.add(@workbook, self, row, col, string, options)
|
2173
2179
|
end
|
2174
2180
|
|
2175
2181
|
#
|
@@ -2508,7 +2514,9 @@ def write_array_formula(*args)
|
|
2508
2514
|
col1, col2 = col2, col1 if col1 > col2
|
2509
2515
|
|
2510
2516
|
# Check that row and col are valid and store max and min values
|
2517
|
+
check_dimensions(row1, col1)
|
2511
2518
|
check_dimensions(row2, col2)
|
2519
|
+
store_row_col_max_min_values(row1, col1)
|
2512
2520
|
store_row_col_max_min_values(row2, col2)
|
2513
2521
|
|
2514
2522
|
# Define array range
|
@@ -2781,7 +2789,7 @@ def write_url(*args)
|
|
2781
2789
|
store_hyperlink(row, col, hyperlink)
|
2782
2790
|
|
2783
2791
|
if hyperlinks_count > 65_530
|
2784
|
-
raise "URL '#{url}' added but
|
2792
|
+
raise "URL '#{url}' added but URL exceeds Excel's limit of 65,530 URLs per worksheet."
|
2785
2793
|
end
|
2786
2794
|
|
2787
2795
|
# Add the default URL format.
|
@@ -2990,13 +2998,25 @@ def write_date_time(*args)
|
|
2990
2998
|
#
|
2991
2999
|
def insert_chart(*args)
|
2992
3000
|
# Check for a cell reference in A1 notation and substitute row and column.
|
2993
|
-
row, col, chart,
|
3001
|
+
row, col, chart, *options = row_col_notation(args)
|
2994
3002
|
raise WriteXLSXInsufficientArgumentError if [row, col, chart].include?(nil)
|
2995
3003
|
|
3004
|
+
if options.first.class == Hash
|
3005
|
+
params = options.first
|
3006
|
+
x_offset = params[:x_offset]
|
3007
|
+
y_offset = params[:y_offset]
|
3008
|
+
x_scale = params[:x_scale]
|
3009
|
+
y_scale = params[:y_scale]
|
3010
|
+
anchor = params[:object_position]
|
3011
|
+
|
3012
|
+
else
|
3013
|
+
x_offset, y_offset, x_scale, y_scale, anchor = options
|
3014
|
+
end
|
2996
3015
|
x_offset ||= 0
|
2997
3016
|
y_offset ||= 0
|
2998
3017
|
x_scale ||= 1
|
2999
3018
|
y_scale ||= 1
|
3019
|
+
anchor ||= 1
|
3000
3020
|
|
3001
3021
|
raise "Not a Chart object in insert_chart()" unless chart.is_a?(Chart) || chart.is_a?(Chartsheet)
|
3002
3022
|
raise "Not a embedded style Chart object in insert_chart()" if chart.respond_to?(:embedded) && chart.embedded == 0
|
@@ -3014,61 +3034,41 @@ def insert_chart(*args)
|
|
3014
3034
|
x_offset = chart.x_offset if ptrue?(chart.x_offset)
|
3015
3035
|
y_offset = chart.y_offset if ptrue?(chart.y_offset)
|
3016
3036
|
|
3017
|
-
@charts << [row, col, chart, x_offset, y_offset, x_scale, y_scale]
|
3037
|
+
@charts << [row, col, chart, x_offset, y_offset, x_scale, y_scale, anchor]
|
3018
3038
|
end
|
3019
3039
|
|
3020
3040
|
#
|
3021
3041
|
# :call-seq:
|
3022
|
-
# insert_image(row, column, filename,
|
3023
|
-
#
|
3024
|
-
# Partially supported. Currently only works for 96 dpi images.
|
3025
|
-
#
|
3026
|
-
# This method can be used to insert a image into a worksheet. The image
|
3027
|
-
# can be in PNG, JPEG or BMP format. The x, y, x_scale and y_scale
|
3028
|
-
# parameters are optional.
|
3029
|
-
#
|
3030
|
-
# worksheet1.insert_image('A1', 'ruby.bmp')
|
3031
|
-
# worksheet2.insert_image('A1', '../images/ruby.bmp')
|
3032
|
-
# worksheet3.insert_image('A1', '.c:\images\ruby.bmp')
|
3033
|
-
#
|
3034
|
-
# The parameters +x+ and +y+ can be used to specify an offset from the top
|
3035
|
-
# left hand corner of the cell specified by +row+ and +column+. The offset
|
3036
|
-
# values are in pixels.
|
3037
|
-
#
|
3038
|
-
# worksheet1.insert_image('A1', 'ruby.bmp', 32, 10)
|
3039
|
-
#
|
3040
|
-
# The offsets can be greater than the width or height of the underlying
|
3041
|
-
# cell. This can be occasionally useful if you wish to align two or more
|
3042
|
-
# images relative to the same cell.
|
3043
|
-
#
|
3044
|
-
# The parameters +x_scale+ and +y_scale+ can be used to scale the inserted
|
3045
|
-
# image horizontally and vertically:
|
3046
|
-
#
|
3047
|
-
# # Scale the inserted image: width x 2.0, height x 0.8
|
3048
|
-
# worksheet.insert_image('A1', 'perl.bmp', 0, 0, 2, 0.8)
|
3049
|
-
#
|
3050
|
-
# Note: you must call set_row() or set_column() before insert_image()
|
3051
|
-
# if you wish to change the default dimensions of any of the rows or
|
3052
|
-
# columns that the image occupies. The height of a row can also change
|
3053
|
-
# if you use a font that is larger than the default. This in turn will
|
3054
|
-
# affect the scaling of your image. To avoid this you should explicitly
|
3055
|
-
# set the height of the row using set_row() if it contains a font size
|
3056
|
-
# that will change the row height.
|
3057
|
-
#
|
3058
|
-
# BMP images must be 24 bit, true colour, bitmaps. In general it is
|
3059
|
-
# best to avoid BMP images since they aren't compressed.
|
3042
|
+
# insert_image(row, column, filename, options)
|
3060
3043
|
#
|
3061
3044
|
def insert_image(*args)
|
3062
3045
|
# Check for a cell reference in A1 notation and substitute row and column.
|
3063
|
-
row, col, image,
|
3046
|
+
row, col, image, *options = row_col_notation(args)
|
3064
3047
|
raise WriteXLSXInsufficientArgumentError if [row, col, image].include?(nil)
|
3065
3048
|
|
3049
|
+
if options.first.class == Hash
|
3050
|
+
# Newer hash bashed options
|
3051
|
+
params = options.first
|
3052
|
+
x_offset = params[:x_offset]
|
3053
|
+
y_offset = params[:y_offset]
|
3054
|
+
x_scale = params[:x_scale]
|
3055
|
+
y_scale = params[:y_scale]
|
3056
|
+
anchor = params[:object_position]
|
3057
|
+
url = params[:url]
|
3058
|
+
tip = params[:tip]
|
3059
|
+
else
|
3060
|
+
x_offset, y_offset, x_scale, y_scale, anchor = options
|
3061
|
+
end
|
3066
3062
|
x_offset ||= 0
|
3067
3063
|
y_offset ||= 0
|
3068
3064
|
x_scale ||= 1
|
3069
3065
|
y_scale ||= 1
|
3066
|
+
anchor ||= 2
|
3070
3067
|
|
3071
|
-
@images << [
|
3068
|
+
@images << [
|
3069
|
+
row, col, image, x_offset, y_offset,
|
3070
|
+
x_scale, y_scale, url, tip, anchor
|
3071
|
+
]
|
3072
3072
|
end
|
3073
3073
|
|
3074
3074
|
#
|
@@ -3306,10 +3306,8 @@ def set_row(*args)
|
|
3306
3306
|
# Store the row change to allow optimisations.
|
3307
3307
|
@row_size_changed = true
|
3308
3308
|
|
3309
|
-
height = 0 if ptrue?(hidden)
|
3310
|
-
|
3311
3309
|
# Store the row sizes for use when calculating image vertices.
|
3312
|
-
@row_sizes[row] = height
|
3310
|
+
@row_sizes[row] = [height, hidden]
|
3313
3311
|
end
|
3314
3312
|
|
3315
3313
|
#
|
@@ -3367,9 +3365,11 @@ def merge_range(*args)
|
|
3367
3365
|
row_first, row_last = row_last, row_first if row_first > row_last
|
3368
3366
|
col_first, col_last = col_last, col_first if col_first > col_last
|
3369
3367
|
|
3370
|
-
# Check that
|
3371
|
-
check_dimensions(
|
3372
|
-
|
3368
|
+
# Check that the data range is valid and store the max and min values.
|
3369
|
+
check_dimensions(row_first, col_first)
|
3370
|
+
check_dimensions(row_last, col_last)
|
3371
|
+
store_row_col_max_min_values(row_first, col_first)
|
3372
|
+
store_row_col_max_min_values(row_last, col_last)
|
3373
3373
|
|
3374
3374
|
# Store the merge range.
|
3375
3375
|
@merge << [row_first, col_first, row_last, col_last]
|
@@ -3432,9 +3432,11 @@ def merge_range_type(type, *args)
|
|
3432
3432
|
row_first, row_last = row_last, row_first if row_first > row_last
|
3433
3433
|
col_first, col_last = col_last, col_first if col_first > col_last
|
3434
3434
|
|
3435
|
-
# Check that
|
3436
|
-
check_dimensions(
|
3437
|
-
|
3435
|
+
# Check that the data range is valid and store the max and min values.
|
3436
|
+
check_dimensions(row_first, col_first)
|
3437
|
+
check_dimensions(row_last, col_last)
|
3438
|
+
store_row_col_max_min_values(row_first, col_first)
|
3439
|
+
store_row_col_max_min_values(row_last, col_last)
|
3438
3440
|
|
3439
3441
|
# Store the merge range.
|
3440
3442
|
@merge << [row_first, col_first, row_last, col_last]
|
@@ -5724,7 +5726,7 @@ def set_external_comment_links(comment_id) # :nodoc:
|
|
5724
5726
|
def prepare_chart(index, chart_id, drawing_id) # :nodoc:
|
5725
5727
|
drawing_type = 1
|
5726
5728
|
|
5727
|
-
row, col, chart, x_offset, y_offset, x_scale, y_scale = @charts[index]
|
5729
|
+
row, col, chart, x_offset, y_offset, x_scale, y_scale, anchor = @charts[index]
|
5728
5730
|
chart.id = chart_id - 1
|
5729
5731
|
x_scale ||= 0
|
5730
5732
|
y_scale ||= 0
|
@@ -5736,22 +5738,21 @@ def prepare_chart(index, chart_id, drawing_id) # :nodoc:
|
|
5736
5738
|
width = (0.5 + (width * x_scale)).to_i
|
5737
5739
|
height = (0.5 + (height * y_scale)).to_i
|
5738
5740
|
|
5739
|
-
dimensions = position_object_emus(col, row, x_offset, y_offset, width, height)
|
5741
|
+
dimensions = position_object_emus(col, row, x_offset, y_offset, width, height, anchor)
|
5740
5742
|
|
5741
5743
|
# Set the chart name for the embedded object if it has been specified.
|
5742
5744
|
name = chart.name
|
5743
5745
|
|
5744
5746
|
# Create a Drawing object to use with worksheet unless one already exists.
|
5745
|
-
|
5746
|
-
|
5747
|
-
|
5748
|
-
drawing
|
5749
|
-
|
5750
|
-
@drawing = drawing
|
5747
|
+
drawing = Drawing.new(drawing_type, dimensions, 0, 0, name, nil, anchor, drawing_rel_index, 0, nil)
|
5748
|
+
if !drawings?
|
5749
|
+
@drawings = Drawings.new
|
5750
|
+
@drawings.add_drawing_object(drawing)
|
5751
|
+
@drawings.embedded = 1
|
5751
5752
|
|
5752
5753
|
@external_drawing_links << ['/drawing', "../drawings/drawing#{drawing_id}.xml" ]
|
5753
5754
|
else
|
5754
|
-
@
|
5755
|
+
@drawings.add_drawing_object(drawing)
|
5755
5756
|
end
|
5756
5757
|
@drawing_links << ['/chart', "../charts/chart#{chart_id}.xml"]
|
5757
5758
|
end
|
@@ -5822,6 +5823,10 @@ def get_range_data(row_start, col_start, row_end, col_end) # :nodoc:
|
|
5822
5823
|
# The values of col_start and row_start are passed in from the calling
|
5823
5824
|
# function. The values of col_end and row_end are calculated by subtracting
|
5824
5825
|
# the width and height of the object from the width and height of the
|
5826
|
+
# The anchor/object position defines how images are scaled for hidden rows and
|
5827
|
+
# columns. For option 1 "Move and size with cells" the size of the hidden
|
5828
|
+
# row/column is subtracted from the image.
|
5829
|
+
#
|
5825
5830
|
# underlying cells.
|
5826
5831
|
#
|
5827
5832
|
# col_start # Col containing upper left corner of object.
|
@@ -5834,7 +5839,7 @@ def get_range_data(row_start, col_start, row_end, col_end) # :nodoc:
|
|
5834
5839
|
# y2 # Distance to bottom of object.
|
5835
5840
|
# width # Width of object frame.
|
5836
5841
|
# height # Height of object frame.
|
5837
|
-
def position_object_pixels(col_start, row_start, x1, y1, width, height) #:nodoc:
|
5842
|
+
def position_object_pixels(col_start, row_start, x1, y1, width, height, anchor = nil) #:nodoc:
|
5838
5843
|
# Adjust start column for negative offsets.
|
5839
5844
|
while x1 < 0 && col_start > 0
|
5840
5845
|
x1 += size_col(col_start - 1)
|
@@ -5853,7 +5858,7 @@ def position_object_pixels(col_start, row_start, x1, y1, width, height) #:nodoc:
|
|
5853
5858
|
|
5854
5859
|
# Calculate the absolute x offset of the top-left vertex.
|
5855
5860
|
if @col_size_changed
|
5856
|
-
x_abs = (0 .. col_start-1).inject(0) {|sum, col| sum += size_col(col)}
|
5861
|
+
x_abs = (0 .. col_start-1).inject(0) {|sum, col| sum += size_col(col, anchor)}
|
5857
5862
|
else
|
5858
5863
|
# Optimisation for when the column widths haven't changed.
|
5859
5864
|
x_abs = @default_col_pixels * col_start
|
@@ -5863,7 +5868,7 @@ def position_object_pixels(col_start, row_start, x1, y1, width, height) #:nodoc:
|
|
5863
5868
|
# Calculate the absolute y offset of the top-left vertex.
|
5864
5869
|
# Store the column change to allow optimisations.
|
5865
5870
|
if @row_size_changed
|
5866
|
-
y_abs = (0 .. row_start-1).inject(0) {|sum, row| sum += size_row(row)}
|
5871
|
+
y_abs = (0 .. row_start-1).inject(0) {|sum, row| sum += size_row(row, anchor)}
|
5867
5872
|
else
|
5868
5873
|
# Optimisation for when the row heights haven't changed.
|
5869
5874
|
y_abs = @default_row_pixels * row_start
|
@@ -5871,23 +5876,36 @@ def position_object_pixels(col_start, row_start, x1, y1, width, height) #:nodoc:
|
|
5871
5876
|
y_abs += y1
|
5872
5877
|
|
5873
5878
|
# Adjust start column for offsets that are greater than the col width.
|
5874
|
-
x1
|
5879
|
+
while x1 >= size_col(col_start, anchor)
|
5880
|
+
x1 -= size_col(col_start)
|
5881
|
+
col_start += 1
|
5882
|
+
end
|
5875
5883
|
|
5876
5884
|
# Adjust start row for offsets that are greater than the row height.
|
5877
|
-
y1
|
5885
|
+
while y1 >= size_row(row_start, anchor)
|
5886
|
+
y1 -= size_row(row_start)
|
5887
|
+
row_start += 1
|
5888
|
+
end
|
5878
5889
|
|
5879
5890
|
# Initialise end cell to the same as the start cell.
|
5880
5891
|
col_end = col_start
|
5881
5892
|
row_end = row_start
|
5882
5893
|
|
5883
|
-
|
5884
|
-
|
5894
|
+
# Only offset the image in the cell if the row/col isn't hidden.
|
5895
|
+
width += x1 if size_col(col_start, anchor) > 0
|
5896
|
+
height += y1 if size_row(row_start, anchor) > 0
|
5885
5897
|
|
5886
5898
|
# Subtract the underlying cell widths to find the end cell of the object.
|
5887
|
-
width
|
5899
|
+
while width >= size_col(col_end, anchor)
|
5900
|
+
width -= size_col(col_end, anchor)
|
5901
|
+
col_end += 1
|
5902
|
+
end
|
5888
5903
|
|
5889
5904
|
# Subtract the underlying cell heights to find the end cell of the object.
|
5890
|
-
height
|
5905
|
+
while height >= size_row(row_end, anchor)
|
5906
|
+
height -= size_row(row_end, anchor)
|
5907
|
+
row_end += 1
|
5908
|
+
end
|
5891
5909
|
|
5892
5910
|
# The end vertices are whatever is left from the width and height.
|
5893
5911
|
x2 = width
|
@@ -6072,6 +6090,33 @@ def write_sparkline_groups
|
|
6072
6090
|
|
6073
6091
|
private
|
6074
6092
|
|
6093
|
+
#
|
6094
|
+
# Get the index used to address a drawing rel link.
|
6095
|
+
#
|
6096
|
+
def drawing_rel_index(target = nil)
|
6097
|
+
if !target
|
6098
|
+
# Undefined values for drawings like charts will always be unique.
|
6099
|
+
@drawing_rels_id += 1
|
6100
|
+
elsif ptrue?(@drawing_rels[target])
|
6101
|
+
@drawing_rels[target]
|
6102
|
+
else
|
6103
|
+
@drawing_rels_id += 1
|
6104
|
+
@drawing_rels[target] = @drawing_rels_id
|
6105
|
+
end
|
6106
|
+
end
|
6107
|
+
|
6108
|
+
#
|
6109
|
+
# Get the index used to address a vml_drawing rel link.
|
6110
|
+
#
|
6111
|
+
def get_vml_drawing_rel_index(target)
|
6112
|
+
if @vml_drawing_rels[target]
|
6113
|
+
@vml_drawing_rels[target]
|
6114
|
+
else
|
6115
|
+
@vml_drawing_rels_id += 1
|
6116
|
+
@vml_drawing_rels[target] = @vml_drawing_rels_id
|
6117
|
+
end
|
6118
|
+
end
|
6119
|
+
|
6075
6120
|
def hyperlinks_count
|
6076
6121
|
@hyperlinks.keys.inject(0) { |s, n| s += @hyperlinks[n].keys.size }
|
6077
6122
|
end
|
@@ -6347,32 +6392,16 @@ def sort_pagebreaks(*args) #:nodoc:
|
|
6347
6392
|
end
|
6348
6393
|
end
|
6349
6394
|
|
6350
|
-
def adjust_column_offset(x, column)
|
6351
|
-
while x >= size_col(column)
|
6352
|
-
x -= size_col(column)
|
6353
|
-
column += 1
|
6354
|
-
end
|
6355
|
-
[x, column]
|
6356
|
-
end
|
6357
|
-
|
6358
|
-
def adjust_row_offset(y, row)
|
6359
|
-
while y >= size_row(row)
|
6360
|
-
y -= size_row(row)
|
6361
|
-
row += 1
|
6362
|
-
end
|
6363
|
-
[y, row]
|
6364
|
-
end
|
6365
|
-
|
6366
6395
|
#
|
6367
6396
|
# Calculate the vertices that define the position of a graphical object within
|
6368
6397
|
# the worksheet in EMUs.
|
6369
6398
|
#
|
6370
6399
|
# The vertices are expressed as English Metric Units (EMUs). There are 12,700
|
6371
|
-
# EMUs per point. Therefore, 12,700 * 3 /4 = 9,525 EMUs per
|
6400
|
+
# EMUs per point. Therefore, 12,700 * 3 /4 = 9,525 EMUs per el.
|
6372
6401
|
#
|
6373
|
-
def position_object_emus(col_start, row_start, x1, y1, width, height,
|
6402
|
+
def position_object_emus(col_start, row_start, x1, y1, width, height, anchor = nil) #:nodoc:
|
6374
6403
|
col_start, row_start, x1, y1, col_end, row_end, x2, y2, x_abs, y_abs =
|
6375
|
-
position_object_pixels(col_start, row_start, x1, y1, width, height)
|
6404
|
+
position_object_pixels(col_start, row_start, x1, y1, width, height, anchor)
|
6376
6405
|
|
6377
6406
|
# Convert the pixel values to EMUs. See above.
|
6378
6407
|
x1 = (0.5 + 9_525 * x1).to_i
|
@@ -6388,15 +6417,16 @@ def position_object_emus(col_start, row_start, x1, y1, width, height, x_dpi = 96
|
|
6388
6417
|
#
|
6389
6418
|
# Convert the width of a cell from user's units to pixels. Excel rounds the
|
6390
6419
|
# column width to the nearest pixel. If the width hasn't been set by the user
|
6391
|
-
# we use the default value.
|
6420
|
+
# we use the default value. A hidden column is treated as having a width of
|
6421
|
+
# zero unless it has the special "object_position" of 4 (size with cells).
|
6392
6422
|
#
|
6393
|
-
def size_col(col) #:nodoc:
|
6423
|
+
def size_col(col, anchor = 0) #:nodoc:
|
6394
6424
|
# Look up the cell value to see if it has been changed.
|
6395
6425
|
if @col_sizes[col]
|
6396
|
-
width = @col_sizes[col]
|
6426
|
+
width, hidden = @col_sizes[col]
|
6397
6427
|
|
6398
6428
|
# Convert to pixels.
|
6399
|
-
if
|
6429
|
+
if hidden == 1 && anchor != 4
|
6400
6430
|
pixels = 0
|
6401
6431
|
elsif width < 1
|
6402
6432
|
pixels = (width * (MAX_DIGIT_WIDTH + PADDING) + 0.5).to_i
|
@@ -6411,15 +6441,16 @@ def size_col(col) #:nodoc:
|
|
6411
6441
|
|
6412
6442
|
#
|
6413
6443
|
# Convert the height of a cell from user's units to pixels. If the height
|
6414
|
-
# hasn't been set by the user we use the default value.
|
6415
|
-
#
|
6444
|
+
# hasn't been set by the user we use the default value. A hidden row is
|
6445
|
+
# treated as having a height of zero unless it has the special
|
6446
|
+
# "object_position" of 4 (size with cells).
|
6416
6447
|
#
|
6417
|
-
def size_row(row) #:nodoc:
|
6448
|
+
def size_row(row, anchor = 0) #:nodoc:
|
6418
6449
|
# Look up the cell value to see if it has been changed
|
6419
6450
|
if @row_sizes[row]
|
6420
|
-
height = @row_sizes[row]
|
6451
|
+
height, hidden = @row_sizes[row]
|
6421
6452
|
|
6422
|
-
if
|
6453
|
+
if hidden == 1 && anchor != 4
|
6423
6454
|
pixels = 0
|
6424
6455
|
else
|
6425
6456
|
pixels = (4 / 3.0 * height).to_i
|
@@ -6433,13 +6464,13 @@ def size_row(row) #:nodoc:
|
|
6433
6464
|
#
|
6434
6465
|
# Set up image/drawings.
|
6435
6466
|
#
|
6436
|
-
def prepare_image(index, image_id, drawing_id, width, height, name, image_type, x_dpi = 96, y_dpi = 96) #:nodoc:
|
6467
|
+
def prepare_image(index, image_id, drawing_id, width, height, name, image_type, x_dpi = 96, y_dpi = 96, md5 = nil) #:nodoc:
|
6437
6468
|
x_dpi ||= 96
|
6438
6469
|
y_dpi ||= 96
|
6439
6470
|
drawing_type = 2
|
6440
|
-
drawing
|
6441
6471
|
|
6442
|
-
row, col, image, x_offset, y_offset,
|
6472
|
+
row, col, image, x_offset, y_offset,
|
6473
|
+
x_scale, y_scale, url, tip, anchor = @images[index]
|
6443
6474
|
|
6444
6475
|
width *= x_scale
|
6445
6476
|
height *= y_scale
|
@@ -6447,36 +6478,72 @@ def prepare_image(index, image_id, drawing_id, width, height, name, image_type,
|
|
6447
6478
|
width *= 96.0 / x_dpi
|
6448
6479
|
height *= 96.0 / y_dpi
|
6449
6480
|
|
6450
|
-
dimensions = position_object_emus(col, row, x_offset, y_offset, width, height)
|
6481
|
+
dimensions = position_object_emus(col, row, x_offset, y_offset, width, height, anchor)
|
6451
6482
|
|
6452
6483
|
# Convert from pixels to emus.
|
6453
6484
|
width = (0.5 + (width * 9_525)).to_i
|
6454
6485
|
height = (0.5 + (height * 9_525)).to_i
|
6455
6486
|
|
6456
6487
|
# Create a Drawing object to use with worksheet unless one already exists.
|
6457
|
-
|
6458
|
-
|
6459
|
-
|
6488
|
+
drawing = Drawing.new(drawing_type, dimensions, width, height, name, nil, anchor, 0, 0, tip)
|
6489
|
+
if !drawings?
|
6490
|
+
drawings = Drawings.new
|
6491
|
+
drawings.embedded = 1
|
6460
6492
|
|
6461
|
-
@
|
6493
|
+
@drawings = drawings
|
6462
6494
|
|
6463
6495
|
@external_drawing_links << ['/drawing', "../drawings/drawing#{drawing_id}.xml"]
|
6464
6496
|
else
|
6465
|
-
|
6497
|
+
drawings = @drawings
|
6498
|
+
end
|
6499
|
+
drawings.add_drawing_object(drawing)
|
6500
|
+
|
6501
|
+
if url
|
6502
|
+
rel_type = '/hyperlink'
|
6503
|
+
target_mode = 'External'
|
6504
|
+
if url =~ %r!^[fh]tt?ps?://! || url =~ /^mailto:/
|
6505
|
+
target = escape_url(url)
|
6506
|
+
end
|
6507
|
+
if url =~ /^external:/
|
6508
|
+
target = escape_url(url.sub(/^external:/, 'file:///'))
|
6509
|
+
# Additional escape not required in worksheet hyperlinks
|
6510
|
+
target = target.gsub(/#/, '%23')
|
6511
|
+
end
|
6512
|
+
if url =~ /^internal:/
|
6513
|
+
target = url.sub(/^internal:/, '#')
|
6514
|
+
target_mode = nil
|
6515
|
+
end
|
6516
|
+
|
6517
|
+
if target.length > 255
|
6518
|
+
raise <<"EOS"
|
6519
|
+
Ignoring URL #{target} where link or anchor > 255 characters since it exceeds Excel's limit for URLS. See LIMITATIONS section of the WriteXLSX documentation.
|
6520
|
+
EOS
|
6521
|
+
end
|
6522
|
+
|
6523
|
+
if target && !@drawing_rels[url]
|
6524
|
+
@drawing_links << [rel_type, target, target_mode]
|
6525
|
+
end
|
6526
|
+
drawing.url_rel_index = drawing_rel_index(url)
|
6466
6527
|
end
|
6467
|
-
drawing.add_drawing_object(drawing_type, dimensions, width, height, name)
|
6468
6528
|
|
6469
|
-
|
6529
|
+
if !@drawing_rels[md5]
|
6530
|
+
@drawing_links << ['/image', "../media/image#{image_id}.#{image_type}"]
|
6531
|
+
end
|
6532
|
+
drawing.rel_index = drawing_rel_index(md5)
|
6470
6533
|
end
|
6471
6534
|
public :prepare_image
|
6472
6535
|
|
6473
|
-
def prepare_header_image(image_id, width, height, name, image_type, position, x_dpi, y_dpi)
|
6536
|
+
def prepare_header_image(image_id, width, height, name, image_type, position, x_dpi, y_dpi, md5)
|
6474
6537
|
# Strip the extension from the filename.
|
6475
6538
|
body = name.dup
|
6476
6539
|
body[/\.[^\.]+$/, 0] = ''
|
6477
6540
|
|
6478
|
-
|
6479
|
-
|
6541
|
+
if !@vml_drawing_rels[md5]
|
6542
|
+
@vml_drawing_links << ['/image', "../media/image#{image_id}.#{image_type}" ]
|
6543
|
+
end
|
6544
|
+
|
6545
|
+
ref_id = get_vml_drawing_rel_index(md5)
|
6546
|
+
@header_images_array << [width, height, body, position, x_dpi, y_dpi, ref_id]
|
6480
6547
|
end
|
6481
6548
|
public :prepare_header_image
|
6482
6549
|
|
@@ -6519,16 +6586,16 @@ def prepare_header_image(image_id, width, height, name, image_type, position, x_
|
|
6519
6586
|
#
|
6520
6587
|
def insert_shape(*args)
|
6521
6588
|
# Check for a cell reference in A1 notation and substitute row and column.
|
6522
|
-
row_start, column_start, shape, x_offset, y_offset, x_scale, y_scale =
|
6589
|
+
row_start, column_start, shape, x_offset, y_offset, x_scale, y_scale, anchor =
|
6523
6590
|
row_col_notation(args)
|
6524
6591
|
if [row_start, column_start, shape].include?(nil)
|
6525
6592
|
raise "Insufficient arguments in insert_shape()"
|
6526
6593
|
end
|
6527
6594
|
|
6528
6595
|
shape.set_position(
|
6529
|
-
|
6530
|
-
|
6531
|
-
|
6596
|
+
row_start, column_start, x_offset, y_offset,
|
6597
|
+
x_scale, y_scale, anchor
|
6598
|
+
)
|
6532
6599
|
# Assign a shape ID.
|
6533
6600
|
while true
|
6534
6601
|
id = shape.id || 0
|
@@ -6572,9 +6639,9 @@ def prepare_shape(index, drawing_id)
|
|
6572
6639
|
shape = @shapes[index]
|
6573
6640
|
|
6574
6641
|
# Create a Drawing object to use with worksheet unless one already exists.
|
6575
|
-
unless
|
6576
|
-
@
|
6577
|
-
@
|
6642
|
+
unless drawings?
|
6643
|
+
@drawings = Drawings.new
|
6644
|
+
@drawings.embedded = 1
|
6578
6645
|
@external_drawing_links << ['/drawing', "../drawings/drawing#{drawing_id}.xml"]
|
6579
6646
|
@has_shapes = true
|
6580
6647
|
end
|
@@ -6584,13 +6651,14 @@ def prepare_shape(index, drawing_id)
|
|
6584
6651
|
shape.calc_position_emus(self)
|
6585
6652
|
|
6586
6653
|
drawing_type = 3
|
6587
|
-
drawing.
|
6654
|
+
drawing = Drawing.new(drawing_type, shape.dimensions, shape.width_emu, shape.height_emu, shape.name, shape, shape.anchor, drawing_rel_index, 0, nil)
|
6655
|
+
drawings.add_drawing_object(drawing)
|
6588
6656
|
end
|
6589
6657
|
public :prepare_shape
|
6590
6658
|
|
6591
6659
|
#
|
6592
6660
|
# This method handles the parameters passed to insert_button as well as
|
6593
|
-
# calculating the
|
6661
|
+
# calculating the button object position and vertices.
|
6594
6662
|
#
|
6595
6663
|
def button_params(row, col, params)
|
6596
6664
|
button = Writexlsx::Package::Button.new
|
@@ -6619,7 +6687,7 @@ def button_params(row, col, params)
|
|
6619
6687
|
params[:x_offset] = 0 if !params[:x_offset]
|
6620
6688
|
params[:y_offset] = 0 if !params[:y_offset]
|
6621
6689
|
|
6622
|
-
# Scale the size of the
|
6690
|
+
# Scale the size of the button box if required.
|
6623
6691
|
if params[:x_scale]
|
6624
6692
|
params[:width] = params[:width] * params[:x_scale]
|
6625
6693
|
end
|
@@ -6634,15 +6702,15 @@ def button_params(row, col, params)
|
|
6634
6702
|
params[:start_row] = row
|
6635
6703
|
params[:start_col] = col
|
6636
6704
|
|
6637
|
-
# Calculate the positions of
|
6705
|
+
# Calculate the positions of button object.
|
6638
6706
|
vertices = position_object_pixels(
|
6639
|
-
|
6640
|
-
|
6641
|
-
|
6642
|
-
|
6643
|
-
|
6644
|
-
|
6645
|
-
|
6707
|
+
params[:start_col],
|
6708
|
+
params[:start_row],
|
6709
|
+
params[:x_offset],
|
6710
|
+
params[:y_offset],
|
6711
|
+
params[:width],
|
6712
|
+
params[:height]
|
6713
|
+
)
|
6646
6714
|
|
6647
6715
|
# Add the width and height for VML.
|
6648
6716
|
vertices << [params[:width], params[:height]]
|
@@ -6882,7 +6950,7 @@ def col_info_attributes(args)
|
|
6882
6950
|
custom_width = false if width.nil? && hidden == 0
|
6883
6951
|
custom_width = false if width == 8.43
|
6884
6952
|
|
6885
|
-
width = hidden == 0 ?
|
6953
|
+
width = hidden == 0 ? @default_col_width : 0 unless width
|
6886
6954
|
|
6887
6955
|
# Convert column width from user units to character width.
|
6888
6956
|
if width && width < 1
|
@@ -7492,7 +7560,7 @@ def write_sheet_protection #:nodoc:
|
|
7492
7560
|
# Write the <drawing> elements.
|
7493
7561
|
#
|
7494
7562
|
def write_drawings #:nodoc:
|
7495
|
-
increment_rel_id_and_write_r_id('drawing') if
|
7563
|
+
increment_rel_id_and_write_r_id('drawing') if drawings?
|
7496
7564
|
end
|
7497
7565
|
|
7498
7566
|
#
|
@@ -7970,8 +8038,8 @@ def autofilter_ref? #:nodoc:
|
|
7970
8038
|
!!@autofilter_ref
|
7971
8039
|
end
|
7972
8040
|
|
7973
|
-
def
|
7974
|
-
!!@
|
8041
|
+
def drawings? #:nodoc:
|
8042
|
+
!!@drawings
|
7975
8043
|
end
|
7976
8044
|
|
7977
8045
|
def remove_white_space(margin) #:nodoc:
|