rubyXL 1.2.10 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/Gemfile +14 -10
  2. data/Gemfile.lock +80 -21
  3. data/LICENSE.txt +1 -1
  4. data/README.rdoc +88 -82
  5. data/Rakefile +7 -2
  6. data/VERSION +1 -1
  7. data/lib/rubyXL.rb +13 -7
  8. data/lib/rubyXL/cell.rb +108 -268
  9. data/lib/rubyXL/generic_storage.rb +40 -0
  10. data/lib/rubyXL/objects/border.rb +66 -0
  11. data/lib/rubyXL/objects/calculation_chain.rb +28 -0
  12. data/lib/rubyXL/objects/cell_style.rb +75 -0
  13. data/lib/rubyXL/objects/color.rb +25 -0
  14. data/lib/rubyXL/objects/column_range.rb +74 -0
  15. data/lib/rubyXL/objects/container_nodes.rb +122 -0
  16. data/lib/rubyXL/objects/data_validation.rb +43 -0
  17. data/lib/rubyXL/objects/document_properties.rb +76 -0
  18. data/lib/rubyXL/objects/extensions.rb +36 -0
  19. data/lib/rubyXL/objects/fill.rb +57 -0
  20. data/lib/rubyXL/objects/font.rb +111 -0
  21. data/lib/rubyXL/objects/formula.rb +24 -0
  22. data/lib/rubyXL/objects/ooxml_object.rb +295 -0
  23. data/lib/rubyXL/objects/reference.rb +110 -0
  24. data/lib/rubyXL/objects/relationships.rb +59 -0
  25. data/lib/rubyXL/objects/shared_strings.rb +57 -0
  26. data/lib/rubyXL/objects/sheet_data.rb +149 -0
  27. data/lib/rubyXL/objects/sheet_view.rb +71 -0
  28. data/lib/rubyXL/objects/stylesheet.rb +200 -0
  29. data/lib/rubyXL/objects/text.rb +87 -0
  30. data/lib/rubyXL/objects/theme.rb +64 -0
  31. data/lib/rubyXL/objects/workbook.rb +233 -0
  32. data/lib/rubyXL/objects/worksheet.rb +485 -0
  33. data/lib/rubyXL/parser.rb +78 -442
  34. data/lib/rubyXL/workbook.rb +216 -385
  35. data/lib/rubyXL/worksheet.rb +509 -1062
  36. data/lib/rubyXL/writer/content_types_writer.rb +104 -68
  37. data/lib/rubyXL/writer/core_writer.rb +26 -43
  38. data/lib/rubyXL/writer/generic_writer.rb +43 -0
  39. data/lib/rubyXL/writer/root_rels_writer.rb +11 -19
  40. data/lib/rubyXL/writer/styles_writer.rb +6 -398
  41. data/lib/rubyXL/writer/theme_writer.rb +321 -327
  42. data/lib/rubyXL/writer/workbook_writer.rb +63 -67
  43. data/lib/rubyXL/writer/worksheet_writer.rb +29 -218
  44. data/rdoc/created.rid +39 -0
  45. data/rdoc/fonts.css +167 -0
  46. data/rdoc/fonts/Lato-Light.ttf +0 -0
  47. data/rdoc/fonts/Lato-LightItalic.ttf +0 -0
  48. data/rdoc/fonts/Lato-Regular.ttf +0 -0
  49. data/rdoc/fonts/Lato-RegularItalic.ttf +0 -0
  50. data/rdoc/fonts/SourceCodePro-Bold.ttf +0 -0
  51. data/rdoc/fonts/SourceCodePro-Regular.ttf +0 -0
  52. data/rdoc/images/add.png +0 -0
  53. data/rdoc/images/arrow_up.png +0 -0
  54. data/rdoc/images/brick.png +0 -0
  55. data/rdoc/images/brick_link.png +0 -0
  56. data/rdoc/images/bug.png +0 -0
  57. data/rdoc/images/bullet_black.png +0 -0
  58. data/rdoc/images/bullet_toggle_minus.png +0 -0
  59. data/rdoc/images/bullet_toggle_plus.png +0 -0
  60. data/rdoc/images/date.png +0 -0
  61. data/rdoc/images/delete.png +0 -0
  62. data/rdoc/images/find.png +0 -0
  63. data/rdoc/images/loadingAnimation.gif +0 -0
  64. data/rdoc/images/macFFBgHack.png +0 -0
  65. data/rdoc/images/package.png +0 -0
  66. data/rdoc/images/page_green.png +0 -0
  67. data/rdoc/images/page_white_text.png +0 -0
  68. data/rdoc/images/page_white_width.png +0 -0
  69. data/rdoc/images/plugin.png +0 -0
  70. data/rdoc/images/ruby.png +0 -0
  71. data/rdoc/images/tag_blue.png +0 -0
  72. data/rdoc/images/tag_green.png +0 -0
  73. data/rdoc/images/transparent.png +0 -0
  74. data/rdoc/images/wrench.png +0 -0
  75. data/rdoc/images/wrench_orange.png +0 -0
  76. data/rdoc/images/zoom.png +0 -0
  77. data/rdoc/js/darkfish.js +140 -0
  78. data/rdoc/js/jquery.js +18 -0
  79. data/rdoc/js/navigation.js +142 -0
  80. data/rdoc/js/search.js +109 -0
  81. data/rdoc/js/search_index.js +1 -0
  82. data/rdoc/js/searcher.js +228 -0
  83. data/rdoc/rdoc.css +580 -0
  84. data/rubyXL.gemspec +90 -34
  85. data/spec/lib/cell_spec.rb +29 -59
  86. data/spec/lib/parser_spec.rb +35 -19
  87. data/spec/lib/reference_spec.rb +29 -0
  88. data/spec/lib/stylesheet_spec.rb +29 -0
  89. data/spec/lib/workbook_spec.rb +22 -17
  90. data/spec/lib/worksheet_spec.rb +47 -202
  91. metadata +185 -148
  92. data/lib/.DS_Store +0 -0
  93. data/lib/rubyXL/Hash.rb +0 -60
  94. data/lib/rubyXL/color.rb +0 -14
  95. data/lib/rubyXL/private_class.rb +0 -265
  96. data/lib/rubyXL/writer/app_writer.rb +0 -62
  97. data/lib/rubyXL/writer/calc_chain_writer.rb +0 -33
  98. data/lib/rubyXL/writer/shared_strings_writer.rb +0 -30
  99. data/lib/rubyXL/writer/workbook_rels_writer.rb +0 -59
  100. data/lib/rubyXL/zip.rb +0 -20
  101. data/spec/lib/hash_spec.rb +0 -28
@@ -1,204 +1,168 @@
1
1
  module RubyXL
2
- class Worksheet < PrivateClass
2
+ module LegacyWorksheet
3
3
  include Enumerable
4
4
 
5
- attr_accessor :sheet_name, :sheet_data, :cols, :merged_cells, :pane,
6
- :validations, :sheet_view, :legacy_drawing, :extLst, :workbook, :row_styles
7
-
8
- def initialize(workbook, sheet_name='Sheet1',sheet_data=[[nil]],cols=[], merged_cells=[])
9
- @workbook = workbook
10
-
11
- @sheet_name = sheet_name
12
- @sheet_data = sheet_data
13
- @cols = cols
14
- @merged_cells = merged_cells
15
- @row_styles={}
16
- @sheet_view = {
17
- :attributes => {
18
- :workbookViewId => 0, :zoomScale => 100, :tabSelected => 1, :view=>'normalLayout', :zoomScaleNormal => 100
19
- }
20
- }
5
+ attr_accessor :sheet_name, :sheet_id, :validations, :extLst, :workbook
6
+
7
+ def initialize(params = {})
8
+ super
9
+ @workbook = params[:workbook]
10
+ @sheet_name = params[:sheet_name]
11
+ @sheet_id = params[:sheet_id]
12
+ self.sheet_data = RubyXL::SheetData.new
13
+ self.cols = RubyXL::ColumnRanges.new
21
14
  @extLst = nil
22
- @legacy_drawing=nil
15
+ @validations = []
23
16
  end
24
17
 
25
18
  # allows for easier access to sheet_data
26
- def [](row=0)
27
- return @sheet_data[row]
19
+ def [](row = 0)
20
+ sheet_data[row]
28
21
  end
29
22
 
30
23
  def each
31
- @sheet_data.each {|i| yield i}
24
+ sheet_data.rows.each { |row| yield(row) }
32
25
  end
33
26
 
34
27
  #returns 2d array of just the cell values (without style or formula information)
35
28
  def extract_data(args = {})
36
- raw_values = args.delete(:raw) || false
37
- return @sheet_data.map {|row| row.map {|c| if c.is_a?(Cell) then c.value(:raw => raw_values) else nil end}}
29
+ sheet_data.rows.map { |row|
30
+ row && row.cells.map { |c| c && c.value(args) }
31
+ }
38
32
  end
39
33
 
40
- def get_table(headers=[],opts={})
34
+ def get_table(headers = [], opts = {})
41
35
  validate_workbook
42
36
 
43
- if !headers.is_a?(Array)
44
- headers = [headers]
45
- end
46
-
37
+ headers = [headers] unless headers.is_a?(Array)
47
38
  row_num = find_first_row_with_content(headers)
39
+ return nil if row_num.nil?
48
40
 
49
- if row_num.nil?
50
- return nil
51
- end
52
-
53
- table_hash = {}
54
- table_hash[:table] = []
41
+ table_hash = {}
42
+ table_hash[:table] = []
55
43
 
