listen360-rubyXL 1.2.10.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.
- data/Gemfile +16 -0
- data/Gemfile.lock +34 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +197 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/.DS_Store +0 -0
- data/lib/rubyXL.rb +10 -0
- data/lib/rubyXL/Hash.rb +60 -0
- data/lib/rubyXL/cell.rb +461 -0
- data/lib/rubyXL/color.rb +14 -0
- data/lib/rubyXL/parser.rb +468 -0
- data/lib/rubyXL/private_class.rb +265 -0
- data/lib/rubyXL/workbook.rb +450 -0
- data/lib/rubyXL/worksheet.rb +1493 -0
- data/lib/rubyXL/writer/app_writer.rb +62 -0
- data/lib/rubyXL/writer/calc_chain_writer.rb +33 -0
- data/lib/rubyXL/writer/content_types_writer.rb +77 -0
- data/lib/rubyXL/writer/core_writer.rb +51 -0
- data/lib/rubyXL/writer/root_rels_writer.rb +25 -0
- data/lib/rubyXL/writer/shared_strings_writer.rb +30 -0
- data/lib/rubyXL/writer/styles_writer.rb +407 -0
- data/lib/rubyXL/writer/theme_writer.rb +343 -0
- data/lib/rubyXL/writer/workbook_rels_writer.rb +59 -0
- data/lib/rubyXL/writer/workbook_writer.rb +77 -0
- data/lib/rubyXL/writer/worksheet_writer.rb +230 -0
- data/lib/rubyXL/zip.rb +20 -0
- data/rubyXL.gemspec +92 -0
- data/spec/lib/cell_spec.rb +385 -0
- data/spec/lib/color_spec.rb +14 -0
- data/spec/lib/hash_spec.rb +28 -0
- data/spec/lib/parser_spec.rb +66 -0
- data/spec/lib/workbook_spec.rb +51 -0
- data/spec/lib/worksheet_spec.rb +1782 -0
- metadata +207 -0
@@ -0,0 +1,1493 @@
|
|
1
|
+
module RubyXL
|
2
|
+
class Worksheet < PrivateClass
|
3
|
+
include Enumerable
|
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
|
+
}
|
21
|
+
@extLst = nil
|
22
|
+
@legacy_drawing=nil
|
23
|
+
end
|
24
|
+
|
25
|
+
# allows for easier access to sheet_data
|
26
|
+
def [](row=0)
|
27
|
+
return @sheet_data[row]
|
28
|
+
end
|
29
|
+
|
30
|
+
def each
|
31
|
+
@sheet_data.each {|i| yield i}
|
32
|
+
end
|
33
|
+
|
34
|
+
#returns 2d array of just the cell values (without style or formula information)
|
35
|
+
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}}
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_table(headers=[],opts={})
|
41
|
+
validate_workbook
|
42
|
+
|
43
|
+
if !headers.is_a?(Array)
|
44
|
+
headers = [headers]
|
45
|
+
end
|
46
|
+
|
47
|
+
row_num = find_first_row_with_content(headers)
|
48
|
+
|
49
|
+
if row_num.nil?
|
50
|
+
return nil
|
51
|
+
end
|
52
|
+
|
53
|
+
table_hash = {}
|
54
|
+
table_hash[:table] = []
|
55
|
+
|
56
|
+
header_row = @sheet_data[row_num]
|
57
|
+
header_row.each_with_index do |header_cell, index|
|
58
|
+
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
|
+
next if header_cell.nil? || header_cell.value.nil?
|
60
|
+
header = header_cell.value.to_s
|
61
|
+
table_hash[:sorted_headers]||=[]
|
62
|
+
table_hash[:sorted_headers] << header
|
63
|
+
table_hash[header] = []
|
64
|
+
|
65
|
+
original_row = row_num + 1
|
66
|
+
current_row = original_row
|
67
|
+
|
68
|
+
cell = @sheet_data[current_row][index]
|
69
|
+
|
70
|
+
# makes array of hashes in table_hash[:table]
|
71
|
+
# as well as hash of arrays in table_hash[header]
|
72
|
+
table_index = current_row - original_row
|
73
|
+
cell_test= (!cell.nil? && !cell.value.nil?)
|
74
|
+
while cell_test || !table_hash[:table][table_index].empty?
|
75
|
+
|
76
|
+
table_hash[header] << (cell_test ? cell.value : nil)
|
77
|
+
|
78
|
+
table_index = current_row - original_row
|
79
|
+
|
80
|
+
if table_hash[:table][table_index].nil?
|
81
|
+
table_hash[:table][table_index] = {}
|
82
|
+
end
|
83
|
+
|
84
|
+
table_hash[:table][table_index][header] = cell.value if cell_test
|
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
|
95
|
+
|
96
|
+
return table_hash
|
97
|
+
end
|
98
|
+
|
99
|
+
#changes color of fill in (zer0 indexed) row
|
100
|
+
def change_row_fill(row=0,rgb='ffffff')
|
101
|
+
validate_workbook
|
102
|
+
validate_nonnegative(row)
|
103
|
+
increase_rows(row)
|
104
|
+
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
|
+
|
112
|
+
@sheet_data[Integer(row)].each do |c|
|
113
|
+
unless c.nil?
|
114
|
+
c.change_fill(rgb)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
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)
|
128
|
+
end
|
129
|
+
|
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)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Changes font color of row
|
142
|
+
def change_row_font_color(row=0, font_color='000000')
|
143
|
+
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)
|
200
|
+
|
201
|
+
increase_rows(row)
|
202
|
+
|
203
|
+
if height.to_i.to_s == height.to_s
|
204
|
+
height = Integer(height)
|
205
|
+
elsif height.to_f.to_s == height.to_s
|
206
|
+
height = Float(height)
|
207
|
+
else
|
208
|
+
raise 'You must enter a number for the height'
|
209
|
+
end
|
210
|
+
|
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'
|
217
|
+
end
|
218
|
+
|
219
|
+
def change_row_horizontal_alignment(row=0,alignment='center')
|
220
|
+
validate_workbook
|
221
|
+
validate_nonnegative(row)
|
222
|
+
validate_horizontal_alignment(alignment)
|
223
|
+
change_row_alignment(row,alignment,true)
|
224
|
+
end
|
225
|
+
|
226
|
+
def change_row_vertical_alignment(row=0,alignment='center')
|
227
|
+
validate_workbook
|
228
|
+
validate_nonnegative(row)
|
229
|
+
validate_vertical_alignment(alignment)
|
230
|
+
change_row_alignment(row,alignment,false)
|
231
|
+
end
|
232
|
+
|
233
|
+
def change_row_border_top(row=0,weight='thin')
|
234
|
+
change_row_border(row, :top, weight)
|
235
|
+
end
|
236
|
+
|
237
|
+
def change_row_border_left(row=0,weight='thin')
|
238
|
+
change_row_border(row, :left, weight)
|
239
|
+
end
|
240
|
+
|
241
|
+
def change_row_border_right(row=0,weight='thin')
|
242
|
+
change_row_border(row, :right, weight)
|
243
|
+
end
|
244
|
+
|
245
|
+
def change_row_border_bottom(row=0,weight='thin')
|
246
|
+
change_row_border(row, :bottom, weight)
|
247
|
+
end
|
248
|
+
|
249
|
+
def change_row_border_diagonal(row=0,weight='thin')
|
250
|
+
change_row_border(row, :diagonal, weight)
|
251
|
+
end
|
252
|
+
|
253
|
+
# 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)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Changes font size of column
|
265
|
+
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)
|
273
|
+
end
|
274
|
+
|
275
|
+
# Changes font color of column
|
276
|
+
def change_column_font_color(col=0, font_color='000000')
|
277
|
+
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)
|
329
|
+
end
|
330
|
+
|
331
|
+
def change_column_width(col=0,width=13)
|
332
|
+
validate_workbook
|
333
|
+
validate_nonnegative(col)
|
334
|
+
increase_columns(col)
|
335
|
+
|
336
|
+
i = get_cols_index(col)
|
337
|
+
|
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
|
345
|
+
|
346
|
+
change_cols(i,col)
|
347
|
+
@cols.last[:attributes][:width] = width
|
348
|
+
@cols.last[:attributes][:customWidth] = '1'
|
349
|
+
end
|
350
|
+
|
351
|
+
def change_column_fill(col=0, color_index='ffffff')
|
352
|
+
validate_workbook
|
353
|
+
validate_nonnegative(col)
|
354
|
+
Color.validate_color(color_index)
|
355
|
+
increase_columns(col)
|
356
|
+
|
357
|
+
i = get_cols_index(col)
|
358
|
+
|
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)
|
368
|
+
|
369
|
+
change_cols(i,col)
|
370
|
+
|
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
|
377
|
+
|
378
|
+
end
|
379
|
+
|
380
|
+
def change_column_horizontal_alignment(col=0,alignment='center')
|
381
|
+
validate_workbook
|
382
|
+
validate_nonnegative(col)
|
383
|
+
validate_horizontal_alignment(alignment)
|
384
|
+
change_column_alignment(col,alignment,true)
|
385
|
+
end
|
386
|
+
|
387
|
+
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)
|
392
|
+
end
|
393
|
+
|
394
|
+
def change_column_border_top(col=0,weight='thin')
|
395
|
+
change_column_border(col,:top,weight)
|
396
|
+
end
|
397
|
+
|
398
|
+
def change_column_border_left(col=0,weight='thin')
|
399
|
+
change_column_border(col,:left,weight)
|
400
|
+
end
|
401
|
+
|
402
|
+
def change_column_border_right(col=0,weight='thin')
|
403
|
+
change_column_border(col,:right,weight)
|
404
|
+
end
|
405
|
+
|
406
|
+
def change_column_border_bottom(col=0,weight='thin')
|
407
|
+
change_column_border(col,:bottom,weight)
|
408
|
+
end
|
409
|
+
|
410
|
+
def change_column_border_diagonal(col=0,weight='thin')
|
411
|
+
change_column_border(col,:diagonal,weight)
|
412
|
+
end
|
413
|
+
|
414
|
+
# 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)
|
428
|
+
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
|
+
|
456
|
+
add_cell_style(row,column)
|
457
|
+
|
458
|
+
return @sheet_data[row][column]
|
459
|
+
end
|
460
|
+
|
461
|
+
def add_cell_obj(cell, overwrite=true)
|
462
|
+
validate_workbook
|
463
|
+
|
464
|
+
if cell.nil?
|
465
|
+
return cell
|
466
|
+
end
|
467
|
+
|
468
|
+
row = cell.row
|
469
|
+
column = cell.column
|
470
|
+
|
471
|
+
validate_nonnegative(row)
|
472
|
+
validate_nonnegative(column)
|
473
|
+
|
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
|
480
|
+
end
|
481
|
+
|
482
|
+
add_cell_style(row,column)
|
483
|
+
|
484
|
+
return @sheet_data[row][column]
|
485
|
+
end
|
486
|
+
|
487
|
+
def delete_row(row_index=0)
|
488
|
+
validate_workbook
|
489
|
+
validate_nonnegative(row_index)
|
490
|
+
|
491
|
+
if row_index >= @sheet_data.size
|
492
|
+
return nil
|
493
|
+
end
|
494
|
+
|
495
|
+
deleted = @sheet_data.delete_at(row_index)
|
496
|
+
row_num = row_index+1
|
497
|
+
|
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
|
510
|
+
|
511
|
+
return deleted
|
512
|
+
end
|
513
|
+
|
514
|
+
#inserts row at row_index, pushes down, copies style from below (row previously at that index)
|
515
|
+
#USE OF THIS METHOD will break formulas which reference cells which are being "pushed down"
|
516
|
+
def insert_row(row_index=0)
|
517
|
+
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
|
536
|
+
|
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]
|
554
|
+
else
|
555
|
+
@row_styles[row_num.to_s] = nil#@row_styles[(row_num+1).to_s]
|
556
|
+
end
|
557
|
+
|
558
|
+
#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
|
567
|
+
|
568
|
+
return @sheet_data[row_index]
|
569
|
+
end
|
570
|
+
|
571
|
+
def delete_column(col_index=0)
|
572
|
+
validate_workbook
|
573
|
+
validate_nonnegative(col_index)
|
574
|
+
|
575
|
+
if col_index >= @sheet_data[0].size
|
576
|
+
return nil
|
577
|
+
end
|
578
|
+
|
579
|
+
#delete column
|
580
|
+
@sheet_data.map {|r| r.delete_at(col_index)}
|
581
|
+
|
582
|
+
#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
|
590
|
+
|
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
|
601
|
+
end
|
602
|
+
|
603
|
+
# inserts column at col_index, pushes everything right, takes styles from column to left
|
604
|
+
# USE OF THIS METHOD will break formulas which reference cells which are being "pushed down"
|
605
|
+
def insert_column(col_index=0)
|
606
|
+
validate_workbook
|
607
|
+
validate_nonnegative(col_index)
|
608
|
+
increase_columns(col_index)
|
609
|
+
|
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
|
615
|
+
|
616
|
+
#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
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
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
|
638
|
+
|
639
|
+
new_col = @cols.last
|
640
|
+
if @cols.last.nil?
|
641
|
+
@cols.pop
|
642
|
+
end
|
643
|
+
|
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
|
666
|
+
end
|
667
|
+
|
668
|
+
def insert_cell(row=0,col=0,data=nil,formula=nil,shift=nil)
|
669
|
+
validate_workbook
|
670
|
+
validate_nonnegative(row)
|
671
|
+
validate_nonnegative(col)
|
672
|
+
|
673
|
+
increase_rows(row)
|
674
|
+
increase_columns(col)
|
675
|
+
|
676
|
+
if shift && shift != :right && shift != :down
|
677
|
+
raise 'invalid shift option'
|
678
|
+
end
|
679
|
+
|
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
|
+
return add_cell(row,col,data,formula)
|
695
|
+
end
|
696
|
+
|
697
|
+
# by default, only sets cell to nil
|
698
|
+
# if :left is specified, method will shift row contents to the right of the deleted cell to the left
|
699
|
+
# if :up is specified, method will shift column contents below the deleted cell upward
|
700
|
+
def delete_cell(row=0,col=0,shift=nil)
|
701
|
+
validate_workbook
|
702
|
+
validate_nonnegative(row)
|
703
|
+
validate_nonnegative(col)
|
704
|
+
if @sheet_data.size <= row || @sheet_data[row].size <= col
|
705
|
+
return nil
|
706
|
+
end
|
707
|
+
|
708
|
+
cell = @sheet_data[row][col]
|
709
|
+
@sheet_data[row][col]=nil
|
710
|
+
|
711
|
+
if shift && shift != :left && shift != :up
|
712
|
+
raise 'invalid shift option'
|
713
|
+
end
|
714
|
+
|
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
|
733
|
+
end
|
734
|
+
|
735
|
+
return cell
|
736
|
+
end
|
737
|
+
|
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)
|
753
|
+
end
|
754
|
+
|
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]
|
770
|
+
end
|
771
|
+
|
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]
|
787
|
+
end
|
788
|
+
|
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]
|
810
|
+
end
|
811
|
+
|
812
|
+
def is_row_italicized(row=0)
|
813
|
+
return get_row_bool(row,:i)
|
814
|
+
end
|
815
|
+
|
816
|
+
def is_row_bolded(row=0)
|
817
|
+
return get_row_bool(row,:b)
|
818
|
+
end
|
819
|
+
|
820
|
+
def is_row_underlined(row=0)
|
821
|
+
return get_row_bool(row,:u)
|
822
|
+
end
|
823
|
+
|
824
|
+
def is_row_struckthrough(row=0)
|
825
|
+
return get_row_bool(row,:strike)
|
826
|
+
end
|
827
|
+
|
828
|
+
|
829
|
+
def get_row_height(row=0)
|
830
|
+
validate_workbook
|
831
|
+
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
|
842
|
+
end
|
843
|
+
|
844
|
+
def get_row_horizontal_alignment(row=0)
|
845
|
+
return get_row_alignment(row,true)
|
846
|
+
end
|
847
|
+
|
848
|
+
def get_row_vertical_alignment(row=0)
|
849
|
+
return get_row_alignment(row,false)
|
850
|
+
end
|
851
|
+
|
852
|
+
def get_row_border_top(row=0)
|
853
|
+
return get_row_border(row,:top)
|
854
|
+
end
|
855
|
+
|
856
|
+
def get_row_border_left(row=0)
|
857
|
+
return get_row_border(row,:left)
|
858
|
+
end
|
859
|
+
|
860
|
+
def get_row_border_right(row=0)
|
861
|
+
return get_row_border(row,:right)
|
862
|
+
end
|
863
|
+
|
864
|
+
def get_row_border_bottom(row=0)
|
865
|
+
return get_row_border(row,:bottom)
|
866
|
+
end
|
867
|
+
|
868
|
+
def get_row_border_diagonal(row=0)
|
869
|
+
return get_row_border(row,:diagonal)
|
870
|
+
end
|
871
|
+
|
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]
|
883
|
+
end
|
884
|
+
|
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]
|
896
|
+
end
|
897
|
+
|
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
|
+
|
916
|
+
end
|
917
|
+
|
918
|
+
def is_column_italicized(col=0)
|
919
|
+
get_column_bool(col,:i)
|
920
|
+
end
|
921
|
+
|
922
|
+
def is_column_bolded(col=0)
|
923
|
+
get_column_bool(col,:b)
|
924
|
+
end
|
925
|
+
|
926
|
+
def is_column_underlined(col=0)
|
927
|
+
get_column_bool(col,:u)
|
928
|
+
end
|
929
|
+
|
930
|
+
def is_column_struckthrough(col=0)
|
931
|
+
get_column_bool(col,:strike)
|
932
|
+
end
|
933
|
+
|
934
|
+
def get_column_width(col=0)
|
935
|
+
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)
|
943
|
+
|
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]
|
949
|
+
end
|
950
|
+
|
951
|
+
def get_column_fill(col=0)
|
952
|
+
validate_workbook
|
953
|
+
validate_nonnegative(col)
|
954
|
+
|
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])
|
966
|
+
end
|
967
|
+
|
968
|
+
def get_column_horizontal_alignment(col=0)
|
969
|
+
get_column_alignment(col, :horizontal)
|
970
|
+
end
|
971
|
+
|
972
|
+
def get_column_vertical_alignment(col=0)
|
973
|
+
get_column_alignment(col, :vertical)
|
974
|
+
end
|
975
|
+
|
976
|
+
def get_column_border_top(col=0)
|
977
|
+
return get_column_border(col,:top)
|
978
|
+
end
|
979
|
+
|
980
|
+
def get_column_border_left(col=0)
|
981
|
+
return get_column_border(col,:left)
|
982
|
+
end
|
983
|
+
|
984
|
+
def get_column_border_right(col=0)
|
985
|
+
return get_column_border(col,:right)
|
986
|
+
end
|
987
|
+
|
988
|
+
def get_column_border_bottom(col=0)
|
989
|
+
return get_column_border(col,:bottom)
|
990
|
+
end
|
991
|
+
|
992
|
+
def get_column_border_diagonal(col=0)
|
993
|
+
return get_column_border(col,:diagonal)
|
994
|
+
end
|
995
|
+
|
996
|
+
|
997
|
+
private
|
998
|
+
|
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
|
1025
|
+
|
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?
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
def get_row_alignment(row,is_horizontal)
|
1036
|
+
validate_workbook
|
1037
|
+
validate_nonnegative(row)
|
1038
|
+
|
1039
|
+
if @sheet_data.size <= row || @row_styles[(row+1).to_s].nil?
|
1040
|
+
return nil
|
1041
|
+
end
|
1042
|
+
|
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
|
1048
|
+
|
1049
|
+
if is_horizontal
|
1050
|
+
return xf_obj[:alignment][:attributes][:horizontal].to_s
|
1051
|
+
else
|
1052
|
+
return xf_obj[:alignment][:attributes][:vertical].to_s
|
1053
|
+
end
|
1054
|
+
end
|
1055
|
+
|
1056
|
+
def get_row_border(row,border_direction)
|
1057
|
+
validate_workbook
|
1058
|
+
validate_nonnegative(row)
|
1059
|
+
|
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
|
1072
|
+
|
1073
|
+
return @workbook.borders[xf_attr_row(row)[:borderId]][:border][border_direction][:attributes][:style]
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
def get_column_bool(col,property)
|
1077
|
+
validate_workbook
|
1078
|
+
validate_nonnegative(col)
|
1079
|
+
|
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?
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
def get_column_alignment(col, type)
|
1090
|
+
validate_workbook
|
1091
|
+
validate_nonnegative(col)
|
1092
|
+
|
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]
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
def get_column_border(col, border_direction)
|
1108
|
+
validate_workbook
|
1109
|
+
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
|
1128
|
+
|
1129
|
+
def deep_copy(hash)
|
1130
|
+
Marshal.load(Marshal.dump(hash))
|
1131
|
+
end
|
1132
|
+
|
1133
|
+
#validates Workbook, ensures that this worksheet is in @workbook
|
1134
|
+
def validate_workbook()
|
1135
|
+
unless @workbook.nil? || @workbook.worksheets.nil?
|
1136
|
+
@workbook.worksheets.each do |sheet|
|
1137
|
+
if sheet == self
|
1138
|
+
return
|
1139
|
+
end
|
1140
|
+
end
|
1141
|
+
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
|
+
|
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])
|
1170
|
+
end
|
1171
|
+
|
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'
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
# Helper method to update the row styles array
|
1189
|
+
# change_type - NAME or SIZE or COLOR etc
|
1190
|
+
# main method to change font, called from each separate font mutator method
|
1191
|
+
def change_row_font(row, change_type, arg, font, xf_id)
|
1192
|
+
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
|
1207
|
+
|
1208
|
+
@sheet_data[Integer(row)].each do |c|
|
1209
|
+
unless c.nil?
|
1210
|
+
font_switch(c, change_type, arg)
|
1211
|
+
end
|
1212
|
+
end
|
1213
|
+
end
|
1214
|
+
|
1215
|
+
# Helper method to update the fonts and cell styles array
|
1216
|
+
# main method to change font, called from each separate font mutator method
|
1217
|
+
def change_column_font(col, change_type, arg, font, xf_id)
|
1218
|
+
validate_workbook
|
1219
|
+
validate_nonnegative(col)
|
1220
|
+
increase_columns(col)
|
1221
|
+
|
1222
|
+
i = get_cols_index(col)
|
1223
|
+
|
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)
|
1231
|
+
|
1232
|
+
change_cols(i, col)
|
1233
|
+
|
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
|
1240
|
+
end
|
1241
|
+
|
1242
|
+
#performs correct modification based on what type of change_type is specified
|
1243
|
+
def font_switch(c,change_type,arg)
|
1244
|
+
case change_type
|
1245
|
+
when Worksheet::NAME
|
1246
|
+
unless arg.is_a?String
|
1247
|
+
raise 'Not a String'
|
1248
|
+
end
|
1249
|
+
c.change_font_name(arg)
|
1250
|
+
when Worksheet::SIZE
|
1251
|
+
unless arg.is_a?(Integer) || arg.is_a?(Float)
|
1252
|
+
raise 'Not a Number'
|
1253
|
+
end
|
1254
|
+
c.change_font_size(arg)
|
1255
|
+
when Worksheet::COLOR
|
1256
|
+
Color.validate_color(arg)
|
1257
|
+
c.change_font_color(arg)
|
1258
|
+
when Worksheet::ITALICS
|
1259
|
+
unless arg == !!arg
|
1260
|
+
raise 'Not a boolean'
|
1261
|
+
end
|
1262
|
+
c.change_font_italics(arg)
|
1263
|
+
when Worksheet::BOLD
|
1264
|
+
unless arg == !!arg
|
1265
|
+
raise 'Not a boolean'
|
1266
|
+
end
|
1267
|
+
c.change_font_bold(arg)
|
1268
|
+
when Worksheet::UNDERLINE
|
1269
|
+
unless arg == !!arg
|
1270
|
+
raise 'Not a boolean'
|
1271
|
+
end
|
1272
|
+
c.change_font_underline(arg)
|
1273
|
+
when Worksheet::STRIKETHROUGH
|
1274
|
+
unless arg == !!arg
|
1275
|
+
raise 'Not a boolean'
|
1276
|
+
end
|
1277
|
+
c.change_font_strikethrough(arg)
|
1278
|
+
else
|
1279
|
+
raise 'Invalid change_type'
|
1280
|
+
end
|
1281
|
+
end
|
1282
|
+
|
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
|
1298
|
+
|
1299
|
+
# Helper method to get the font id for a style index
|
1300
|
+
def font_id(style_index)
|
1301
|
+
xf_id(style_index)[:fontId]
|
1302
|
+
end
|
1303
|
+
|
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))
|
1307
|
+
end
|
1308
|
+
|
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]
|
1317
|
+
end
|
1318
|
+
|
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
|
1328
|
+
end
|
1329
|
+
|
1330
|
+
def change_row_alignment(row,alignment,is_horizontal)
|
1331
|
+
validate_workbook
|
1332
|
+
validate_nonnegative(row)
|
1333
|
+
|
1334
|
+
increase_rows(row)
|
1335
|
+
|
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
|
1351
|
+
end
|
1352
|
+
end
|
1353
|
+
end
|
1354
|
+
|
1355
|
+
def change_column_alignment(col,alignment,is_horizontal)
|
1356
|
+
validate_workbook
|
1357
|
+
validate_nonnegative(col)
|
1358
|
+
|
1359
|
+
increase_columns(col)
|
1360
|
+
|
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
|
1383
|
+
end
|
1384
|
+
end
|
1385
|
+
end
|
1386
|
+
|
1387
|
+
def change_row_border(row, direction, weight)
|
1388
|
+
validate_workbook
|
1389
|
+
validate_nonnegative(row)
|
1390
|
+
validate_border(weight)
|
1391
|
+
increase_rows(row)
|
1392
|
+
|
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])
|
1398
|
+
|
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
|
1420
|
+
end
|
1421
|
+
end
|
1422
|
+
end
|
1423
|
+
|
1424
|
+
def change_column_border(col,direction,weight)
|
1425
|
+
validate_workbook
|
1426
|
+
validate_nonnegative(col)
|
1427
|
+
validate_border(weight)
|
1428
|
+
|
1429
|
+
increase_columns(col)
|
1430
|
+
|
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
|
1466
|
+
end
|
1467
|
+
end
|
1468
|
+
end
|
1469
|
+
|
1470
|
+
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
|
1475
|
+
end
|
1476
|
+
|
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
|
1481
|
+
|
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
|
1490
|
+
end
|
1491
|
+
|
1492
|
+
end #end class
|
1493
|
+
end
|