rubyXL 1.2.10 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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