56
- header_row = @sheet_data[row_num]
57
- header_row.each_with_index do |header_cell, index|
44
+ header_row = sheet_data[row_num]
45
+ header_row.cells.each_with_index { |header_cell, index|
58
46
  break if index>0 && !opts[:last_header].nil? && !header_row[index-1].nil? && !header_row[index-1].value.nil? && header_row[index-1].value.to_s==opts[:last_header]
59
47
  next if header_cell.nil? || header_cell.value.nil?
60
48
  header = header_cell.value.to_s
61
49
  table_hash[:sorted_headers]||=[]
62
50
  table_hash[:sorted_headers] << header
63
- table_hash[header] = []
51
+ table_hash[header] = []
64
52
 
65
- original_row = row_num + 1
66
- current_row = original_row
53
+ original_row = row_num + 1
54
+ current_row = original_row
67
55
 
68
- cell = @sheet_data[current_row][index]
56
+ row = sheet_data.rows[current_row]
57
+ cell = row && row.cells[index]
69
58
 
70
59
  # makes array of hashes in table_hash[:table]
71
- # as well as hash of arrays in table_hash[header]
60
+ # as well as hash of arrays in table_hash[header]
72
61
  table_index = current_row - original_row
73
- cell_test= (!cell.nil? && !cell.value.nil?)
74
- while cell_test || !table_hash[:table][table_index].empty?
62
+ cell_test = (!cell.nil? && !cell.value.nil?)
75
63
 
76
- table_hash[header] << (cell_test ? cell.value : nil)
64
+ while cell_test || (table_hash[:table][table_index] && !table_hash[:table][table_index].empty?)
65
+ table_hash[header] << cell.value if cell_test
66
+ table_index = current_row - original_row
77
67
 
78
- table_index = current_row - original_row
68
+ if cell_test then
69
+ table_hash[:table][table_index] ||= {}
70
+ table_hash[:table][table_index][header] = cell.value
71
+ end
79
72
 
80
- if table_hash[:table][table_index].nil?
81
- table_hash[:table][table_index] = {}
82
- end
73
+ current_row += 1
74
+ if sheet_data.rows[current_row].nil? then
75
+ cell = nil
76
+ else
77
+ cell = sheet_data.rows[current_row].cells[index]
78
+ end
79
+ cell_test = (!cell.nil? && !cell.value.nil?)
80
+ end
81
+ }
83
82
 
84
- table_hash[:table][table_index][header] = cell.value if cell_test
83
+ return table_hash
84
+ end
85
85
 
86
- current_row += 1
87
- if @sheet_data[current_row].nil?
88
- cell = nil
89
- else
90
- cell = @sheet_data[current_row][index]
91
- end
92
- cell_test= (!cell.nil? && !cell.value.nil?)
93
- end
94
- end
86
+ # finds first row which contains at least all strings in cells_content
87
+ def find_first_row_with_content(cells_content)
88
+ validate_workbook
89
+
90
+ sheet_data.rows.each_with_index { |row, index|
91
+ next if row.nil?
92
+ cells_content = cells_content.map { |header| header.to_s.strip.downcase }
93
+ original_cells_content = row.cells.map { |cell| (cell && cell.value).to_s.strip.downcase }
95
94
 
96
- return table_hash
95
+ if (cells_content & original_cells_content).size == cells_content.size
96
+ return index
97
+ end
98
+ }
99
+ return nil
97
100
  end
101
+ private :find_first_row_with_content
98
102
 
99
103
  #changes color of fill in (zer0 indexed) row
100
- def change_row_fill(row=0,rgb='ffffff')
104
+ def change_row_fill(row_index = 0, rgb = 'ffffff')
101
105
  validate_workbook
102
- validate_nonnegative(row)
103
- increase_rows(row)
106
+ ensure_cell_exists(row_index)
104
107
  Color.validate_color(rgb)
105
- if @row_styles[(Integer(row)+1).to_s].nil?
106
- @row_styles[(Integer(row)+1).to_s] = {}
107
- @row_styles[(Integer(row)+1).to_s][:style] = '0'
108
- end
109
-
110
- @row_styles[(Integer(row)+1).to_s][:style] = modify_fill(@workbook,Integer(@row_styles[(Integer(row)+1).to_s][:style]),rgb)
111
108
 
112
- @sheet_data[Integer(row)].each do |c|
113
- unless c.nil?
114
- c.change_fill(rgb)
115
- end
116
- end
109
+ sheet_data.rows[row_index].s = @workbook.modify_fill(get_row_style(row_index), rgb)
110
+ sheet_data[row_index].cells.each { |c| c.change_fill(rgb) unless c.nil? }
117
111
  end
118
112
 
119
- # Changes font name of row
120
- def change_row_font_name(row=0, font_name='Verdana')
121
- # Get style object
122
- xf_id = xf_id(get_row_style(row))
123
- # Get copy of font object with modified name
124
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
125
- font[:name][:attributes][:val] = font_name.to_s
126
- # Update font and xf array
127
- change_row_font(row, Worksheet::NAME, font_name, font, xf_id)
113
+ def change_row_font_name(row = 0, font_name = 'Verdana')
114
+ ensure_cell_exists(row)
115
+ font = row_font(row).dup
116
+ font.set_name(font_name)
117
+ change_row_font(row, Worksheet::NAME, font_name, font)
128
118
  end
129
119
 
130
- # Changes font size of row
131
- def change_row_font_size(row=0, font_size=10)
132
- # Get style object
133
- xf_id = xf_id(get_row_style(row))
134
- # Get copy of font object with modified size
135
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
136
- font[:sz][:attributes][:val] = font_size
137
- # Update font and xf array
138
- change_row_font(row, Worksheet::SIZE, font_size, font, xf_id)
120
+ def change_row_font_size(row = 0, font_size=10)
121
+ ensure_cell_exists(row)
122
+ font = row_font(row).dup
123
+ font.set_size(font_size)
124
+ change_row_font(row, Worksheet::SIZE, font_size, font)
139
125
  end
140
126
 
141
- # Changes font color of row
142
- def change_row_font_color(row=0, font_color='000000')
127
+ def change_row_font_color(row = 0, font_color='000000')
128
+ ensure_cell_exists(row)
143
129
  Color.validate_color(font_color)
144
- # Get style object
145
- xf_id = xf_id(get_row_style(row))
146
- # Get copy of font object with modified color
147
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
148
- font = modify_font_color(font, font_color.to_s)
149
- # Update font and xf array
150
- change_row_font(row, Worksheet::COLOR, font_color, font, xf_id)
151
- end
152
-
153
- # Changes font italics settings of row
154
- def change_row_italics(row=0, italicized=false)
155
- # Get style object
156
- xf_id = xf_id(get_row_style(row))
157
- # Get copy of font object with modified italics settings
158
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
159
- font = modify_font_italics(font, italicized)
160
- # Update font and xf array
161
- change_row_font(row, Worksheet::ITALICS, italicized, font, xf_id)
162
- end
163
-
164
- # Changes font bold settings of row
165
- def change_row_bold(row=0, bolded=false)
166
- # Get style object
167
- xf_id = xf_id(get_row_style(row))
168
- # Get copy of font object with modified bold settings
169
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
170
- font = modify_font_bold(font, bolded)
171
- # Update font and xf array
172
- change_row_font(row, Worksheet::BOLD, bolded, font, xf_id)
173
- end
174
-
175
- # Changes font underline settings of row
176
- def change_row_underline(row=0, underlined=false)
177
- # Get style object
178
- xf_id = xf_id(get_row_style(row))
179
- # Get copy of font object with modified underline settings
180
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
181
- font = modify_font_underline(font, underlined)
182
- # Update font and xf array
183
- change_row_font(row, Worksheet::UNDERLINE, underlined, font, xf_id)
184
- end
185
-
186
- # Changes font strikethrough settings of row
187
- def change_row_strikethrough(row=0, struckthrough=false)
188
- # Get style object
189
- xf_id = xf_id(get_row_style(row))
190
- # Get copy of font object with modified strikethrough settings
191
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
192
- font = modify_font_strikethrough(font, struckthrough)
193
- # Update font and xf array
194
- change_row_font(row, Worksheet::STRIKETHROUGH, struckthrough, font, xf_id)
195
- end
196
-
197
- def change_row_height(row=0,height=10)
198
- validate_workbook
199
- validate_nonnegative(row)
130
+ font = row_font(row).dup
131
+ font.set_rgb_color(font_color)
132
+ change_row_font(row, Worksheet::COLOR, font_color, font)
133
+ end
134
+
135
+ def change_row_italics(row = 0, italicized=false)
136
+ ensure_cell_exists(row)
137
+ font = row_font(row).dup
138
+ font.set_italic(italicized)
139
+ change_row_font(row, Worksheet::ITALICS, italicized, font)
140
+ end
141
+
142
+ def change_row_bold(row = 0, bolded=false)
143
+ ensure_cell_exists(row)
144
+ font = row_font(row).dup
145
+ font.set_bold(bolded)
146
+ change_row_font(row, Worksheet::BOLD, bolded, font)
147
+ end
148
+
149
+ def change_row_underline(row = 0, underlined=false)
150
+ ensure_cell_exists(row)
151
+ font = row_font(row).dup
152
+ font.set_underline(underlined)
153
+ change_row_font(row, Worksheet::UNDERLINE, underlined, font)
154
+ end
200
155
 
201
- increase_rows(row)
156
+ def change_row_strikethrough(row = 0, struckthrough=false)
157
+ ensure_cell_exists(row)
158
+ font = row_font(row).dup
159
+ font.set_strikethrough(struckthrough)
160
+ change_row_font(row, Worksheet::STRIKETHROUGH, struckthrough, font)
161
+ end
162
+
163
+ def change_row_height(row = 0, height=10)
164
+ validate_workbook
165
+ ensure_cell_exists(row)
202
166
 
203
167
  if height.to_i.to_s == height.to_s
204
168
  height = Integer(height)
@@ -208,761 +172,449 @@ class Worksheet < PrivateClass
208
172
  raise 'You must enter a number for the height'
209
173
  end
210
174
 
211
- if @row_styles[(row+1).to_s].nil?
212
- @row_styles[(row+1).to_s] = {}
213
- @row_styles[(row+1).to_s][:style] = '0'
214
- end
215
- @row_styles[(row+1).to_s][:height] = height
216
- @row_styles[(row+1).to_s][:customHeight] = '1'
175
+ sheet_data.rows[row].ht = height
176
+ sheet_data.rows[row].custom_height = true
217
177
  end
218
178
 
219
- def change_row_horizontal_alignment(row=0,alignment='center')
179
+ def change_row_horizontal_alignment(row = 0,alignment='center')
220
180
  validate_workbook
221
181
  validate_nonnegative(row)
222
- validate_horizontal_alignment(alignment)
223
182
  change_row_alignment(row,alignment,true)
224
183
  end
225
184
 
226
- def change_row_vertical_alignment(row=0,alignment='center')
185
+ def change_row_vertical_alignment(row = 0,alignment='center')
227
186
  validate_workbook
228
187
  validate_nonnegative(row)
229
- validate_vertical_alignment(alignment)
230
188
  change_row_alignment(row,alignment,false)
231
189
  end
232
190
 
