surpass 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/History.txt +0 -0
  2. data/README.txt +133 -0
  3. data/Rakefile +35 -0
  4. data/examples/big-16mb.rb +25 -0
  5. data/examples/big-random-strings.rb +28 -0
  6. data/examples/blanks.rb +34 -0
  7. data/examples/col_width.rb +16 -0
  8. data/examples/dates.rb +31 -0
  9. data/examples/format.rb +23 -0
  10. data/examples/hello-world.rb +9 -0
  11. data/examples/image.rb +10 -0
  12. data/examples/merged.rb +36 -0
  13. data/examples/merged0.rb +27 -0
  14. data/examples/merged1.rb +99 -0
  15. data/examples/num_formats.rb +55 -0
  16. data/examples/numbers.rb +24 -0
  17. data/examples/outline.rb +110 -0
  18. data/examples/panes.rb +48 -0
  19. data/examples/protection.rb +132 -0
  20. data/examples/python.bmp +0 -0
  21. data/examples/row_styles.rb +16 -0
  22. data/examples/row_styles_empty.rb +15 -0
  23. data/examples/set_cell_and_range_style.rb +12 -0
  24. data/examples/wrapped-text.rb +13 -0
  25. data/examples/write_arrays.rb +16 -0
  26. data/examples/ws_props.rb +80 -0
  27. data/lib/biff_record.rb +2168 -0
  28. data/lib/bitmap.rb +218 -0
  29. data/lib/cell.rb +214 -0
  30. data/lib/chart.rb +16 -0
  31. data/lib/column.rb +40 -0
  32. data/lib/document.rb +406 -0
  33. data/lib/excel_formula.rb +6 -0
  34. data/lib/excel_magic.rb +1013 -0
  35. data/lib/formatting.rb +554 -0
  36. data/lib/row.rb +137 -0
  37. data/lib/style.rb +179 -0
  38. data/lib/surpass.rb +51 -0
  39. data/lib/utilities.rb +86 -0
  40. data/lib/workbook.rb +206 -0
  41. data/lib/worksheet.rb +561 -0
  42. data/spec/biff_record_spec.rb +268 -0
  43. data/spec/cell_spec.rb +56 -0
  44. data/spec/data/random-strings.txt +10000 -0
  45. data/spec/document_spec.rb +168 -0
  46. data/spec/excel_formula_spec.rb +0 -0
  47. data/spec/formatting_spec.rb +53 -0
  48. data/spec/reference/P-0508-0000507647-3280-5298.xls +0 -0
  49. data/spec/reference/all-cell-styles.bin +0 -0
  50. data/spec/reference/all-number-formats.bin +0 -0
  51. data/spec/reference/all-styles.bin +0 -0
  52. data/spec/reference/mini.xls +0 -0
  53. data/spec/row_spec.rb +19 -0
  54. data/spec/spec_helper.rb +10 -0
  55. data/spec/style_spec.rb +89 -0
  56. data/spec/utilities_spec.rb +57 -0
  57. data/spec/workbook_spec.rb +48 -0
  58. data/spec/worksheet_spec.rb +0 -0
  59. data/stats/cloc.txt +8 -0
  60. data/stats/rcov.txt +0 -0
  61. data/stats/specdoc.txt +158 -0
  62. data/surpass-manual-0-0-3.pdf +0 -0
  63. data/surpass.gemspec +34 -0
  64. data/tasks/ann.rake +80 -0
  65. data/tasks/bones.rake +20 -0
  66. data/tasks/excel.rake +6 -0
  67. data/tasks/gem.rake +201 -0
  68. data/tasks/git.rake +40 -0
  69. data/tasks/metrics.rake +42 -0
  70. data/tasks/notes.rake +27 -0
  71. data/tasks/post_load.rake +34 -0
  72. data/tasks/rdoc.rake +51 -0
  73. data/tasks/rubyforge.rake +55 -0
  74. data/tasks/setup.rb +292 -0
  75. data/tasks/spec.rake +54 -0
  76. data/tasks/svn.rake +47 -0
  77. data/tasks/test.rake +40 -0
  78. metadata +144 -0
