write_xlsx 0.99.0 → 1.07.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.
- 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:
|