233
- def change_row_border_top(row=0,weight='thin')
191
+ def change_row_border_top(row = 0, weight = 'thin')
234
192
  change_row_border(row, :top, weight)
235
193
  end
236
194
 
237
- def change_row_border_left(row=0,weight='thin')
195
+ def change_row_border_left(row = 0, weight = 'thin')
238
196
  change_row_border(row, :left, weight)
239
197
  end
240
198
 
241
- def change_row_border_right(row=0,weight='thin')
199
+ def change_row_border_right(row = 0, weight = 'thin')
242
200
  change_row_border(row, :right, weight)
243
201
  end
244
202
 
245
- def change_row_border_bottom(row=0,weight='thin')
203
+ def change_row_border_bottom(row = 0, weight = 'thin')
246
204
  change_row_border(row, :bottom, weight)
247
205
  end
248
206
 
249
- def change_row_border_diagonal(row=0,weight='thin')
207
+ def change_row_border_diagonal(row = 0, weight = 'thin')
250
208
  change_row_border(row, :diagonal, weight)
251
209
  end
252
210
 
253
211
  # Changes font name of column
254
- def change_column_font_name(col=0, font_name='Verdana')
255
- # Get style object
256
- xf_id = xf_id(get_col_style(col))
257
- # Get copy of font object with modified name
258
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
259
- font[:name][:attributes][:val] = font_name.to_s
260
- # Update font and xf array
261
- change_column_font(col, Worksheet::NAME, font_name, font, xf_id)
212
+ def change_column_font_name(col = 0, font_name = 'Verdana')
213
+ xf = get_col_xf(col)
214
+ font = @workbook.fonts[xf.font_id].dup
215
+ font.set_name(font_name)
216
+ change_column_font(col, Worksheet::NAME, font_name, font, xf)
262
217
  end
263
218
 
264
219
  # Changes font size of column
265
220
  def change_column_font_size(col=0, font_size=10)
266
- # Get style object
267
- xf_id = xf_id(get_col_style(col))
268
- # Get copy of font object with modified size
269
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
270
- font[:sz][:attributes][:val] = font_size
271
- # Update font and xf array
272
- change_column_font(col, Worksheet::SIZE, font_size, font, xf_id)
221
+ xf = get_col_xf(col)
222
+ font = @workbook.fonts[xf.font_id].dup
223
+ font.set_size(font_size)
224
+ change_column_font(col, Worksheet::SIZE, font_size, font, xf)
273
225
  end
274
226
 
275
227
  # Changes font color of column
276
228
  def change_column_font_color(col=0, font_color='000000')
277
229
  Color.validate_color(font_color)
278
- # Get style object
279
- xf_id = xf_id(get_col_style(col))
280
- # Get copy of font object with modified color
281
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
282
- font = modify_font_color(font, font_color.to_s)
283
- # Update font and xf array
284
- change_column_font(col, Worksheet::COLOR, font_color, font, xf_id)
285
- end
286
-
287
- # Changes font italics settings of column
288
- def change_column_italics(col=0, italicized=false)
289
- # Get style object
290
- xf_id = xf_id(get_col_style(col))
291
- # Get copy of font object with modified italics settings
292
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
293
- font = modify_font_italics(font, italicized)
294
- # Update font and xf array
295
- change_column_font(col, Worksheet::ITALICS, italicized, font, xf_id)
296
- end
297
-
298
- # Changes font bold settings of column
299
- def change_column_bold(col=0, bolded=false)
300
- # Get style object
301
- xf_id = xf_id(get_col_style(col))
302
- # Get copy of font object with modified bold settings
303
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
304
- font = modify_font_bold(font, bolded)
305
- # Update font and xf array
306
- change_column_font(col, Worksheet::BOLD, bolded, font, xf_id)
307
- end
308
-
309
- # Changes font underline settings of column
310
- def change_column_underline(col=0, underlined=false)
311
- # Get style object
312
- xf_id = xf_id(get_col_style(col))
313
- # Get copy of font object with modified underline settings
314
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
315
- font = modify_font_underline(font, underlined)
316
- # Update font and xf array
317
- change_column_font(col, Worksheet::UNDERLINE, underlined, font, xf_id)
318
- end
319
-
320
- # Changes font strikethrough settings of column
321
- def change_column_strikethrough(col=0, struckthrough=false)
322
- # Get style object
323
- xf_id = xf_id(get_col_style(col))
324
- # Get copy of font object with modified strikethrough settings
325
- font = deep_copy(@workbook.fonts[xf_id[:fontId].to_s][:font])
326
- font = modify_font_strikethrough(font, struckthrough)
327
- # Update font and xf array
328
- change_column_font(col, Worksheet::STRIKETHROUGH, struckthrough, font, xf_id)
230
+
231
+ xf = get_col_xf(col)
232
+ font = @workbook.fonts[xf.font_id].dup
233
+ font.set_rgb_color(font_color)
234
+ change_column_font(col, Worksheet::COLOR, font_color, font, xf)
329
235
  end
330
236
 
331
- def change_column_width(col=0,width=13)
332
- validate_workbook
333
- validate_nonnegative(col)
334
- increase_columns(col)
237
+ def change_column_italics(col = 0, italicized = false)
238
+ xf = get_col_xf(col)
239
+ font = @workbook.fonts[xf.font_id].dup
240
+ font.set_italic(italicized)
241
+ change_column_font(col, Worksheet::ITALICS, italicized, font, xf)
242
+ end
335
243
 
336
- i = get_cols_index(col)
244
+ def change_column_bold(col = 0, bolded = false)
245
+ xf = get_col_xf(col)
246
+ font = @workbook.fonts[xf.font_id].dup
247
+ font.set_bold(bolded)
248
+ change_column_font(col, Worksheet::BOLD, bolded, font, xf)
249
+ end
337
250
 
338
- if width.to_i.to_s == width.to_s
339
- width = Integer(width)
340
- elsif width.to_f.to_s == width.to_s
341
- width = Float(width)
342
- else
343
- raise 'You must enter a number for the width'
344
- end
251
+ def change_column_underline(col = 0, underlined = false)
252
+ xf = get_col_xf(col)
253
+ font = @workbook.fonts[xf.font_id].dup
254
+ font.set_underline(underlined)
255
+ change_column_font(col, Worksheet::UNDERLINE, underlined, font, xf)
256
+ end
345
257
 
346
- change_cols(i,col)
347
- @cols.last[:attributes][:width] = width
348
- @cols.last[:attributes][:customWidth] = '1'
258
+ def change_column_strikethrough(col=0, struckthrough=false)
259
+ xf = get_col_xf(col)
260
+ font = @workbook.fonts[xf.font_id].dup
261
+ font.set_strikethrough(struckthrough)
262
+ change_column_font(col, Worksheet::STRIKETHROUGH, struckthrough, font, xf)
349
263
  end
350
264
 
351
- def change_column_fill(col=0, color_index='ffffff')
265
+ def change_column_width(column_index = 0, width = 13)
352
266
  validate_workbook
353
- validate_nonnegative(col)
354
- Color.validate_color(color_index)
355
- increase_columns(col)
356
-
357
- i = get_cols_index(col)
267
+ ensure_cell_exists(0, column_index)
358
268
 
359
- if cols[i].nil?
360
- style_index = 0
361
- else
362
- #just copies any style if there is none which already exists for this col
363
- #while it changes style/min/max, width *might* be preserved
364
- style_index = Integer(@cols[i][:attributes][:style])
365
- end
366
-
367
- modify_fill(@workbook,style_index,color_index)
269
+ range = cols.get_range(column_index)
270
+ range.width = width
271
+ range.custom_width = true
272
+ end
368
273
 
369
- change_cols(i,col)
274
+ def change_column_fill(column_index = 0, color_index='ffffff')
275
+ validate_workbook
276
+ Color.validate_color(color_index)
277
+ ensure_cell_exists(0, column_index)
370
278
 
371
- @sheet_data.each_with_index do |row,i|
372
- c = row[Integer(col)]
373
- unless c.nil?
374
- c.change_fill(color_index)
375
- end
376
- end
279
+ cols.get_range(column_index).style = @workbook.modify_fill(get_col_style(column_index), color_index)
377
280
 
281
+ sheet_data.rows.each { |row|
282
+ c = row[column_index]
283
+ c.change_fill(color_index) if c
284
+ }
378
285
  end
379
286
 
380
287
  def change_column_horizontal_alignment(col=0,alignment='center')
381
- validate_workbook
382
- validate_nonnegative(col)
383
- validate_horizontal_alignment(alignment)
384
288
  change_column_alignment(col,alignment,true)
385
289
  end
386
290
 
387
291
  def change_column_vertical_alignment(col=0,alignment='center')
388
- validate_workbook
389
- validate_nonnegative(col)
390
- validate_vertical_alignment(alignment)
391
- change_column_alignment(col,alignment,false)
292
+ change_column_alignment(col, alignment, false)
392
293
  end
393
294
 
394
- def change_column_border_top(col=0,weight='thin')
395
- change_column_border(col,:top,weight)
295
+ def change_column_border_top(col=0,weight = 'thin')
296
+ change_column_border(col, :top, weight)
396
297
  end
397
298
 
398
- def change_column_border_left(col=0,weight='thin')
399
- change_column_border(col,:left,weight)
299
+ def change_column_border_left(col=0,weight = 'thin')
300
+ change_column_border(col, :left, weight)
400
301
  end
401
302
 
402
- def change_column_border_right(col=0,weight='thin')
403
- change_column_border(col,:right,weight)
303
+ def change_column_border_right(col=0,weight = 'thin')
304
+ change_column_border(col, :right, weight)
404
305
  end
405
306
 
406
- def change_column_border_bottom(col=0,weight='thin')
407
- change_column_border(col,:bottom,weight)
307
+ def change_column_border_bottom(col=0,weight = 'thin')
308
+ change_column_border(col, :bottom, weight)
408
309
  end
409
310
 
410
- def change_column_border_diagonal(col=0,weight='thin')
411
- change_column_border(col,:diagonal,weight)
311
+ def change_column_border_diagonal(col=0,weight = 'thin')
312
+ change_column_border(col, :diagonal, weight)
412
313
  end
413
314
 
414
315
  # merges cells within a rectangular range