data/lib/worksheet.rb ADDED
@@ -0,0 +1,561 @@
1
+ class Worksheet
2
+ include Utilities
3
+
4
+ attr_accessor :name
5
+ attr_accessor :parent
6
+ attr_accessor :rows
7
+ attr_accessor :cols
8
+ attr_accessor :merged_ranges
9
+ attr_accessor :bmp_rec
10
+ attr_accessor :show_formulas
11
+ attr_accessor :show_grid
12
+ attr_accessor :show_headers
13
+ attr_accessor :panes_frozen
14
+ attr_accessor :show_empty_as_zero
15
+ attr_accessor :auto_colour_grid
16
+ attr_accessor :cols_right_to_left
17
+ attr_accessor :show_outline
18
+ attr_accessor :remove_splits
19
+ attr_accessor :selected
20
+ # RED HERRING ALERT: "sheet_visible" is a clone of the "selected" attribute.
21
+ # Typically a workbook created by the Excel UI will have one sheet
22
+ # (the sheet that was selected when the user saved it)
23
+ # with both bits set to 1, and all other sheets will have both
24
+ # bits set to 0. The true visibility of the sheet is found in the "visibility"
25
+ # attribute obtained from the BOUNDSHEET record.
26
+ attr_accessor :sheet_visible
27
+ attr_accessor :page_preview
28
+ attr_accessor :first_visible_row
29
+ attr_accessor :first_visible_col
30
+ attr_accessor :grid_colour
31
+ attr_accessor :preview_magn
32
+ attr_accessor :normal_magn
33
+ attr_accessor :visibility
34
+ attr_accessor :vert_split_pos
35
+ attr_accessor :horz_split_pos
36
+ attr_accessor :vert_split_first_visible
37
+ attr_accessor :horz_split_first_visible
38
+
39
+ attr_accessor :delta
40
+ attr_accessor :save_recalc
41
+
42
+ attr_accessor :print_headers
43
+ attr_accessor :print_grid
44
+ attr_accessor :grid_set
45
+ attr_accessor :vert_page_breaks
46
+ attr_accessor :horz_page_breaks
47
+ attr_accessor :header_str
48
+ attr_accessor :footer_str
49
+ attr_accessor :print_centered_vert
50
+ attr_accessor :print_centered_horz
51
+ attr_accessor :left_margin
52
+ attr_accessor :right_margin
53
+ attr_accessor :top_margin
54
+ attr_accessor :bottom_margin
55
+ attr_accessor :paper_size_code
56
+ attr_accessor :print_scaling
57
+ attr_accessor :start_page_number
58
+ attr_accessor :fit_width_to_pages
59
+ attr_accessor :fit_height_to_pages
60
+ attr_accessor :print_in_rows
61
+ attr_accessor :portrait
62
+ attr_accessor :print_not_colour
63
+ attr_accessor :print_draft
64
+ attr_accessor :print_notes
65
+ attr_accessor :print_notes_at_end
66
+ attr_accessor :print_omit_errors
67
+ attr_accessor :print_hres
68
+ attr_accessor :print_vres
69
+ attr_accessor :header_margin
70
+ attr_accessor :footer_margin
71
+ attr_accessor :copies_num
72
+
73
+ attr_accessor :show_auto_page_breaks
74
+ attr_accessor :dialogue_sheet
75
+ attr_accessor :auto_style_outline
76
+ attr_accessor :outline_below
77
+ attr_accessor :outline_right
78
+ attr_accessor :fit_num_pages
79
+ attr_accessor :show_row_outline
80
+ attr_accessor :show_col_outline
81
+ attr_accessor :alt_expr_eval
82
+ attr_accessor :alt_formula_entries
83
+
84
+ attr_accessor :col_default_width
85
+ attr_reader :calc_mode
86
+ attr_accessor :calc_count
87
+
88
+ attr_accessor :protect
89
+ attr_accessor :wnd_protect
90
+ attr_accessor :obj_protect
91
+ attr_accessor :scen_protect
92
+ attr_accessor :password
93
+
94
+ def initialize(name, parent)
95
+ @name = name
96
+ @parent = parent
97
+ @rows = {}
98
+ @cols = {}
99
+ @merged_ranges = []
100
+ @bmp_rec = ''
101
+ @show_formulas = 0
102
+ @show_grid = 1
103
+ @show_headers = 1
104
+ @panes_frozen = 0
105
+ @show_empty_as_zero = 1
106
+ @auto_colour_grid = 1
107
+ @cols_right_to_left = 0
108
+ @show_outline = 1
109
+ @remove_splits = 0
110
+ @selected = 0
111
+ @sheet_visible = 0
112
+ @page_preview = 0
113
+
114
+ @first_visible_row = 0
115
+ @first_visible_col = 0
116
+ @grid_colour = 0x40
117
+ @preview_magn = 0
118
+ @normal_magn = 0
119
+ @visibility = 0
120
+
121
+ @vert_split_pos = nil
122
+ @horz_split_pos = nil
123
+ @vert_split_first_visible = nil
124
+ @horz_split_first_visible = nil
125
+ @split_active_pane = nil # TODO test implications of converting None -> Nil
126
+
127
+ @row_gut_width = 0
128
+ @col_gut_height = 0
129
+
130
+ @show_auto_page_breaks = 1
131
+ @dialogue_sheet = 0
132
+ @auto_style_outline = 0
133
+ @outline_below = 0
134
+ @outline_right = 0
135
+ @fit_num_pages = 0
136
+ @show_row_outline = 1
137
+ @show_col_outline = 1
138
+ @alt_expr_eval = 0
139
+ @alt_formula_entries = 0
140
+
141
+ @row_default_height = 0x00FF
142
+ @col_default_width = 0x0008
143
+
144
+ @default_row_height_mismatch = 0
145
+ @default_row_hidden = 0
146
+ @default_row_space_above = 0
147
+ @default_row_space_below = 0
148
+
149
+ @calc_mode = 1
150
+ @calc_count = 0x0064
151
+ @rc_ref_mode = 1
152
+ @iterations_on = 0
153
+ @delta = 0.001
154
+ @save_recalc = 0
155
+ @formula_options = ExcelFormula::RECALC_ALWAYS | ExcelFormula::CALC_ON_OPEN
156
+
157
+ @print_headers = 0
158
+ @print_grid = 0
159
+ @grid_set = 1
160
+ @vert_page_breaks = []
161
+ @horz_page_breaks = []
162
+ @header_str = '&P'
163
+ @footer_str = '&F'
164
+ @print_centered_vert = 0
165
+ @print_centered_horz = 1
166
+ @left_margin = 0.3 #0.5
167
+ @right_margin = 0.3 #0.5
168
+ @top_margin = 0.61 #1.0
169
+ @bottom_margin = 0.37 #1.0
170
+ @paper_size_code = 9 # A4
171
+ @print_scaling = 100
172
+ @start_page_number = 1
173
+ @fit_width_to_pages = 1
174
+ @fit_height_to_pages = 1
175
+ @print_in_rows = 1
176
+ @portrait = 1
177
+ @print_not_colour = 0
178
+ @print_draft = 0
179
+ @print_notes = 0
180
+ @print_notes_at_end = 0
181
+ @print_omit_errors = 0
182
+ @print_hres = 0x012C # 300 dpi
183
+ @print_vres = 0x012C # 300 dpi
184
+ @header_margin = 0.1
185
+ @footer_margin = 0.1
186
+ @copies_num = 1
187
+
188
+ @wnd_protect = 0
189
+ @obj_protect = 0
190
+ @protect = 0
191
+ @scen_protect = 0
192
+ @password = ''
193
+
194
+ @charts = []
195
+ end
196
+
197
+ # Accessors Performing Conversions
198
+ def row_default_height
199
+ twips_to_pixels(@row_default_height)
200
+ end
201
+
202
+ def row_default_height=(pixels)
203
+ @row_default_height = pixels_to_twips(pixels)
204
+ end
205
+
206
+ def calc_mode=(value)
207
+ @calc_mode = (value == 0xFFFF && value) || value & 0x01
208
+ end
209
+
210
+ def set_cell_style(r, c, style, create_blanks = false)
211
+ cell = rows[r].cell(c)
212
+ if cell.nil?
213
+ write(r, c, nil, style) if create_blanks
214
+ else
215
+ cell.set_style(style)
216
+ end
217
+ end
218
+
219
+ def hide_columns(col_range)
220
+ col_range.each do |c|
221
+ hide_column(c)
222
+ end
223
+ end
224
+
225
+ def unhide_columns(col_range)
226
+ col_range.each do |c|
227
+ unhide_column(c)
228
+ end
229
+ end
230
+
231
+ def set_column_widths(col_range, width)
232
+ col_range.each do |c|
233
+ set_column_width(c, width)
234
+ end
235
+ end
236
+
237
+ def hide_column(c)
238
+ col(c).hidden = true
239
+ end
240
+
241
+ def unhide_column(c)
242
+ col(c).hidden = false
243
+ end
244
+
245
+ # TODO fix this if column doesn't exist yet.
246
+ def set_column_width(c, width)
247
+ if width < 100
248
+ # Assume we are trying to use Excel-user style widths, scale up accordingly.
249
+ # You can call col's width method directly to avoid this.
250
+ width = width * 260
251
+ end
252
+ col(c).width = width
253
+ end
254
+
255
+ # Change the style for a range of cells. If nil is supplied for row_range,
256
+ # the new style is supplied to every row (i.e. the entire column). Only
257
+ # changes style for cells which actually exist, so this does not paint
258
+ # anything which has not been written to.
259
+ def set_range_style(row_range, col_range, style, create_blanks = false)
260
+ row_range ||= 0..65535
261
+ col_range ||= 0..255
262
+
263
+ @rows.each do |i, r|
264
+ next unless row_range.include?(i)
265
+ r.cells.each do |c|
266
+ next unless col_range.include?(c.col)
267
+ c.set_style(style)
268
+ end
269
+ end
270
+ end
271
+
272
+ # Write the text stored in label in a single cell at (r,c) according to style.
273
+ def write(r, c, label = "", style = @parent.styles.default_style)
274
+ row(r).write(c, label, style)
275
+ end
276
+
277
+ def write_array_to_row(array, r, c = 0, style = @parent.styles.default_style)
278
+ array.each_with_index do |a, i|
279
+ row(r).write(c + i, a, style)
280
+ end
281
+ end
282
+ alias :rarray :write_array_to_row
283
+
284
+ def write_array_to_column(array, c, r = 0, style = @parent.styles.default_style)
285
+ array.each_with_index do |a, i|
286
+ row(r + i).write(c, a, style)
287
+ end
288
+ end
289
+ alias :carray :write_array_to_column
290
+
291
+ def write_arrays(array_of_arrays, r = 0, c = 0, style = @parent.styles.default_style)
292
+ array_of_arrays.each_with_index do |a, i|
293
+ raise "not an array of arrays!" unless a.is_a?(Array)
294
+ write_array_to_row(a, r + i, c, style)
295
+ end
296
+ end
297
+
298
+ # Comment from xlwt:
299
+ ## Stand-alone merge of previously written cells.
300
+ ## Problems: (1) style to be used should be existing style of
301
+ ## the top-left cell, not an arg.
302
+ ## (2) should ensure that any previous data value in
303
+ ## non-top-left cells is nobbled.
304
+ ## Note: if a cell is set by a data record then later
305
+ ## is referenced by a [MUL]BLANK record, Excel will blank
306
+ ## out the cell on the screen, but OOo & Gnu will not
307
+ ## blank it out. Need to do something better than writing
308
+ ## multiple records. In the meantime, avoid this method and use
309
+ ## write_merge() instead.
310
+ def merge(r1, r2, c1, c2, style = @parent.styles.default_style)
311
+ row(r1).write_blanks(c1 + 1, c2, style) if c2 > c1
312
+ ((r1+1)...(r2+1)).each do |r|
313
+ row(r).write_blanks(c1, c2, style)
314
+ end
315
+ @merged_ranges << [r1, r2, c1, c2]
316
+ end
317
+
318
+ def write_merge(r1, r2, c1, c2, label="", style = @parent.styles.default_style)
319
+ write(r1, c1, label, style)
320
+ merge(r1, r2, c1, c2, style)
321
+ end
322
+
323
+ def to_biff
324
+ result = []
325
+ result << Biff8BOFRecord.new(Biff8BOFRecord::WORKSHEET).to_biff
326
+ # Calc Settings
327
+ result << CalcModeRecord.new(@calc_mode).to_biff
328
+ result << CalcCountRecord.new(@calc_count & 0xFFFF).to_biff
329
+ result << RefModeRecord.new(@rc_ref_mode & 0x01).to_biff
330
+ result << IterationRecord.new(@iterations_on & 0x01).to_biff
331
+ result << DeltaRecord.new(@delta).to_biff
332
+ result << SaveRecalcRecord.new(@save_recalc & 0x01).to_biff
333
+
334
+ result << guts_record
335
+ result << default_row_height_record
336
+ result << wsbool_record
337
+ result << @cols.sort.collect {|k, v| v.to_biff }.join
338
+ result << dimensions_rec
339
+
340
+ # Print Settings
341
+ result << PrintHeadersRecord.new(@print_headers).to_biff
342
+ result << PrintGridLinesRecord.new(@print_grid).to_biff
343
+ result << GridSetRecord.new(@grid_set).to_biff
344
+ result << HorizontalPageBreaksRecord.new(@horz_page_breaks.collect {|b| b.is_a?(Integer) ? [b, 0, -1] : b }).to_biff
345
+ result << VerticalPageBreaksRecord.new(@vert_page_breaks.collect {|b| b.is_a?(Integer) ? [b, 0, -1] : b }).to_biff
346
+ result << HeaderRecord.new(@header_str).to_biff
347
+ result << FooterRecord.new(@footer_str).to_biff
348
+ result << HCenterRecord.new(@print_centered_horz).to_biff
349
+ result << VCenterRecord.new(@print_centered_vert).to_biff
350
+ result << LeftMarginRecord.new(@left_margin).to_biff
351
+ result << RightMarginRecord.new(@right_margin).to_biff
352
+ result << TopMarginRecord.new(@top_margin).to_biff
353
+ result << BottomMarginRecord.new(@bottom_margin).to_biff
354
+ result << setup_page_record
355
+
356
+ # Protection Settings
357
+ result << ProtectRecord.new(as_numeric(@protect)).to_biff()
358
+ result << ScenarioProtectRecord.new(as_numeric(@scen_protect)).to_biff()
359
+ result << WindowProtectRecord.new(as_numeric(@wnd_protect)).to_biff()
360
+ result << ObjectProtectRecord.new(as_numeric(@obj_protect)).to_biff()
361
+ result << PasswordRecord.new(@password).to_biff()
362
+
363
+ keys = @rows.keys.sort
364
+ keys.each do |i|
365
+ result << @rows[i].to_biff
366
+ result << @rows[i].cells_biff
367
+ end
368
+
369
+ # @charts.each do |c|
370
+ # result << c.to_biff
371
+ # end
372
+ result << MergedCellsRecord.new(@merged_ranges).to_biff
373
+ result << @bmp_rec
374
+ result << window_2_record
375
+ result << panes_record
376
+ # result << hyperlink_table_record
377
+ result << EOFRecord.new.to_biff
378
+
379
+ result.join
380
+ end
381
+
382
+ def guts_record
383
+ max_row_level = @rows.values.inject(-1) {|level, row| row.level > level ? row.level : level }
384
+ max_col_level = @cols.values.inject(-1) {|level, col| col.level > level ? col.level : level }
385
+
386
+ row_visible_levels = @rows.empty? ? 0 : max_row_level + 1
387
+ col_visible_levels = @cols.empty? ? 0 : max_col_level + 1
388
+
389
+ GutsRecord.new(@row_gut_width, @col_gut_height, row_visible_levels, col_visible_levels).to_biff
390
+ end
391
+
392
+ def default_row_height_record
393
+ options = 0x00
394
+ options |= (@default_row_height_mismatch & 0x01) << 0
395
+ options |= (@default_row_hidden & 0x01) << 1
396
+ options |= (@default_row_space_above & 0x01) << 2
397
+ options |= (@default_row_space_below & 0x01) << 3
398
+
399
+ DefaultRowHeight.new(options, @row_default_height).to_biff
400
+ end
401
+
402
+ def wsbool_record
403
+ options = 0x00
404
+ options |= (@show_auto_page_breaks & 0x01) << 0
405
+ options |= (@dialogue_sheet & 0x01) << 4
406
+ options |= (@auto_style_outline & 0x01) << 5
407
+ options |= (@outline_below & 0x01) << 6
408
+ options |= (@outline_right & 0x01) << 7
409
+ options |= (@fit_num_pages & 0x01) << 8
410
+ options |= (@show_row_outline & 0x01) << 10
411
+ options |= (@show_col_outline & 0x01) << 11
412
+ options |= (@alt_expr_eval & 0x01) << 14
413
+ options |= (@alt_formula_entries & 0x01) << 15
414
+
415
+ WSBoolRecord.new(options).to_biff
416
+ end
417
+
418
+ def dimensions_rec
419
+ first_used_row = 0
420
+ last_used_row = 0
421
+ first_used_col = 0
422
+ last_used_col = 0
423
+
424
+ if !@rows.empty?
425
+ first_used_row = @rows.keys.sort.first
426
+ last_used_row = @rows.keys.sort.last
427
+ first_used_col = 0xFFFFFFFF
428
+ last_used_col = 0
429
+ end
430
+
431
+ first_used_col = @rows.values.inject(first_used_col) {|min_col, r| r.min_col_index < min_col ? min_col = r.min_col_index : min_col }
432
+ last_used_col = @rows.values.inject(last_used_col) {|max_col, r| r.max_col_index > max_col ? max_col = r.max_col_index : max_col }
433
+
434
+ DimensionsRecord.new(first_used_row, last_used_row, first_used_col, last_used_col).to_biff
435
+ end
436
+
437
+ def setup_page_record
438
+ setup_page_options = (@print_in_rows & 0x01) << 0
439
+ setup_page_options |= (@portrait & 0x01) << 1
440
+ setup_page_options |= (0x00 & 0x01) << 2
441
+ setup_page_options |= (@print_not_colour & 0x01) << 3
442
+ setup_page_options |= (@print_draft & 0x01) << 4
443
+ setup_page_options |= (@print_notes & 0x01) << 5
444
+ setup_page_options |= (0x00 & 0x01) << 6
445
+ setup_page_options |= (0x01 & 0x01) << 7
446
+ setup_page_options |= (@print_notes_at_end & 0x01) << 9
447
+ setup_page_options |= (@print_omit_errors & 0x03) << 10
448
+
449
+ args = [
450
+ @paper_size_code,
451
+ @print_scaling,
452
+ @start_page_number,
453
+ @fit_width_to_pages,
454
+ @fit_height_to_pages,
455
+ setup_page_options,
456
+ @print_hres,
457
+ @print_vres,
458
+ @header_margin,
459
+ @footer_margin,
460
+ @copies_num
461
+ ]
462
+ SetupPageRecord.new(*args).to_biff
463
+ end
464
+
465
+ def window_2_record
466
+ options = 0
467
+ options |= (as_numeric(@show_formulas ) & 0x01) << 0
468
+ options |= (as_numeric(@show_grid ) & 0x01) << 1
469
+ options |= (as_numeric(@show_headers ) & 0x01) << 2
470
+ options |= (as_numeric(@panes_frozen ) & 0x01) << 3
471
+ options |= (as_numeric(@show_empty_as_zero ) & 0x01) << 4
472
+ options |= (as_numeric(@auto_colour_grid ) & 0x01) << 5
473
+ options |= (as_numeric(@cols_right_to_left ) & 0x01) << 6
474
+ options |= (as_numeric(@show_outline ) & 0x01) << 7
475
+ options |= (as_numeric(@remove_splits ) & 0x01) << 8
476
+ options |= (as_numeric(@selected ) & 0x01) << 9
477
+ options |= (as_numeric(@sheet_visible ) & 0x01) << 10
478
+ options |= (as_numeric(@page_preview ) & 0x01) << 11
479
+
480
+ if @page_preview != 0
481
+ if @preview_magn == 0
482
+ scl_magn = 60
483
+ else
484
+ scl_magn = @preview_magn
485
+ end
486
+ else
487
+ scl_magn = @normal_magn
488
+ end
489
+
490
+ Window2Record.new(options, @first_visible_row, @first_visible_col, @grid_colour, @preview_magn, @normal_magn, scl_magn).to_biff
491
+ end
492
+
493
+ def panes_record
494
+ return '' if @vert_split_pos.nil? && @horz_split_pos.nil?
495
+ @vert_split_pos = 0 if @vert_split_pos.nil?
496
+ @horz_split_pos = 0 if @horz_split_pos.nil?
497
+ if @panes_frozen
498
+ @vert_split_first_visible = @vert_split_pos if @vert_split_first_visible.nil?
499
+ @horz_split_first_visible = @horz_split_pos if @horz_split_first_visible.nil?
500
+ else
501
+ @vert_split_first_visible = 0 if @vert_split_first_visible.nil?
502
+ @horz_split_first_visible = 0 if @horz_split_first_visible.nil?
503
+ # inspired by pyXLWriter
504
+ @horz_split_pos = 20 * @horz_split_pos + 255
505
+ @vert_split_pos = 113.879 * @vert_split_pos + 390
506
+ end
507
+ @split_active_pane = 0 if @vert_split_pos > 0 and @horz_split_pos > 0
508
+ @split_active_pane = 1 if @vert_split_pos < 0 and @horz_split_pos == 0
509
+ @split_active_pane = 2 if @vert_split_pos == 0 and @horz_split_pos > 0
510
+ @split_active_pane = 3
511
+
512
+ args = [@vert_split_pos, @horz_split_pos, @horz_split_first_visible, @vert_split_first_visible, @split_active_pane]
513
+ PanesRecord.new(*args).to_biff
514
+ end
515
+
516
+ def hyperlink_table_record
517
+ result = ''
518
+ return result if @links.nil?
519
+ @links.each do |a, b|
520
+ x, y = a
521
+ url, target, textmark, description = b
522
+ result += HyperlinkRecord.new(x, x, y, y, url, target, textmark, description).to_biff
523
+ result += QuicktipRecord(x, x, y, y).to_biff unless description.nil?
524
+ end
525
+ result
526
+ end
527
+
528
+ # Fetch the row indicated by index, or create it if necessary.
529
+ def row(index)
530
+ rows[index] ||= Row.new(index, self)
531
+ end
532
+
533
+ # Fetch the col indicated by index, or create it if necessary.
534
+ def col(index)
535
+ cols[index] ||= Column.new(index, self)
536
+ end
537
+ alias :column :col
538
+
539
+ def row_height(row)
540
+ if @rows.include?(row)
541
+ @rows[row].height_in_pixels
542
+ else
543
+ 17
544
+ end
545
+ end
546
+
547
+ def col_width(col)
548
+ if cols.keys.include?(col)
549
+ col.width_in_pixels
550
+ else
551
+ 64
552
+ end
553
+ end
554
+
555
+ def insert_bitmap(filename, row, col, x = 0, y = 0, scale_x = 1, scale_y = 1)
556
+ bmp = ImDataBmpRecord.new(filename)
557
+ obj = ObjBmpRecord.new(row, col, self, bmp, x, y, scale_x, scale_y)
558
+
559
+ @bmp_rec += obj.to_biff + bmp.to_biff
560
+ end
561
+ end