write_xlsx 0.97.0 → 1.04.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/Changes +78 -0
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- 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_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 +43 -35
- data/lib/write_xlsx/chart/area.rb +1 -1
- data/lib/write_xlsx/chart/axis.rb +2 -2
- 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/legend.rb +14 -0
- data/lib/write_xlsx/chart/line.rb +16 -2
- data/lib/write_xlsx/chart/pie.rb +30 -15
- data/lib/write_xlsx/chart/radar.rb +1 -1
- data/lib/write_xlsx/chart/scatter.rb +1 -1
- data/lib/write_xlsx/chart/stock.rb +1 -1
- data/lib/write_xlsx/chartsheet.rb +35 -7
- data/lib/write_xlsx/drawing.rb +86 -30
- data/lib/write_xlsx/format.rb +9 -9
- data/lib/write_xlsx/package/comments.rb +61 -58
- data/lib/write_xlsx/package/conditional_format.rb +9 -1
- 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 +13 -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 +96 -7
- data/lib/write_xlsx/version.rb +1 -1
- data/lib/write_xlsx/workbook.rb +99 -49
- data/lib/write_xlsx/worksheet.rb +225 -145
- data/lib/write_xlsx/worksheet/data_validation.rb +10 -14
- data/lib/write_xlsx/worksheet/hyperlink.rb +16 -37
- data/test/chart/test_write_legend_pos.rb +9 -1
- data/test/chartsheet/test_write_sheet_protection.rb +91 -0
- 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/package/comments/test_comments_01.rb +54 -0
- data/test/package/comments/test_comments_02.rb +54 -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/formats.xlsx +0 -0
- data/test/perl_output/tables.xlsx +0 -0
- data/test/regression/images/happy.jpg +0 -0
- data/test/regression/images/red2.png +0 -0
- data/test/regression/test_array_formula03.rb +36 -0
- data/test/regression/test_autofilter08.rb +110 -0
- data/test/regression/test_autofilter09.rb +110 -0
- data/test/regression/test_autofilter10.rb +110 -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_axis42.rb +44 -0
- data/test/regression/test_chart_axis43.rb +44 -0
- 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_doughnut07.rb +37 -0
- data/test/regression/test_chart_font09.rb +1 -1
- data/test/regression/test_chart_legend03.rb +41 -0
- data/test/regression/test_chart_legend04.rb +41 -0
- data/test/regression/test_chart_legend05.rb +41 -0
- data/test/regression/test_chart_legend06.rb +41 -0
- data/test/regression/test_chart_legend07.rb +38 -0
- 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_comment13.rb +36 -0
- 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_cond_format19.rb +64 -0
- data/test/regression/test_cond_format20.rb +43 -0
- data/test/regression/test_format15.rb +26 -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_image36.rb +26 -0
- 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_table23.rb +56 -0
- data/test/regression/test_table24.rb +27 -0
- data/test/regression/test_table25.rb +27 -0
- data/test/regression/xlsx_files/array_formula03.xlsx +0 -0
- data/test/regression/xlsx_files/autofilter08.xlsx +0 -0
- data/test/regression/xlsx_files/autofilter09.xlsx +0 -0
- data/test/regression/xlsx_files/autofilter10.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_axis42.xlsx +0 -0
- data/test/regression/xlsx_files/chart_axis43.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_doughnut07.xlsx +0 -0
- data/test/regression/xlsx_files/chart_font09.xlsx +0 -0
- data/test/regression/xlsx_files/chart_legend03.xlsx +0 -0
- data/test/regression/xlsx_files/chart_legend04.xlsx +0 -0
- data/test/regression/xlsx_files/chart_legend05.xlsx +0 -0
- data/test/regression/xlsx_files/chart_legend06.xlsx +0 -0
- data/test/regression/xlsx_files/chart_legend07.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/comment13.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/cond_format19.xlsx +0 -0
- data/test/regression/xlsx_files/cond_format20.xlsx +0 -0
- data/test/regression/xlsx_files/format15.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/image36.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/table23.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 +955 -780
- data/test/workbook/test_check_sheetname.rb +51 -0
- data/test/workbook/test_write_workbook_view.rb +36 -0
- data/test/worksheet/test_write_data_validation_02.rb +17 -0
- data/test/worksheet/test_write_sheet_view.rb +19 -1
- data/write_xlsx.gemspec +1 -0
- metadata +349 -7
- data/test/package/comments/test_write_text_t.rb +0 -44
data/lib/write_xlsx/shape.rb
CHANGED
@@ -8,14 +8,14 @@ module Writexlsx
|
|
8
8
|
# Used in conjunction with WriteXLSX.
|
9
9
|
#
|
10
10
|
# Copyright 2000-2012, John McNamara, jmcnamara@cpan.org
|
11
|
-
# Converted to ruby by Hideo NAKAMURA,
|
11
|
+
# Converted to ruby by Hideo NAKAMURA, nakamura.hideo@gmail.com
|
12
12
|
#
|
13
13
|
class Shape
|
14
14
|
include Writexlsx::Utility
|
15
15
|
|
16
16
|
attr_reader :edit_as, :type, :drawing
|
17
17
|
attr_reader :tx_box, :fill, :line, :format
|
18
|
-
attr_reader :align, :valign
|
18
|
+
attr_reader :align, :valign, :anchor
|
19
19
|
attr_accessor :name, :connect, :type, :id, :start, :end, :rotation
|
20
20
|
attr_accessor :flip_h, :flip_v, :adjustments, :palette, :text, :stencil
|
21
21
|
attr_accessor :row_start, :row_end, :column_start, :column_end
|
@@ -183,11 +183,12 @@ def calc_position_emus(worksheet)
|
|
183
183
|
@y_abs = (y_abslt * 9_525).to_i
|
184
184
|
end
|
185
185
|
|
186
|
-
def set_position(row_start, column_start, x_offset, y_offset, x_scale, y_scale)
|
186
|
+
def set_position(row_start, column_start, x_offset, y_offset, x_scale, y_scale, anchor)
|
187
187
|
@row_start = row_start
|
188
188
|
@column_start = column_start
|
189
189
|
@x_offset = x_offset || 0
|
190
190
|
@y_offset = y_offset || 0
|
191
|
+
@anchor = anchor || 1
|
191
192
|
|
192
193
|
# Override shape scale if supplied as an argument. Otherwise, use the
|
193
194
|
# existing shape scale factors.
|
data/lib/write_xlsx/sheets.rb
CHANGED
@@ -67,18 +67,18 @@ def write_vml_files(package_dir)
|
|
67
67
|
vml = Package::Vml.new
|
68
68
|
vml.set_xml_writer("#{dir}/vmlDrawing#{index}.vml")
|
69
69
|
vml.assemble_xml_file(
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
sheet.vml_data_id, sheet.vml_shape_id,
|
71
|
+
sheet.sorted_comments, sheet.buttons_data
|
72
|
+
)
|
73
73
|
index += 1
|
74
74
|
end
|
75
75
|
if sheet.has_header_vml?
|
76
76
|
vml = Package::Vml.new
|
77
77
|
vml.set_xml_writer("#{dir}/vmlDrawing#{index}.vml")
|
78
78
|
vml.assemble_xml_file(
|
79
|
-
|
80
|
-
|
81
|
-
|
79
|
+
sheet.vml_header_id, sheet.vml_header_id * 1024,
|
80
|
+
[], [], sheet.header_images_data
|
81
|
+
)
|
82
82
|
write_vml_drawing_rels_files(package_dir, sheet, index)
|
83
83
|
index += 1
|
84
84
|
end
|
@@ -106,16 +106,12 @@ def write_table_files(package_dir)
|
|
106
106
|
end
|
107
107
|
|
108
108
|
def write_chartsheet_rels_files(package_dir)
|
109
|
-
write_sheet_rels_files_base(
|
110
|
-
|
109
|
+
write_sheet_rels_files_base(
|
110
|
+
chartsheets, "#{package_dir}/xl/chartsheets/_rels", 'sheet'
|
111
|
+
)
|
111
112
|
end
|
112
113
|
|
113
114
|
def write_drawing_rels_files(package_dir)
|
114
|
-
# write_rels_files_base(
|
115
|
-
# self.reject { |sheet| sheet.drawing_links[0].empty? },
|
116
|
-
# "#{package_dir}/xl/drawings/_rels",
|
117
|
-
|
118
|
-
# )
|
119
115
|
dir = "#{package_dir}/xl/drawings/_rels"
|
120
116
|
|
121
117
|
index = 0
|
@@ -159,8 +155,9 @@ def write_vml_drawing_rels_files(package_dir, worksheet, index)
|
|
159
155
|
end
|
160
156
|
|
161
157
|
def write_worksheet_rels_files(package_dir)
|
162
|
-
write_sheet_rels_files_base(
|
163
|
-
|
158
|
+
write_sheet_rels_files_base(
|
159
|
+
worksheets, "#{package_dir}/xl/worksheets/_rels", 'sheet'
|
160
|
+
)
|
164
161
|
end
|
165
162
|
|
166
163
|
def write_sheet_rels_files_base(sheets, dir, body)
|
@@ -230,10 +227,15 @@ def check_valid_sheetname(name)
|
|
230
227
|
raise 'Invalid character []:*?/\\ in worksheet name: ' + name
|
231
228
|
end
|
232
229
|
|
230
|
+
# Check that sheetname doesn't start or end with an apostrophe.
|
231
|
+
if name =~ /^'/ || name =~ /'$/
|
232
|
+
raise "Worksheet name #{name} cannot start or end with an "
|
233
|
+
end
|
234
|
+
|
233
235
|
# Check that the worksheet name doesn't already exist since this is a fatal
|
234
236
|
# error in Excel 97. The check must also exclude case insensitive matches.
|
235
237
|
unless is_sheetname_uniq?(name)
|
236
|
-
raise "
|
238
|
+
raise "apostropheWorksheet name '#{name}', with case ignored, is already used."
|
237
239
|
end
|
238
240
|
end
|
239
241
|
|
data/lib/write_xlsx/sparkline.rb
CHANGED
@@ -9,7 +9,7 @@ module Writexlsx
|
|
9
9
|
# Used in conjunction with WriteXLSX.
|
10
10
|
#
|
11
11
|
# Copyright 2000-2012, John McNamara, jmcnamara@cpan.org
|
12
|
-
# Converted to ruby by Hideo NAKAMURA,
|
12
|
+
# Converted to ruby by Hideo NAKAMURA, nakamura.hideo@gmail.com
|
13
13
|
#
|
14
14
|
class Sparkline
|
15
15
|
include Writexlsx::Utility
|
data/lib/write_xlsx/utility.rb
CHANGED
@@ -119,7 +119,7 @@ def check_dimensions(row, col)
|
|
119
119
|
# nil if the date is invalid.
|
120
120
|
#
|
121
121
|
def convert_date_time(date_time_string) #:nodoc:
|
122
|
-
date_time = date_time_string.sub(/^\s+/, '').sub(/\s+$/, '').sub(/Z$/, '')
|
122
|
+
date_time = date_time_string.to_s.sub(/^\s+/, '').sub(/\s+$/, '').sub(/Z$/, '')
|
123
123
|
|
124
124
|
# Check for invalid date char.
|
125
125
|
return nil if date_time =~ /[^0-9T:\-\.Z]/
|
@@ -218,6 +218,25 @@ def convert_date_time(date_time_string) #:nodoc:
|
|
218
218
|
end
|
219
219
|
end
|
220
220
|
|
221
|
+
def escape_url(url)
|
222
|
+
unless url =~ /%[0-9a-fA-F]{2}/
|
223
|
+
# Escape the URL escape symbol.
|
224
|
+
url = url.gsub(/%/, "%25")
|
225
|
+
|
226
|
+
# Escape whitespae in URL.
|
227
|
+
url = url.gsub(/[\s\x00]/, '%20')
|
228
|
+
|
229
|
+
# Escape other special characters in URL.
|
230
|
+
re = /(["<>\[\]`^{}])/
|
231
|
+
while re =~ url
|
232
|
+
match = $~[1]
|
233
|
+
url = url.sub(re, sprintf("%%%x", match.ord))
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
url
|
238
|
+
end
|
239
|
+
|
221
240
|
def absolute_char(absolute)
|
222
241
|
absolute ? '$' : ''
|
223
242
|
end
|
@@ -361,6 +380,64 @@ def float_to_str(float)
|
|
361
380
|
end
|
362
381
|
end
|
363
382
|
|
383
|
+
#
|
384
|
+
# Convert user defined legend properties to the structure required internally.
|
385
|
+
#
|
386
|
+
def legend_properties(params)
|
387
|
+
legend = Writexlsx::Chart::Legend.new
|
388
|
+
|
389
|
+
legend.position = params[:position] || 'right'
|
390
|
+
legend.delete_series = params[:delete_series]
|
391
|
+
legend.font = convert_font_args(params[:font])
|
392
|
+
|
393
|
+
# Set the legend layout.
|
394
|
+
legend.layout = layout_properties(params[:layout])
|
395
|
+
|
396
|
+
# Turn off the legend.
|
397
|
+
if params[:none]
|
398
|
+
legend.position = 'none'
|
399
|
+
end
|
400
|
+
|
401
|
+
# Set the line properties for the legend.
|
402
|
+
line = line_properties(params[:line])
|
403
|
+
|
404
|
+
# Allow 'border' as a synonym for 'line'.
|
405
|
+
if params[:border]
|
406
|
+
line = line_properties(params[:border])
|
407
|
+
end
|
408
|
+
|
409
|
+
# Set the fill properties for the legend.
|
410
|
+
fill = fill_properties(params[:fill])
|
411
|
+
|
412
|
+
# Set the pattern properties for the legend.
|
413
|
+
pattern = pattern_properties(params[:pattern])
|
414
|
+
|
415
|
+
# Set the gradient fill properties for the legend.
|
416
|
+
gradient = gradient_properties(params[:gradient])
|
417
|
+
|
418
|
+
# Pattern fill overrides solid fill.
|
419
|
+
if pattern
|
420
|
+
fill = nil
|
421
|
+
end
|
422
|
+
|
423
|
+
# Gradient fill overrides solid and pattern fills.
|
424
|
+
if gradient
|
425
|
+
pattern = nil
|
426
|
+
fill = nil
|
427
|
+
end
|
428
|
+
|
429
|
+
# Set the legend layout.
|
430
|
+
layout = layout_properties(params[:layout])
|
431
|
+
|
432
|
+
legend.line = line
|
433
|
+
legend.fill = fill
|
434
|
+
legend.pattern = pattern
|
435
|
+
legend.gradient = gradient
|
436
|
+
legend.layout = layout
|
437
|
+
|
438
|
+
@legend = legend
|
439
|
+
end
|
440
|
+
|
364
441
|
#
|
365
442
|
# Convert user defined layout properties to the format required internally.
|
366
443
|
#
|
@@ -727,14 +804,14 @@ def params_to_font(params)
|
|
727
804
|
#
|
728
805
|
# Write the <c:txPr> element.
|
729
806
|
#
|
730
|
-
def write_tx_pr(
|
807
|
+
def write_tx_pr(is_y_axis, font) # :nodoc:
|
731
808
|
rotation = nil
|
732
809
|
if font && font[:_rotation]
|
733
810
|
rotation = font[:_rotation]
|
734
811
|
end
|
735
812
|
@writer.tag_elements('c:txPr') do
|
736
813
|
# Write the a:bodyPr element.
|
737
|
-
write_a_body_pr(rotation,
|
814
|
+
write_a_body_pr(rotation, is_y_axis)
|
738
815
|
# Write the a:lstStyle element.
|
739
816
|
write_a_lst_style
|
740
817
|
# Write the a:p element.
|
@@ -745,11 +822,23 @@ def write_tx_pr(horiz, font) # :nodoc:
|
|
745
822
|
#
|
746
823
|
# Write the <a:bodyPr> element.
|
747
824
|
#
|
748
|
-
def write_a_body_pr(rot,
|
749
|
-
rot = -5400000 if !rot && ptrue?(
|
825
|
+
def write_a_body_pr(rot, is_y_axis = nil) # :nodoc:
|
826
|
+
rot = -5400000 if !rot && ptrue?(is_y_axis)
|
750
827
|
attributes = []
|
751
|
-
|
752
|
-
|
828
|
+
if rot
|
829
|
+
if rot == 16_200_000
|
830
|
+
# 270 deg/stacked angle.
|
831
|
+
attributes << ['rot', 0]
|
832
|
+
attributes << ['vert', 'wordArtVert']
|
833
|
+
elsif rot == 16_260_000
|
834
|
+
# 271 deg/stacked angle.
|
835
|
+
attributes << ['rot', 0]
|
836
|
+
attributes << ['vert', 'eaVert']
|
837
|
+
else
|
838
|
+
attributes << ['rot', rot]
|
839
|
+
attributes << ['vert', 'horz']
|
840
|
+
end
|
841
|
+
end
|
753
842
|
|
754
843
|
@writer.empty_tag('a:bodyPr', attributes)
|
755
844
|
end
|
data/lib/write_xlsx/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
WriteXLSX_VERSION = "
|
1
|
+
WriteXLSX_VERSION = "1.04.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
|
|
@@ -123,13 +124,20 @@ def initialize(file, *option_params)
|
|
123
124
|
@y_window = 15
|
124
125
|
@window_width = 16095
|
125
126
|
@window_height = 9660
|
126
|
-
@tab_ratio =
|
127
|
+
@tab_ratio = 600
|
127
128
|
@excel2003_style = options[:excel2003_style] || false
|
128
129
|
@table_count = 0
|
129
130
|
@image_types = {}
|
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
|
|
@@ -784,6 +792,19 @@ def set_size(width = nil, height = nil)
|
|
784
792
|
end
|
785
793
|
end
|
786
794
|
|
795
|
+
#
|
796
|
+
# Set the ratio of space for worksheet tabs.
|
797
|
+
#
|
798
|
+
def set_tab_ratio(tab_ratio = nil)
|
799
|
+
return if !tab_ratio
|
800
|
+
|
801
|
+
if tab_ratio < 0 || tab_ratio > 100
|
802
|
+
raise "Tab ratio outside range: 0 <= zoom <= 100"
|
803
|
+
else
|
804
|
+
@tab_ratio = (tab_ratio * 10).to_i
|
805
|
+
end
|
806
|
+
end
|
807
|
+
|
787
808
|
#
|
788
809
|
# The set_properties method can be used to set the document properties
|
789
810
|
# of the Excel file created by WriteXLSX. These properties are visible
|
@@ -1095,7 +1116,8 @@ def style_properties
|
|
1095
1116
|
@border_count,
|
1096
1117
|
@fill_count,
|
1097
1118
|
@custom_colors,
|
1098
|
-
@dxf_formats
|
1119
|
+
@dxf_formats,
|
1120
|
+
@has_comments
|
1099
1121
|
]
|
1100
1122
|
end
|
1101
1123
|
|
@@ -1308,7 +1330,7 @@ def write_workbook_view #:nodoc:
|
|
1308
1330
|
['windowWidth', @window_width],
|
1309
1331
|
['windowHeight', @window_height]
|
1310
1332
|
]
|
1311
|
-
if @tab_ratio !=
|
1333
|
+
if @tab_ratio != 600
|
1312
1334
|
attributes << ['tabRatio', @tab_ratio]
|
1313
1335
|
end
|
1314
1336
|
if @firstsheet > 0
|
@@ -1512,9 +1534,17 @@ def prepare_num_formats #:nodoc:
|
|
1512
1534
|
# string but would evaluate to zero.
|
1513
1535
|
#
|
1514
1536
|
if num_format.to_s =~ /^\d+$/ && num_format.to_s !~ /^0+\d/
|
1537
|
+
# Number format '0' is indexed as 1 in Excel.
|
1538
|
+
if num_format == 0
|
1539
|
+
num_format = 1
|
1540
|
+
end
|
1515
1541
|
# Index to a built-in number format.
|
1516
1542
|
format.num_format_index = num_format
|
1517
1543
|
next
|
1544
|
+
elsif num_format.to_s == 'General'
|
1545
|
+
# The 'General' format has an number format index of 0.
|
1546
|
+
format.num_format_index = 0
|
1547
|
+
next
|
1518
1548
|
end
|
1519
1549
|
|
1520
1550
|
if num_formats[num_format]
|
@@ -1683,11 +1713,14 @@ def prepare_vml_objects #:nodoc:
|
|
1683
1713
|
if sheet.has_comments?
|
1684
1714
|
comment_files += 1
|
1685
1715
|
comment_id += 1
|
1716
|
+
@has_comments = true
|
1686
1717
|
end
|
1687
1718
|
vml_drawing_id += 1
|
1688
1719
|
|
1689
|
-
sheet.prepare_vml_objects(
|
1690
|
-
|
1720
|
+
sheet.prepare_vml_objects(
|
1721
|
+
vml_data_id, vml_shape_id,
|
1722
|
+
vml_drawing_id, comment_id
|
1723
|
+
)
|
1691
1724
|
|
1692
1725
|
# Each VML file should start with a shape id incremented by 1024.
|
1693
1726
|
vml_data_id += 1 * ( 1 + sheet.num_comments_block )
|
@@ -1710,8 +1743,6 @@ def prepare_vml_objects #:nodoc:
|
|
1710
1743
|
end
|
1711
1744
|
end
|
1712
1745
|
|
1713
|
-
add_font_format_for_cell_comments if num_comment_files > 0
|
1714
|
-
|
1715
1746
|
# Set the workbook vba_codename if one of the sheets has a button and
|
1716
1747
|
# the workbook has a vbaProject binary.
|
1717
1748
|
if has_button && @vba_project && !@vba_codename
|
@@ -1731,19 +1762,6 @@ def prepare_tables
|
|
1731
1762
|
end
|
1732
1763
|
end
|
1733
1764
|
|
1734
|
-
def add_font_format_for_cell_comments
|
1735
|
-
format = Format.new(
|
1736
|
-
@formats,
|
1737
|
-
:font => 'Tahoma',
|
1738
|
-
:size => 8,
|
1739
|
-
:color_indexed => 81,
|
1740
|
-
:font_only => 1
|
1741
|
-
)
|
1742
|
-
|
1743
|
-
format.get_xf_index
|
1744
|
-
@formats.formats << format
|
1745
|
-
end
|
1746
|
-
|
1747
1765
|
#
|
1748
1766
|
# Add "cached" data to charts to provide the numCache and strCache data for
|
1749
1767
|
# series and title/axis ranges.
|
@@ -1894,16 +1912,19 @@ def extract_named_ranges(defined_names) #:nodoc:
|
|
1894
1912
|
# Iterate through the worksheets and set up any chart or image drawings.
|
1895
1913
|
#
|
1896
1914
|
def prepare_drawings #:nodoc:
|
1897
|
-
chart_ref_id
|
1898
|
-
image_ref_id
|
1899
|
-
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 = {}
|
1900
1921
|
@worksheets.each do |sheet|
|
1901
1922
|
chart_count = sheet.charts.size
|
1902
1923
|
image_count = sheet.images.size
|
1903
1924
|
shape_count = sheet.shapes.size
|
1904
1925
|
header_image_count = sheet.header_images.size
|
1905
1926
|
footer_image_count = sheet.footer_images.size
|
1906
|
-
|
1927
|
+
has_drawings = false
|
1907
1928
|
|
1908
1929
|
# Check that some image or drawing needs to be processed.
|
1909
1930
|
next if chart_count + image_count + shape_count + header_image_count + footer_image_count == 0
|
@@ -1911,7 +1932,24 @@ def prepare_drawings #:nodoc:
|
|
1911
1932
|
# Don't increase the drawing_id header/footer images.
|
1912
1933
|
if chart_count + image_count + shape_count > 0
|
1913
1934
|
drawing_id += 1
|
1914
|
-
|
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
|
+
)
|
1915
1953
|
end
|
1916
1954
|
|
1917
1955
|
# Prepare the worksheet charts.
|
@@ -1920,13 +1958,6 @@ def prepare_drawings #:nodoc:
|
|
1920
1958
|
sheet.prepare_chart(index, chart_ref_id, drawing_id)
|
1921
1959
|
end
|
1922
1960
|
|
1923
|
-
# Prepare the worksheet images.
|
1924
|
-
sheet.images.each_with_index do |image, index|
|
1925
|
-
type, width, height, name, x_dpi, y_dpi = get_image_properties(image[2])
|
1926
|
-
image_ref_id += 1
|
1927
|
-
sheet.prepare_image(index, image_ref_id, drawing_id, width, height, name, type, x_dpi, y_dpi)
|
1928
|
-
end
|
1929
|
-
|
1930
1961
|
# Prepare the worksheet shapes.
|
1931
1962
|
sheet.shapes.each_with_index do |shape, index|
|
1932
1963
|
sheet.prepare_shape(index, drawing_id)
|
@@ -1937,13 +1968,21 @@ def prepare_drawings #:nodoc:
|
|
1937
1968
|
filename = sheet.header_images[index][0]
|
1938
1969
|
position = sheet.header_images[index][1]
|
1939
1970
|
|
1940
|
-
type, width, height, name, x_dpi, y_dpi =
|
1971
|
+
type, width, height, name, x_dpi, y_dpi, md5 =
|
1941
1972
|
get_image_properties(filename)
|
1942
1973
|
|
1943
|
-
|
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
|
1944
1981
|
|
1945
|
-
sheet.prepare_header_image(
|
1946
|
-
|
1982
|
+
sheet.prepare_header_image(
|
1983
|
+
ref_id, width, height, name, type,
|
1984
|
+
position, x_dpi, y_dpi, md5
|
1985
|
+
)
|
1947
1986
|
end
|
1948
1987
|
|
1949
1988
|
# Prepare the footer images.
|
@@ -1951,18 +1990,26 @@ def prepare_drawings #:nodoc:
|
|
1951
1990
|
filename = sheet.footer_images[index][0]
|
1952
1991
|
position = sheet.footer_images[index][1]
|
1953
1992
|
|
1954
|
-
type, width, height, name, x_dpi, y_dpi =
|
1993
|
+
type, width, height, name, x_dpi, y_dpi, md5 =
|
1955
1994
|
get_image_properties(filename)
|
1956
1995
|
|
1957
|
-
|
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
|
1958
2003
|
|
1959
|
-
sheet.prepare_header_image(
|
1960
|
-
|
2004
|
+
sheet.prepare_header_image(
|
2005
|
+
ref_id, width, height, name, type,
|
2006
|
+
position, x_dpi, y_dpi, md5
|
2007
|
+
)
|
1961
2008
|
end
|
1962
2009
|
|
1963
|
-
if
|
1964
|
-
|
1965
|
-
@drawings <<
|
2010
|
+
if has_drawings
|
2011
|
+
drawings = sheet.drawings
|
2012
|
+
@drawings << drawings
|
1966
2013
|
end
|
1967
2014
|
end
|
1968
2015
|
|
@@ -1986,6 +2033,7 @@ def get_image_properties(filename)
|
|
1986
2033
|
|
1987
2034
|
# Open the image file and import the data.
|
1988
2035
|
data = File.binread(filename)
|
2036
|
+
md5 = Digest::MD5.hexdigest(data)
|
1989
2037
|
if data.unpack('x A3')[0] == 'PNG'
|
1990
2038
|
# Test for PNGs.
|
1991
2039
|
type, width, height, x_dpi, y_dpi = process_png(data)
|
@@ -2003,13 +2051,11 @@ def get_image_properties(filename)
|
|
2003
2051
|
raise "Unsupported image format for file: #{filename}\n"
|
2004
2052
|
end
|
2005
2053
|
|
2006
|
-
@images << [filename, type]
|
2007
|
-
|
2008
2054
|
# Set a default dpi for images with 0 dpi.
|
2009
2055
|
x_dpi = 96 if x_dpi == 0
|
2010
2056
|
y_dpi = 96 if y_dpi == 0
|
2011
2057
|
|
2012
|
-
[type, width, height, File.basename(filename), x_dpi, y_dpi]
|
2058
|
+
[type, width, height, File.basename(filename), x_dpi, y_dpi, md5]
|
2013
2059
|
end
|
2014
2060
|
|
2015
2061
|
#
|
@@ -2064,16 +2110,20 @@ def process_jpg(data, filename)
|
|
2064
2110
|
offset = 2
|
2065
2111
|
data_length = data.bytesize
|
2066
2112
|
|
2067
|
-
# Search through the image data to read the
|
2068
|
-
# 0xFFC0/C2 element. Also read the DPI in the 0xFFE0 element.
|
2113
|
+
# Search through the image data to read the JPEG markers.
|
2069
2114
|
while offset < data_length
|
2070
2115
|
marker = data[offset+0, 2].unpack("n")[0]
|
2071
2116
|
length = data[offset+2, 2].unpack("n")[0]
|
2072
2117
|
|
2073
|
-
|
2118
|
+
# Read the height and width in the 0xFFCn elements
|
2119
|
+
# (Except C4, C8 and CC which aren't SOF markers).
|
2120
|
+
if (marker & 0xFFF0) == 0xFFC0 &&
|
2121
|
+
marker != 0xFFC4 && marker != 0xFFCC
|
2074
2122
|
height = data[offset+5, 2].unpack("n")[0]
|
2075
2123
|
width = data[offset+7, 2].unpack("n")[0]
|
2076
2124
|
end
|
2125
|
+
|
2126
|
+
# Read the DPI in the 0xFFE0 element.
|
2077
2127
|
if marker == 0xFFE0
|
2078
2128
|
units = data[offset + 11, 1].unpack("C")[0]
|
2079
2129
|
x_density = data[offset + 12, 2].unpack("n")[0]
|