415
- def merge_cells(row1=0,col1=0,row2=0,col2=0)
416
- validate_workbook
417
- @merged_cells << {
418
- :attributes => {
419
- :ref => ''
420
- }
421
- }
422
- cell1 = Cell.convert_to_cell(row1,col1)
423
- cell2 = Cell.convert_to_cell(row2,col2)
424
- @merged_cells.last[:attributes][:ref] = cell1+':'+cell2
425
- end
426
-
427
- def add_cell(row=0, column=0, data='', formula=nil,overwrite=true)
316
+ def merge_cells(row1 = 0, col1 = 0, row2 = 0, col2 = 0)
428
317
  validate_workbook
429
- validate_nonnegative(row)
430
- validate_nonnegative(column)
431
-
432
- unless @sheet_data.size > row && @sheet_data[row].size > column
433
- increase_columns(column)
434
- increase_rows(row)
435
- end
436
-
437
- datatype = 'str'
438
- unless formula.nil?
439
- datatype = ''
440
- end
441
- if overwrite || @sheet_data[row][column].nil?
442
- @sheet_data[row][column] = Cell.new(self,row,column,data,formula,datatype)
443
-
444
- if (data.is_a?Integer) || (data.is_a?Float)
445
- @sheet_data[row][column].datatype = ''
446
- end
447
- col = @cols[get_cols_index(column)]
448
-
449
- if @row_styles[(row+1).to_s] != nil
450
- @sheet_data[row][column].style_index = @row_styles[(row+1).to_s][:style]
451
- elsif col != nil
452
- @sheet_data[row][column].style_index = col[:attributes][:style]
453
- end
454
- end
455
318
 
456
- add_cell_style(row,column)
319
+ self.merged_cells_list ||= RubyXL::MergedCells.new
320
+ merged_cells_list.merge_cell << RubyXL::MergedCell.new(:ref => RubyXL::Reference.new(row1, row2, col1, col2))
321
+ end
457
322
 
458
- return @sheet_data[row][column]
323
+ def add_row(row = 0, params = {})
324
+ new_row = RubyXL::Row.new(params)
325
+ new_row.worksheet = self
326
+ sheet_data.rows[row] = new_row
459
327
  end
460
328
 
461
- def add_cell_obj(cell, overwrite=true)
329
+ def add_cell(row = 0, column = 0, data = '', formula = nil, overwrite = true)
462
330
  validate_workbook
331
+ ensure_cell_exists(row, column)
463
332
 
464
- if cell.nil?
465
- return cell
466
- end
467
-
468
- row = cell.row
469
- column = cell.column
333
+ if overwrite || sheet_data.rows[row].cells[column].nil?
334
+ c = RubyXL::Cell.new
335
+ c.worksheet = self
336
+ c.row = row
337
+ c.column = column
338
+ c.raw_value = data
339
+ c.datatype = (formula || data.is_a?(Numeric)) ? '' : RubyXL::Cell::RAW_STRING
340
+ c.formula = formula
470
341
 
471
- validate_nonnegative(row)
472
- validate_nonnegative(column)
342
+ range = cols && cols.find(column)
343
+ c.style_index = sheet_data.rows[row].s || (range && range.style_index) || 0
473
344
 
474
- unless @sheet_data.size > row && @sheet_data[row].size > column
475
- increase_columns(column)
476
- increase_rows(row)
477
- end
478
- if overwrite || @sheet_data[row][column].nil?
479
- @sheet_data[row][column] = cell
345
+ sheet_data.rows[row].cells[column] = c
480
346
  end
481
347
 
482
- add_cell_style(row,column)
348
+ add_cell_style(row, column)
483
349
 
484
- return @sheet_data[row][column]
350
+ sheet_data.rows[row].cells[column]
485
351
  end
486
352
 
487
353
  def delete_row(row_index=0)
488
354
  validate_workbook
489
355
  validate_nonnegative(row_index)
356
+ return nil unless row_exists(row_index)
490
357
 
491
- if row_index >= @sheet_data.size
492
- return nil
493
- end
494
-
495
- deleted = @sheet_data.delete_at(row_index)
358
+ deleted = sheet_data.rows.delete_at(row_index)
496
359
  row_num = row_index+1
497
360
 
498
- row_num.upto(@sheet_data.size) do |index|
499
- @row_styles[(index-1).to_s] = deep_copy(@row_styles[index.to_s])
500
- end
501
- @row_styles.delete(@sheet_data.size.to_s)
502
-
503
- #change row styles
504
- # raise row_styles.inspect
505
-
506
- #change cell row numbers
507
- (row_index...(@sheet_data.size-1)).each do |index|
508
- @sheet_data[index].map {|c| c.row -= 1 if c}
509
- end
361
+ # Change cell row numbers
362
+ row_index.upto(sheet_data.size - 1) { |index|
363
+ sheet_data[index].cells.each{ |c| c.row -= 1 unless c.nil? }
364
+ }
510
365
 
511
366
  return deleted
512
367
  end
513
368
 
514
- #inserts row at row_index, pushes down, copies style from below (row previously at that index)
369
+ # Inserts row at row_index, pushes down, copies style from the row above (that's what Excel 2013 does!)
515
370
  #USE OF THIS METHOD will break formulas which reference cells which are being "pushed down"
516
- def insert_row(row_index=0)
371
+ def insert_row(row_index = 0)
517
372
  validate_workbook
518
- validate_nonnegative(row_index)
519
-
520
- increase_rows(row_index)
521
-
522
- @sheet_data.insert(row_index,Array.new(@sheet_data[row_index].size))
523
-
524
- row_num = row_index+1
525
-
526
- #copy cell styles from row above, (or below if first row)
527
- @sheet_data[row_index].each_index do |i|
528
- if row_index > 0
529
- old_cell = @sheet_data[row_index-1][i]
530
- else
531
- old_cell = @sheet_data[row_index+1][i]
532
- end
533
-
534
- unless old_cell.nil?
535
- #only add cell if style exists, not copying content
373
+ ensure_cell_exists(row_index)
536
374
 
537
- if @row_styles[(row_num+1).to_s].nil?
538
- @row_styles[(row_num+1).to_s] = {:style=>0}
539
- end
540
- if old_cell.style_index != 0 && old_cell.style_index.to_s != @row_styles[(row_num+1).to_s][:style].to_s
541
- c = Cell.new(self,row_index,i)
542
- c.style_index = old_cell.style_index
543
- @sheet_data[row_index][i] = c
544
- end
545
- end
546
- end
547
-
548
- #copy row styles from row above, (or below if first row)
549
- (@row_styles.size+1).downto(row_num+1) do |i|
550
- @row_styles[i.to_s] = @row_styles[(i-1).to_s]
551
- end
552
- if row_index > 0
553
- @row_styles[row_num.to_s] = @row_styles[(row_num-1).to_s]
375
+ if row_index == 0 then
376
+ old_row = nil
377
+ new_cells = Array.new(sheet_data.rows[0].cells.size)
554
378
  else
555
- @row_styles[row_num.to_s] = nil#@row_styles[(row_num+1).to_s]
379
+ old_row = sheet_data.rows[row_index - 1]
380
+ new_cells = old_row.cells.collect { |c|
381
+ if c.nil? then nil
382
+ else RubyXL::Cell.new(:style_index => c.style_index)
383
+ end }
556
384
  end
557
385
 
386
+ sheet_data.rows.insert(row_index, nil)
387
+ new_row = add_row(row_index, :cells => new_cells, :s => old_row && old_row.s)
388
+
558
389
  #update row value for all rows below
559
- (row_index+1).upto(@sheet_data.size-1) do |i|
560
- row = @sheet_data[i]
561
- row.each do |c|
562
- unless c.nil?
563
- c.row += 1
564
- end
565
- end
566
- end
390
+ row_index.upto(sheet_data.rows.size - 1) { |i|
391
+ row = sheet_data.rows[i]
392
+ row.cells.each { |c| c.row = i unless c.nil? }
393
+ }
567
394
 
568
- return @sheet_data[row_index]
395
+ return new_row
569
396
  end
570
397
 
571
- def delete_column(col_index=0)
398
+ def delete_column(column_index = 0)
572
399
  validate_workbook
573
- validate_nonnegative(col_index)
400
+ validate_nonnegative(column_index)
574
401
 
575
- if col_index >= @sheet_data[0].size
576
- return nil
577
- end
402
+ return nil unless column_exists(column_index)
578
403
 
579
404
  #delete column
580
- @sheet_data.map {|r| r.delete_at(col_index)}
405
+ sheet_data.rows.each { |row| row.cells.delete_at(column_index) }
581
406
 
582
407
  #change column numbers for cells to right of deleted column
583
- @sheet_data.each_with_index do |row,row_index|
584
- (col_index...(row.size)).each do |index|
585
- if @sheet_data[row_index][index].is_a?(Cell)
586
- @sheet_data[row_index][index].column -= 1
587
- end
588
- end
589
- end
408
+ sheet_data.rows.each_with_index { |row, row_index|
409
+ row.cells.each_with_index { |c, column_index|
410
+ c.column -= 1 if c.is_a?(Cell)
411
+ }
412
+ }
590
413
 
591
- #shift column styles
592
- #shift col styles 'left'
593
- @cols.each do |col|
594
- if Integer(col[:attributes][:min]) >= col_index
595
- col[:attributes][:min] = (Integer(col[:attributes][:min]) - 1).to_s
596
- end
597
- if Integer(col[:attributes][:max]) >= col_index
598
- col[:attributes][:max] = (Integer(col[:attributes][:max]) - 1).to_s
599
- end
600
- end
414
+ cols.column_ranges.each { |range| range.delete_column(column_index) }
601
415
  end
602
416
 
603
- # inserts column at col_index, pushes everything right, takes styles from column to left
417
+ # inserts column at +column_index+, pushes everything right, takes styles from column to left
604
418
  # USE OF THIS METHOD will break formulas which reference cells which are being "pushed down"
605
- def insert_column(col_index=0)
419
+ def insert_column(column_index = 0)
606
420
  validate_workbook
607
- validate_nonnegative(col_index)
608
- increase_columns(col_index)
421
+ ensure_cell_exists(0, column_index)
609
422
 
610
- old_index = col_index > 0 ? col_index-1 : col_index+1
611
- old_col = @cols[get_cols_index(old_index)]
612
- if old_index == 1
613
- old_col = nil
614
- end
423
+ old_range = cols.get_range(column_index)
615
424
 
616
425
  #go through each cell in column
