spreet 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +47 -1
- data/VERSION +1 -1
- data/lib/big_array.rb +100 -0
- data/lib/duration.rb +145 -0
- data/lib/spreet.rb +75 -103
- data/lib/spreet/coordinates.rb +62 -0
- data/lib/spreet/handlers/open_document.rb +310 -31
- data/lib/time.rb +13 -0
- data/test/helper.rb +15 -0
- data/test/samples/pascal.ods +0 -0
- data/test/test_big_array.rb +24 -0
- data/test/test_coordinates.rb +31 -0
- data/test/test_csv.rb +39 -0
- data/test/test_duration.rb +34 -0
- data/test/test_open_document.rb +17 -0
- data/test/test_spreet.rb +58 -36
- metadata +56 -9
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Spreet
|
3
|
+
|
4
|
+
# This class permit to manipulate coordinates in a table
|
5
|
+
class Coordinates
|
6
|
+
# Limit coordinates x and y in 0..65535 but coordinates are in one integer of 32 bits
|
7
|
+
X_BIT_SHIFT = 20 # ((RUBY_PLATFORM.match(/^[^\-]*[^\-0-9]64/) ? 64 : 32) / 2).freeze
|
8
|
+
# 2²⁰ rows = 1_048_576, 2¹² cols = 4_096,
|
9
|
+
Y_FILTER = ((1 << X_BIT_SHIFT) - 1).freeze
|
10
|
+
|
11
|
+
BASE_26_BEF = "0123456789abcdefghijklmnop"
|
12
|
+
BASE_26_AFT = "abcdefghijklmnopqrstuvwxyz"
|
13
|
+
|
14
|
+
attr_accessor :x, :y
|
15
|
+
def initialize(*args)
|
16
|
+
value = (args.size == 1 ? args[0] : args)
|
17
|
+
@x, @y = 0, 0
|
18
|
+
if value.is_a? String
|
19
|
+
if value.downcase.match(/^[a-z]+[0-9]+$/)
|
20
|
+
value = value.downcase.split(/([A-Z]+|[0-9]+)/).delete_if{|x| x.size.zero?}
|
21
|
+
@x, @y = value[0].tr(BASE_26_AFT, BASE_26_BEF).to_i(26), value[1].to_i(10)-1
|
22
|
+
elsif value.downcase.match(/^[0-9]+[^0-9]+[0-9]+$/)
|
23
|
+
value = value.downcase.split(/[^0-9]+/)
|
24
|
+
@x, @y = value[0].to_i(10), value[1].to_i(10)
|
25
|
+
end
|
26
|
+
elsif value.is_a? Integer
|
27
|
+
@x, @y = (value >> X_BIT_SHIFT), value & Y_FILTER
|
28
|
+
elsif value.is_a? Coordinates
|
29
|
+
@x, @y = value.x, value.y
|
30
|
+
elsif value.is_a? Array
|
31
|
+
@x, @y = value[0].to_i, value[1].to_i
|
32
|
+
elsif value.is_a? Hash
|
33
|
+
@x, @y = value[:x] || value[:column] || 0, value[:y] || value[:row] || 0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
@x.to_s(26).tr(BASE_26_BEF, BASE_26_AFT).upcase+(@y+1).to_s(10)
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_a
|
42
|
+
[@x, @y]
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_hash
|
46
|
+
{:x=>@x, :y=>@y}
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_i
|
50
|
+
(@x << X_BIT_SHIFT) + @y
|
51
|
+
end
|
52
|
+
|
53
|
+
def ==(other_coordinate)
|
54
|
+
other_coordinate.x == self.x and other_coordinate.y == self.y
|
55
|
+
end
|
56
|
+
|
57
|
+
def <=>(other_coordinate)
|
58
|
+
self.to_i <=> other_coordinate.to_i
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'zip/zip'
|
3
|
+
require 'libxml'
|
3
4
|
|
4
5
|
module Spreet
|
5
6
|
module Handlers
|
@@ -11,9 +12,41 @@ module Spreet
|
|
11
12
|
"Y" => "<number:year/>"
|
12
13
|
}
|
13
14
|
|
15
|
+
MIME = {
|
16
|
+
:ods => "application/vnd.oasis.opendocument.spreadsheet",
|
17
|
+
:xml => "text/xml"
|
18
|
+
}.freeze.each{|n,ns| self.const_set("MIME_#{n}".upcase, ns.freeze)}
|
19
|
+
|
20
|
+
|
21
|
+
XMLNS = {
|
22
|
+
:manifest => 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0',
|
23
|
+
:office => 'urn:oasis:names:tc:opendocument:xmlns:office:1.0',
|
24
|
+
:style => 'urn:oasis:names:tc:opendocument:xmlns:style:1.0',
|
25
|
+
:text => 'urn:oasis:names:tc:opendocument:xmlns:text:1.0',
|
26
|
+
:table => 'urn:oasis:names:tc:opendocument:xmlns:table:1.0',
|
27
|
+
:draw => 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0',
|
28
|
+
:fo => 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0',
|
29
|
+
:meta => 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0',
|
30
|
+
:number => 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0',
|
31
|
+
:presentation => 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0',
|
32
|
+
:svg => 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0',
|
33
|
+
:chart => 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0',
|
34
|
+
:dr3d => 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0',
|
35
|
+
:form => 'urn:oasis:names:tc:opendocument:xmlns:form:1.0',
|
36
|
+
:script => 'urn:oasis:names:tc:opendocument:xmlns:script:1.0',
|
37
|
+
:dc => 'http://purl.org/dc/elements/1.1/',
|
38
|
+
:ooo => 'http://openoffice.org/2004/office',
|
39
|
+
:ooow => 'http://openoffice.org/2004/writer',
|
40
|
+
:oooc => 'http://openoffice.org/2004/calc',
|
41
|
+
:math => 'http://www.w3.org/1998/Math/MathML',
|
42
|
+
:xlink => 'http://www.w3.org/1999/xlink',
|
43
|
+
:dom => 'http://www.w3.org/2001/xml-events',
|
44
|
+
:xsd => 'http://www.w3.org/2001/XMLSchema',
|
45
|
+
:xsi => 'http://www.w3.org/2001/XMLSchema-instance',
|
46
|
+
:xforms => 'http://www.w3.org/2002/xforms',
|
47
|
+
:field => 'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:field:1.0'
|
48
|
+
}.freeze.each{|n,ns| self.const_set("XMLNS_#{n}".upcase, ns.freeze)}
|
14
49
|
|
15
|
-
def self.mimetype
|
16
|
-
end
|
17
50
|
|
18
51
|
def self.xmlec(string)
|
19
52
|
zs = string.to_s.gsub('&', '&').gsub('\'', ''').gsub('<', '<').gsub('>', '>')
|
@@ -21,56 +54,302 @@ module Spreet
|
|
21
54
|
return zs
|
22
55
|
end
|
23
56
|
|
57
|
+
def self.add_attr(node, name, value, ns=nil)
|
58
|
+
attr = LibXML::XML::Attr.new(node, name, value.to_s)
|
59
|
+
attr.namespaces.namespace = ns if ns
|
60
|
+
return attr
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.read(file, options={})
|
64
|
+
spreet = nil
|
65
|
+
Zip::ZipFile.open(file) do |zile|
|
66
|
+
# Check mime_type
|
67
|
+
entry = zile.find_entry "mimetype"
|
68
|
+
if entry.nil?
|
69
|
+
raise StandardError.new("First element in archive must be a non-compressed 'mimetype'-named file.")
|
70
|
+
else
|
71
|
+
mime_type = zile.read(entry)
|
72
|
+
unless mime_type == MIME_ODS
|
73
|
+
raise StandardError.new("Mimetype mismatch")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Get manifest
|
78
|
+
entry, files = zile.find_entry("META-INF/manifest.xml"), {}
|
79
|
+
if entry.nil?
|
80
|
+
raise StandardError.new("Second element in archive must be a 'META-INF/manifest.xml'-named file.")
|
81
|
+
else
|
82
|
+
doc = LibXML::XML::Parser.string(zile.read(entry)).parse
|
83
|
+
for child in doc.root.children
|
84
|
+
if child.name == 'file-entry'
|
85
|
+
files[child["full-path"]] = child
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
if files["/"]["media-type"] != MIME_ODS
|
90
|
+
raise StandardError.new("Mimetype difference")
|
91
|
+
end
|
92
|
+
|
93
|
+
# Get content
|
94
|
+
if files["content.xml"] and entry = zile.find_entry("content.xml")
|
95
|
+
doc = LibXML::XML::Parser.string(zile.read(entry)).parse
|
96
|
+
unless doc.root.name == 'document-content'
|
97
|
+
raise StandardError.new("<document-content> element expected at root of content.xml")
|
98
|
+
end
|
99
|
+
if spreadsheet = doc.root.find('./office:body/office:spreadsheet', XMLNS_OFFICE).first
|
100
|
+
spreet = Spreet::Document.new()
|
101
|
+
for table in spreadsheet.find('./table:table', XMLNS_TABLE)
|
102
|
+
sheet = spreet.sheets.add(table["name"])
|
103
|
+
# Ignore table-column for now
|
104
|
+
|
105
|
+
rows = table.find("./table:table-rows").first || table
|
106
|
+
# # Expand rows and cells
|
107
|
+
# array = []
|
108
|
+
# for row in table.find('./table:table-row', XMLNS_TABLE)
|
109
|
+
# line = []
|
110
|
+
# for cell in row.find('./table:table-cell', XMLNS_TABLE)
|
111
|
+
# (cell["number-columns-repeated"]||'1').to_i.times do
|
112
|
+
# line << cell
|
113
|
+
# end
|
114
|
+
# end
|
115
|
+
# (row["number-rows-repeated"]||'1').to_i.times do
|
116
|
+
# array << line
|
117
|
+
# end
|
118
|
+
# end
|
119
|
+
# Fill sheet
|
120
|
+
row_offset = 0
|
121
|
+
rows.find('./table:table-row', XMLNS_TABLE).each_with_index do |row, y|
|
122
|
+
row_content, cell_offset = false, 0
|
123
|
+
row.find('./table:table-cell|./table:covered-table-cell', XMLNS_TABLE).each_with_index do |cell, x|
|
124
|
+
x += cell_offset
|
125
|
+
cell_content = false
|
126
|
+
if cell.name == "covered-table-cell"
|
127
|
+
# puts "covered-table-cell"
|
128
|
+
else
|
129
|
+
if value_type = cell.attributes.get_attribute_ns(XMLNS_OFFICE, "value-type")
|
130
|
+
value_type = value_type.value.to_sym
|
131
|
+
p = cell.find('./text:p', XMLNS_TEXT).first
|
132
|
+
if [:float, :percentage].include?(value_type)
|
133
|
+
value = cell.attributes.get_attribute_ns(XMLNS_OFFICE, "value").value
|
134
|
+
sheet[x,y] = value.to_f
|
135
|
+
elsif value_type == :currency
|
136
|
+
value = cell.attributes.get_attribute_ns(XMLNS_OFFICE, "value").value
|
137
|
+
currency = cell.attributes.get_attribute_ns(XMLNS_OFFICE, "currency").value
|
138
|
+
sheet[x,y] = Money.new(value, currency)
|
139
|
+
elsif value_type == :date
|
140
|
+
value = cell.attributes.get_attribute_ns(XMLNS_OFFICE, "date-value").value
|
141
|
+
if value.match(/\d{1,8}-\d{1,2}-\d{1,2}/)
|
142
|
+
value = Date.civil(*value.split(/[\-]+/).collect{|v| v.to_f})
|
143
|
+
elsif value.match(/\d{1,8}-\d{1,2}-\d{1,2}T\d{1,2}\:\d{1,2}\:\d{1,2}(\.\d+)?/)
|
144
|
+
value = Time.new(*value.split(/[\-\:\.\T]+/).collect{|v| v.to_f})
|
145
|
+
else
|
146
|
+
raise Exception.new("Bad date format")
|
147
|
+
end
|
148
|
+
sheet[x,y] = value
|
149
|
+
elsif value_type == :time
|
150
|
+
value = cell.attributes.get_attribute_ns(XMLNS_OFFICE, "time-value").value
|
151
|
+
sheet[x,y] = Duration.new(value)
|
152
|
+
elsif value_type == :boolean
|
153
|
+
value = cell.attributes.get_attribute_ns(XMLNS_OFFICE, "boolean-value").value
|
154
|
+
sheet[x,y] = (value == "true" ? true : false)
|
155
|
+
elsif value_type == :string
|
156
|
+
sheet[x,y] = p.content.to_s if p
|
157
|
+
end
|
158
|
+
sheet[x,y].text = p.content.to_s if p
|
159
|
+
cell_content = true
|
160
|
+
end
|
161
|
+
if annotation = cell.find("./office:annotation", XMLNS_OFFICE).first
|
162
|
+
if text = annotation.find("./text:p", XMLNS_TEXT).first
|
163
|
+
sheet[x,y].annotation = text.content.to_s
|
164
|
+
cell_content = true
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
repeated = (cell["number-columns-repeated"]||'1').to_i - 1
|
169
|
+
if repeated > 0
|
170
|
+
repeated.times do |i|
|
171
|
+
sheet[x+i+1,y] = sheet[x,y]
|
172
|
+
end if cell_content
|
173
|
+
cell_offset += repeated
|
174
|
+
end
|
175
|
+
row_content = true if cell_content
|
176
|
+
end
|
177
|
+
|
178
|
+
repeated = (row["number-rows-repeated"]||'1').to_i - 1
|
179
|
+
if repeated > 0
|
180
|
+
repeated.times do |i|
|
181
|
+
sheet.row(sheet.rows(y), :row=>(y+i+1))
|
182
|
+
end if row_content
|
183
|
+
row_offset += repeated
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
# What else ?
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
if spreet.nil?
|
193
|
+
raise StandardError.new("Missing or bad content.xml")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
return spreet
|
197
|
+
end
|
198
|
+
|
24
199
|
|
25
200
|
def self.write(spreet, file, options={})
|
26
201
|
xml_escape = "to_s.gsub('&', '&').gsub('\\'', ''').gsub('<', '<').gsub('>', '>')"
|
27
202
|
xml_escape << ".force_encoding('US-ASCII')" if xml_escape.respond_to?(:force_encoding)
|
28
|
-
|
203
|
+
mime_type = MIME_ODS
|
29
204
|
# name = #{table.model.name}.model_name.human.gsub(/[^a-z0-9]/i,'_')
|
30
205
|
Zip::ZipOutputStream.open(file) do |zile|
|
31
206
|
# MimeType in first place
|
32
207
|
zile.put_next_entry('mimetype', nil, nil, Zip::ZipEntry::STORED)
|
33
|
-
zile <<
|
208
|
+
zile << mime_type
|
34
209
|
|
35
210
|
# Manifest
|
211
|
+
doc = LibXML::XML::Document.new
|
212
|
+
doc.root = LibXML::XML::Node.new('manifest')
|
213
|
+
ns = LibXML::XML::Namespace.new(doc.root, 'manifest', XMLNS_MANIFEST)
|
214
|
+
doc.root.namespaces.namespace = ns
|
215
|
+
files = {
|
216
|
+
"/" => {"media-type" => mime_type},
|
217
|
+
"content.xml" => {"media-type" => MIME_XML}
|
218
|
+
}
|
219
|
+
for path, attributes in files
|
220
|
+
doc.root << entry = LibXML::XML::Node.new('file-entry', nil, ns)
|
221
|
+
attributes['full-path'] = path
|
222
|
+
for name, value in attributes.sort
|
223
|
+
self.add_attr(entry, name, value, ns)
|
224
|
+
end
|
225
|
+
end
|
36
226
|
zile.put_next_entry('META-INF/manifest.xml')
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
227
|
+
xml = doc.to_s(:indent=>false)
|
228
|
+
xml.force_encoding('US-ASCII') if xml.respond_to? :force_encoding
|
229
|
+
zile << xml
|
230
|
+
|
231
|
+
# Content
|
232
|
+
doc = LibXML::XML::Document.new
|
233
|
+
doc.root = LibXML::XML::Node.new('document-content')
|
234
|
+
nss = {}
|
235
|
+
for prefix, ns in XMLNS.select{|k,v| k != :manifest}
|
236
|
+
nss[prefix] = LibXML::XML::Namespace.new(doc.root, prefix.to_s, ns)
|
237
|
+
end
|
238
|
+
doc.root.namespaces.namespace = nss[:office]
|
239
|
+
add_attr(doc.root, "version", "1.1", nss[:office])
|
240
|
+
|
241
|
+
doc.root << automatic_styles = LibXML::XML::Node.new("automatic-styles", nil, nss[:office])
|
242
|
+
|
243
|
+
automatic_styles << style = LibXML::XML::Node.new("date-style", nil, nss[:number])
|
244
|
+
add_attr(style, "name", "DMY", nss[:style])
|
245
|
+
add_attr(style, "automatic-order", "true", nss[:number])
|
246
|
+
style << token = LibXML::XML::Node.new("day", nil, nss[:number])
|
247
|
+
add_attr(token, "style", "long", nss[:number])
|
248
|
+
style << token = LibXML::XML::Node.new("text", "/", nss[:number])
|
249
|
+
style << token = LibXML::XML::Node.new("month", nil, nss[:number])
|
250
|
+
add_attr(token, "style", "long", nss[:number])
|
251
|
+
style << token = LibXML::XML::Node.new("text", "/", nss[:number])
|
252
|
+
style << token = LibXML::XML::Node.new("year", nil, nss[:number])
|
253
|
+
|
254
|
+
automatic_styles << style = LibXML::XML::Node.new("style", nil, nss[:style])
|
255
|
+
add_attr(style, "name", "CE1", nss[:style])
|
256
|
+
add_attr(style, "family", "table-cell", nss[:style])
|
257
|
+
add_attr(style, "data-style-name", "DMY", nss[:style])
|
258
|
+
|
259
|
+
automatic_styles << style = LibXML::XML::Node.new("style", nil, nss[:number])
|
260
|
+
add_attr(style, "name", "COL", nss[:style])
|
261
|
+
add_attr(style, "family", "table-column", nss[:number])
|
262
|
+
style << token = LibXML::XML::Node.new("table-column-properties", nil, nss[:style])
|
263
|
+
add_attr(token, "break-before", "auto", nss[:fo])
|
264
|
+
add_attr(token, "use-optimal-column-width", "true", nss[:style])
|
265
|
+
|
266
|
+
doc.root << body = LibXML::XML::Node.new("body", nil, nss[:office])
|
267
|
+
body << spreadsheet = LibXML::XML::Node.new("spreadsheet", nil, nss[:office])
|
47
268
|
for sheet in spreet.sheets
|
48
|
-
|
49
|
-
|
50
|
-
|
269
|
+
spreadsheet << table = LibXML::XML::Node.new("table", nil, nss[:table])
|
270
|
+
add_attr(table, "name", sheet.name, nss[:table])
|
271
|
+
table << table_columns = LibXML::XML::Node.new("table-columns", nil, nss[:table])
|
272
|
+
for x in 0..sheet.bound.x
|
273
|
+
table_columns << table_column = LibXML::XML::Node.new("table-column", nil, nss[:table])
|
274
|
+
add_attr(table_column, "style-name", "COL", nss[:table])
|
275
|
+
end
|
276
|
+
table << table_rows = LibXML::XML::Node.new("table-rows", nil, nss[:table])
|
51
277
|
sheet.each_row do |row| # #{record} in #{table.records_variable_name}\n"
|
52
|
-
|
278
|
+
table_rows << table_row = LibXML::XML::Node.new("table-row", nil, nss[:table])
|
53
279
|
for cell in row
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
280
|
+
table_row << table_cell = LibXML::XML::Node.new("table-cell", nil, nss[:table])
|
281
|
+
unless cell.empty?
|
282
|
+
add_attr(table_cell, "value-type", cell.type, nss[:office])
|
283
|
+
if cell.type == :float # or percentage
|
284
|
+
add_attr(table_cell, "value", cell.value, nss[:office])
|
285
|
+
elsif cell.type == :currency
|
286
|
+
add_attr(table_cell, "value", cell.value.to_f, nss[:office])
|
287
|
+
add_attr(table_cell, "currency", cell.value.currency_as_string, nss[:office])
|
288
|
+
elsif cell.type == :date
|
289
|
+
if cell.value.is_a? Date
|
290
|
+
add_attr(table_cell, "date-value", cell.value.to_s, nss[:office])
|
291
|
+
add_attr(table_cell, "style-name", "CE1", nss[:table])
|
292
|
+
elsif cell.value.is_a?(DateTime) or cell.value.is_a?(Time)
|
293
|
+
add_attr(table_cell, "datetime-value", cell.value.to_xsd, nss[:office])
|
294
|
+
end
|
295
|
+
elsif cell.type == :time
|
296
|
+
add_attr(table_cell, "time-value", cell.value.to_s, nss[:office])
|
297
|
+
elsif cell.type == :boolean
|
298
|
+
add_attr(table_cell, "boolean-value", cell.value.to_s, nss[:office])
|
299
|
+
end
|
300
|
+
table_cell << LibXML::XML::Node.new("p", cell.text, nss[:text])
|
301
|
+
end
|
302
|
+
unless cell.annotation.nil?
|
303
|
+
table_cell << annotation = LibXML::XML::Node.new("annotation", nil, nss[:office])
|
304
|
+
annotation << LibXML::XML::Node.new("p", cell.annotation, nss[:text])
|
305
|
+
end
|
63
306
|
end
|
64
|
-
zile << "</table:table-row>"
|
65
307
|
end
|
66
|
-
zile << ("</table:table>")
|
67
308
|
end
|
68
|
-
|
309
|
+
|
310
|
+
zile.put_next_entry('content.xml')
|
311
|
+
xml = doc.to_s(:indent=>false)
|
312
|
+
xml.force_encoding('US-ASCII') if xml.respond_to? :force_encoding
|
313
|
+
zile << xml
|
314
|
+
|
315
|
+
# zile.put_next_entry('content.xml')
|
316
|
+
# zile << ("<?xml version=\"1.0\" encoding=\"UTF-8\"?><office:document-content xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\" xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\" xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\" xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\" xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\" xmlns:presentation=\"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0\" xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\" xmlns:chart=\"urn:oasis:names:tc:opendocument:xmlns:chart:1.0\" xmlns:dr3d=\"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0\" xmlns:math=\"http://www.w3.org/1998/Math/MathML\" xmlns:form=\"urn:oasis:names:tc:opendocument:xmlns:form:1.0\" xmlns:script=\"urn:oasis:names:tc:opendocument:xmlns:script:1.0\" xmlns:ooo=\"http://openoffice.org/2004/office\" xmlns:ooow=\"http://openoffice.org/2004/writer\" xmlns:oooc=\"http://openoffice.org/2004/calc\" xmlns:dom=\"http://www.w3.org/2001/xml-events\" xmlns:xforms=\"http://www.w3.org/2002/xforms\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:field=\"urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:field:1.0\" office:version=\"1.1\"><office:scripts/>")
|
317
|
+
# # Styles
|
318
|
+
# default_date_format = '%d/%m%Y' # ::I18n.translate("date.formats.default")
|
319
|
+
# zile << ("<office:automatic-styles><style:style style:name=\"co1\" style:family=\"table-column\"><style:table-column-properties fo:break-before=\"auto\" style:use-optimal-column-width=\"true\"/></style:style><style:style style:name=\"header\" style:family=\"table-cell\"><style:text-properties fo:font-weight=\"bold\" style:font-weight-asian=\"bold\" style:font-weight-complex=\"bold\"/></style:style><number:date-style style:name=\"K4D\" number:automatic-order=\"true\"><number:text>"+default_date_format.gsub(DATE_REGEXP){|x| "</number:text>"+DATE_ELEMENTS[x[1..1]]+"<number:text>"} +"</number:text></number:date-style><style:style style:name=\"ce1\" style:family=\"table-cell\" style:data-style-name=\"K4D\"/></office:automatic-styles>")
|
320
|
+
|
321
|
+
# zile << ("<office:body><office:spreadsheet>")
|
322
|
+
# # Tables
|
323
|
+
# for sheet in spreet.sheets
|
324
|
+
# zile << ("<table:table table:name=\"#{xmlec(sheet.name)}\">")
|
325
|
+
# zile << ("<table:table-column table:number-columns-repeated=\"#{sheet.bound.x+1}\"/>")
|
326
|
+
# # zile << ("<table:table-header-rows><table:table-row>"+columns_headers(table).collect{|h| "<table:table-cell table:style-name=\"header\" office:value-type=\"string\"><text:p>'+(#{h}).#{xml_escape}+'</text:p></table:table-cell>"}.join+"</table:table-row></table:table-header-rows>")
|
327
|
+
# sheet.each_row do |row| # #{record} in #{table.records_variable_name}\n"
|
328
|
+
# zile << "<table:table-row>"
|
329
|
+
# for cell in row
|
330
|
+
# if cell.empty?
|
331
|
+
# zile << "<table:table-cell/>"
|
332
|
+
# else
|
333
|
+
# zile << "<table:table-cell"+(if cell.type == :decimal
|
334
|
+
# " office:value-type=\"float\" office:value=\"#{xmlec(cell.value)}\""
|
335
|
+
# elsif cell.type == :boolean
|
336
|
+
# " office:value-type=\"boolean\" office:boolean-value=\"#{xmlec(cell.value ? 'true' : 'false')}\""
|
337
|
+
# elsif cell.type == :date
|
338
|
+
# " office:value-type=\"date\" table:style-name=\"ce1\" office:date-value=\"#{xmlec(cell.value)}\""
|
339
|
+
# else
|
340
|
+
# " office:value-type=\"string\""
|
341
|
+
# end)+"><text:p>"+xmlec(cell.text)+"</text:p></table:table-cell>"
|
342
|
+
# end
|
343
|
+
# end
|
344
|
+
# zile << "</table:table-row>"
|
345
|
+
# end
|
346
|
+
# zile << ("</table:table>")
|
347
|
+
# end
|
348
|
+
# zile << ("</office:spreadsheet></office:body></office:document-content>")
|
69
349
|
end
|
70
350
|
# Zile is finished
|
71
351
|
end
|
72
352
|
|
73
|
-
|
74
353
|
end
|
75
354
|
end
|
76
355
|
end
|