axlsx 1.1.3 → 1.2.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.
- data/.yardopts +5 -2
- data/CHANGELOG.md +60 -0
- data/LICENSE +1 -1
- data/README.md +115 -415
- data/Rakefile +11 -3
- data/examples/basic_charts.rb +54 -0
- data/examples/chart_colors.rb +88 -0
- data/examples/data_validation.rb +50 -0
- data/examples/example.rb +299 -155
- data/examples/example.xlsx +0 -0
- data/examples/example_streamed.xlsx +0 -0
- data/examples/extractive.pdf +0 -0
- data/examples/extractive.rb +45 -0
- data/examples/no-use_autowidth.xlsx +0 -0
- data/examples/scraping_html.rb +91 -0
- data/examples/shared_strings_example.xlsx +0 -0
- data/examples/sheet_protection.rb +10 -0
- data/examples/sheet_view.rb +34 -0
- data/examples/two_cell_anchor_image.rb +11 -0
- data/lib/axlsx/content_type/content_type.rb +2 -0
- data/lib/axlsx/content_type/default.rb +30 -15
- data/lib/axlsx/content_type/override.rb +29 -14
- data/lib/axlsx/doc_props/app.rb +161 -104
- data/lib/axlsx/doc_props/core.rb +9 -5
- data/lib/axlsx/drawing/ax_data_source.rb +26 -0
- data/lib/axlsx/drawing/axis.rb +92 -37
- data/lib/axlsx/drawing/bar_3D_chart.rb +49 -45
- data/lib/axlsx/drawing/bar_series.rb +25 -7
- data/lib/axlsx/drawing/cat_axis.rb +50 -22
- data/lib/axlsx/drawing/chart.rb +69 -56
- data/lib/axlsx/drawing/d_lbls.rb +100 -0
- data/lib/axlsx/drawing/drawing.rb +28 -12
- data/lib/axlsx/drawing/graphic_frame.rb +2 -1
- data/lib/axlsx/drawing/line_3D_chart.rb +3 -10
- data/lib/axlsx/drawing/line_series.rb +20 -4
- data/lib/axlsx/drawing/num_data.rb +52 -0
- data/lib/axlsx/drawing/num_data_source.rb +61 -0
- data/lib/axlsx/drawing/num_val.rb +32 -0
- data/lib/axlsx/drawing/pic.rb +44 -4
- data/lib/axlsx/drawing/pie_3D_chart.rb +10 -7
- data/lib/axlsx/drawing/pie_series.rb +18 -4
- data/lib/axlsx/drawing/scatter_chart.rb +2 -8
- data/lib/axlsx/drawing/scatter_series.rb +28 -2
- data/lib/axlsx/drawing/ser_axis.rb +1 -1
- data/lib/axlsx/drawing/series.rb +1 -1
- data/lib/axlsx/drawing/str_data.rb +42 -0
- data/lib/axlsx/drawing/str_val.rb +33 -0
- data/lib/axlsx/drawing/title.rb +21 -9
- data/lib/axlsx/drawing/two_cell_anchor.rb +46 -9
- data/lib/axlsx/drawing/view_3D.rb +44 -31
- data/lib/axlsx/drawing/vml_drawing.rb +42 -0
- data/lib/axlsx/drawing/vml_shape.rb +125 -0
- data/lib/axlsx/package.rb +44 -16
- data/lib/axlsx/rels/relationship.rb +3 -3
- data/lib/axlsx/rels/relationships.rb +1 -11
- data/lib/axlsx/stylesheet/gradient_fill.rb +1 -1
- data/lib/axlsx/stylesheet/styles.rb +1 -1
- data/lib/axlsx/stylesheet/table_style.rb +3 -3
- data/lib/axlsx/util/constants.rb +28 -0
- data/lib/axlsx/util/simple_typed_list.rb +15 -21
- data/lib/axlsx/util/validators.rb +81 -8
- data/lib/axlsx/version.rb +2 -7
- data/lib/axlsx/workbook/defined_name.rb +174 -0
- data/lib/axlsx/workbook/defined_names.rb +21 -0
- data/lib/axlsx/workbook/workbook.rb +65 -13
- data/lib/axlsx/workbook/worksheet/auto_filter.rb +34 -0
- data/lib/axlsx/workbook/worksheet/cell.rb +35 -7
- data/lib/axlsx/workbook/worksheet/col.rb +17 -1
- data/lib/axlsx/workbook/worksheet/cols.rb +20 -0
- data/lib/axlsx/workbook/worksheet/comment.rb +101 -0
- data/lib/axlsx/workbook/worksheet/comments.rb +85 -0
- data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +25 -0
- data/lib/axlsx/workbook/worksheet/data_bar.rb +1 -1
- data/lib/axlsx/workbook/worksheet/data_validation.rb +245 -0
- data/lib/axlsx/workbook/worksheet/data_validations.rb +28 -0
- data/lib/axlsx/workbook/worksheet/dimension.rb +65 -0
- data/lib/axlsx/workbook/worksheet/merged_cells.rb +35 -0
- data/lib/axlsx/workbook/worksheet/page_setup.rb +113 -0
- data/lib/axlsx/workbook/worksheet/pane.rb +144 -0
- data/lib/axlsx/workbook/worksheet/print_options.rb +63 -0
- data/lib/axlsx/workbook/worksheet/protected_range.rb +46 -0
- data/lib/axlsx/workbook/worksheet/protected_ranges.rb +34 -0
- data/lib/axlsx/workbook/worksheet/row.rb +67 -12
- data/lib/axlsx/workbook/worksheet/selection.rb +111 -0
- data/lib/axlsx/workbook/worksheet/sheet_data.rb +25 -0
- data/lib/axlsx/workbook/worksheet/sheet_pr.rb +24 -0
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +224 -0
- data/lib/axlsx/workbook/worksheet/sheet_view.rb +379 -0
- data/lib/axlsx/workbook/worksheet/table.rb +3 -3
- data/lib/axlsx/workbook/worksheet/tables.rb +31 -0
- data/lib/axlsx/workbook/worksheet/worksheet.rb +377 -255
- data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +57 -0
- data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +64 -0
- data/lib/axlsx.rb +30 -15
- data/test/content_type/tc_content_type.rb +1 -6
- data/test/doc_props/tc_app.rb +31 -1
- data/test/doc_props/tc_core.rb +3 -1
- data/test/drawing/tc_axis.rb +38 -3
- data/test/drawing/tc_bar_3D_chart.rb +12 -12
- data/test/drawing/tc_bar_series.rb +17 -13
- data/test/drawing/tc_cat_axis.rb +3 -3
- data/test/drawing/tc_cat_axis_data.rb +23 -13
- data/test/drawing/tc_chart.rb +29 -11
- data/test/drawing/tc_d_lbls.rb +47 -0
- data/test/drawing/tc_data_source.rb +17 -0
- data/test/drawing/tc_drawing.rb +11 -5
- data/test/drawing/tc_hyperlink.rb +4 -5
- data/test/drawing/tc_line_series.rb +9 -11
- data/test/drawing/tc_named_axis_data.rb +27 -0
- data/test/drawing/tc_num_data.rb +31 -0
- data/test/drawing/tc_num_val.rb +29 -0
- data/test/drawing/tc_pic.rb +22 -2
- data/test/drawing/tc_pie_3D_chart.rb +4 -8
- data/test/drawing/tc_pie_series.rb +11 -13
- data/test/drawing/tc_scatter_chart.rb +6 -1
- data/test/drawing/tc_scatter_series.rb +6 -5
- data/test/drawing/tc_series.rb +1 -1
- data/test/drawing/tc_str_data.rb +18 -0
- data/test/drawing/tc_str_val.rb +21 -0
- data/test/drawing/tc_title.rb +16 -0
- data/test/drawing/tc_two_cell_anchor.rb +2 -3
- data/test/drawing/tc_view_3D.rb +18 -18
- data/test/drawing/tc_vml_drawing.rb +25 -0
- data/test/drawing/tc_vml_shape.rb +100 -0
- data/test/rels/tc_relationship.rb +1 -0
- data/test/stylesheet/tc_gradient_fill.rb +8 -0
- data/test/stylesheet/tc_pattern_fill.rb +7 -1
- data/test/stylesheet/tc_styles.rb +3 -4
- data/test/stylesheet/tc_table_style.rb +8 -0
- data/test/stylesheet/tc_table_style_element.rb +10 -1
- data/test/tc_helper.rb +1 -0
- data/test/tc_package.rb +93 -17
- data/test/util/tc_simple_typed_list.rb +13 -0
- data/test/util/tc_validators.rb +95 -9
- data/test/workbook/tc_defined_name.rb +41 -0
- data/test/workbook/tc_workbook.rb +5 -3
- data/test/workbook/worksheet/table/tc_table.rb +3 -11
- data/test/workbook/worksheet/tc_cell.rb +30 -6
- data/test/workbook/worksheet/tc_col.rb +9 -0
- data/test/workbook/worksheet/tc_comment.rb +57 -0
- data/test/workbook/worksheet/tc_comments.rb +57 -0
- data/test/workbook/worksheet/tc_conditional_formatting.rb +44 -0
- data/test/workbook/worksheet/tc_data_bar.rb +1 -1
- data/test/workbook/worksheet/tc_data_validation.rb +265 -0
- data/test/workbook/worksheet/tc_page_setup.rb +138 -0
- data/test/workbook/worksheet/tc_pane.rb +94 -0
- data/test/workbook/worksheet/tc_print_options.rb +72 -0
- data/test/workbook/worksheet/tc_protected_range.rb +17 -0
- data/test/workbook/worksheet/tc_row.rb +36 -12
- data/test/workbook/worksheet/tc_selection.rb +94 -0
- data/test/workbook/worksheet/tc_sheet_protection.rb +117 -0
- data/test/workbook/worksheet/tc_sheet_view.rb +214 -0
- data/test/workbook/worksheet/tc_worksheet.rb +138 -48
- metadata +164 -52
- data/examples/example.csv +0 -1000
- data/lib/axlsx/drawing/cat_axis_data.rb +0 -34
- data/lib/axlsx/drawing/hlink_click.rb~ +0 -0
- data/lib/axlsx/drawing/hyperlink.rb~ +0 -64
- data/lib/axlsx/drawing/named_axis_data.rb +0 -36
- data/lib/axlsx/drawing/picture_locking.rb~ +0 -36
- data/lib/axlsx/drawing/val_axis_data.rb +0 -27
- data/lib/axlsx/util/cbf.rb +0 -333
- data/lib/axlsx/util/cfb.rb~ +0 -201
- data/lib/axlsx/util/font_tables.rb~ +0 -0
- data/lib/axlsx/util/ms_off_crypto.rb +0 -189
- data/lib/axlsx/util/ms_off_crypto.rb~ +0 -3
- data/lib/axlsx/util/ms_offcrypto.rb~ +0 -0
- data/lib/axlsx/util/parser.rb~ +0 -6
- data/lib/axlsx/util/storage.rb~ +0 -0
- data/lib/axlsx/workbook/shared_strings_table.rb~ +0 -69
- data/lib/axlsx/workbook/worksheet/cfvo.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/color_scale.rb~ +0 -46
- data/lib/axlsx/workbook/worksheet/data_bar.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/icon_set.rb~ +0 -95
- data/lib/axlsx/workbook/worksheet/shared_strings_table.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/table.rb~ +0 -97
- data/lib/schema/dc.xsd~ +0 -118
- data/lib/schema/dcterms.xsd~ +0 -331
- data/lib/schema/opc-coreProperties.xsd~ +0 -50
- data/test/drawing/tc_val_axis_data.rb +0 -17
- data/test/workbook/worksheet/table/tc_table.rb~ +0 -72
- data/test/workbook/worksheet/tc_cfvo.rb~ +0 -20
- data/test/workbook/worksheet/tc_col.rb~ +0 -10
- data/test/workbook/worksheet/tc_color_scale.rb~ +0 -0
- data/test/workbook/worksheet/tc_data_bar.rb~ +0 -0
- data/test/workbook/worksheet/tc_icon_set.rb~ +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module Axlsx
|
|
3
|
+
|
|
4
|
+
#This class specifies data for a particular data point.
|
|
5
|
+
class StrVal
|
|
6
|
+
|
|
7
|
+
# a string value.
|
|
8
|
+
# @return [String]
|
|
9
|
+
attr_reader :v
|
|
10
|
+
|
|
11
|
+
# creates a new StrVal object
|
|
12
|
+
# @option options [String] v
|
|
13
|
+
def initialize(options={})
|
|
14
|
+
@v = ""
|
|
15
|
+
@idx = 0
|
|
16
|
+
options.each do |o|
|
|
17
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
# @see v
|
|
21
|
+
def v=(v)
|
|
22
|
+
@v = v.to_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# serialize the object
|
|
26
|
+
def to_xml_string(idx, str = "")
|
|
27
|
+
Axlsx::validate_unsigned_int(idx)
|
|
28
|
+
str << '<c:pt idx="' << idx.to_s << '"><c:v>' << v.to_s << '</c:v></c:pt>'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
data/lib/axlsx/drawing/title.rb
CHANGED
|
@@ -46,15 +46,27 @@ module Axlsx
|
|
|
46
46
|
str << '<c:title>'
|
|
47
47
|
unless @text.empty?
|
|
48
48
|
str << '<c:tx>'
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
if @cell.is_a?(Cell)
|
|
50
|
+
str << '<c:strRef>'
|
|
51
|
+
str << '<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>'
|
|
52
|
+
str << '<c:strCache>'
|
|
53
|
+
str << '<c:ptCount val="1"/>'
|
|
54
|
+
str << '<c:pt idx="0">'
|
|
55
|
+
str << '<c:v>' << @text << '</c:v>'
|
|
56
|
+
str << '</c:pt>'
|
|
57
|
+
str << '</c:strCache>'
|
|
58
|
+
str << '</c:strRef>'
|
|
59
|
+
else
|
|
60
|
+
str << '<c:rich>'
|
|
61
|
+
str << '<a:bodyPr/>'
|
|
62
|
+
str << '<a:lstStyle/>'
|
|
63
|
+
str << '<a:p>'
|
|
64
|
+
str << '<a:r>'
|
|
65
|
+
str << '<a:t>' << @text.to_s << '</a:t>'
|
|
66
|
+
str << '</a:r>'
|
|
67
|
+
str << '</a:p>'
|
|
68
|
+
str << '</c:rich>'
|
|
69
|
+
end
|
|
58
70
|
str << '</c:tx>'
|
|
59
71
|
end
|
|
60
72
|
str << '<c:layout/>'
|
|
@@ -25,23 +25,33 @@ module Axlsx
|
|
|
25
25
|
# @return [Drawing]
|
|
26
26
|
attr_reader :drawing
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
# Creates a new TwoCellAnchor object and sets up a reference to the from and to markers in the
|
|
30
|
-
# graphic_frame's chart. That means that you can do stuff like
|
|
31
|
-
# c = worksheet.add_chart Axlsx::Chart
|
|
28
|
+
# Creates a new TwoCellAnchor object
|
|
32
29
|
# c.start_at 5, 9
|
|
33
|
-
# @note the chart_type parameter will be replaced with object in v. 2.0.0
|
|
34
30
|
# @param [Drawing] drawing
|
|
35
|
-
# @
|
|
36
|
-
# @
|
|
37
|
-
# @option options [Array] start_at the col, row to start at
|
|
38
|
-
# @option options [Array] end_at the col, row to end at
|
|
31
|
+
# @option options [Array] :start_at the col, row to start at THIS IS DOCUMENTED BUT NOT IMPLEMENTED HERE!
|
|
32
|
+
# @option options [Array] :end_at the col, row to end at
|
|
39
33
|
def initialize(drawing, options={})
|
|
40
34
|
@drawing = drawing
|
|
41
35
|
drawing.anchors << self
|
|
42
36
|
@from, @to = Marker.new, Marker.new(:col => 5, :row=>10)
|
|
43
37
|
end
|
|
44
38
|
|
|
39
|
+
# sets the col, row attributes for the from marker.
|
|
40
|
+
# @note The recommended way to set the start position for graphical
|
|
41
|
+
# objects is directly thru the object.
|
|
42
|
+
# @see Chart#start_at
|
|
43
|
+
def start_at(x, y)
|
|
44
|
+
set_marker_coords(x, y, from)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# sets the col, row attributes for the to marker
|
|
48
|
+
# @note the recommended way to set the to position for graphical
|
|
49
|
+
# objects is directly thru the object
|
|
50
|
+
# @see Char#end_at
|
|
51
|
+
def end_at(x, y)
|
|
52
|
+
set_marker_coords(x, y, to)
|
|
53
|
+
end
|
|
54
|
+
|
|
45
55
|
# Creates a graphic frame and chart object associated with this anchor
|
|
46
56
|
# @return [Chart]
|
|
47
57
|
def add_chart(chart_type, options)
|
|
@@ -49,6 +59,11 @@ module Axlsx
|
|
|
49
59
|
@object.chart
|
|
50
60
|
end
|
|
51
61
|
|
|
62
|
+
# Creates an image associated with this anchor.
|
|
63
|
+
def add_pic(options={})
|
|
64
|
+
@object = Pic.new(self, options)
|
|
65
|
+
end
|
|
66
|
+
|
|
52
67
|
# The index of this anchor in the drawing
|
|
53
68
|
# @return [Integer]
|
|
54
69
|
def index
|
|
@@ -70,6 +85,28 @@ module Axlsx
|
|
|
70
85
|
str << '<xdr:clientData/>'
|
|
71
86
|
str << '</xdr:twoCellAnchor>'
|
|
72
87
|
end
|
|
88
|
+
private
|
|
89
|
+
|
|
90
|
+
# parses coordinates and sets up a marker's row/col propery
|
|
91
|
+
def set_marker_coords(x, y, marker)
|
|
92
|
+
marker.col, marker.row = *parse_coord_args(x, y)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# handles multiple inputs for setting the position of a marker
|
|
96
|
+
# @see Chart#start_at
|
|
97
|
+
def parse_coord_args(x, y=0)
|
|
98
|
+
if x.is_a?(String)
|
|
99
|
+
x, y = *Axlsx::name_to_indices(x)
|
|
100
|
+
end
|
|
101
|
+
if x.is_a?(Cell)
|
|
102
|
+
x, y = *x.pos
|
|
103
|
+
end
|
|
104
|
+
if x.is_a?(Array)
|
|
105
|
+
x, y = *x
|
|
106
|
+
end
|
|
107
|
+
[x, y]
|
|
108
|
+
end
|
|
109
|
+
|
|
73
110
|
|
|
74
111
|
end
|
|
75
112
|
end
|
|
@@ -4,68 +4,81 @@ module Axlsx
|
|
|
4
4
|
class View3D
|
|
5
5
|
|
|
6
6
|
# Validation for hPercent
|
|
7
|
-
H_PERCENT_REGEX = /0*(([5-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)
|
|
7
|
+
H_PERCENT_REGEX = /0*(([5-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)/
|
|
8
8
|
|
|
9
9
|
# validation for depthPercent
|
|
10
|
-
DEPTH_PERCENT_REGEX = /0*(([2-9][0-9])|([1-9][0-9][0-9])|(1[0-9][0-9][0-9])|2000)
|
|
10
|
+
DEPTH_PERCENT_REGEX = /0*(([2-9][0-9])|([1-9][0-9][0-9])|(1[0-9][0-9][0-9])|2000)/
|
|
11
11
|
|
|
12
12
|
# x rotation for the chart
|
|
13
13
|
# must be between -90 and 90
|
|
14
14
|
# @return [Integer]
|
|
15
|
-
attr_reader :
|
|
16
|
-
|
|
15
|
+
attr_reader :rot_x
|
|
16
|
+
alias :rotX :rot_x
|
|
17
|
+
|
|
17
18
|
# height of chart as % of chart
|
|
18
19
|
# must be between 5% and 500%
|
|
19
20
|
# @return [String]
|
|
20
|
-
attr_reader :
|
|
21
|
+
attr_reader :h_percent
|
|
22
|
+
alias :hPercent :h_percent
|
|
21
23
|
|
|
22
24
|
# y rotation for the chart
|
|
23
25
|
# must be between 0 and 360
|
|
24
26
|
# @return [Integer]
|
|
25
|
-
attr_reader :
|
|
26
|
-
|
|
27
|
+
attr_reader :rot_y
|
|
28
|
+
alias :rotY :rot_y
|
|
29
|
+
|
|
27
30
|
# depth or chart as % of chart width
|
|
28
31
|
# must be between 20% and 2000%
|
|
29
32
|
# @return [String]
|
|
30
|
-
attr_reader :
|
|
33
|
+
attr_reader :depth_percent
|
|
34
|
+
alias :depthPercent :depth_percent
|
|
31
35
|
|
|
32
36
|
# Chart axis are at right angles
|
|
33
37
|
# @return [Boolean]
|
|
34
|
-
attr_reader :
|
|
38
|
+
attr_reader :r_ang_ax
|
|
39
|
+
alias :rAngAx :r_ang_ax
|
|
35
40
|
|
|
36
41
|
# field of view angle
|
|
37
42
|
# @return [Integer]
|
|
38
43
|
attr_reader :perspective
|
|
39
44
|
|
|
40
45
|
# Creates a new View3D for charts
|
|
41
|
-
# @option options [Integer]
|
|
42
|
-
# @option options [String]
|
|
43
|
-
# @option options [Integer]
|
|
44
|
-
# @option options [String]
|
|
45
|
-
# @option options [Boolean]
|
|
46
|
+
# @option options [Integer] rot_x
|
|
47
|
+
# @option options [String] h_percent
|
|
48
|
+
# @option options [Integer] rot_y
|
|
49
|
+
# @option options [String] depth_percent
|
|
50
|
+
# @option options [Boolean] r_ang_ax
|
|
46
51
|
# @option options [Integer] perspective
|
|
47
52
|
def initialize(options={})
|
|
48
|
-
@
|
|
53
|
+
@rot_x, @h_percent, @rot_y, @depth_percent, @r_ang_ax, @perspective = nil, nil, nil, nil, nil, nil
|
|
49
54
|
options.each do |o|
|
|
50
55
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
51
56
|
end
|
|
52
57
|
end
|
|
53
58
|
|
|
54
|
-
# @see
|
|
55
|
-
def
|
|
59
|
+
# @see rot_x
|
|
60
|
+
def rot_x=(v) DataTypeValidator.validate "#{self.class}.rot_x", [Integer, Fixnum], v, lambda {|arg| arg >= -90 && arg <= 90 }; @rot_x = v; end
|
|
61
|
+
alias :rotX= :rot_x=
|
|
56
62
|
|
|
57
|
-
# @see
|
|
58
|
-
def
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
# @see h_percent
|
|
64
|
+
def h_percent=(v)
|
|
65
|
+
RegexValidator.validate "#{self.class}.h_percent", H_PERCENT_REGEX, v
|
|
66
|
+
@h_percent = v
|
|
67
|
+
end
|
|
68
|
+
alias :hPercent= :h_percent=
|
|
62
69
|
|
|
63
|
-
# @see
|
|
64
|
-
def
|
|
70
|
+
# @see rot_y
|
|
71
|
+
def rot_y=(v) DataTypeValidator.validate "#{self.class}.rot_y", [Integer, Fixnum], v, lambda {|arg| arg >= 0 && arg <= 360 }; @rot_y = v; end
|
|
72
|
+
alias :rotY= :rot_y=
|
|
65
73
|
|
|
66
|
-
# @see
|
|
67
|
-
def
|
|
74
|
+
# @see depth_percent
|
|
75
|
+
def depth_percent=(v) RegexValidator.validate "#{self.class}.depth_percent", DEPTH_PERCENT_REGEX, v; @depth_percent = v; end
|
|
76
|
+
alias :depthPercent= :depth_percent=
|
|
68
77
|
|
|
78
|
+
# @see r_ang_ax
|
|
79
|
+
def r_ang_ax=(v) Axlsx::validate_boolean(v); @r_ang_ax = v; end
|
|
80
|
+
alias :rAngAx= :r_ang_ax=
|
|
81
|
+
|
|
69
82
|
# @see perspective
|
|
70
83
|
def perspective=(v) DataTypeValidator.validate "#{self.class}.perspective", [Integer, Fixnum], v, lambda {|arg| arg >= 0 && arg <= 240 }; @perspective = v; end
|
|
71
84
|
|
|
@@ -75,11 +88,11 @@ module Axlsx
|
|
|
75
88
|
# @return [String]
|
|
76
89
|
def to_xml_string(str = '')
|
|
77
90
|
str << '<c:view3D>'
|
|
78
|
-
str << '<c:rotX val="' << @
|
|
79
|
-
str << '<c:hPercent val="' << @
|
|
80
|
-
str << '<c:rotY val="' << @
|
|
81
|
-
str << '<c:depthPercent val="' << @
|
|
82
|
-
str << '<c:rAngAx val="' << @
|
|
91
|
+
str << '<c:rotX val="' << @rot_x.to_s << '"/>' unless @rot_x.nil?
|
|
92
|
+
str << '<c:hPercent val="' << @h_percent.to_s << '"/>' unless @h_percent.nil?
|
|
93
|
+
str << '<c:rotY val="' << @rot_y.to_s << '"/>' unless @rot_y.nil?
|
|
94
|
+
str << '<c:depthPercent val="' << @depth_percent.to_s << '"/>' unless @depth_percent.nil?
|
|
95
|
+
str << '<c:rAngAx val="' << @r_ang_ax.to_s << '"/>' unless @r_ang_ax.nil?
|
|
83
96
|
str << '<c:perspective val="' << @perspective.to_s << '"/>' unless @perspective.nil?
|
|
84
97
|
str << '</c:view3D>'
|
|
85
98
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
|
|
3
|
+
# a vml drawing used for comments in excel.
|
|
4
|
+
class VmlDrawing
|
|
5
|
+
|
|
6
|
+
# creates a new Vml Drawing object.
|
|
7
|
+
# @param [Comments] comments the comments object this drawing is associated with
|
|
8
|
+
def initialize(comments)
|
|
9
|
+
raise ArgumentError, "you must provide a comments object" unless comments.is_a?(Comments)
|
|
10
|
+
@comments = comments
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# The part name for this vml drawing
|
|
14
|
+
# @return [String]
|
|
15
|
+
def pn
|
|
16
|
+
"#{VML_DRAWING_PN}" % (@comments.worksheet.index + 1)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# serialize the vml_drawing to xml.
|
|
20
|
+
# @param [String] str
|
|
21
|
+
# @return [String]
|
|
22
|
+
def to_xml_string(str = '')
|
|
23
|
+
str = <<BAD_PROGRAMMER
|
|
24
|
+
<xml xmlns:v="urn:schemas-microsoft-com:vml"
|
|
25
|
+
xmlns:o="urn:schemas-microsoft-com:office:office"
|
|
26
|
+
xmlns:x="urn:schemas-microsoft-com:office:excel">
|
|
27
|
+
<o:shapelayout v:ext="edit">
|
|
28
|
+
<o:idmap v:ext="edit" data="#{@comments.worksheet.index+1}"/>
|
|
29
|
+
</o:shapelayout>
|
|
30
|
+
<v:shapetype id="_x0000_t202" coordsize="21600,21600" o:spt="202"
|
|
31
|
+
path="m0,0l0,21600,21600,21600,21600,0xe">
|
|
32
|
+
<v:stroke joinstyle="miter"/>
|
|
33
|
+
<v:path gradientshapeok="t" o:connecttype="rect"/>
|
|
34
|
+
</v:shapetype>
|
|
35
|
+
BAD_PROGRAMMER
|
|
36
|
+
@comments.each { |comment| comment.vml_shape.to_xml_string str }
|
|
37
|
+
str << "</xml>"
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
|
|
3
|
+
# A VmlShape is used to position and render a comment.
|
|
4
|
+
class VmlShape
|
|
5
|
+
|
|
6
|
+
# The row anchor position for this shape determined by the comment's ref value
|
|
7
|
+
# @return [Integer]
|
|
8
|
+
attr_reader :row
|
|
9
|
+
|
|
10
|
+
# The column anchor position for this shape determined by the comment's ref value
|
|
11
|
+
# @return [Integer]
|
|
12
|
+
attr_reader :column
|
|
13
|
+
|
|
14
|
+
# The left column for this shape
|
|
15
|
+
# @return [Integer]
|
|
16
|
+
attr_reader :left_column
|
|
17
|
+
|
|
18
|
+
# The left offset for this shape
|
|
19
|
+
# @return [Integer]
|
|
20
|
+
attr_reader :left_offset
|
|
21
|
+
|
|
22
|
+
# The top row for this shape
|
|
23
|
+
# @return [Integer]
|
|
24
|
+
attr_reader :top_row
|
|
25
|
+
|
|
26
|
+
# The top offset for this shape
|
|
27
|
+
# @return [Integer]
|
|
28
|
+
attr_reader :top_offset
|
|
29
|
+
|
|
30
|
+
# The right column for this shape
|
|
31
|
+
# @return [Integer]
|
|
32
|
+
attr_reader :right_column
|
|
33
|
+
|
|
34
|
+
# The right offset for this shape
|
|
35
|
+
# @return [Integer]
|
|
36
|
+
attr_reader :right_offset
|
|
37
|
+
|
|
38
|
+
# The botttom row for this shape
|
|
39
|
+
# @return [Integer]
|
|
40
|
+
attr_reader :bottom_row
|
|
41
|
+
|
|
42
|
+
# The bottom offset for this shape
|
|
43
|
+
# @return [Integer]
|
|
44
|
+
attr_reader :bottom_offset
|
|
45
|
+
|
|
46
|
+
# Creates a new VmlShape
|
|
47
|
+
# @option options [Integer|String] left_column
|
|
48
|
+
# @option options [Integer|String] left_offset
|
|
49
|
+
# @option options [Integer|String] top_row
|
|
50
|
+
# @option options [Integer|String] top_offset
|
|
51
|
+
# @option options [Integer|String] right_column
|
|
52
|
+
# @option options [Integer|String] right_offset
|
|
53
|
+
# @option options [Integer|String] bottom_row
|
|
54
|
+
# @option options [Integer|String] bottom_offset
|
|
55
|
+
def initialize(options={})
|
|
56
|
+
@row = @column = @left_column = @top_row = @right_column = @bottom_row = 0
|
|
57
|
+
@left_offset = 15
|
|
58
|
+
@top_offset = 2
|
|
59
|
+
@right_offset = 50
|
|
60
|
+
@bottom_offset = 5
|
|
61
|
+
@id = (0...8).map{65.+(rand(25)).chr}.join
|
|
62
|
+
options.each do |o|
|
|
63
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
64
|
+
end
|
|
65
|
+
yield self if block_given?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @see column
|
|
69
|
+
def column=(v); Axlsx::validate_integerish(v); @column = v.to_i end
|
|
70
|
+
|
|
71
|
+
# @see row
|
|
72
|
+
def row=(v); Axlsx::validate_integerish(v); @row = v.to_i end
|
|
73
|
+
# @see left_column
|
|
74
|
+
def left_column=(v); Axlsx::validate_integerish(v); @left_column = v.to_i end
|
|
75
|
+
|
|
76
|
+
# @see left_offset
|
|
77
|
+
def left_offset=(v); Axlsx::validate_integerish(v); @left_offset = v.to_i end
|
|
78
|
+
|
|
79
|
+
# @see top_row
|
|
80
|
+
def top_row=(v); Axlsx::validate_integerish(v); @top_row = v.to_i end
|
|
81
|
+
|
|
82
|
+
# @see top_offset
|
|
83
|
+
def top_offset=(v); Axlsx::validate_integerish(v); @top_offset = v.to_i end
|
|
84
|
+
|
|
85
|
+
# @see right_column
|
|
86
|
+
def right_column=(v); Axlsx::validate_integerish(v); @right_column = v.to_i end
|
|
87
|
+
|
|
88
|
+
# @see right_offset
|
|
89
|
+
def right_offset=(v); Axlsx::validate_integerish(v); @right_offset = v.to_i end
|
|
90
|
+
|
|
91
|
+
# @see bottom_row
|
|
92
|
+
def bottom_row=(v); Axlsx::validate_integerish(v); @bottom_row = v.to_i end
|
|
93
|
+
|
|
94
|
+
# @see bottom_offset
|
|
95
|
+
def bottom_offset=(v); Axlsx::validate_integerish(v); @bottom_offset = v.to_i end
|
|
96
|
+
|
|
97
|
+
# serialize the shape to a string
|
|
98
|
+
# @param [String] str
|
|
99
|
+
# @return [String]
|
|
100
|
+
def to_xml_string(str ='')
|
|
101
|
+
str << <<SHAME_ON_YOU
|
|
102
|
+
|
|
103
|
+
<v:shape id="#{@id}" type="#_x0000_t202" fillcolor="#ffffa1 [80]" o:insetmode="auto">
|
|
104
|
+
<v:fill color2="#ffffa1 [80]"/>
|
|
105
|
+
<v:shadow on="t" obscured="t"/>
|
|
106
|
+
<v:path o:connecttype="none"/>
|
|
107
|
+
<v:textbox style='mso-fit-text-with-word-wrap:t'>
|
|
108
|
+
<div style='text-align:left'></div>
|
|
109
|
+
</v:textbox>
|
|
110
|
+
|
|
111
|
+
<x:ClientData ObjectType="Note">
|
|
112
|
+
<x:MoveWithCells/>
|
|
113
|
+
<x:SizeWithCells/>
|
|
114
|
+
<x:Anchor>#{left_column}, #{left_offset}, #{top_row}, #{top_offset}, #{right_column}, #{right_offset}, #{bottom_row}, #{bottom_offset}</x:Anchor>
|
|
115
|
+
<x:AutoFill>False</x:AutoFill>
|
|
116
|
+
<x:Row>#{row}</x:Row>
|
|
117
|
+
<x:Column>#{column}</x:Column>
|
|
118
|
+
<x:Visible/>
|
|
119
|
+
</x:ClientData>
|
|
120
|
+
</v:shape>
|
|
121
|
+
SHAME_ON_YOU
|
|
122
|
+
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
data/lib/axlsx/package.rb
CHANGED
|
@@ -80,9 +80,8 @@ module Axlsx
|
|
|
80
80
|
|
|
81
81
|
# Serialize your workbook to disk as an xlsx document.
|
|
82
82
|
#
|
|
83
|
-
# @param [
|
|
83
|
+
# @param [String] output The name of the file you want to serialize your package to
|
|
84
84
|
# @param [Boolean] confirm_valid Validate the package prior to serialization.
|
|
85
|
-
# @option options stream indicates if we should be writing to a stream or a file. True for stream, nil for file
|
|
86
85
|
# @return [Boolean] False if confirm_valid and validation errors exist. True if the package was serialized
|
|
87
86
|
# @note A tremendous amount of effort has gone into ensuring that you cannot create invalid xlsx documents.
|
|
88
87
|
# confirm_valid should be used in the rare case that you cannot open the serialized file.
|
|
@@ -90,10 +89,15 @@ module Axlsx
|
|
|
90
89
|
# @example
|
|
91
90
|
# # This is how easy it is to create a valid xlsx file. Of course you might want to add a sheet or two, and maybe some data, styles and charts.
|
|
92
91
|
# # Take a look at the README for an example of how to do it!
|
|
93
|
-
# f = File.open('test.xlsx', 'w')
|
|
94
|
-
# Package.new.serialize(f)
|
|
95
92
|
#
|
|
96
|
-
# #
|
|
93
|
+
# #serialize to a file
|
|
94
|
+
# p = Axlsx::Package.new
|
|
95
|
+
# # ......add cool stuff to your workbook......
|
|
96
|
+
# p.serialize("example.xlsx")
|
|
97
|
+
#
|
|
98
|
+
# # Serialize to a stream
|
|
99
|
+
# s = p.to_stream()
|
|
100
|
+
# File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) }
|
|
97
101
|
def serialize(output, confirm_valid=false)
|
|
98
102
|
return false unless !confirm_valid || self.validate.empty?
|
|
99
103
|
Zip::ZipOutputStream.open(output) do |zip|
|
|
@@ -152,18 +156,18 @@ module Axlsx
|
|
|
152
156
|
# @return [Zip::ZipOutputStream]
|
|
153
157
|
def write_parts(zip)
|
|
154
158
|
p = parts
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
end
|
|
159
|
+
p.each do |part|
|
|
160
|
+
unless part[:doc].nil?
|
|
161
|
+
zip.put_next_entry(part[:entry])
|
|
162
|
+
entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc]
|
|
163
|
+
zip.puts(entry)
|
|
164
|
+
end
|
|
165
|
+
unless part[:path].nil?
|
|
166
|
+
zip.put_next_entry(part[:entry]);
|
|
167
|
+
# binread for 1.9.3
|
|
168
|
+
zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path])
|
|
166
169
|
end
|
|
170
|
+
end
|
|
167
171
|
zip
|
|
168
172
|
end
|
|
169
173
|
|
|
@@ -180,15 +184,24 @@ module Axlsx
|
|
|
180
184
|
{:entry => CONTENT_TYPES_PN, :doc => content_types.to_xml_string, :schema => CONTENT_TYPES_XSD},
|
|
181
185
|
{:entry => WORKBOOK_PN, :doc => workbook.to_xml_string, :schema => SML_XSD}
|
|
182
186
|
]
|
|
187
|
+
|
|
183
188
|
workbook.drawings.each do |drawing|
|
|
184
189
|
@parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml_string, :schema => RELS_XSD}
|
|
185
190
|
@parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml_string, :schema => DRAWING_XSD}
|
|
186
191
|
end
|
|
187
192
|
|
|
193
|
+
|
|
188
194
|
workbook.tables.each do |table|
|
|
189
195
|
@parts << {:entry => "xl/#{table.pn}", :doc => table.to_xml_string, :schema => SML_XSD}
|
|
190
196
|
end
|
|
191
197
|
|
|
198
|
+
workbook.comments.each do|comment|
|
|
199
|
+
if comment.size > 0
|
|
200
|
+
@parts << { :entry => "xl/#{comment.pn}", :doc => comment.to_xml_string, :schema => SML_XSD }
|
|
201
|
+
@parts << { :entry => "xl/#{comment.vml_drawing.pn}", :doc => comment.vml_drawing.to_xml_string, :schema => nil }
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
192
205
|
workbook.charts.each do |chart|
|
|
193
206
|
@parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml_string, :schema => DRAWING_XSD}
|
|
194
207
|
end
|
|
@@ -229,18 +242,33 @@ module Axlsx
|
|
|
229
242
|
# @private
|
|
230
243
|
def content_types
|
|
231
244
|
c_types = base_content_types
|
|
245
|
+
|
|
232
246
|
workbook.drawings.each do |drawing|
|
|
233
247
|
c_types << Axlsx::Override.new(:PartName => "/xl/#{drawing.pn}",
|
|
234
248
|
:ContentType => DRAWING_CT)
|
|
235
249
|
end
|
|
250
|
+
|
|
236
251
|
workbook.charts.each do |chart|
|
|
237
252
|
c_types << Axlsx::Override.new(:PartName => "/xl/#{chart.pn}",
|
|
238
253
|
:ContentType => CHART_CT)
|
|
239
254
|
end
|
|
255
|
+
|
|
240
256
|
workbook.tables.each do |table|
|
|
241
257
|
c_types << Axlsx::Override.new(:PartName => "/xl/#{table.pn}",
|
|
242
258
|
:ContentType => TABLE_CT)
|
|
243
259
|
end
|
|
260
|
+
|
|
261
|
+
workbook.comments.each do |comment|
|
|
262
|
+
if comment.size > 0
|
|
263
|
+
c_types << Axlsx::Override.new(:PartName => "/xl/#{comment.pn}",
|
|
264
|
+
:ContentType => COMMENT_CT)
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
if workbook.comments.size > 0
|
|
269
|
+
c_types << Axlsx::Default.new(:Extension => "vml", :ContentType => VML_DRAWING_CT)
|
|
270
|
+
end
|
|
271
|
+
|
|
244
272
|
workbook.worksheets.each do |sheet|
|
|
245
273
|
c_types << Axlsx::Override.new(:PartName => "/xl/#{sheet.pn}",
|
|
246
274
|
:ContentType => WORKSHEET_CT)
|
|
@@ -30,9 +30,9 @@ module Axlsx
|
|
|
30
30
|
attr_reader :TargetMode
|
|
31
31
|
|
|
32
32
|
# creates a new relationship
|
|
33
|
-
# @param [String]
|
|
34
|
-
# @param [String]
|
|
35
|
-
# @option [Symbol] target_mode only accepts :external.
|
|
33
|
+
# @param [String] type The type of the relationship
|
|
34
|
+
# @param [String] target The target for the relationship
|
|
35
|
+
# @option [Symbol] :target_mode only accepts :external.
|
|
36
36
|
def initialize(type, target, options={})
|
|
37
37
|
self.Target=target
|
|
38
38
|
self.Type=type
|
|
@@ -10,23 +10,13 @@ require 'axlsx/rels/relationship.rb'
|
|
|
10
10
|
def initialize
|
|
11
11
|
super Relationship
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
def to_xml_string(str = '')
|
|
15
15
|
str << '<?xml version="1.0" encoding="UTF-8"?>'
|
|
16
16
|
str << '<Relationships xmlns="' << RELS_R << '">'
|
|
17
17
|
each_with_index { |rel, index| rel.to_xml_string(index+1, str) }
|
|
18
18
|
str << '</Relationships>'
|
|
19
19
|
end
|
|
20
|
-
# Serializes the relationships document.
|
|
21
|
-
# @return [String]
|
|
22
|
-
def to_xml()
|
|
23
|
-
builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
|
|
24
|
-
xml.Relationships(:xmlns => Axlsx::RELS_R) {
|
|
25
|
-
each_with_index { |rel, index| rel.to_xml(xml, "rId#{index+1}") }
|
|
26
|
-
}
|
|
27
|
-
end
|
|
28
|
-
builder.to_xml(:save_with => 0)
|
|
29
|
-
end
|
|
30
20
|
|
|
31
21
|
end
|
|
32
22
|
end
|
|
@@ -68,7 +68,7 @@ module Axlsx
|
|
|
68
68
|
# @param [String] str
|
|
69
69
|
# @return [String]
|
|
70
70
|
def to_xml_string(str = '')
|
|
71
|
-
str << '<gradientFill'
|
|
71
|
+
str << '<gradientFill '
|
|
72
72
|
h = self.instance_values.reject { |k,v| k.to_sym == :stop }
|
|
73
73
|
str << h.map { |key, value| '' << key.to_s << '="' << value.to_s << '"' }.join(' ')
|
|
74
74
|
str << '>'
|
|
@@ -133,7 +133,7 @@ module Axlsx
|
|
|
133
133
|
# @option options [Integer] family The font family to use.
|
|
134
134
|
# @option options [String] font_name The name of the font to use
|
|
135
135
|
# @option options [Integer] num_fmt The number format to apply
|
|
136
|
-
# @option options [String] format_code The formatting to apply.
|
|
136
|
+
# @option options [String] format_code The formatting to apply.
|
|
137
137
|
# @option options [Integer|Hash] border The border style to use.
|
|
138
138
|
# @option options [String] bg_color The background color to apply to the cell
|
|
139
139
|
# @option options [Boolean] hidden Indicates if the cell should be hidden
|
|
@@ -40,10 +40,10 @@ module Axlsx
|
|
|
40
40
|
# @param [String] str
|
|
41
41
|
# @return [String]
|
|
42
42
|
def to_xml_string(str = '')
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
attrs = instance_values.reject { |k, v| ![:name, :pivot, :table].include?(k) }
|
|
44
|
+
attrs[:count] = self.size
|
|
45
45
|
str << '<tableStyle '
|
|
46
|
-
str <<
|
|
46
|
+
str << attrs.map { |key, value| '' << key.to_s << '="' << value.to_s << '"' }.join(' ')
|
|
47
47
|
str << '>'
|
|
48
48
|
each { |table_style_el| table_style_el.to_xml_string(str) }
|
|
49
49
|
str << '</tableStyle>'
|