617
- @sheet_data.each_with_index do |r,i|
618
- #insert "column" in each row
619
- r.insert(col_index, nil)
620
-
621
- #copy styles over to each cell
622
- old_cell = r[old_index]
623
- unless old_cell.nil?
624
- #only add cell if style exists, not copying content
625
- if old_cell.style_index != 0
626
- if !old_col.nil? && old_cell.style_index.to_s != old_col[:attributes][:style].to_s
627
- c = Cell.new(self,i,col_index)
628
- c.style_index = old_cell.style_index
629
- @sheet_data[i][col_index] = c
630
- end
631
- end
426
+ sheet_data.rows.each_with_index { |row, row_index|
427
+ old_cell = row[column_index]
428
+ c = nil
429
+
430
+ if old_cell && old_cell.style_index != 0 &&
431
+ old_range && old_range.style != old_cell.style_index then
432
+
433
+ c = Cell.new
434
+ c.worksheet = self
435
+ c.row = row_index
436
+ c.column = column_index
437
+ c.datatype = RubyXL::Cell::SHARED_STRING
438
+ c.style_index = old_cell.style_index
632
439
  end
633
- end
634
440
 
635
- #copy over column-level styles
636
- new_col = change_cols(get_cols_index(old_index),old_index)
637
- @cols[-1] = deep_copy(old_col)#-1 = last
441
+ row.insert_cell_shift_right(c, column_index)
442
+ }
638
443
 
639
- new_col = @cols.last
640
- if @cols.last.nil?
641
- @cols.pop
642
- end
444
+ cols.insert_column(column_index)
643
445
 
644
- #shift col styles 'right'
645
- @cols.each do |col|
646
- if Integer(col[:attributes][:min]) > col_index
647
- col[:attributes][:min] = (1 + Integer(col[:attributes][:min])).to_s
648
- end
649
- if Integer(col[:attributes][:max]) > col_index
650
- col[:attributes][:max] = (1 + Integer(col[:attributes][:max])).to_s
651
- end
652
- end
653
- unless new_col.nil?
654
- new_col[:attributes][:min] = (1 + Integer(new_col[:attributes][:min])).to_s
655
- new_col[:attributes][:max] = (1 + Integer(new_col[:attributes][:max])).to_s
656
- end
657
-
658
- #update column numbers
659
- @sheet_data.each do |row|
660
- (col_index+1).upto(row.size) do |j|
661
- unless row[j].nil?
662
- row[j].column += 1
663
- end
664
- end
665
- end
446
+ # TODO: update column numbers
666
447
  end
667
448
 
668
- def insert_cell(row=0,col=0,data=nil,formula=nil,shift=nil)
449
+ def insert_cell(row = 0, col = 0, data = nil, formula = nil, shift = nil)
669
450
  validate_workbook
670
- validate_nonnegative(row)
671
- validate_nonnegative(col)
672
-
673
- increase_rows(row)
674
- increase_columns(col)
451
+ ensure_cell_exists(row, col)
675
452
 
676
- if shift && shift != :right && shift != :down
453
+ case shift
454
+ when nil then # No shifting at all
455
+ when :right then
456
+ sheet_data.rows[row].insert_cell_shift_right(nil, col)
457
+ when :down then
458
+ add_row(sheet_data.size, :cells => Array.new(sheet_data.rows[row].size))
459
+ (sheet_data.size - 1).downto(row+1) { |index|
460
+ sheet_data.rows[index].cells[col] = sheet_data.rows[index-1].cells[col]
461
+ }
462
+ else
677
463
  raise 'invalid shift option'
678
464
  end
679
465
 
680
- if shift == :right
681
- @sheet_data[row].insert(col,nil)
682
- (row...(@sheet_data[row].size)).each do |index|
683
- if @sheet_data[row][index].is_a?(Cell)
684
- @sheet_data[row][index].column += 1
685
- end
686
- end
687
- elsif shift == :down
688
- @sheet_data << Array.new(@sheet_data[row].size)
689
- (@sheet_data.size-1).downto(row+1) do |index|
690
- @sheet_data[index][col] = @sheet_data[index-1][col]
691
- end
692
- end
693
-
694
466
  return add_cell(row,col,data,formula)
695
467
  end
696
468
 
697
469
  # by default, only sets cell to nil
698
470
  # if :left is specified, method will shift row contents to the right of the deleted cell to the left
699
471
  # if :up is specified, method will shift column contents below the deleted cell upward
700
- def delete_cell(row=0,col=0,shift=nil)
472
+ def delete_cell(row = 0, col=0, shift=nil)
701
473
  validate_workbook
702
474
  validate_nonnegative(row)
703
475
  validate_nonnegative(col)
704
- if @sheet_data.size <= row || @sheet_data[row].size <= col
705
- return nil
706
- end
707
476
 
708
- cell = @sheet_data[row][col]
709
- @sheet_data[row][col]=nil
477
+ return nil unless row_exists(row) && column_exists(col)
710
478
 
711
- if shift && shift != :left && shift != :up
712
- raise 'invalid shift option'
713
- end
479
+ cell = sheet_data[row][col]
714
480
 
715
- if shift == :left
716
- @sheet_data[row].delete_at(col)
717
- @sheet_data[row] << nil
718
- (col...(@sheet_data[row].size)).each do |index|
719
- if @sheet_data[row][index].is_a?(Cell)
720
- @sheet_data[row][index].column -= 1
721
- end
722
- end
723
- elsif shift == :up
724
- (row...(@sheet_data.size-1)).each do |index|
725
- @sheet_data[index][col] = @sheet_data[index+1][col]
726
- if @sheet_data[index][col].is_a?(Cell)
727
- @sheet_data[index][col].row -= 1
728
- end
729
- end
730
- if @sheet_data.last[col].is_a?(Cell)
731
- @sheet_data.last[col].row -= 1
732
- end
481
+ case shift
482
+ when nil then
483
+ sheet_data.rows[row].cells[col] = nil
484
+ when :left then
485
+ sheet_data.rows[row].delete_cell_shift_left(col)
486
+ when :up then
487
+ (row...(sheet_data.size - 1)).each { |index|
488
+ c = sheet_data.rows[index].cells[col] = sheet_data.rows[index + 1].cells[col]
489
+ c.row -= 1 if c.is_a?(Cell)
490
+ }
491
+ else
492
+ raise 'invalid shift option'
733
493
  end
734
494
 
735
495
  return cell
736
496
  end
737
497
 
738
- def get_row_fill(row=0)
739
- validate_workbook
740
- validate_nonnegative(row)
741
-
742
- if @sheet_data.size <= row
743
- return nil
744
- end
745
-
746
- if @row_styles[(row+1).to_s].nil?
747
- return "ffffff" #default, white
748
- end
749
-
750
- xf = xf_attr_row(row)
751
-
752
- return @workbook.get_fill_color(xf)
498
+ def get_row_fill(row = 0)
499
+ (row = sheet_data.rows[row]) && row.get_fill_color
753
500
  end
754
501
 
755
- def get_row_font_name(row=0)
756
- validate_workbook
757
- validate_nonnegative(row)
758
-
759
- if @sheet_data.size <= row
760
- return nil
761
- end
762
-
763
- if @row_styles[(row+1).to_s].nil?
764
- return 'Verdana'
765
- end
766
-
767
- xf = xf_attr_row(row)
768
-
769
- return @workbook.fonts[xf[:fontId].to_s][:font][:name][:attributes][:val]
502
+ def get_row_font_name(row = 0)
503
+ (font = row_font(row)) && font.get_name
770
504
  end
771
505
 
772
- def get_row_font_size(row=0)
773
- validate_workbook
774
- validate_nonnegative(row)
775
-
776
- if @sheet_data.size <= row
777
- return nil
778
- end
779
-
780
- if @row_styles[(row+1).to_s].nil?
781
- return '10'
782
- end
783
-
784
- xf = xf_attr_row(row)
785
-
786
- return @workbook.fonts[xf[:fontId].to_s][:font][:sz][:attributes][:val]
506
+ def get_row_font_size(row = 0)
507
+ (font = row_font(row)) && font.get_size
787
508
  end
788
509
 
789
- def get_row_font_color(row=0)
790
- validate_workbook
791
- validate_nonnegative(row)
792
-
793
- if @sheet_data.size <= row
794
- return nil
795
- end
796
-
797
- if @row_styles[(row+1).to_s].nil?
798
- return '000000'
799
- end
800
-
801
- xf = xf_attr_row(row)
802
-
803
- color = @workbook.fonts[xf[:fontId].to_s][:font][:color]
804
-
805
- if color.nil? || color[:attributes].nil? || color[:attributes][:rgb].nil?
806
- return '000000'
807
- end
808
-
809
- return color[:attributes][:rgb]
510
+ def get_row_font_color(row = 0)
511
+ font = row_font(row)
512
+ color = font && font.color
513
+ color && (color.rgb || '000000')
810
514
  end
811
515
 
812
- def is_row_italicized(row=0)
813
- return get_row_bool(row,:i)
516
+ def is_row_italicized(row = 0)
517
+ (font = row_font(row)) && font.is_italic
814
518
  end
815
519
 
816
- def is_row_bolded(row=0)
817
- return get_row_bool(row,:b)
520
+ def is_row_bolded(row = 0)
521
+ (font = row_font(row)) && font.is_bold
818
522
  end
819
523
 
820
- def is_row_underlined(row=0)
821
- return get_row_bool(row,:u)
524
+ def is_row_underlined(row = 0)
525
+ (font = row_font(row)) && font.is_underlined
822
526
  end
823
527
 
824
- def is_row_struckthrough(row=0)
825
- return get_row_bool(row,:strike)
528
+ def is_row_struckthrough(row = 0)
529
+ (font = row_font(row)) && font.is_strikethrough
826
530
  end
827
531
 
828
-
829
- def get_row_height(row=0)
532
+ def get_row_height(row = 0)
830
533
  validate_workbook
831
534
  validate_nonnegative(row)
832
-
833
- if @sheet_data.size <= row
834
- return nil
835
- end
836
-
837
- if @row_styles[(row+1).to_s].nil?
838
- return 13
839
- else
840
- @row_styles[(row+1).to_s][:height]
841
- end
535
+ return nil unless row_exists(row)
536
+ row = sheet_data.rows[row]
537
+ row && row.ht || 13
842
538
  end
843
539
 
844
- def get_row_horizontal_alignment(row=0)
845
- return get_row_alignment(row,true)
540
+ def get_row_horizontal_alignment(row = 0)
541
+ return get_row_alignment(row, true)
846
542
  end
