surpass 0.0.3

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 (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