axlsx 1.0.17 → 1.0.18
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/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
|