847
543
 
848
- def get_row_vertical_alignment(row=0)
849
- return get_row_alignment(row,false)
544
+ def get_row_vertical_alignment(row = 0)
545
+ return get_row_alignment(row, false)
850
546
  end
851
547
 
852
- def get_row_border_top(row=0)
853
- return get_row_border(row,:top)
548
+ def get_row_border_top(row = 0)
549
+ return get_row_border(row, :top)
854
550
  end
855
551
 
856
- def get_row_border_left(row=0)
857
- return get_row_border(row,:left)
858
- end
552
+ def get_row_border_left(row = 0)
553
+ return get_row_border(row, :left)
554
+ end
859
555
 
860
- def get_row_border_right(row=0)
861
- return get_row_border(row,:right)
556
+ def get_row_border_right(row = 0)
557
+ return get_row_border(row, :right)
862
558
  end
863
559
 
864
- def get_row_border_bottom(row=0)
865
- return get_row_border(row,:bottom)
560
+ def get_row_border_bottom(row = 0)
561
+ return get_row_border(row, :bottom)
866
562
  end
867
563
 
868
- def get_row_border_diagonal(row=0)
869
- return get_row_border(row,:diagonal)
564
+ def get_row_border_diagonal(row = 0)
565
+ return get_row_border(row, :diagonal)
870
566
  end
871
567
 
872
- def get_column_font_name(col=0)
873
- validate_workbook
874
- validate_nonnegative(col)
875
-
876
- if @sheet_data[0].size <= col
877
- return nil
878
- end
879
-
880
- style_index = get_cols_style_index(col)
881
-
882
- return @workbook.fonts[font_id( style_index ).to_s][:font][:name][:attributes][:val]
568
+ def get_column_font_name(col = 0)
569
+ font = column_font(col)
570
+ font && font.get_name
883
571
  end
884
572
 
885
- def get_column_font_size(col=0)
886
- validate_workbook
887
- validate_nonnegative(col)
888
-
889
- if @sheet_data[0].size <= col
890
- return nil
891
- end
892
-
893
- style_index = get_cols_style_index(col)
894
-
895
- return @workbook.fonts[font_id( style_index ).to_s][:font][:sz][:attributes][:val]
573
+ def get_column_font_size(col = 0)
574
+ font = column_font(col)
575
+ font && font.get_size
896
576
  end
897
577
 
898
- def get_column_font_color(col=0)
899
- validate_workbook
900
- validate_nonnegative(col)
901
-
902
- if @sheet_data[0].size <= col
903
- return nil
904
- end
905
-
906
- style_index = get_cols_style_index(col)
907
-
908
- font = @workbook.fonts[font_id( style_index ).to_s][:font]
909
-
910
- if font[:color].nil? || font[:color][:attributes].nil? || font[:color][:attributes][:rgb].nil?
911
- return '000000'
912
- end
913
-
914
- return font[:color][:attributes][:rgb]
915
-
578
+ def get_column_font_color(col = 0)
579
+ font = column_font(col)
580
+ font && (font.get_rgb_color || '000000')
916
581
  end
917
582
 
918
- def is_column_italicized(col=0)
919
- get_column_bool(col,:i)
583
+ def is_column_italicized(col = 0)
584
+ font = column_font(col)
585
+ font && font.is_italic
920
586
  end
921
587
 
922
- def is_column_bolded(col=0)
923
- get_column_bool(col,:b)
588
+ def is_column_bolded(col = 0)
589
+ font = column_font(col)
590
+ font && font.is_bold
924
591
  end
925
592
 
926
- def is_column_underlined(col=0)
927
- get_column_bool(col,:u)
593
+ def is_column_underlined(col = 0)
594
+ font = column_font(col)
595
+ font && font.is_underlined
928
596
  end
929
597
 
930
- def is_column_struckthrough(col=0)
931
- get_column_bool(col,:strike)
598
+ def is_column_struckthrough(col = 0)
599
+ font = column_font(col)
600
+ font && font.is_strikethrough
932
601
  end
933
602
 
934
- def get_column_width(col=0)
603
+ def get_column_width(column_index = 0)
935
604
  validate_workbook
936
- validate_nonnegative(col)
937
-
938
- if @sheet_data[0].size <= col
939
- return nil
940
- end
941
-
942
- cols_index = get_cols_index(col)
605
+ validate_nonnegative(column_index)
606
+ return nil unless column_exists(column_index)
943
607
 
944
- if @cols[cols_index].nil? || @cols[cols_index][:attributes].nil? || @cols[cols_index][:attributes][:width].to_s == ''
945
- return 10
946
- end
947
-
948
- return @cols[cols_index][:attributes][:width]
608
+ range = cols.find(column_index)
609
+ (range && range.width) || 10
949
610
  end
950
611
 
951
612
  def get_column_fill(col=0)
952
613
  validate_workbook
953
614
  validate_nonnegative(col)
615
+ return nil unless column_exists(col)
954
616
 
955
- if @sheet_data[0].size <= col
956
- return nil
957
- end
958
-
959
- style_index = get_cols_style_index(col)
960
-
961
- if style_index == 0
962
- return "ffffff" #default, white
963
- end
964
-
965
- return @workbook.get_fill_color(@workbook.cell_xfs[:xf][style_index][:attributes])
617
+ @workbook.get_fill_color(get_col_xf(col))
966
618
  end
967
619
 
968
620
  def get_column_horizontal_alignment(col=0)
@@ -974,269 +626,132 @@ class Worksheet < PrivateClass
974
626
  end
975
627
 
976
628
  def get_column_border_top(col=0)
977
- return get_column_border(col,:top)
629
+ get_column_border(col, :top)
978
630
  end
979
631
 
980
632
  def get_column_border_left(col=0)
981
- return get_column_border(col,:left)
633
+ get_column_border(col, :left)
982
634
  end
983
635
 
984
636
  def get_column_border_right(col=0)
985
- return get_column_border(col,:right)
637
+ get_column_border(col, :right)
986
638
  end
987
639
 
988
640
  def get_column_border_bottom(col=0)
989
- return get_column_border(col,:bottom)
641
+ get_column_border(col, :bottom)
990
642
  end
991
643
 
992
644
  def get_column_border_diagonal(col=0)
993
- return get_column_border(col,:diagonal)
645
+ get_column_border(col, :diagonal)
994
646
  end
995
647
 
996
648
 
997
649
  private
998
650
 
999
- Worksheet::NAME = 0
1000
- Worksheet::SIZE = 1
1001
- Worksheet::COLOR = 2
1002
- Worksheet::ITALICS = 3
1003
- Worksheet::BOLD = 4
1004
- Worksheet::UNDERLINE = 5
1005
- Worksheet::STRIKETHROUGH = 6
1006
-
1007
- #row_styles is assumed to not be nil at specified row
1008
- def xf_attr_row(row)
1009
- row_style = @row_styles[(row+1).to_s][:style]
1010
- return @workbook.get_style_attributes(@workbook.get_style(row_style))
1011
- end
1012
-
1013
- def xf_attr_col(column)
1014
- col_style = @cols[get_cols_index(column)][:style]
1015
- return @workbook.get_style_attributes(@workbook.get_style(Integer(col_style)))
1016
- end
1017
-
1018
- def get_row_bool(row,property)
1019
- validate_workbook
1020
- validate_nonnegative(row)
1021
-
1022
- if @sheet_data.size <= row
1023
- return nil
1024
- end
651
+ NAME = 0
652
+ SIZE = 1
653
+ COLOR = 2
654
+ ITALICS = 3
655
+ BOLD = 4
656
+ UNDERLINE = 5
657
+ STRIKETHROUGH = 6
1025
658
 
1026
- if @row_styles[(row+1).to_s].nil?
1027
- return false
1028
- end
1029
-
1030
- xf = xf_attr_row(row)
1031
-
1032
- return !@workbook.fonts[xf[:fontId].to_s][:font][property].nil?
659
+ def row_font(row)
660
+ (row = sheet_data.rows[row]) && row.get_font
1033
661
  end
1034
662
 
1035
- def get_row_alignment(row,is_horizontal)
663
+ def get_row_alignment(row, is_horizontal)
1036
664
  validate_workbook
1037
665
  validate_nonnegative(row)
1038
666
 
1039
- if @sheet_data.size <= row || @row_styles[(row+1).to_s].nil?
1040
- return nil
1041
- end
667
+ return nil unless row_exists(row)
1042
668
 
1043
- xf_obj = @workbook.get_style(@row_styles[(row+1).to_s][:style])
1044
-
1045
- if xf_obj[:alignment].nil? || xf_obj[:alignment][:attributes].nil?
1046
- return nil
1047
- end
669
+ xf_obj = get_row_xf(row)
670
+ return nil if xf_obj.alignment.nil?
1048
671
 
1049
- if is_horizontal
1050
- return xf_obj[:alignment][:attributes][:horizontal].to_s
1051
- else
1052
- return xf_obj[:alignment][:attributes][:vertical].to_s
672
+ if is_horizontal then return xf_obj.alignment.horizontal
673
+ else return xf_obj.alignment.vertical
1053
674
  end
1054
675
  end
1055
676
 
1056
- def get_row_border(row,border_direction)
677
+ def get_row_border(row, border_direction)
1057
678
  validate_workbook
1058
679
  validate_nonnegative(row)
1059
680
 
1060
- if @sheet_data.size <= row || @row_styles[(row+1).to_s].nil?
1061
- return nil
1062
- end
1063
-
1064
- if @workbook.borders[xf_attr_row(row)[:borderId]].nil? && !@workbook.borders[xf_attr_row(row)[:borderId].to_s].nil?
1065
- @workbook.borders[xf_attr_row(row)[:borderId]] = deep_copy(@workbook.borders[xf_attr_row(row)[:borderId].to_s])
1066
- @workbook.borders.delete(xf_attr_row(row)[:borderId].to_s)
1067
- end
1068
-
1069
- if @workbook.borders[xf_attr_row(row)[:borderId]][:border][border_direction][:attributes].nil?
1070
- return nil
1071
- end
681
+ return nil unless row_exists(row)
1072
682
 
1073
- return @workbook.borders[xf_attr_row(row)[:borderId]][:border][border_direction][:attributes][:style]
683
+ border = @workbook.borders[get_row_xf(row).border_id]
684
+ border && border.get_edge_style(border_direction)
1074
685
  end
1075
686
 
