axlsx 1.0.17 → 1.0.18
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +70 -37
- data/examples/example.rb +163 -150
- data/lib/axlsx.rb +2 -2
- data/lib/axlsx/content_type/content_type.rb +3 -3
- data/lib/axlsx/drawing/chart.rb +3 -3
- data/lib/axlsx/drawing/pic.rb +1 -0
- data/lib/axlsx/package.rb +29 -29
- data/lib/axlsx/rels/relationship.rb +3 -3
- data/lib/axlsx/stylesheet/font.rb +7 -0
- data/lib/axlsx/stylesheet/styles.rb +6 -3
- data/lib/axlsx/util/constants.rb +16 -14
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/workbook.rb +24 -24
- data/lib/axlsx/workbook/worksheet/cell.rb +68 -53
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +29 -0
- data/lib/axlsx/workbook/worksheet/page_margins.rb +94 -0
- data/lib/axlsx/workbook/worksheet/row.rb +31 -14
- data/lib/axlsx/workbook/worksheet/worksheet.rb +127 -45
- data/test/drawing/tc_chart.rb +2 -2
- data/test/stylesheet/tc_cell_alignment.rb +8 -3
- data/test/stylesheet/tc_font.rb +8 -0
- data/test/stylesheet/tc_styles.rb +6 -2
- data/test/workbook/worksheet/tc_cell.rb +39 -9
- data/test/workbook/worksheet/tc_date_time_converter.rb +127 -0
- data/test/workbook/worksheet/tc_date_time_converter.rb~ +69 -0
- data/test/workbook/worksheet/tc_page_margins.rb +100 -0
- data/test/workbook/worksheet/tc_row.rb +36 -0
- data/test/workbook/worksheet/tc_worksheet.rb +78 -1
- metadata +87 -119
data/lib/axlsx.rb
CHANGED
@@ -56,8 +56,8 @@ module Axlsx
|
|
56
56
|
|
57
57
|
def self.name_to_indices(name)
|
58
58
|
raise ArgumentError, 'invalid cell name' unless name.size > 1
|
59
|
-
v = name[/[A-Z]+/].reverse.chars.reduce({:base=>1, :i=>0}) do |
|
60
|
-
|
59
|
+
v = name[/[A-Z]+/].reverse.chars.reduce({:base=>1, :i=>0}) do |val, c|
|
60
|
+
val[:i] += ((c.bytes.first - 65) + val[:base]); val[:base] *= 26; val
|
61
61
|
end
|
62
62
|
|
63
63
|
[v[:i]-1, ((name[/[1-9]+/]).to_i)-1]
|
@@ -3,13 +3,13 @@ module Axlsx
|
|
3
3
|
require 'axlsx/content_type/default.rb'
|
4
4
|
require 'axlsx/content_type/override.rb'
|
5
5
|
|
6
|
-
# ContentTypes used in the package. This is
|
6
|
+
# ContentTypes used in the package. This is automatically managed by the package package.
|
7
7
|
class ContentType < SimpleTypedList
|
8
|
-
|
8
|
+
|
9
9
|
def initialize
|
10
10
|
super [Override, Default]
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
# Generates the xml document for [Content_Types].xml
|
14
14
|
# @return [String] The document as a string.
|
15
15
|
def to_xml()
|
data/lib/axlsx/drawing/chart.rb
CHANGED
@@ -52,8 +52,8 @@ module Axlsx
|
|
52
52
|
options.each do |o|
|
53
53
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
54
54
|
end
|
55
|
-
start_at
|
56
|
-
end_at
|
55
|
+
start_at(*options[:start_at]) if options[:start_at]
|
56
|
+
end_at(*options[:end_at]) if options[:start_at]
|
57
57
|
yield self if block_given?
|
58
58
|
end
|
59
59
|
|
@@ -137,7 +137,7 @@ module Axlsx
|
|
137
137
|
xml.layout
|
138
138
|
xml.overlay :val => 0
|
139
139
|
}
|
140
|
-
|
140
|
+
end
|
141
141
|
xml.plotVisOnly :val => 1
|
142
142
|
xml.dispBlanksAs :val => :zero
|
143
143
|
xml.showDLblsOverMax :val => 1
|
data/lib/axlsx/drawing/pic.rb
CHANGED
@@ -39,6 +39,7 @@ module Axlsx
|
|
39
39
|
# @option options [Intger] height
|
40
40
|
def initialize(anchor, options={})
|
41
41
|
@anchor = anchor
|
42
|
+
@hyperlink = nil
|
42
43
|
@anchor.drawing.worksheet.workbook.images << self
|
43
44
|
options.each do |o|
|
44
45
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
data/lib/axlsx/package.rb
CHANGED
@@ -4,7 +4,7 @@ module Axlsx
|
|
4
4
|
# xlsx document including valdation and serialization.
|
5
5
|
class Package
|
6
6
|
|
7
|
-
|
7
|
+
|
8
8
|
# provides access to the app doc properties for this package
|
9
9
|
# see App
|
10
10
|
attr_reader :app
|
@@ -31,8 +31,8 @@ module Axlsx
|
|
31
31
|
|
32
32
|
# Shortcut to specify that the workbook should use shared strings
|
33
33
|
# @see Workbook#use_shared_strings
|
34
|
-
def use_shared_strings=(v)
|
35
|
-
Axlsx::validate_boolean(v);
|
34
|
+
def use_shared_strings=(v)
|
35
|
+
Axlsx::validate_boolean(v);
|
36
36
|
workbook.use_shared_strings = v
|
37
37
|
end
|
38
38
|
|
@@ -45,7 +45,7 @@ module Axlsx
|
|
45
45
|
# The workbook this package will serialize or validate.
|
46
46
|
# @return [Workbook] If no workbook instance has been assigned with this package a new Workbook instance is returned.
|
47
47
|
# @raise ArgumentError if workbook parameter is not a Workbook instance.
|
48
|
-
# @note As there are multiple ways to instantiate a workbook for the package,
|
48
|
+
# @note As there are multiple ways to instantiate a workbook for the package,
|
49
49
|
# here are a few examples:
|
50
50
|
# # assign directly during package instanciation
|
51
51
|
# wb = Package.new(:workbook => Workbook.new).workbook
|
@@ -59,13 +59,13 @@ module Axlsx
|
|
59
59
|
yield @workbook if block_given?
|
60
60
|
@workbook
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
#def self.parse(input, confirm_valid = false)
|
64
64
|
# p = Package.new
|
65
65
|
# z = Zip::ZipFile.open(input)
|
66
66
|
# p.workbook = Workbook.parse z.get_entry(WORKBOOK_PN)
|
67
67
|
# p
|
68
|
-
#end
|
68
|
+
#end
|
69
69
|
|
70
70
|
# @see workbook
|
71
71
|
def workbook=(workbook) DataTypeValidator.validate "Package.workbook", Workbook, workbook; @workbook = workbook; end
|
@@ -77,7 +77,7 @@ module Axlsx
|
|
77
77
|
# @option options stream indicates if we should be writing to a stream or a file. True for stream, nil for file
|
78
78
|
# @return [Boolean] False if confirm_valid and validation errors exist. True if the package was serialized
|
79
79
|
# @note A tremendous amount of effort has gone into ensuring that you cannot create invalid xlsx documents.
|
80
|
-
# confirm_valid should be used in the rare case that you cannot open the serialized file.
|
80
|
+
# confirm_valid should be used in the rare case that you cannot open the serialized file.
|
81
81
|
# @see Package#validate
|
82
82
|
# @example
|
83
83
|
# # 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.
|
@@ -105,20 +105,20 @@ module Axlsx
|
|
105
105
|
stream.rewind
|
106
106
|
stream
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
# Encrypt the package into a CFB using the password provided
|
110
110
|
# This is not ready yet
|
111
|
-
def encrypt(file_name, password)
|
111
|
+
def encrypt(file_name, password)
|
112
112
|
return false
|
113
|
-
moc = MsOffCrypto.new(file_name, password)
|
114
|
-
moc.save
|
113
|
+
# moc = MsOffCrypto.new(file_name, password)
|
114
|
+
# moc.save
|
115
115
|
end
|
116
|
-
|
117
|
-
# Validate all parts of the package against xsd schema.
|
116
|
+
|
117
|
+
# Validate all parts of the package against xsd schema.
|
118
118
|
# @return [Array] An array of all validation errors found.
|
119
119
|
# @note This gem includes all schema from OfficeOpenXML-XMLSchema-Transitional.zip and OpenPackagingConventions-XMLSchema.zip
|
120
120
|
# as per ECMA-376, Third edition. opc schema require an internet connection to import remote schema from dublin core for dc,
|
121
|
-
# dcterms and xml namespaces. Those remote schema are included in this gem, and the original files have been altered to
|
121
|
+
# dcterms and xml namespaces. Those remote schema are included in this gem, and the original files have been altered to
|
122
122
|
# refer to the local versions.
|
123
123
|
#
|
124
124
|
# If by chance you are able to creat a package that does not validate it indicates that the internal
|
@@ -135,30 +135,30 @@ module Axlsx
|
|
135
135
|
errors
|
136
136
|
end
|
137
137
|
|
138
|
-
private
|
138
|
+
private
|
139
139
|
|
140
140
|
# Writes the package parts to a zip archive.
|
141
141
|
# @param [Zip::ZipOutputStream] zip
|
142
142
|
# @return [Zip::ZipOutputStream]
|
143
143
|
def write_parts(zip)
|
144
144
|
p = parts
|
145
|
-
p.each do |part|
|
145
|
+
p.each do |part|
|
146
146
|
unless part[:doc].nil?
|
147
147
|
zip.put_next_entry(part[:entry]);
|
148
148
|
entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc]
|
149
149
|
zip.puts(entry)
|
150
150
|
end
|
151
151
|
unless part[:path].nil?
|
152
|
-
zip.put_next_entry(part[:entry]);
|
152
|
+
zip.put_next_entry(part[:entry]);
|
153
153
|
# binread for 1.9.3
|
154
154
|
zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path])
|
155
|
-
end
|
155
|
+
end
|
156
156
|
end
|
157
157
|
zip
|
158
158
|
end
|
159
159
|
|
160
160
|
# The parts of a package
|
161
|
-
# @return [Array] An array of hashes that define the entry, document and schema for each part of the package.
|
161
|
+
# @return [Array] An array of hashes that define the entry, document and schema for each part of the package.
|
162
162
|
# @private
|
163
163
|
def parts
|
164
164
|
@parts = [
|
@@ -174,10 +174,10 @@ module Axlsx
|
|
174
174
|
@parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml, :schema => RELS_XSD}
|
175
175
|
@parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml, :schema => DRAWING_XSD}
|
176
176
|
end
|
177
|
-
|
178
|
-
workbook.charts.each do |chart|
|
177
|
+
|
178
|
+
workbook.charts.each do |chart|
|
179
179
|
@parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml, :schema => DRAWING_XSD}
|
180
|
-
end
|
180
|
+
end
|
181
181
|
|
182
182
|
workbook.images.each do |image|
|
183
183
|
@parts << {:entry => "xl/#{image.pn}", :path => image.image_src}
|
@@ -187,9 +187,9 @@ module Axlsx
|
|
187
187
|
@parts << {:entry => "xl/#{SHARED_STRINGS_PN}", :doc => workbook.shared_strings.to_xml, :schema => SML_XSD}
|
188
188
|
end
|
189
189
|
|
190
|
-
workbook.worksheets.each do |sheet|
|
190
|
+
workbook.worksheets.each do |sheet|
|
191
191
|
@parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships.to_xml, :schema => RELS_XSD}
|
192
|
-
@parts << {:entry => "xl/#{sheet.pn}", :doc => sheet.to_xml, :schema => SML_XSD}
|
192
|
+
@parts << {:entry => "xl/#{sheet.pn}", :doc => sheet.to_xml, :schema => SML_XSD}
|
193
193
|
end
|
194
194
|
@parts
|
195
195
|
end
|
@@ -217,15 +217,15 @@ module Axlsx
|
|
217
217
|
def content_types
|
218
218
|
c_types = base_content_types
|
219
219
|
workbook.drawings.each do |drawing|
|
220
|
-
c_types << Axlsx::Override.new(:PartName => "/xl/#{drawing.pn}",
|
220
|
+
c_types << Axlsx::Override.new(:PartName => "/xl/#{drawing.pn}",
|
221
221
|
:ContentType => DRAWING_CT)
|
222
222
|
end
|
223
223
|
workbook.charts.each do |chart|
|
224
|
-
c_types << Axlsx::Override.new(:PartName => "/xl/#{chart.pn}",
|
225
|
-
:ContentType => CHART_CT)
|
224
|
+
c_types << Axlsx::Override.new(:PartName => "/xl/#{chart.pn}",
|
225
|
+
:ContentType => CHART_CT)
|
226
226
|
end
|
227
227
|
workbook.worksheets.each do |sheet|
|
228
|
-
c_types << Axlsx::Override.new(:PartName => "/xl/#{sheet.pn}",
|
228
|
+
c_types << Axlsx::Override.new(:PartName => "/xl/#{sheet.pn}",
|
229
229
|
:ContentType => WORKSHEET_CT)
|
230
230
|
end
|
231
231
|
exts = workbook.images.map { |image| image.extname }
|
@@ -256,7 +256,7 @@ module Axlsx
|
|
256
256
|
c_types << Override.new(:PartName => "/#{APP_PN}", :ContentType => APP_CT)
|
257
257
|
c_types << Override.new(:PartName => "/#{CORE_PN}", :ContentType => CORE_CT)
|
258
258
|
c_types << Override.new(:PartName => "/xl/#{STYLES_PN}", :ContentType => STYLES_CT)
|
259
|
-
c_types << Axlsx::Override.new(:PartName => "/#{WORKBOOK_PN}", :ContentType => WORKBOOK_CT)
|
259
|
+
c_types << Axlsx::Override.new(:PartName => "/#{WORKBOOK_PN}", :ContentType => WORKBOOK_CT)
|
260
260
|
c_types.lock
|
261
261
|
c_types
|
262
262
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
module Axlsx
|
3
3
|
# A relationship defines a reference between package parts.
|
4
|
-
# @note Packages
|
4
|
+
# @note Packages automatically manage relationships.
|
5
5
|
class Relationship
|
6
6
|
|
7
7
|
# The location of the relationship target
|
@@ -32,7 +32,7 @@ module Axlsx
|
|
32
32
|
# creates a new relationship
|
33
33
|
# @param [String] Type The type of the relationship
|
34
34
|
# @param [String] Target The target for the relationship
|
35
|
-
# @option [Symbol] target_mode only accepts :external.
|
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
|
@@ -47,7 +47,7 @@ module Axlsx
|
|
47
47
|
# @see TargetMode
|
48
48
|
def TargetMode=(v) RestrictionValidator.validate 'Relationship.TargetMode', [:External, :Internal], v; @TargetMode = v; end
|
49
49
|
|
50
|
-
# Serializes the relationship
|
50
|
+
# Serializes the relationship
|
51
51
|
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
52
52
|
# @param [String] rId the reference id of the object.
|
53
53
|
# @return [String]
|
@@ -54,6 +54,10 @@ module Axlsx
|
|
54
54
|
# @return [Boolean]
|
55
55
|
attr_reader :i
|
56
56
|
|
57
|
+
# Indicates if the font should be rendered underlined
|
58
|
+
# @return [Boolean]
|
59
|
+
attr_reader :u
|
60
|
+
|
57
61
|
# Indicates if the font should be rendered with a strikthrough
|
58
62
|
# @return [Boolean]
|
59
63
|
attr_reader :strike
|
@@ -89,6 +93,7 @@ module Axlsx
|
|
89
93
|
# @option options [Integer] family
|
90
94
|
# @option options [Boolean] b
|
91
95
|
# @option options [Boolean] i
|
96
|
+
# @option options [Boolean] u
|
92
97
|
# @option options [Boolean] strike
|
93
98
|
# @option options [Boolean] outline
|
94
99
|
# @option options [Boolean] shadow
|
@@ -111,6 +116,8 @@ module Axlsx
|
|
111
116
|
def b=(v) Axlsx::validate_boolean v; @b = v end
|
112
117
|
# @see i
|
113
118
|
def i=(v) Axlsx::validate_boolean v; @i = v end
|
119
|
+
# @see u
|
120
|
+
def u=(v) Axlsx::validate_boolean v; @u = v end
|
114
121
|
# @see strike
|
115
122
|
def strike=(v) Axlsx::validate_boolean v; @strike = v end
|
116
123
|
# @see outline
|
@@ -125,11 +125,12 @@ module Axlsx
|
|
125
125
|
# @option options [Integer] sz The text size
|
126
126
|
# @option options [Boolean] b Indicates if the text should be bold
|
127
127
|
# @option options [Boolean] i Indicates if the text should be italicised
|
128
|
+
# @option options [Boolean] u Indicates if the text should be underlined
|
128
129
|
# @option options [Boolean] strike Indicates if the text should be rendered with a strikethrough
|
129
130
|
# @option options [Boolean] strike Indicates if the text should be rendered with a shadow
|
130
131
|
# @option options [Integer] charset The character set to use.
|
131
132
|
# @option options [Integer] family The font family to use.
|
132
|
-
# @option options [String]
|
133
|
+
# @option options [String] font_name The name of the font to use
|
133
134
|
# @option options [Integer] num_fmt The number format to apply
|
134
135
|
# @option options [String] format_code The formatting to apply. If this is specified, num_fmt is ignored.
|
135
136
|
# @option options [Integer] border The border style to use.
|
@@ -199,6 +200,7 @@ module Axlsx
|
|
199
200
|
end
|
200
201
|
|
201
202
|
borderId = options[:border] || 0
|
203
|
+
|
202
204
|
raise ArgumentError, "Invalid borderId" unless borderId < borders.size
|
203
205
|
|
204
206
|
fill = if options[:bg_color]
|
@@ -209,9 +211,9 @@ module Axlsx
|
|
209
211
|
0
|
210
212
|
end
|
211
213
|
|
212
|
-
fontId = if (options.values_at(:fg_color, :sz, :b, :i, :strike, :outline, :shadow, :charset, :family, :font_name).length)
|
214
|
+
fontId = if (options.values_at(:fg_color, :sz, :b, :i, :u, :strike, :outline, :shadow, :charset, :family, :font_name).length)
|
213
215
|
font = Font.new()
|
214
|
-
[:b, :i, :strike, :outline, :shadow, :charset, :family, :sz].each { |k| font.send("#{k}=", options[k]) unless options[k].nil? }
|
216
|
+
[:b, :i, :u, :strike, :outline, :shadow, :charset, :family, :sz].each { |k| font.send("#{k}=", options[k]) unless options[k].nil? }
|
215
217
|
font.color = Color.new(:rgb => options[:fg_color]) unless options[:fg_color].nil?
|
216
218
|
font.name = options[:font_name] unless options[:font_name].nil?
|
217
219
|
fonts << font
|
@@ -224,6 +226,7 @@ module Axlsx
|
|
224
226
|
xf = Xf.new(:fillId => fill, :fontId=>fontId, :applyFill=>1, :applyFont=>1, :numFmtId=>numFmtId, :borderId=>borderId, :applyProtection=>applyProtection)
|
225
227
|
|
226
228
|
xf.applyNumberFormat = true if xf.numFmtId > 0
|
229
|
+
xf.applyBorder = true if borderId > 0
|
227
230
|
|
228
231
|
if options[:alignment]
|
229
232
|
xf.alignment = CellAlignment.new(options[:alignment])
|
data/lib/axlsx/util/constants.rb
CHANGED
@@ -21,7 +21,7 @@ module Axlsx
|
|
21
21
|
|
22
22
|
# dc elements (core) namespace
|
23
23
|
CORE_NS_DC = "http://purl.org/dc/elements/1.1/"
|
24
|
-
|
24
|
+
|
25
25
|
# dcmit (core) namespcace
|
26
26
|
CORE_NS_DCMIT = "http://purl.org/dc/dcmitype/"
|
27
27
|
|
@@ -30,10 +30,10 @@ module Axlsx
|
|
30
30
|
|
31
31
|
# xml schema namespace
|
32
32
|
CORE_NS_XSI = "http://www.w3.org/2001/XMLSchema-instance"
|
33
|
-
|
33
|
+
|
34
34
|
# spreadsheet drawing namespace
|
35
35
|
XML_NS_XDR = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
|
36
|
-
|
36
|
+
|
37
37
|
# drawing namespace
|
38
38
|
XML_NS_A = "http://schemas.openxmlformats.org/drawingml/2006/main"
|
39
39
|
|
@@ -43,13 +43,12 @@ module Axlsx
|
|
43
43
|
# relationships namespace
|
44
44
|
XML_NS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
45
45
|
|
46
|
-
|
47
46
|
# relationships name space
|
48
47
|
RELS_R = "http://schemas.openxmlformats.org/package/2006/relationships"
|
49
48
|
|
50
49
|
# table rels namespace
|
51
50
|
TABLE_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"
|
52
|
-
|
51
|
+
|
53
52
|
# workbook rels namespace
|
54
53
|
WORKBOOK_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
|
55
54
|
|
@@ -80,7 +79,7 @@ module Axlsx
|
|
80
79
|
# image rels namespace
|
81
80
|
HYPERLINK_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
82
81
|
|
83
|
-
# table content type
|
82
|
+
# table content type
|
84
83
|
TABLE_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"
|
85
84
|
|
86
85
|
# workbook content type
|
@@ -90,14 +89,14 @@ module Axlsx
|
|
90
89
|
APP_CT = "application/vnd.openxmlformats-officedocument.extended-properties+xml"
|
91
90
|
|
92
91
|
# rels content type
|
93
|
-
RELS_CT = "application/vnd.openxmlformats-package.relationships+xml"
|
92
|
+
RELS_CT = "application/vnd.openxmlformats-package.relationships+xml"
|
94
93
|
|
95
94
|
# styles content type
|
96
95
|
STYLES_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"
|
97
96
|
|
98
97
|
# xml content type
|
99
98
|
XML_CT = "application/xml"
|
100
|
-
|
99
|
+
|
101
100
|
# worksheet content type
|
102
101
|
WORKSHEET_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"
|
103
102
|
|
@@ -127,7 +126,7 @@ module Axlsx
|
|
127
126
|
|
128
127
|
# jpeg extension
|
129
128
|
JPEG_EX = "jpeg"
|
130
|
-
|
129
|
+
|
131
130
|
# gif extension
|
132
131
|
GIF_EX = "gif"
|
133
132
|
|
@@ -145,10 +144,10 @@ module Axlsx
|
|
145
144
|
|
146
145
|
# shared_strings part
|
147
146
|
SHARED_STRINGS_PN = "sharedStrings.xml"
|
148
|
-
|
147
|
+
|
149
148
|
# app part
|
150
149
|
APP_PN = "docProps/app.xml"
|
151
|
-
|
150
|
+
|
152
151
|
# core part
|
153
152
|
CORE_PN = "docProps/core.xml"
|
154
153
|
|
@@ -196,12 +195,12 @@ module Axlsx
|
|
196
195
|
|
197
196
|
# spreadsheetML validation schema
|
198
197
|
SML_XSD = SCHEMA_BASE + "sml.xsd"
|
199
|
-
|
198
|
+
|
200
199
|
# drawing validation schema
|
201
200
|
DRAWING_XSD = SCHEMA_BASE + "dml-spreadsheetDrawing.xsd"
|
202
201
|
|
203
202
|
# number format id for pecentage formatting using the default formatting id.
|
204
|
-
NUM_FMT_PERCENT = 9
|
203
|
+
NUM_FMT_PERCENT = 9
|
205
204
|
|
206
205
|
# number format id for date format like 2011/11/13
|
207
206
|
NUM_FMT_YYYYMMDD = 100
|
@@ -216,7 +215,7 @@ module Axlsx
|
|
216
215
|
STYLE_DATE = 2
|
217
216
|
|
218
217
|
# error messages RestrictionValidor
|
219
|
-
ERR_RESTRICTION = "Invalid Data: %s. %s must be one of %s."
|
218
|
+
ERR_RESTRICTION = "Invalid Data: %s. %s must be one of %s."
|
220
219
|
|
221
220
|
# error message DataTypeValidator
|
222
221
|
ERR_TYPE = "Invalid Data %s for %s. must be %s."
|
@@ -224,6 +223,9 @@ module Axlsx
|
|
224
223
|
# error message for RegexValidator
|
225
224
|
ERR_REGEX = "Invalid Data. %s does not match %s."
|
226
225
|
|
226
|
+
# error message for sheets that use a name which is longer than 31 bytes
|
227
|
+
ERR_SHEET_NAME_TOO_LONG = "Your worksheet name '%s' is too long. Worksheet names must be 31 characters (bytes) or less"
|
228
|
+
|
227
229
|
# error message for duplicate sheet names
|
228
230
|
ERR_DUPLICATE_SHEET_NAME = "There is already a worksheet in this workbook named '%s'. Please use a unique name"
|
229
231
|
end
|
data/lib/axlsx/version.rb
CHANGED
@@ -5,6 +5,6 @@ module Axlsx
|
|
5
5
|
# When using bunle exec rake and referencing the gem on github or locally
|
6
6
|
# it will use the gemspec, which preloads this constant for the gem's version.
|
7
7
|
# We check to make sure that it has not already been loaded
|
8
|
-
VERSION="1.0.
|
8
|
+
VERSION="1.0.18" unless Axlsx.const_defined? :VERSION
|
9
9
|
|
10
10
|
end
|
@@ -1,14 +1,16 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
module Axlsx
|
2
|
+
module Axlsx
|
3
3
|
|
4
|
+
require 'axlsx/workbook/worksheet/date_time_converter.rb'
|
4
5
|
require 'axlsx/workbook/worksheet/cell.rb'
|
6
|
+
require 'axlsx/workbook/worksheet/page_margins.rb'
|
5
7
|
require 'axlsx/workbook/worksheet/row.rb'
|
6
8
|
require 'axlsx/workbook/worksheet/worksheet.rb'
|
7
9
|
require 'axlsx/workbook/shared_strings_table.rb'
|
8
10
|
|
9
11
|
# The Workbook class is an xlsx workbook that manages worksheets, charts, drawings and styles.
|
10
12
|
# The following parts of the Office Open XML spreadsheet specification are not implimented in this version.
|
11
|
-
#
|
13
|
+
#
|
12
14
|
# bookViews
|
13
15
|
# calcPr
|
14
16
|
# customWorkbookViews
|
@@ -38,13 +40,13 @@ require 'axlsx/workbook/shared_strings_table.rb'
|
|
38
40
|
attr_reader :use_shared_strings
|
39
41
|
|
40
42
|
# @see use_shared_strings
|
41
|
-
def use_shared_strings=(v)
|
43
|
+
def use_shared_strings=(v)
|
42
44
|
Axlsx::validate_boolean(v)
|
43
45
|
@use_shared_strings = v
|
44
46
|
end
|
45
47
|
|
46
48
|
|
47
|
-
# A collection of worksheets associated with this workbook.
|
49
|
+
# A collection of worksheets associated with this workbook.
|
48
50
|
# @note The recommended way to manage worksheets is add_worksheet
|
49
51
|
# @see Workbook#add_worksheet
|
50
52
|
# @see Worksheet
|
@@ -86,39 +88,31 @@ require 'axlsx/workbook/shared_strings_table.rb'
|
|
86
88
|
# Indicates if the epoc date for serialization should be 1904. If false, 1900 is used.
|
87
89
|
@@date1904 = false
|
88
90
|
|
89
|
-
# lets come back to this later when we are ready for parsing.
|
91
|
+
# lets come back to this later when we are ready for parsing.
|
90
92
|
#def self.parse entry
|
91
93
|
# io = entry.get_input_stream
|
92
94
|
# w = self.new
|
93
95
|
# w.parser_xml = Nokogiri::XML(io.read)
|
94
|
-
# w.parse_string :date1904, "//xmlns:workbookPr/@date1904"
|
96
|
+
# w.parse_string :date1904, "//xmlns:workbookPr/@date1904"
|
95
97
|
# w
|
96
98
|
#end
|
97
99
|
|
98
100
|
# Creates a new Workbook
|
99
101
|
# The recomended way to work with workbooks is via Package#workbook
|
100
|
-
# @option options [Boolean] date1904. If this is not specified,
|
102
|
+
# @option options [Boolean] date1904. If this is not specified, date1904 is set to false. Office 2011 for Mac defaults to false.
|
101
103
|
def initialize(options={})
|
102
104
|
@styles = Styles.new
|
103
105
|
@worksheets = SimpleTypedList.new Worksheet
|
104
106
|
@drawings = SimpleTypedList.new Drawing
|
105
107
|
@charts = SimpleTypedList.new Chart
|
106
108
|
@images = SimpleTypedList.new Pic
|
107
|
-
self.date1904= options[:date1904].nil?
|
108
|
-
yield self if block_given?
|
109
|
-
end
|
110
|
-
|
111
|
-
# Uses RUBY_PLATFORM constant to determine if the OS is freebsd or darwin
|
112
|
-
# based on this value we attempt to set date1904.
|
113
|
-
# @return [Boolean]
|
114
|
-
def is_bsd?
|
115
|
-
platform = RUBY_PLATFORM.downcase
|
116
|
-
platform.include?('freebsd') || platform.include?('darwin')
|
109
|
+
self.date1904= !options[:date1904].nil? && options[:date1904]
|
110
|
+
yield self if block_given?
|
117
111
|
end
|
118
112
|
|
119
113
|
# Instance level access to the class variable 1904
|
120
114
|
# @return [Boolean]
|
121
|
-
def date1904() @@date1904; end
|
115
|
+
def date1904() @@date1904; end
|
122
116
|
|
123
117
|
# see @date1904
|
124
118
|
def date1904=(v) Axlsx::validate_boolean v; @@date1904 = v; end
|
@@ -134,6 +128,7 @@ require 'axlsx/workbook/shared_strings_table.rb'
|
|
134
128
|
# Adds a worksheet to this workbook
|
135
129
|
# @return [Worksheet]
|
136
130
|
# @option options [String] name The name of the worksheet.
|
131
|
+
# @option options [Hash] page_margins The page margins for the worksheet.
|
137
132
|
# @see Worksheet#initialize
|
138
133
|
def add_worksheet(options={})
|
139
134
|
worksheet = Worksheet.new(self, options)
|
@@ -147,7 +142,7 @@ require 'axlsx/workbook/shared_strings_table.rb'
|
|
147
142
|
r = Relationships.new
|
148
143
|
@worksheets.each do |sheet|
|
149
144
|
r << Relationship.new(WORKSHEET_R, WORKSHEET_PN % (r.size+1))
|
150
|
-
end
|
145
|
+
end
|
151
146
|
r << Relationship.new(STYLES_R, STYLES_PN)
|
152
147
|
if use_shared_strings
|
153
148
|
r << Relationship.new(SHARED_STRINGS_R, SHARED_STRINGS_PN)
|
@@ -162,13 +157,13 @@ require 'axlsx/workbook/shared_strings_table.rb'
|
|
162
157
|
end
|
163
158
|
|
164
159
|
# returns a range of cells in a worksheet
|
165
|
-
# @param [String] cell_def The excel style reference defining the worksheet and cells. The range must specify the sheet to
|
160
|
+
# @param [String] cell_def The excel style reference defining the worksheet and cells. The range must specify the sheet to
|
166
161
|
# retrieve the cells from. e.g. range('Sheet1!A1:B2') will return an array of four cells [A1, A2, B1, B2] while range('Sheet1!A1') will return a single Cell.
|
167
162
|
# @return [Cell, Array]
|
168
163
|
def [](cell_def)
|
169
164
|
sheet_name = cell_def.split('!')[0] if cell_def.match('!')
|
170
165
|
worksheet = self.worksheets.select { |s| s.name == sheet_name }.first
|
171
|
-
raise ArgumentError, 'Unknown Sheet' unless sheet_name && worksheet.is_a?(Worksheet)
|
166
|
+
raise ArgumentError, 'Unknown Sheet' unless sheet_name && worksheet.is_a?(Worksheet)
|
172
167
|
worksheet[cell_def.gsub(/.+!/,"")]
|
173
168
|
end
|
174
169
|
|
@@ -176,17 +171,22 @@ require 'axlsx/workbook/shared_strings_table.rb'
|
|
176
171
|
# @return [String]
|
177
172
|
def to_xml()
|
178
173
|
add_worksheet unless worksheets.size > 0
|
179
|
-
builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
|
174
|
+
builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
|
180
175
|
xml.workbook(:xmlns => XML_NS, :'xmlns:r' => XML_NS_R) {
|
181
176
|
xml.workbookPr(:date1904=>@@date1904)
|
182
177
|
#<x:workbookProtection workbookPassword="xsd:hexBinary data" lockStructure="1" lockWindows="1" />
|
178
|
+
# Required to support rubyXL parsing as it requires sheetView, which requires this.
|
179
|
+
# and removed because it seems to cause some odd [Grouped] behaviour in excel.
|
180
|
+
# xml.bookViews {
|
181
|
+
# xml.workbookView :activeTab=>0
|
182
|
+
# }
|
183
183
|
xml.sheets {
|
184
|
-
@worksheets.each_with_index do |sheet, index|
|
184
|
+
@worksheets.each_with_index do |sheet, index|
|
185
185
|
xml.sheet(:name=>sheet.name, :sheetId=>index+1, :"r:id"=>sheet.rId)
|
186
186
|
end
|
187
187
|
}
|
188
188
|
}
|
189
|
-
end
|
189
|
+
end
|
190
190
|
builder.to_xml(:save_with => 0)
|
191
191
|
end
|
192
192
|
end
|