spreadbase 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,8 +1,17 @@
1
+ [![Build Status][BS img]](https://travis-ci.org/saveriomiroddi/spreadbase)
2
+
1
3
  SpreadBase!!
2
4
  ============
3
5
 
4
6
  ... because Excel IS a database.
5
7
 
8
+ Status
9
+ ------
10
+
11
+ The library itself is stable, and can be regularly used.
12
+
13
+ I plan to add features on request, but if nobody asks for them, I will update the project very infrequently.
14
+
6
15
  What is SpreadBase©?
7
16
  --------------------
8
17
 
@@ -132,12 +141,7 @@ Notes
132
141
 
133
142
  `SpreadBase::Document.new( "Random numbers für alle!.ods", :floats_as_bigdecimal => true )`
134
143
 
135
- - The archives are always encoded in UTF-8. In Ruby 1.8.7, input strings are assumed to be UTF-8; if not, it's possible to open a document as:
136
-
137
- `SpreadBase::Document.new( "Today's menu.ods", :force_18_strings_encoding => '<encoding>' )`
138
-
139
- in order to override the input encoding.
140
- - The gem has been tested on Ruby 1.8.7 and 1.9.3-p125, on Linux and Mac OS X.
144
+ - The gem has been tested on Ruby 1.9.3-p125, on Linux and Mac OS X.
141
145
  - The column widths are retained (decoding/encoding), but at the current version, they're not [officially] accessible via any API.
142
146
 
143
147
  Currently unsupported features
@@ -146,18 +150,9 @@ Currently unsupported features
146
150
  - Styles; Date and and [Date]Times are formatted as, respectively, '%Y-%m-%d' and '%Y-%m-%d %H:%M:%S %z'
147
151
  - Percentage data type - they're handled using their float value (e.g. 50% = 0.5)
148
152
 
149
- Supporting SpreadBase
150
- ---------------------
151
-
152
- If you find SpreadBase useful for any reason, I invite you to join Kiva.org, using this invitation:
153
-
154
- http://www.kiva.org/invitedby/saveriomiroddi
155
-
156
- it will cost you **nothing** (zero/0 €/£/$), it will take three to five minutes of your time, and you will have actively done something for economically disadvantaged countries.
157
-
158
- If you want to do more, in addition to accepting the invitation, you can donate to my Paypal account (saverio.pub2 \<a-hat!\> gmail.com) - I will publish your donation and use the entire amount for making loans using the mentioned website.
159
-
160
153
  Roadmap/Todo
161
154
  ------------
162
155
 
163
156
  https://github.com/saveriomiroddi/spreadbase/wiki/Todo-%28roadmap%29
157
+
158
+ [BS img]: https://travis-ci.org/saveriomiroddi/spreadbase.svg?branch=master
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ task default: :spec
data/docs/STRUCTURE.md ADDED
@@ -0,0 +1,3 @@
1
+ - the base directory contains the abstract concept classes (document, table, etc.)
2
+ - `codecs` contains the codec classes, for encoding/decoding
3
+ - `helpers` contains functionality of generic nature
data/docs/TESTING.md ADDED
@@ -0,0 +1,11 @@
1
+ Files
2
+ =====
3
+
4
+ - the `elements` suites test the abstract concept classes (document, table, etc.)
5
+ - the `codecs` suites have functional testing (encode -> decode cycle) of each code, plus UTs for codec-specific functionalities
6
+ - `spec_helpers.rb` are a few constants and methods useful for testing
7
+
8
+ Methodology
9
+ ===========
10
+
11
+ The general workflow is to write specific UTs, then extend the functional test(s), then test on files generated with Libreoffice (from Libreoffice-built to spreadbase, from spreadbase-built to Libreoffice, and from Libreoffice-build to spreadbase to Libreoffice), using the `utils` scripts.
@@ -0,0 +1,19 @@
1
+ module SpreadBase # :nodoc:
2
+
3
+ # Represents the abstraction of a cell; values and their types are merged into a single entity.
4
+ #
5
+ class Cell
6
+
7
+ attr_accessor :value
8
+
9
+ def initialize(value)
10
+ @value = value
11
+ end
12
+
13
+ def ==(other)
14
+ other.is_a?(Cell) && @value == other.value
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -1,23 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- =begin
4
- Copyright 2012 Saverio Miroddi saverio.pub2 <a-hat!> gmail.com
5
-
6
- This file is part of SpreadBase.
7
-
8
- SpreadBase is free software: you can redistribute it and/or modify it under the
9
- terms of the GNU Lesser General Public License as published by the Free Software
10
- Foundation, either version 3 of the License, or (at your option) any later
11
- version.
12
-
13
- SpreadBase is distributed in the hope that it will be useful, but WITHOUT ANY
14
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15
- PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
-
17
- You should have received a copy of the GNU Lesser General Public License along
18
- with SpreadBase. If not, see <http://www.gnu.org/licenses/>.
19
- =end
20
-
21
1
  require 'zipruby'
22
2
  require 'rexml/document'
23
3
 
@@ -49,20 +29,19 @@ module SpreadBase # :nodoc:
49
29
  #
50
30
  # _options_:
51
31
  #
52
- # +force_18_strings_encoding+:: ('UTF-8') on ruby 1.8, when converting to UTF-8, assume the strings are using the specified format.
53
32
  # +prettify+:: (false )prettifies the content.xml to be human readable.
54
33
  #
55
34
  # _returns_ the archive as binary string.
56
35
  #
57
- def encode_to_archive( el_document, options={} )
58
- document_buffer = encode_to_content_xml( el_document, options )
36
+ def encode_to_archive(el_document, options={})
37
+ document_buffer = encode_to_content_xml(el_document, options)
59
38
  zip_buffer = ''
60
39
 
61
- Zip::Archive.open_buffer( zip_buffer, Zip::CREATE ) do | zip_file |
62
- zip_file.add_dir( 'META-INF' )
40
+ Zip::Archive.open_buffer(zip_buffer, Zip::CREATE) do | zip_file |
41
+ zip_file.add_dir('META-INF')
63
42
 
64
- zip_file.add_buffer( 'META-INF/manifest.xml', MANIFEST_XML );
65
- zip_file.add_buffer( 'content.xml', document_buffer );
43
+ zip_file.add_buffer('META-INF/manifest.xml', MANIFEST_XML);
44
+ zip_file.add_buffer('content.xml', document_buffer);
66
45
  end
67
46
 
68
47
  zip_buffer
@@ -81,12 +60,12 @@ module SpreadBase # :nodoc:
81
60
  #
82
61
  # _returns_ the SpreadBase::Document instance.
83
62
  #
84
- def decode_archive( zip_buffer, options={} )
85
- content_xml_data = Zip::Archive.open_buffer( zip_buffer ) do | zip_file |
86
- zip_file.fopen( 'content.xml' ) { | file | file.read }
63
+ def decode_archive(zip_buffer, options={})
64
+ content_xml_data = Zip::Archive.open_buffer(zip_buffer) do | zip_file |
65
+ zip_file.fopen('content.xml') { | file | file.read }
87
66
  end
88
67
 
89
- decode_content_xml( content_xml_data, options )
68
+ decode_content_xml(content_xml_data, options)
90
69
  end
91
70
 
92
71
  # Utility method; encodes the Document to the content.xml format.
@@ -97,18 +76,17 @@ module SpreadBase # :nodoc:
97
76
  #
98
77
  # _options_:
99
78
  #
100
- # +force_18_strings_encoding+:: ('UTF-8') on ruby 1.8, when converting to UTF-8, assume the strings are using the specified format.
101
79
  # +prettify+:: (false ) prettifies the content.xml to be human readable.
102
80
  #
103
81
  # _returns_ content.xml as string.
104
82
  #--
105
83
  # "utility" is a fancy name for testing/utils helper.
106
84
  #
107
- def encode_to_content_xml( el_document, options={} )
108
- prettify = options[ :prettify ]
85
+ def encode_to_content_xml(el_document, options={})
86
+ prettify = options[:prettify]
109
87
 
110
- document_xml_root = encode_to_document_node( el_document, options )
111
- document_buffer = prettify ? pretty_xml( document_xml_root ) : document_xml_root.to_s
88
+ document_xml_root = encode_to_document_node(el_document)
89
+ document_buffer = prettify ? pretty_xml(document_xml_root) : document_xml_root.to_s
112
90
 
113
91
  document_buffer
114
92
  end
@@ -123,20 +101,20 @@ module SpreadBase # :nodoc:
123
101
  #--
124
102
  # "utility" is a fancy name for testing/utils helper.
125
103
  #
126
- def decode_content_xml( content_xml_data, options={} )
127
- root_node = REXML::Document.new( content_xml_data )
104
+ def decode_content_xml(content_xml_data, options={})
105
+ root_node = REXML::Document.new(content_xml_data)
128
106
 
129
- decode_document_node( root_node, options )
107
+ decode_document_node(root_node, options)
130
108
  end
131
109
 
132
110
  private
133
111
 
134
- def pretty_xml( document )
112
+ def pretty_xml(document)
135
113
  buffer = ""
136
114
 
137
115
  xml_formatter = REXML::Formatters::Pretty.new
138
116
  xml_formatter.compact = true
139
- xml_formatter.write( document, buffer )
117
+ xml_formatter.write(document, buffer)
140
118
 
141
119
  buffer
142
120
  end
@@ -1,23 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- =begin
4
- Copyright 2012 Saverio Miroddi saverio.pub2 <a-hat!> gmail.com
5
-
6
- This file is part of SpreadBase.
7
-
8
- SpreadBase is free software: you can redistribute it and/or modify it under the
9
- terms of the GNU Lesser General Public License as published by the Free Software
10
- Foundation, either version 3 of the License, or (at your option) any later
11
- version.
12
-
13
- SpreadBase is distributed in the hope that it will be useful, but WITHOUT ANY
14
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15
- PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
-
17
- You should have received a copy of the GNU Lesser General Public License along
18
- with SpreadBase. If not, see <http://www.gnu.org/licenses/>.
19
- =end
20
-
21
1
  require 'date'
22
2
  require 'bigdecimal'
23
3
 
@@ -37,32 +17,32 @@ module SpreadBase # :nodoc:
37
17
 
38
18
  # Returns a Document instance.
39
19
  #
40
- def decode_document_node( root_node, options={} )
20
+ def decode_document_node(root_node, options={})
41
21
  document = Document.new
42
22
 
43
- style_nodes = root_node.elements.to_a( '//office:document-content/office:automatic-styles/style:style' )
44
- table_nodes = root_node.elements.to_a( '//office:document-content/office:body/office:spreadsheet/table:table' )
23
+ style_nodes = root_node.elements.to_a('//office:document-content/office:automatic-styles/style:style')
24
+ table_nodes = root_node.elements.to_a('//office:document-content/office:body/office:spreadsheet/table:table')
45
25
 
46
- document.column_width_styles = decode_column_width_styles( style_nodes )
26
+ document.column_width_styles = decode_column_width_styles(style_nodes)
47
27
 
48
- document.tables = table_nodes.map { | node | decode_table_node( node, options ) }
28
+ document.tables = table_nodes.map { | node | decode_table_node(node, options) }
49
29
 
50
30
  document
51
31
  end
52
32
 
53
33
  # Currently it has only the purpose of decoding the column widths (for this reason it has a different naming convention).
54
34
  #
55
- def decode_column_width_styles( style_nodes )
56
- style_nodes.inject( {} ) do | column_width_styles, style_node |
57
- column_node = style_node.elements[ 'style:table-column-properties' ]
35
+ def decode_column_width_styles(style_nodes)
36
+ style_nodes.inject({}) do | column_width_styles, style_node |
37
+ column_node = style_node.elements['style:table-column-properties']
58
38
 
59
39
  if column_node
60
- column_width = column_node.attributes[ 'style:column-width' ]
40
+ column_width = column_node.attributes['style:column-width']
61
41
 
62
42
  if column_width
63
- style_name = style_node.attributes[ 'style:name' ]
43
+ style_name = style_node.attributes['style:name']
64
44
 
65
- column_width_styles[ style_name] = column_width
45
+ column_width_styles[style_name] = column_width
66
46
  end
67
47
  end
68
48
 
@@ -70,98 +50,98 @@ module SpreadBase # :nodoc:
70
50
  end
71
51
  end
72
52
 
73
- def decode_table_node( table_node, options )
74
- table = Table.new( table_node.attributes[ 'table:name' ] )
53
+ def decode_table_node(table_node, options)
54
+ table = Table.new(table_node.attributes['table:name'])
75
55
 
76
- column_nodes = table_node.elements.to_a( 'table:table-column' )
77
- row_nodes = table_node.elements.to_a( 'table:table-row' )
56
+ column_nodes = table_node.elements.to_a('table:table-column')
57
+ row_nodes = table_node.elements.to_a('table:table-row')
78
58
 
79
59
  # A single column/row can represent multiple columns (table:number-(columns|rows)-repeated)
80
60
  #
81
- table.column_width_styles = column_nodes.inject( [] ) { | current_styles, node | current_styles + decode_column_width_style( node ) }
82
- table.data = row_nodes.inject( [] ) { | current_rows, node | current_rows + decode_row_node( node, options ) }
61
+ table.column_width_styles = column_nodes.inject([]) { | current_styles, node | current_styles + decode_column_width_style(node) }
62
+ table.data = row_nodes.inject([]) { | current_rows, node | current_rows + decode_row_node(node, options) }
83
63
 
84
64
  table
85
65
  end
86
66
 
87
- def decode_column_width_style( column_node )
88
- repetitions = ( column_node.attributes[ 'table:number-columns-repeated' ] || '1' ).to_i
89
- style_name = column_node.attributes[ 'table:style-name' ]
67
+ def decode_column_width_style(column_node)
68
+ repetitions = (column_node.attributes['table:number-columns-repeated'] || '1').to_i
69
+ style_name = column_node.attributes['table:style-name']
90
70
 
91
71
  # WATCH OUT! See module note
92
72
  #
93
- make_array_from_repetitions( style_name, repetitions )
73
+ make_array_from_repetitions(style_name, repetitions)
94
74
  end
95
75
 
96
- def decode_row_node( row_node, options )
97
- repetitions = ( row_node.attributes[ 'table:number-rows-repeated' ] || '1' ).to_i
98
- cell_nodes = row_node.elements.to_a( 'table:table-cell' )
76
+ def decode_row_node(row_node, options)
77
+ repetitions = (row_node.attributes['table:number-rows-repeated'] || '1').to_i
78
+ cell_nodes = row_node.elements.to_a('table:table-cell')
99
79
 
100
80
  # Watch out the :flatten; a single cell can represent multiple cells (table:number-columns-repeated)
101
81
  #
102
- values = cell_nodes.map { | node | decode_cell_node( node, options ) }.flatten
82
+ values = cell_nodes.map { | node | decode_cell_node(node, options) }.flatten
103
83
 
104
- make_array_from_repetitions( values, repetitions )
84
+ make_array_from_repetitions(values, repetitions)
105
85
  end
106
86
 
107
- def decode_cell_node( cell_node, options )
108
- floats_as_bigdecimal = options[ :floats_as_bigdecimal ]
87
+ def decode_cell_node(cell_node, options)
88
+ value = decode_cell_value(cell_node, options)
109
89
 
110
- value_type = cell_node.attributes[ 'office:value-type' ]
90
+ repetitions = (cell_node.attributes['table:number-columns-repeated'] || '1').to_i
111
91
 
112
- value = \
113
- case value_type
114
- when 'string'
115
- value_node = cell_node.elements[ 'text:p' ]
92
+ make_array_from_repetitions(value, repetitions)
93
+ end
116
94
 
117
- value_node.text
118
- when 'date'
119
- date_string = cell_node.attributes[ 'office:date-value' ]
95
+ def decode_cell_value(cell_node, options)
96
+ floats_as_bigdecimal = options[:floats_as_bigdecimal]
120
97
 
121
- if date_string =~ /T/
122
- DateTime.strptime( date_string, '%Y-%m-%dT%H:%M:%S' )
123
- else
124
- Date.strptime( date_string, '%Y-%m-%d' )
125
- end
126
- when 'float', 'percentage'
127
- float_string = cell_node.attributes[ 'office:value' ]
128
-
129
- if float_string.include?( '.' )
130
- if floats_as_bigdecimal
131
- BigDecimal.new( float_string )
132
- else
133
- float_string.to_f
134
- end
135
- else
136
- float_string.to_i
137
- end
138
- when 'boolean'
139
- boolean_string = cell_node.attributes[ 'office:boolean-value' ]
140
-
141
- case boolean_string
142
- when 'true'
143
- true
144
- when 'false'
145
- false
98
+ value_type = cell_node.attributes['office:value-type']
99
+
100
+ case value_type
101
+ when 'string'
102
+ value_node = cell_node.elements['text:p']
103
+
104
+ value_node.text
105
+ when 'date'
106
+ date_string = cell_node.attributes['office:date-value']
107
+
108
+ if date_string =~ /T/
109
+ DateTime.strptime(date_string, '%Y-%m-%dT%H:%M:%S')
110
+ else
111
+ Date.strptime(date_string, '%Y-%m-%d')
112
+ end
113
+ when 'float', 'percentage'
114
+ float_string = cell_node.attributes['office:value']
115
+
116
+ if float_string.include?('.')
117
+ if floats_as_bigdecimal
118
+ BigDecimal(float_string)
146
119
  else
147
- raise "Invalid boolean value: #{ boolean_string }"
120
+ float_string.to_f
148
121
  end
149
- when nil
150
- nil
151
122
  else
152
- raise "Unrecognized value type found in a cell: #{ value_type }"
123
+ float_string.to_i
153
124
  end
154
-
155
- repetitions = ( cell_node.attributes[ 'table:number-columns-repeated' ] || '1' ).to_i
156
-
157
- make_array_from_repetitions( value, repetitions )
125
+ when 'boolean'
126
+ boolean_string = cell_node.attributes['office:boolean-value']
127
+
128
+ case boolean_string
129
+ when 'true'
130
+ true
131
+ when 'false'
132
+ false
133
+ else
134
+ raise "Invalid boolean value: #{ boolean_string }"
135
+ end
136
+ when nil
137
+ nil
138
+ else
139
+ raise "Unrecognized value type found in a cell: #{ value_type }"
140
+ end
158
141
  end
159
142
 
160
143
  end
161
144
 
162
- private
163
-
164
-
165
145
  end
166
146
 
167
147
  end
@@ -1,27 +1,6 @@
1
- # encoding: UTF-8
2
-
3
- =begin
4
- Copyright 2012 Saverio Miroddi saverio.pub2 <a-hat!> gmail.com
5
-
6
- This file is part of SpreadBase.
7
-
8
- SpreadBase is free software: you can redistribute it and/or modify it under the
9
- terms of the GNU Lesser General Public License as published by the Free Software
10
- Foundation, either version 3 of the License, or (at your option) any later
11
- version.
12
-
13
- SpreadBase is distributed in the hope that it will be useful, but WITHOUT ANY
14
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15
- PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
-
17
- You should have received a copy of the GNU Lesser General Public License along
18
- with SpreadBase. If not, see <http://www.gnu.org/licenses/>.
19
- =end
20
-
21
1
  require 'rexml/document'
22
2
  require 'date'
23
3
  require 'bigdecimal'
24
- require 'iconv' if RUBY_VERSION < '1.9'
25
4
 
26
5
  module SpreadBase # :nodoc:
27
6
 
@@ -81,17 +60,17 @@ module SpreadBase # :nodoc:
81
60
 
82
61
  # Returns the XML root node
83
62
  #
84
- def encode_to_document_node( el_document, options={} )
85
- root_node = REXML::Document.new( BASE_CONTENT_XML )
86
- spreadsheet_node = root_node.elements[ '//office:document-content/office:body/office:spreadsheet' ]
87
- styles_node = root_node.elements[ '//office:document-content/office:automatic-styles' ]
63
+ def encode_to_document_node(el_document)
64
+ root_node = REXML::Document.new(BASE_CONTENT_XML)
65
+ spreadsheet_node = root_node.elements['//office:document-content/office:body/office:spreadsheet']
66
+ styles_node = root_node.elements['//office:document-content/office:automatic-styles']
88
67
 
89
68
  el_document.column_width_styles.each do | style_name, column_width |
90
- encode_style( styles_node, style_name, column_width )
69
+ encode_style(styles_node, style_name, column_width)
91
70
  end
92
71
 
93
72
  el_document.tables.each do | table |
94
- encode_table( table, spreadsheet_node, options )
73
+ encode_table(table, spreadsheet_node)
95
74
  end
96
75
 
97
76
  root_node
@@ -99,91 +78,83 @@ module SpreadBase # :nodoc:
99
78
 
100
79
  # Currently only encodes column width styles
101
80
  #
102
- def encode_style( styles_node, style_name, column_width )
103
- style_node = styles_node.add_element( 'style:style', 'style:name' => style_name, 'style:family' => 'table-column' )
81
+ def encode_style(styles_node, style_name, column_width)
82
+ style_node = styles_node.add_element('style:style', 'style:name' => style_name, 'style:family' => 'table-column')
104
83
 
105
- style_node.add_element( 'style:table-column-properties', 'style:column-width' => column_width )
84
+ style_node.add_element('style:table-column-properties', 'style:column-width' => column_width)
106
85
  end
107
86
 
108
- def encode_table( table, spreadsheet_node, options={} )
109
- table_node = spreadsheet_node.add_element( 'table:table' )
87
+ def encode_table(table, spreadsheet_node)
88
+ table_node = spreadsheet_node.add_element('table:table')
110
89
 
111
- table_node.attributes[ 'table:name' ] = table.name
90
+ table_node.attributes['table:name'] = table.name
112
91
 
113
92
  table.column_width_styles.each do | style_name |
114
- encode_column( table_node, style_name ) if style_name
93
+ encode_column(table_node, style_name) if style_name
115
94
  end
116
95
 
117
96
  # At least one column element is required
118
97
  #
119
- table_node.add_element( 'table:table-column' ) if table.column_width_styles.size == 0
98
+ table_node.add_element('table:table-column') if table.column_width_styles.size == 0
120
99
 
121
- table.data.each do | row |
122
- encode_row( row, table_node, options )
100
+ table.data(as_cell: true).each do | row |
101
+ encode_row(row, table_node)
123
102
  end
124
103
  end
125
104
 
126
105
  # Currently only encodes column width styles
127
106
  #
128
- def encode_column( table_node, style_name )
129
- table_node.add_element( 'table:table-column', 'table:style-name' => style_name )
107
+ def encode_column(table_node, style_name)
108
+ table_node.add_element('table:table-column', 'table:style-name' => style_name)
130
109
  end
131
110
 
132
- def encode_row( row, table_node, options={} )
133
- row_node = table_node.add_element( 'table:table-row' )
111
+ def encode_row(row, table_node)
112
+ row_node = table_node.add_element('table:table-row')
134
113
 
135
- row.each do | value |
136
- encode_cell( value, row_node, options )
114
+ row.each do | cell |
115
+ encode_cell(cell.value, row_node)
137
116
  end
138
117
  end
139
118
 
140
- def encode_cell( value, row_node, options={} )
141
- force_18_strings_encoding = options[ :force_18_strings_encoding ] || 'UTF-8'
142
-
143
- cell_node = row_node.add_element( 'table:table-cell' )
119
+ def encode_cell(value, row_node)
120
+ cell_node = row_node.add_element('table:table-cell')
144
121
 
145
122
  # WATCH OUT!!! DateTime.new.is_a?( Date )!!!
146
123
  #
147
124
  case value
148
125
  when String
149
- cell_node.attributes[ 'office:value-type' ] = 'string'
150
-
151
- cell_value_node = cell_node.add_element( 'text:p' )
126
+ cell_node.attributes['office:value-type'] = 'string'
152
127
 
153
- if RUBY_VERSION >= '1.9'
154
- value = value.encode( 'UTF-8' )
155
- else
156
- value = Iconv.conv( 'UTF-8', force_18_strings_encoding, value )
157
- end
128
+ cell_value_node = cell_node.add_element('text:p')
158
129
 
159
- cell_value_node.text = value
130
+ cell_value_node.text = value.encode('UTF-8')
160
131
  when Time, DateTime
161
- cell_node.attributes[ 'office:value-type' ] = 'date'
162
- cell_node.attributes[ 'table:style-name' ] = 'datetime'
132
+ cell_node.attributes['office:value-type'] = 'date'
133
+ cell_node.attributes['table:style-name'] = 'datetime'
163
134
 
164
- encoded_value = value.strftime( '%Y-%m-%dT%H:%M:%S' )
135
+ encoded_value = value.strftime('%Y-%m-%dT%H:%M:%S')
165
136
 
166
- cell_node.attributes[ 'office:date-value' ] = encoded_value
137
+ cell_node.attributes['office:date-value'] = encoded_value
167
138
  when Date
168
- cell_node.attributes[ 'office:value-type' ] = 'date'
169
- cell_node.attributes[ 'table:style-name' ] = 'date'
139
+ cell_node.attributes['office:value-type'] = 'date'
140
+ cell_node.attributes['table:style-name'] = 'date'
170
141
 
171
- encoded_value = value.strftime( '%Y-%m-%d' )
142
+ encoded_value = value.strftime('%Y-%m-%d')
172
143
 
173
- cell_node.attributes[ 'office:date-value' ] = encoded_value
144
+ cell_node.attributes['office:date-value'] = encoded_value
174
145
  when BigDecimal
175
- cell_node.attributes[ 'office:value-type' ] = 'float'
146
+ cell_node.attributes['office:value-type'] = 'float'
176
147
 
177
- cell_node.attributes[ 'office:value' ] = value.to_s( 'F' )
178
- when Float, Fixnum
179
- cell_node.attributes[ 'office:value-type' ] = 'float'
148
+ cell_node.attributes['office:value'] = value.to_s('F')
149
+ when Float, Integer
150
+ cell_node.attributes['office:value-type'] = 'float'
180
151
 
181
- cell_node.attributes[ 'office:value' ] = value.to_s
152
+ cell_node.attributes['office:value'] = value.to_s
182
153
  when true, false
183
- cell_node.attributes[ 'office:value-type' ] = 'boolean'
184
- cell_node.attributes[ 'table:style-name' ] = 'boolean'
154
+ cell_node.attributes['office:value-type'] = 'boolean'
155
+ cell_node.attributes['table:style-name'] = 'boolean'
185
156
 
186
- cell_node.attributes[ 'office:boolean-value' ] = value.to_s
157
+ cell_node.attributes['office:boolean-value'] = value.to_s
187
158
  when nil
188
159
  # do nothing
189
160
  else