1076
- def get_column_bool(col,property)
687
+ def column_font(col)
1077
688
  validate_workbook
1078
689
  validate_nonnegative(col)
690
+ return nil unless column_exists(col)
1079
691
 
1080
- if @sheet_data[0].size <= col
1081
- return nil
1082
- end
1083
-
1084
- style_index = get_cols_style_index(col)
1085
-
1086
- return !@workbook.fonts[font_id( style_index ).to_s][:font][property].nil?
692
+ @workbook.fonts[@workbook.cell_xfs[get_cols_style_index(col)].font_id]
1087
693
  end
1088
694
 
1089
695
  def get_column_alignment(col, type)
1090
696
  validate_workbook
1091
697
  validate_nonnegative(col)
698
+ return nil unless column_exists(col)
1092
699
 
1093
- if @sheet_data[0].size <= col
1094
- return nil
1095
- end
1096
-
1097
- style_index = get_cols_style_index(col)
1098
-
1099
- xf_obj = @workbook.get_style(style_index)
1100
- if xf_obj[:alignment].nil?
1101
- return nil
1102
- end
1103
-
1104
- return xf_obj[:alignment][:attributes][type]
700
+ xf = @workbook.cell_xfs[get_cols_style_index(col)]
701
+ xf.alignment && xf.alignment.send(type)
1105
702
  end
1106
703
 
1107
704
  def get_column_border(col, border_direction)
1108
705
  validate_workbook
1109
706
  validate_nonnegative(col)
1110
- style_index = get_cols_style_index(col)
1111
- xf = @workbook.get_style_attributes(@workbook.get_style(style_index))
1112
-
1113
- if @sheet_data[0].size <= col
1114
- return nil
1115
- end
1116
-
1117
- if @workbook.borders[xf[:borderId]].nil? && !@workbook.borders[xf[:borderId].to_s].nil?
1118
- @workbook.borders[xf[:borderId]] = deep_copy(@workbook.borders[xf[:borderId].to_s])
1119
- @workbook.borders.delete(xf[:borderId].to_s)
1120
- end
1121
-
1122
- if @workbook.borders[xf[:borderId]][:border][border_direction][:attributes].nil?
1123
- return nil
1124
- end
1125
-
1126
- return @workbook.borders[xf[:borderId]][:border][border_direction][:attributes][:style]
1127
- end
707
+ return nil unless column_exists(col)
1128
708
 
1129
- def deep_copy(hash)
1130
- Marshal.load(Marshal.dump(hash))
709
+ xf = @workbook.cell_xfs[get_cols_style_index(col)]
710
+ border = @workbook.borders[xf.border_id]
711
+ border && border.get_edge_style(border_direction)
1131
712
  end
1132
713
 
1133
714
  #validates Workbook, ensures that this worksheet is in @workbook
1134
715
  def validate_workbook()
1135
716
  unless @workbook.nil? || @workbook.worksheets.nil?
1136
- @workbook.worksheets.each do |sheet|
1137
- if sheet == self
1138
- return
1139
- end
1140
- end
717
+ return if @workbook.worksheets.include?(self)
1141
718
  end
1142
- raise "This worksheet #{self} is not in workbook #{@workbook}"
1143
- end
1144
-
1145
- # because cols is not ordered by col num, this actually gets
1146
- # the index in the array based on which column is actually being asked for by the user
1147
- def get_cols_index(col)
1148
- i = @cols.size - 1
1149
-
1150
- @cols.reverse_each do |column|
1151
- if col >= (Integer(column[:attributes][:min])-1)
1152
- if col <= (Integer(column[:attributes][:max])-1)
1153
- break
1154
- end
1155
- end
1156
- i -= 1
1157
- end
1158
- if i < 0
1159
- i = @cols.size #effectively nil
1160
- end
1161
- i
1162
- end
1163
719
 
1164
- def get_cols_style_index(col)
1165
- cols_index = get_cols_index(col)
1166
- if cols_index == @cols.size
1167
- return 0
1168
- end
1169
- return Integer(@cols[cols_index][:attributes][:style])
720
+ raise "This worksheet #{self} is not in workbook #{@workbook}"
1170
721
  end
1171
722
 
1172
- #change cols array
1173
- def change_cols(i,col_index)
1174
- style = '0'
1175
- if @cols[i].nil?
1176
- @cols << {:attributes=>{:style=>nil,:min=>nil,:max=>nil,:width=>nil,:customWidth=>nil}}
1177
- else
1178
- @cols << deep_copy(@cols[i])
1179
- style = @cols[i][:attributes][:style]
1180
- end
1181
- @cols.last[:attributes][:style] = style
1182
- @cols.last[:attributes][:min] = (Integer(col_index)+1).to_s
1183
- @cols.last[:attributes][:max] = (Integer(col_index)+1).to_s
1184
- @cols.last[:attributes][:width] = '10'
1185
- @cols.last[:attributes][:customWidth] = '0'
723
+ def get_cols_style_index(column_index)
724
+ range = cols.find(column_index)
725
+ (range && range.style) || 0
1186
726
  end
1187
727
 
1188
728
  # Helper method to update the row styles array
1189
729
  # change_type - NAME or SIZE or COLOR etc
1190
730
  # main method to change font, called from each separate font mutator method
1191
- def change_row_font(row, change_type, arg, font, xf_id)
731
+ def change_row_font(row, change_type, arg, font)
1192
732
  validate_workbook
1193
- validate_nonnegative(row)
1194
- increase_rows(row)
1195
-
1196
- # Modify font array and retrieve new font id
1197
- font_id = modify_font(@workbook, font, xf_id[:fontId].to_s)
1198
- # Get copy of xf object with modified font id
1199
- xf = deep_copy(xf_id)
1200
- xf[:fontId] = Integer(font_id)
1201
- # Modify xf array and retrieve new xf id
1202
- @row_styles[(row+1).to_s][:style] = modify_xf(@workbook, xf)
1203
-
1204
- if @sheet_data[row].nil?
1205
- @sheet_data[row] = []
1206
- end
733
+ ensure_cell_exists(row)
1207
734
 
1208
- @sheet_data[Integer(row)].each do |c|
1209
- unless c.nil?
1210
- font_switch(c, change_type, arg)
1211
- end
1212
- end
735
+ xf = workbook.register_new_font(font, get_row_xf(row))
736
+ sheet_data.rows[row].s = workbook.register_new_xf(xf, get_row_style(row))
737
+
738
+ sheet_data[row].cells.each { |c| font_switch(c, change_type, arg) unless c.nil? }
1213
739
  end
1214
740
 
1215
741
  # Helper method to update the fonts and cell styles array
1216
742
  # main method to change font, called from each separate font mutator method
1217
- def change_column_font(col, change_type, arg, font, xf_id)
743
+ def change_column_font(column_index, change_type, arg, font, xf)
1218
744
  validate_workbook
1219
- validate_nonnegative(col)
1220
- increase_columns(col)
1221
-
1222
- i = get_cols_index(col)
745
+ ensure_cell_exists(0, column_index)
1223
746
 
1224
- # Modify font array and retrieve new font id
1225
- font_id = modify_font(@workbook, font, xf_id[:fontId].to_s)
1226
- # Get copy of xf object with modified font id
1227
- xf = deep_copy(xf_id)
1228
- xf[:fontId] = Integer(font_id)
1229
- # Modify xf array and retrieve new xf id
1230
- modify_xf(@workbook, xf)
747
+ xf = workbook.register_new_font(font, xf)
1231
748
 
1232
- change_cols(i, col)
749
+ cols.get_range(column_index).style = workbook.register_new_xf(xf, get_col_style(column_index))
1233
750
 
1234
- @sheet_data.each_with_index do |row, i|
1235
- c = row[col]
1236
- unless c.nil?
1237
- font_switch(c, change_type, arg)
1238
- end
1239
- end
751
+ sheet_data.rows.each { |row|
752
+ c = row[column_index]
753
+ font_switch(c, change_type, arg) unless c.nil?
754
+ }
1240
755
  end
1241
756
 
1242
757
  #performs correct modification based on what type of change_type is specified
@@ -1280,214 +795,146 @@ class Worksheet < PrivateClass
1280
795
  end
1281
796
  end
1282
797
 
1283
- #increases number of rows until the array at index row is not nil
1284
- def increase_rows(row)
1285
- @sheet_data.size.upto(row) do
1286
- @sheet_data << Array.new(@sheet_data[0].size)
1287
- end
1288
- end
1289
-
1290
- #increases number of columns until the array at index column is not nil
1291
- def increase_columns(column)
1292
- @sheet_data.each do |r|
1293
- r.size.upto(column) do
1294
- r << nil
1295
- end
1296
- end
1297
- end
798
+ # Ensures that cell with +row_index+ and +column_index+ exists in
799
+ # +sheet_data+ arrays, growing them up if necessary.
800
+ def ensure_cell_exists(row_index, column_index = 0)
801
+ validate_nonnegative(row_index)
802
+ validate_nonnegative(column_index)
803
+
804
+ existing_row_count = sheet_data.rows.size
805
+
806
+ # Expand cell arrays in existing rows, if necessary.
807
+ # Writing anything to a cell in the array automatically creates all the members
808
+ # with lower indices, filling them with +nil+s. But, we can't just write +nil+
809
+ # to +column_index+ because it may be less than +size+! So we read from that index
810
+ # (if it didn't exist, we will get nil) and write right back.
811
+ sheet_data.rows.each { |r| r.cells[column_index] = r.cells[column_index] }
812
+
813
+ first_row = sheet_data.rows.first
814
+ col_size = [ first_row && first_row.cells.size || 0, column_index ].max
815
+
816
+ # Now create new rows with the required number of cells.
817
+ # Doing +.downto()+ here so the reallocation of row array has to only happen once,
818
+ # when it is extended to max size; after that, we will be writing into existing
819
+ # (but empty) members. Additional checks are not necessary, because if +row_index+
820
+ # is less than +size+, then +.downto()+ will not execute, and if it equals +size+,
821
+ # then the block will be invoked exactly once, which takes care of the case when
822
+ # +row_index+ is greater than the current max index by exactly 1.
823
+ row_index.downto(existing_row_count) { |r|
824
+ add_row(r, :cells => Array.new(col_size))
825
+ }
826
+ end
1298
827
 
