surpass 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +0 -0
- data/README.txt +133 -0
- data/Rakefile +35 -0
- data/examples/big-16mb.rb +25 -0
- data/examples/big-random-strings.rb +28 -0
- data/examples/blanks.rb +34 -0
- data/examples/col_width.rb +16 -0
- data/examples/dates.rb +31 -0
- data/examples/format.rb +23 -0
- data/examples/hello-world.rb +9 -0
- data/examples/image.rb +10 -0
- data/examples/merged.rb +36 -0
- data/examples/merged0.rb +27 -0
- data/examples/merged1.rb +99 -0
- data/examples/num_formats.rb +55 -0
- data/examples/numbers.rb +24 -0
- data/examples/outline.rb +110 -0
- data/examples/panes.rb +48 -0
- data/examples/protection.rb +132 -0
- data/examples/python.bmp +0 -0
- data/examples/row_styles.rb +16 -0
- data/examples/row_styles_empty.rb +15 -0
- data/examples/set_cell_and_range_style.rb +12 -0
- data/examples/wrapped-text.rb +13 -0
- data/examples/write_arrays.rb +16 -0
- data/examples/ws_props.rb +80 -0
- data/lib/biff_record.rb +2168 -0
- data/lib/bitmap.rb +218 -0
- data/lib/cell.rb +214 -0
- data/lib/chart.rb +16 -0
- data/lib/column.rb +40 -0
- data/lib/document.rb +406 -0
- data/lib/excel_formula.rb +6 -0
- data/lib/excel_magic.rb +1013 -0
- data/lib/formatting.rb +554 -0
- data/lib/row.rb +137 -0
- data/lib/style.rb +179 -0
- data/lib/surpass.rb +51 -0
- data/lib/utilities.rb +86 -0
- data/lib/workbook.rb +206 -0
- data/lib/worksheet.rb +561 -0
- data/spec/biff_record_spec.rb +268 -0
- data/spec/cell_spec.rb +56 -0
- data/spec/data/random-strings.txt +10000 -0
- data/spec/document_spec.rb +168 -0
- data/spec/excel_formula_spec.rb +0 -0
- data/spec/formatting_spec.rb +53 -0
- data/spec/reference/P-0508-0000507647-3280-5298.xls +0 -0
- data/spec/reference/all-cell-styles.bin +0 -0
- data/spec/reference/all-number-formats.bin +0 -0
- data/spec/reference/all-styles.bin +0 -0
- data/spec/reference/mini.xls +0 -0
- data/spec/row_spec.rb +19 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/style_spec.rb +89 -0
- data/spec/utilities_spec.rb +57 -0
- data/spec/workbook_spec.rb +48 -0
- data/spec/worksheet_spec.rb +0 -0
- data/stats/cloc.txt +8 -0
- data/stats/rcov.txt +0 -0
- data/stats/specdoc.txt +158 -0
- data/surpass-manual-0-0-3.pdf +0 -0
- data/surpass.gemspec +34 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/excel.rake +6 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/metrics.rake +42 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- 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
|