1299
- # Helper method to get the font id for a style index
1300
- def font_id(style_index)
1301
- xf_id(style_index)[:fontId]
828
+ # Helper method to get the style index for a column
829
+ def get_col_style(column_index)
830
+ range = cols.find(column_index)
831
+ (range && range.style) || 0
1302
832
  end
1303
833
 
1304
- # Helper method to get the style attributes for a style index
1305
- def xf_id(style_index)
1306
- @workbook.get_style_attributes(@workbook.get_style(style_index))
834
+ def get_row_style(row)
835
+ r = sheet_data.rows[row]
836
+ (r && r.s) || 0
1307
837
  end
1308
838
 
1309
- # Helper method to get the style index for a row
1310
- def get_row_style(row)
1311
- if @row_styles[(row+1).to_s].nil?
1312
- @row_styles[(row+1).to_s] = {}
1313
- @row_styles[(row+1).to_s][:style] = '0'
1314
- @workbook.fonts['0'][:count] += 1
1315
- end
1316
- return @row_styles[(row+1).to_s][:style]
839
+ def get_col_xf(column_index)
840
+ @workbook.cell_xfs[get_col_style(column_index)]
1317
841
  end
1318
842
 
1319
- # Helper method to get the style index for a column
1320
- def get_col_style(col)
1321
- i = get_cols_index(col)
1322
- if @cols[i].nil?
1323
- @workbook.fonts['0'][:count] += 1
1324
- return 0
1325
- else
1326
- return Integer(@cols[i][:attributes][:style])
1327
- end
843
+ def get_row_xf(row)
844
+ @workbook.cell_xfs[get_row_style(row)]
1328
845
  end
1329
846
 
1330
847
  def change_row_alignment(row,alignment,is_horizontal)
1331
848
  validate_workbook
1332
849
  validate_nonnegative(row)
850
+ ensure_cell_exists(row)
1333
851
 
1334
- increase_rows(row)
852
+ sheet_data.rows[row].s = @workbook.modify_alignment(get_row_style(row), is_horizontal, alignment)
1335
853
 
1336
- if @row_styles[(row+1).to_s].nil?
1337
- @row_styles[(row+1).to_s] = {}
1338
- @row_styles[(row+1).to_s][:style] = '0'
1339
- end
1340
-
1341
- @row_styles[(row+1).to_s][:style] =
1342
- modify_alignment(@workbook,@row_styles[(row+1).to_s][:style],is_horizontal,alignment)
1343
-
1344
- @sheet_data[row].each do |c|
1345
- unless c.nil?
1346
- if is_horizontal
1347
- c.change_horizontal_alignment(alignment)
1348
- else
1349
- c.change_vertical_alignment(alignment)
1350
- end
854
+ sheet_data[row].cells.each { |c|
855
+ next if c.nil?
856
+ if is_horizontal then c.change_horizontal_alignment(alignment)
857
+ else c.change_vertical_alignment(alignment)
1351
858
  end
1352
- end
859
+ }
1353
860
  end
1354
861
 
1355
- def change_column_alignment(col,alignment,is_horizontal)
862
+ def change_column_alignment(column_index, alignment, is_horizontal)
1356
863
  validate_workbook
1357
- validate_nonnegative(col)
864
+ ensure_cell_exists(0, column_index)
1358
865
 
1359
- increase_columns(col)
866
+ cols.get_range(column_index).style = @workbook.modify_alignment(get_col_style(column_index), is_horizontal, alignment)
1360
867
 
1361
- i = get_cols_index(col)
1362
-
1363
- if @cols[i].nil?
1364
- style_index = 0
1365
- else
1366
- style_index = Integer(@cols[i][:attributes][:style])
1367
- end
1368
-
1369
- style_index = modify_alignment(@workbook,style_index,is_horizontal,alignment)
1370
-
1371
- change_cols(i,col)
1372
-
1373
- @cols[i][:attributes][:style] = style_index
1374
-
1375
- @sheet_data.each_with_index do |row,i|
1376
- c = row[Integer(col)]
1377
- unless c.nil?
1378
- if is_horizontal
1379
- c.change_horizontal_alignment(alignment)
1380
- else
1381
- c.change_vertical_alignment(alignment)
1382
- end
868
+ sheet_data.rows.each { |row|
869
+ c = row[column_index]
870
+ next if c.nil?
871
+ if is_horizontal
872
+ c.change_horizontal_alignment(alignment)
873
+ else
874
+ c.change_vertical_alignment(alignment)
1383
875
  end
1384
- end
876
+ }
1385
877
  end
1386
878
 
1387
879
  def change_row_border(row, direction, weight)
1388
880
  validate_workbook
1389
- validate_nonnegative(row)
1390
- validate_border(weight)
1391
- increase_rows(row)
881
+ ensure_cell_exists(row)
1392
882
 
1393
- if @row_styles[(row+1).to_s].nil?
1394
- @row_styles[(row+1).to_s]= {}
1395
- @row_styles[(row+1).to_s][:style] = '0'
1396
- end
1397
- @row_styles[(row+1).to_s][:style] = modify_border(@workbook,@row_styles[(row+1).to_s][:style])
883
+ sheet_data.rows[row].s = @workbook.modify_border(get_row_style(row), direction, weight)
1398
884
 
1399
- if @workbook.borders[xf_attr_row(row)[:borderId]][:border][direction][:attributes].nil?
1400
- @workbook.borders[xf_attr_row(row)[:borderId]][:border][direction][:attributes] = { :style => nil }
1401
- end
1402
- @workbook.borders[xf_attr_row(row)[:borderId]][:border][direction][:attributes][:style] = weight.to_s
1403
-
1404
- @sheet_data[row].each do |c|
1405
- unless c.nil?
1406
- case direction
1407
- when :top
1408
- c.change_border_top(weight)
1409
- when :left
1410
- c.change_border_left(weight)
1411
- when :right
1412
- c.change_border_right(weight)
1413
- when :bottom
1414
- c.change_border_bottom(weight)
1415
- when :diagonal
1416
- c.change_border_diagonal(weight)
1417
- else
1418
- raise 'invalid direction'
1419
- end
885
+ sheet_data[row].cells.each { |c|
886
+ next if c.nil?
887
+ case direction
888
+ when :top then c.change_border_top(weight)
889
+ when :left then c.change_border_left(weight)
890
+ when :right then c.change_border_right(weight)
891
+ when :bottom then c.change_border_bottom(weight)
892
+ when :diagonal then c.change_border_diagonal(weight)
893
+ else raise 'invalid direction'
1420
894
  end
1421
- end
895
+ }
1422
896
  end
1423
897
 
1424
- def change_column_border(col,direction,weight)
898
+ def change_column_border(column_index, direction, weight)
1425
899
  validate_workbook
1426
- validate_nonnegative(col)
1427
- validate_border(weight)
900
+ ensure_cell_exists(0, column_index)
1428
901
 
1429
- increase_columns(col)
902
+ cols.get_range(column_index).style = @workbook.modify_border(get_col_style(column_index), direction, weight)
1430
903
 
1431
- i = get_cols_index(col)
1432
- if @cols[i].nil?
1433
- style_index = 0
1434
- else
1435
- style_index = Integer(@cols[i][:attributes][:style])
1436
- end
1437
-
1438
- style_index = modify_border(@workbook,style_index)
1439
-
1440
- change_cols(i,col)
1441
-
1442
- xf = @workbook.get_style_attributes(@workbook.get_style(style_index))
1443
-
1444
- if @workbook.borders[xf[:borderId]][:border][direction][:attributes].nil?
1445
- @workbook.borders[xf[:borderId]][:border][direction][:attributes] = { :style => nil }
1446
- end
1447
- @workbook.borders[xf[:borderId]][:border][direction][:attributes][:style] = weight.to_s
1448
-
1449
- @sheet_data.each_with_index do |row,i|
1450
- c = row[Integer(col)]
1451
- unless c.nil?
1452
- case direction
1453
- when :top
1454
- c.change_border_top(weight)
1455
- when :left
1456
- c.change_border_left(weight)
1457
- when :right
1458
- c.change_border_right(weight)
1459
- when :bottom
1460
- c.change_border_bottom(weight)
1461
- when :diagonal
1462
- c.change_border_diagonal(weight)
1463
- else
1464
- raise 'invalid direction'
1465
- end
904
+ sheet_data.rows.each { |row|
905
+ c = row.cells[column_index]
906
+ next if c.nil?
907
+ case direction
908
+ when :top then c.change_border_top(weight)
909
+ when :left then c.change_border_left(weight)
910
+ when :right then c.change_border_right(weight)
911
+ when :bottom then c.change_border_bottom(weight)
912
+ when :diagonal then c.change_border_diagonal(weight)
913
+ else raise 'invalid direction'
1466
914
  end
1467
- end
915
+ }
1468
916
  end
1469
917
 
1470
918
  def add_cell_style(row,column)
1471
- xf = @workbook.get_style_attributes(@workbook.get_style(@sheet_data[row][column].style_index))
1472
- @workbook.fonts[xf[:fontId].to_s][:count] += 1
1473
- @workbook.fills[xf[:fillId].to_s][:count] += 1
1474
- @workbook.borders[xf[:borderId].to_s][:count] += 1
919
+ xf = @workbook.cell_xfs[sheet_data.rows[row].cells[column].style_index]
920
+ @workbook.fonts[xf.font_id].count += 1
921
+ @workbook.fills[xf.fill_id].count += 1
922
+ @workbook.borders[xf.border_id].count += 1
1475
923
  end
1476
924
 
1477
- # finds first row which contains at least all strings in cells_content
1478
- def find_first_row_with_content(cells_content)
1479
- validate_workbook
1480
- index = nil
925
+ def validate_nonnegative(row_or_col)
926
+ raise 'Row and Column arguments must be nonnegative' if row_or_col < 0
927
+ end
928
+ private :validate_nonnegative
1481
929
 
1482
- @sheet_data.each_with_index do |row, index|
1483
- cells_content = cells_content.map { |header| header.to_s.downcase.strip }
1484
- original_cells_content = row.map { |cell| cell.nil? ? '' : cell.value.to_s.downcase.strip }
1485
- if (cells_content & original_cells_content).size == cells_content.size
1486
- return index
1487
- end
1488
- end
1489
- return nil
930
+ def column_exists(col)
931
+ sheet_data.rows[0].cells.size > col
1490
932
  end
1491
933
 
934
+ def row_exists(row)
935
+ sheet_data.rows.size > row
936
+ end
937
+
938
+
1492
939
  end #end class
1493
940
  end