ricardoo27-writeexcel 0.6.12.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/.document +5 -0
- data/.gitattributes +1 -0
- data/README.rdoc +136 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/charts/chartex.rb +316 -0
- data/charts/demo1.rb +46 -0
- data/charts/demo101.bin +0 -0
- data/charts/demo2.rb +65 -0
- data/charts/demo201.bin +0 -0
- data/charts/demo3.rb +117 -0
- data/charts/demo301.bin +0 -0
- data/charts/demo4.rb +119 -0
- data/charts/demo401.bin +0 -0
- data/charts/demo5.rb +48 -0
- data/charts/demo501.bin +0 -0
- data/examples/a_simple.rb +43 -0
- data/examples/autofilter.rb +265 -0
- data/examples/bigfile.rb +30 -0
- data/examples/chart_area.rb +121 -0
- data/examples/chart_bar.rb +120 -0
- data/examples/chart_column.rb +120 -0
- data/examples/chart_line.rb +120 -0
- data/examples/chart_pie.rb +108 -0
- data/examples/chart_scatter.rb +121 -0
- data/examples/chart_stock.rb +148 -0
- data/examples/chess.rb +142 -0
- data/examples/colors.rb +129 -0
- data/examples/comments1.rb +27 -0
- data/examples/comments2.rb +352 -0
- data/examples/copyformat.rb +52 -0
- data/examples/data_validate.rb +279 -0
- data/examples/date_time.rb +87 -0
- data/examples/defined_name.rb +32 -0
- data/examples/demo.rb +124 -0
- data/examples/diag_border.rb +36 -0
- data/examples/formats.rb +490 -0
- data/examples/formula_result.rb +30 -0
- data/examples/header.rb +137 -0
- data/examples/hide_sheet.rb +29 -0
- data/examples/hyperlink.rb +43 -0
- data/examples/images.rb +63 -0
- data/examples/indent.rb +31 -0
- data/examples/merge1.rb +40 -0
- data/examples/merge2.rb +45 -0
- data/examples/merge3.rb +66 -0
- data/examples/merge4.rb +83 -0
- data/examples/merge5.rb +80 -0
- data/examples/merge6.rb +67 -0
- data/examples/outline.rb +255 -0
- data/examples/outline_collapsed.rb +209 -0
- data/examples/panes.rb +113 -0
- data/examples/password_protection.rb +33 -0
- data/examples/properties.rb +34 -0
- data/examples/properties_jp.rb +33 -0
- data/examples/protection.rb +47 -0
- data/examples/regions.rb +53 -0
- data/examples/repeat.rb +43 -0
- data/examples/republic.png +0 -0
- data/examples/right_to_left.rb +27 -0
- data/examples/row_wrap.rb +53 -0
- data/examples/set_first_sheet.rb +14 -0
- data/examples/stats.rb +74 -0
- data/examples/stocks.rb +81 -0
- data/examples/store_formula.rb +15 -0
- data/examples/tab_colors.rb +31 -0
- data/examples/utf8.rb +15 -0
- data/examples/write_arrays.rb +83 -0
- data/html/en/doc_en.html +5946 -0
- data/html/images/a_simple.jpg +0 -0
- data/html/images/area1.jpg +0 -0
- data/html/images/bar1.jpg +0 -0
- data/html/images/chart_area.xls +0 -0
- data/html/images/column1.jpg +0 -0
- data/html/images/data_validation.jpg +0 -0
- data/html/images/line1.jpg +0 -0
- data/html/images/pie1.jpg +0 -0
- data/html/images/regions.jpg +0 -0
- data/html/images/scatter1.jpg +0 -0
- data/html/images/stats.jpg +0 -0
- data/html/images/stock1.jpg +0 -0
- data/html/images/stocks.jpg +0 -0
- data/html/index.html +16 -0
- data/html/style.css +433 -0
- data/lib/writeexcel.rb +1159 -0
- data/lib/writeexcel/biffwriter.rb +223 -0
- data/lib/writeexcel/caller_info.rb +12 -0
- data/lib/writeexcel/cell_range.rb +332 -0
- data/lib/writeexcel/chart.rb +1968 -0
- data/lib/writeexcel/charts/area.rb +154 -0
- data/lib/writeexcel/charts/bar.rb +177 -0
- data/lib/writeexcel/charts/column.rb +156 -0
- data/lib/writeexcel/charts/external.rb +66 -0
- data/lib/writeexcel/charts/line.rb +154 -0
- data/lib/writeexcel/charts/pie.rb +169 -0
- data/lib/writeexcel/charts/scatter.rb +192 -0
- data/lib/writeexcel/charts/stock.rb +213 -0
- data/lib/writeexcel/col_info.rb +87 -0
- data/lib/writeexcel/colors.rb +68 -0
- data/lib/writeexcel/comments.rb +460 -0
- data/lib/writeexcel/compatibility.rb +65 -0
- data/lib/writeexcel/convert_date_time.rb +117 -0
- data/lib/writeexcel/data_validations.rb +370 -0
- data/lib/writeexcel/debug_info.rb +41 -0
- data/lib/writeexcel/embedded_chart.rb +35 -0
- data/lib/writeexcel/excelformula.y +139 -0
- data/lib/writeexcel/excelformulaparser.rb +587 -0
- data/lib/writeexcel/format.rb +1575 -0
- data/lib/writeexcel/formula.rb +987 -0
- data/lib/writeexcel/helper.rb +78 -0
- data/lib/writeexcel/image.rb +218 -0
- data/lib/writeexcel/olewriter.rb +305 -0
- data/lib/writeexcel/outline.rb +24 -0
- data/lib/writeexcel/properties.rb +242 -0
- data/lib/writeexcel/shared_string_table.rb +153 -0
- data/lib/writeexcel/storage_lite.rb +984 -0
- data/lib/writeexcel/workbook.rb +2478 -0
- data/lib/writeexcel/worksheet.rb +6925 -0
- data/lib/writeexcel/worksheets.rb +25 -0
- data/lib/writeexcel/write_file.rb +63 -0
- data/test/excelfile/Chart1.xls +0 -0
- data/test/excelfile/Chart2.xls +0 -0
- data/test/excelfile/Chart3.xls +0 -0
- data/test/excelfile/Chart4.xls +0 -0
- data/test/excelfile/Chart5.xls +0 -0
- data/test/helper.rb +31 -0
- data/test/perl_output/Chart1.xls.data +0 -0
- data/test/perl_output/Chart2.xls.data +0 -0
- data/test/perl_output/Chart3.xls.data +0 -0
- data/test/perl_output/Chart4.xls.data +0 -0
- data/test/perl_output/Chart5.xls.data +0 -0
- data/test/perl_output/README +31 -0
- data/test/perl_output/a_simple.xls +0 -0
- data/test/perl_output/autofilter.xls +0 -0
- data/test/perl_output/biff_add_continue_testdata +0 -0
- data/test/perl_output/chart_area.xls +0 -0
- data/test/perl_output/chart_bar.xls +0 -0
- data/test/perl_output/chart_column.xls +0 -0
- data/test/perl_output/chart_line.xls +0 -0
- data/test/perl_output/chess.xls +0 -0
- data/test/perl_output/colors.xls +0 -0
- data/test/perl_output/comments0.xls +0 -0
- data/test/perl_output/comments1.xls +0 -0
- data/test/perl_output/comments2.xls +0 -0
- data/test/perl_output/data_validate.xls +0 -0
- data/test/perl_output/date_time.xls +0 -0
- data/test/perl_output/defined_name.xls +0 -0
- data/test/perl_output/demo.xls +0 -0
- data/test/perl_output/demo101.bin +0 -0
- data/test/perl_output/demo201.bin +0 -0
- data/test/perl_output/demo301.bin +0 -0
- data/test/perl_output/demo401.bin +0 -0
- data/test/perl_output/demo501.bin +0 -0
- data/test/perl_output/diag_border.xls +0 -0
- data/test/perl_output/f_font_biff +0 -0
- data/test/perl_output/f_font_key +1 -0
- data/test/perl_output/f_xf_biff +0 -0
- data/test/perl_output/file_font_biff +0 -0
- data/test/perl_output/file_font_key +1 -0
- data/test/perl_output/file_xf_biff +0 -0
- data/test/perl_output/formula_result.xls +0 -0
- data/test/perl_output/headers.xls +0 -0
- data/test/perl_output/hidden.xls +0 -0
- data/test/perl_output/hide_zero.xls +0 -0
- data/test/perl_output/hyperlink.xls +0 -0
- data/test/perl_output/images.xls +0 -0
- data/test/perl_output/indent.xls +0 -0
- data/test/perl_output/merge1.xls +0 -0
- data/test/perl_output/merge2.xls +0 -0
- data/test/perl_output/merge3.xls +0 -0
- data/test/perl_output/merge4.xls +0 -0
- data/test/perl_output/merge5.xls +0 -0
- data/test/perl_output/merge6.xls +0 -0
- data/test/perl_output/ole_write_header +0 -0
- data/test/perl_output/outline.xls +0 -0
- data/test/perl_output/outline_collapsed.xls +0 -0
- data/test/perl_output/panes.xls +0 -0
- data/test/perl_output/password_protection.xls +0 -0
- data/test/perl_output/protection.xls +0 -0
- data/test/perl_output/regions.xls +0 -0
- data/test/perl_output/right_to_left.xls +0 -0
- data/test/perl_output/set_first_sheet.xls +0 -0
- data/test/perl_output/stats.xls +0 -0
- data/test/perl_output/stocks.xls +0 -0
- data/test/perl_output/store_formula.xls +0 -0
- data/test/perl_output/tab_colors.xls +0 -0
- data/test/perl_output/unicode_cyrillic.xls +0 -0
- data/test/perl_output/utf8.xls +0 -0
- data/test/perl_output/workbook1.xls +0 -0
- data/test/perl_output/workbook2.xls +0 -0
- data/test/perl_output/ws_colinfo +1 -0
- data/test/perl_output/ws_store_colinfo +0 -0
- data/test/perl_output/ws_store_dimensions +0 -0
- data/test/perl_output/ws_store_filtermode +0 -0
- data/test/perl_output/ws_store_filtermode_off +0 -0
- data/test/perl_output/ws_store_filtermode_on +0 -0
- data/test/perl_output/ws_store_selection +0 -0
- data/test/perl_output/ws_store_window2 +1 -0
- data/test/republic.png +0 -0
- data/test/test_00_IEEE_double.rb +13 -0
- data/test/test_01_add_worksheet.rb +10 -0
- data/test/test_02_merge_formats.rb +49 -0
- data/test/test_04_dimensions.rb +388 -0
- data/test/test_05_rows.rb +175 -0
- data/test/test_06_extsst.rb +74 -0
- data/test/test_11_date_time.rb +475 -0
- data/test/test_12_date_only.rb +525 -0
- data/test/test_13_date_seconds.rb +477 -0
- data/test/test_21_escher.rb +624 -0
- data/test/test_22_mso_drawing_group.rb +741 -0
- data/test/test_23_note.rb +57 -0
- data/test/test_24_txo.rb +74 -0
- data/test/test_25_position_object.rb +80 -0
- data/test/test_26_autofilter.rb +309 -0
- data/test/test_27_autofilter.rb +126 -0
- data/test/test_28_autofilter.rb +156 -0
- data/test/test_29_process_jpg.rb +670 -0
- data/test/test_30_validation_dval.rb +74 -0
- data/test/test_31_validation_dv_strings.rb +123 -0
- data/test/test_32_validation_dv_formula.rb +203 -0
- data/test/test_40_property_types.rb +188 -0
- data/test/test_41_properties.rb +235 -0
- data/test/test_42_set_properties.rb +434 -0
- data/test/test_50_name_stored.rb +295 -0
- data/test/test_51_name_print_area.rb +353 -0
- data/test/test_52_name_print_titles.rb +450 -0
- data/test/test_53_autofilter.rb +199 -0
- data/test/test_60_chart_generic.rb +574 -0
- data/test/test_61_chart_subclasses.rb +84 -0
- data/test/test_62_chart_formats.rb +268 -0
- data/test/test_63_chart_area_formats.rb +645 -0
- data/test/test_biff.rb +71 -0
- data/test/test_big_workbook.rb +17 -0
- data/test/test_compatibility.rb +12 -0
- data/test/test_example_match.rb +3246 -0
- data/test/test_format.rb +1189 -0
- data/test/test_formula.rb +61 -0
- data/test/test_ole.rb +102 -0
- data/test/test_storage_lite.rb +116 -0
- data/test/test_workbook.rb +146 -0
- data/test/test_worksheet.rb +106 -0
- data/utils/add_magic_comment.rb +80 -0
- data/writeexcel.gemspec +278 -0
- data/writeexcel.rdoc +1425 -0
- metadata +292 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# BIFFwriter - An abstract base class for Excel workbooks and worksheets.
|
|
4
|
+
#
|
|
5
|
+
#
|
|
6
|
+
# Used in conjunction with WriteExcel
|
|
7
|
+
#
|
|
8
|
+
# Copyright 2000-2010, John McNamara, jmcnamara@cpan.org
|
|
9
|
+
#
|
|
10
|
+
# original written in Perl by John McNamara
|
|
11
|
+
# converted to Ruby by Hideo Nakamura, cxn03651@msj.biglobe.ne.jp
|
|
12
|
+
#
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
require 'tempfile'
|
|
16
|
+
require 'writeexcel/write_file'
|
|
17
|
+
|
|
18
|
+
class BIFFWriter < WriteFile #:nodoc:
|
|
19
|
+
|
|
20
|
+
BIFF_Version = 0x0600
|
|
21
|
+
BigEndian = [1].pack("I") == [1].pack("N")
|
|
22
|
+
|
|
23
|
+
attr_reader :data, :datasize
|
|
24
|
+
|
|
25
|
+
######################################################################
|
|
26
|
+
# The args here aren't used by BIFFWriter, but they are needed by its
|
|
27
|
+
# subclasses. I don't feel like creating multiple constructors.
|
|
28
|
+
######################################################################
|
|
29
|
+
|
|
30
|
+
def initialize
|
|
31
|
+
super
|
|
32
|
+
set_byte_order
|
|
33
|
+
@ignore_continue = false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
###############################################################################
|
|
37
|
+
#
|
|
38
|
+
# _set_byte_order()
|
|
39
|
+
#
|
|
40
|
+
# Determine the byte order and store it as class data to avoid
|
|
41
|
+
# recalculating it for each call to new().
|
|
42
|
+
#
|
|
43
|
+
def set_byte_order
|
|
44
|
+
# Check if "pack" gives the required IEEE 64bit float
|
|
45
|
+
teststr = [1.2345].pack("d")
|
|
46
|
+
hexdata = [0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F]
|
|
47
|
+
number = hexdata.pack("C8")
|
|
48
|
+
|
|
49
|
+
if number == teststr
|
|
50
|
+
@byte_order = false # Little Endian
|
|
51
|
+
elsif number == teststr.reverse
|
|
52
|
+
@byte_order = true # Big Endian
|
|
53
|
+
else
|
|
54
|
+
# Give up. I'll fix this in a later version.
|
|
55
|
+
raise( "Required floating point format not supported " +
|
|
56
|
+
"on this platform. See the portability section " +
|
|
57
|
+
"of the documentation."
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
###############################################################################
|
|
63
|
+
#
|
|
64
|
+
# get_data().
|
|
65
|
+
#
|
|
66
|
+
# Retrieves data from memory in one chunk, or from disk in $buffer
|
|
67
|
+
# sized chunks.
|
|
68
|
+
#
|
|
69
|
+
def get_data
|
|
70
|
+
buflen = 4096
|
|
71
|
+
|
|
72
|
+
# Return data stored in memory
|
|
73
|
+
unless @data.nil?
|
|
74
|
+
tmp = @data
|
|
75
|
+
@data = nil
|
|
76
|
+
if @using_tmpfile
|
|
77
|
+
@filehandle.open
|
|
78
|
+
@filehandle.binmode
|
|
79
|
+
end
|
|
80
|
+
return tmp
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Return data stored on disk
|
|
84
|
+
if @using_tmpfile
|
|
85
|
+
return @filehandle.read(buflen)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# No data to return
|
|
89
|
+
nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
###############################################################################
|
|
93
|
+
#
|
|
94
|
+
# _store_bof($type)
|
|
95
|
+
#
|
|
96
|
+
# $type = 0x0005, Workbook
|
|
97
|
+
# $type = 0x0010, Worksheet
|
|
98
|
+
# $type = 0x0020, Chart
|
|
99
|
+
#
|
|
100
|
+
# Writes Excel BOF record to indicate the beginning of a stream or
|
|
101
|
+
# sub-stream in the BIFF file.
|
|
102
|
+
#
|
|
103
|
+
def store_bof(type = 0x0005)
|
|
104
|
+
record = 0x0809 # Record identifier
|
|
105
|
+
length = 0x0010 # Number of bytes to follow
|
|
106
|
+
|
|
107
|
+
# According to the SDK $build and $year should be set to zero.
|
|
108
|
+
# However, this throws a warning in Excel 5. So, use these
|
|
109
|
+
# magic numbers.
|
|
110
|
+
build = 0x0DBB
|
|
111
|
+
year = 0x07CC
|
|
112
|
+
|
|
113
|
+
bfh = 0x00000041
|
|
114
|
+
sfo = 0x00000006
|
|
115
|
+
|
|
116
|
+
header = [record,length].pack("vv")
|
|
117
|
+
data = [BIFF_Version,type,build,year,bfh,sfo].pack("vvvvVV")
|
|
118
|
+
|
|
119
|
+
prepend(header, data)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
###############################################################################
|
|
123
|
+
#
|
|
124
|
+
# _store_eof()
|
|
125
|
+
#
|
|
126
|
+
# Writes Excel EOF record to indicate the end of a BIFF stream.
|
|
127
|
+
#
|
|
128
|
+
def store_eof
|
|
129
|
+
record = 0x000A
|
|
130
|
+
length = 0x0000
|
|
131
|
+
header = [record,length].pack("vv")
|
|
132
|
+
|
|
133
|
+
append(header)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
###############################################################################
|
|
137
|
+
#
|
|
138
|
+
# _add_continue()
|
|
139
|
+
#
|
|
140
|
+
# Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In
|
|
141
|
+
# Excel 97 the limit is 8228 bytes. Records that are longer than these limits
|
|
142
|
+
# must be split up into CONTINUE blocks.
|
|
143
|
+
#
|
|
144
|
+
# This function take a long BIFF record and inserts CONTINUE records as
|
|
145
|
+
# necessary.
|
|
146
|
+
#
|
|
147
|
+
# Some records have their own specialised Continue blocks so there is also an
|
|
148
|
+
# option to bypass this function.
|
|
149
|
+
#
|
|
150
|
+
def add_continue(data)
|
|
151
|
+
# Skip this if another method handles the continue blocks.
|
|
152
|
+
return data if @ignore_continue
|
|
153
|
+
|
|
154
|
+
record = 0x003C # Record identifier
|
|
155
|
+
header = [record, @limit].pack("vv")
|
|
156
|
+
|
|
157
|
+
# The first 2080/8224 bytes remain intact. However, we have to change
|
|
158
|
+
# the length field of the record.
|
|
159
|
+
#
|
|
160
|
+
data_array = split_by_length(data, @limit)
|
|
161
|
+
first_data = data_array.shift
|
|
162
|
+
last_data = data_array.pop || ''
|
|
163
|
+
first_data[2, 2] = [@limit-4].pack('v')
|
|
164
|
+
first_data <<
|
|
165
|
+
data_array.join(header) <<
|
|
166
|
+
[record, last_data.bytesize].pack('vv') <<
|
|
167
|
+
last_data
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
###############################################################################
|
|
171
|
+
#
|
|
172
|
+
# _add_mso_generic()
|
|
173
|
+
# my $type = $_[0];
|
|
174
|
+
# my $version = $_[1];
|
|
175
|
+
# my $instance = $_[2];
|
|
176
|
+
# my $data = $_[3];
|
|
177
|
+
#
|
|
178
|
+
# Create a mso structure that is part of an Escher drawing object. These are
|
|
179
|
+
# are used for images, comments and filters. This generic method is used by
|
|
180
|
+
# other methods to create specific mso records.
|
|
181
|
+
#
|
|
182
|
+
# Returns the packed record.
|
|
183
|
+
#
|
|
184
|
+
def add_mso_generic(type, version, instance, data, length = nil)
|
|
185
|
+
length ||= data.bytesize
|
|
186
|
+
|
|
187
|
+
# The header contains version and instance info packed into 2 bytes.
|
|
188
|
+
header = version | (instance << 4)
|
|
189
|
+
|
|
190
|
+
record = [header, type, length].pack('vvV') + data
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def not_using_tmpfile
|
|
194
|
+
@filehandle.close(true) if @filehandle
|
|
195
|
+
@filehandle = nil
|
|
196
|
+
@using_tmpfile = nil
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def clear_data_for_test # :nodoc:
|
|
200
|
+
@data = ''
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def cleanup # :nodoc:
|
|
204
|
+
@filehandle.close(true) if @filehandle
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# override Object#inspect
|
|
208
|
+
def inspect # :nodoc:
|
|
209
|
+
to_s
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
private
|
|
213
|
+
|
|
214
|
+
def split_by_length(data, length)
|
|
215
|
+
array = []
|
|
216
|
+
s = 0
|
|
217
|
+
while s < data.length
|
|
218
|
+
array << data[s, length]
|
|
219
|
+
s += length
|
|
220
|
+
end
|
|
221
|
+
array
|
|
222
|
+
end
|
|
223
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module CallerInfo
|
|
3
|
+
#
|
|
4
|
+
# return stack trace info if defined?($debug).
|
|
5
|
+
#
|
|
6
|
+
def caller_info
|
|
7
|
+
caller(3).collect { |info|
|
|
8
|
+
file = File.expand_path(info.sub(/:(\d+)[^\d`]*(`([^']+)')?/, ''))
|
|
9
|
+
{ :file => file, :line => $1, :method => $3 }
|
|
10
|
+
}.select { |info| info[:method] } # delete if info[:method] == nil
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
module Writeexcel
|
|
2
|
+
|
|
3
|
+
class Worksheet < BIFFWriter
|
|
4
|
+
class CellRange
|
|
5
|
+
attr_accessor :row_min, :row_max, :col_min, :col_max
|
|
6
|
+
|
|
7
|
+
def initialize(worksheet)
|
|
8
|
+
@worksheet = worksheet
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def increment_row_max
|
|
12
|
+
@row_max += 1 if @row_max
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def increment_col_max
|
|
16
|
+
@col_max += 1 if @col_max
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def row(val)
|
|
20
|
+
@row_min = val if !@row_min || (val < row_min)
|
|
21
|
+
@row_max = val if !@row_max || (val > row_max)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def col(val)
|
|
25
|
+
@col_min = val if !@col_min || (val < col_min)
|
|
26
|
+
@col_max = val if !@col_max || (val > col_max)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# assemble the NAME record in the long format that is used for storing the repeat
|
|
31
|
+
# rows and columns when both are specified. This share a lot of code with
|
|
32
|
+
# name_record_short() but we use a separate method to keep the code clean.
|
|
33
|
+
# Code abstraction for reuse can be carried too far, and I should know. ;-)
|
|
34
|
+
#
|
|
35
|
+
# type
|
|
36
|
+
# ext_ref # TODO
|
|
37
|
+
#
|
|
38
|
+
def name_record_long(type, ext_ref) #:nodoc:
|
|
39
|
+
record = 0x0018 # Record identifier
|
|
40
|
+
length = 0x002a # Number of bytes to follow
|
|
41
|
+
|
|
42
|
+
grbit = 0x0020 # Option flags
|
|
43
|
+
chkey = 0x00 # Keyboard shortcut
|
|
44
|
+
cch = 0x01 # Length of text name
|
|
45
|
+
cce = 0x001a # Length of text definition
|
|
46
|
+
unknown01 = 0x0000 #
|
|
47
|
+
ixals = @worksheet.index + 1 # Sheet index
|
|
48
|
+
unknown02 = 0x00 #
|
|
49
|
+
cch_cust_menu = 0x00 # Length of cust menu text
|
|
50
|
+
cch_description = 0x00 # Length of description text
|
|
51
|
+
cch_helptopic = 0x00 # Length of help topic text
|
|
52
|
+
cch_statustext = 0x00 # Length of status bar text
|
|
53
|
+
rgch = type # Built-in name type
|
|
54
|
+
|
|
55
|
+
unknown03 = 0x29
|
|
56
|
+
unknown04 = 0x0017
|
|
57
|
+
unknown05 = 0x3b
|
|
58
|
+
|
|
59
|
+
header = [record, length].pack("vv")
|
|
60
|
+
data = [grbit].pack("v")
|
|
61
|
+
data += [chkey].pack("C")
|
|
62
|
+
data += [cch].pack("C")
|
|
63
|
+
data += [cce].pack("v")
|
|
64
|
+
data += [unknown01].pack("v")
|
|
65
|
+
data += [ixals].pack("v")
|
|
66
|
+
data += [unknown02].pack("C")
|
|
67
|
+
data += [cch_cust_menu].pack("C")
|
|
68
|
+
data += [cch_description].pack("C")
|
|
69
|
+
data += [cch_helptopic].pack("C")
|
|
70
|
+
data += [cch_statustext].pack("C")
|
|
71
|
+
data += [rgch].pack("C")
|
|
72
|
+
|
|
73
|
+
# Column definition
|
|
74
|
+
data += [unknown03].pack("C")
|
|
75
|
+
data += [unknown04].pack("v")
|
|
76
|
+
data += [unknown05].pack("C")
|
|
77
|
+
data += [ext_ref].pack("v")
|
|
78
|
+
data += [0x0000].pack("v")
|
|
79
|
+
data += [0xffff].pack("v")
|
|
80
|
+
data += [@col_min].pack("v")
|
|
81
|
+
data += [@col_max].pack("v")
|
|
82
|
+
|
|
83
|
+
# Row definition
|
|
84
|
+
data += [unknown05].pack("C")
|
|
85
|
+
data += [ext_ref].pack("v")
|
|
86
|
+
data += [@row_min].pack("v")
|
|
87
|
+
data += [@row_max].pack("v")
|
|
88
|
+
data += [0x00].pack("v")
|
|
89
|
+
data += [0xff].pack("v")
|
|
90
|
+
# End of data
|
|
91
|
+
data += [0x10].pack("C")
|
|
92
|
+
|
|
93
|
+
[header, data]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
#
|
|
97
|
+
# assemble the NAME record in the short format that is used for storing the print
|
|
98
|
+
# area, repeat rows only and repeat columns only.
|
|
99
|
+
#
|
|
100
|
+
# type
|
|
101
|
+
# ext_ref # TODO
|
|
102
|
+
# hidden # Name is hidden
|
|
103
|
+
#
|
|
104
|
+
def name_record_short(type, ext_ref, hidden = nil) #:nodoc:
|
|
105
|
+
record = 0x0018 # Record identifier
|
|
106
|
+
length = 0x001b # Number of bytes to follow
|
|
107
|
+
|
|
108
|
+
grbit = 0x0020 # Option flags
|
|
109
|
+
chkey = 0x00 # Keyboard shortcut
|
|
110
|
+
cch = 0x01 # Length of text name
|
|
111
|
+
cce = 0x000b # Length of text definition
|
|
112
|
+
unknown01 = 0x0000 #
|
|
113
|
+
ixals = @worksheet.index + 1 # Sheet index
|
|
114
|
+
unknown02 = 0x00 #
|
|
115
|
+
cch_cust_menu = 0x00 # Length of cust menu text
|
|
116
|
+
cch_description = 0x00 # Length of description text
|
|
117
|
+
cch_helptopic = 0x00 # Length of help topic text
|
|
118
|
+
cch_statustext = 0x00 # Length of status bar text
|
|
119
|
+
rgch = type # Built-in name type
|
|
120
|
+
unknown03 = 0x3b #
|
|
121
|
+
|
|
122
|
+
grbit = 0x0021 if hidden
|
|
123
|
+
|
|
124
|
+
rowmin = row_min
|
|
125
|
+
rowmax = row_max
|
|
126
|
+
rowmin, rowmax = 0x0000, 0xffff unless row_min
|
|
127
|
+
|
|
128
|
+
colmin = col_min
|
|
129
|
+
colmax = col_max
|
|
130
|
+
colmin, colmax = 0x00, 0xff unless col_min
|
|
131
|
+
|
|
132
|
+
header = [record, length].pack("vv")
|
|
133
|
+
data = [grbit].pack("v")
|
|
134
|
+
data += [chkey].pack("C")
|
|
135
|
+
data += [cch].pack("C")
|
|
136
|
+
data += [cce].pack("v")
|
|
137
|
+
data += [unknown01].pack("v")
|
|
138
|
+
data += [ixals].pack("v")
|
|
139
|
+
data += [unknown02].pack("C")
|
|
140
|
+
data += [cch_cust_menu].pack("C")
|
|
141
|
+
data += [cch_description].pack("C")
|
|
142
|
+
data += [cch_helptopic].pack("C")
|
|
143
|
+
data += [cch_statustext].pack("C")
|
|
144
|
+
data += [rgch].pack("C")
|
|
145
|
+
data += [unknown03].pack("C")
|
|
146
|
+
data += [ext_ref].pack("v")
|
|
147
|
+
|
|
148
|
+
data += [rowmin].pack("v")
|
|
149
|
+
data += [rowmax].pack("v")
|
|
150
|
+
data += [colmin].pack("v")
|
|
151
|
+
data += [colmax].pack("v")
|
|
152
|
+
|
|
153
|
+
[header, data]
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
class CellDimension < CellRange
|
|
158
|
+
def row_min
|
|
159
|
+
@row_min || 0
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def col_min
|
|
163
|
+
@col_min || 0
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def row_max
|
|
167
|
+
@row_max || 0
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def col_max
|
|
171
|
+
@col_max || 0
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
class PrintRange < CellRange
|
|
176
|
+
def name_record_short(ext_ref, hidden)
|
|
177
|
+
super(0x06, ext_ref, hidden) # 0x06 NAME type = Print_Area
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
class TitleRange < CellRange
|
|
182
|
+
def name_record_long(ext_ref)
|
|
183
|
+
super(0x07, ext_ref) # 0x07 NAME type = Print_Titles
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def name_record_short(ext_ref, hidden)
|
|
187
|
+
super(0x07, ext_ref, hidden) # 0x07 NAME type = Print_Titles
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
class FilterRange < CellRange
|
|
192
|
+
def name_record_short(ext_ref, hidden)
|
|
193
|
+
super(0x0D, ext_ref, hidden) # 0x0D NAME type = Filter Database
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def count
|
|
197
|
+
if @col_min && @col_max
|
|
198
|
+
1 + @col_max - @col_min
|
|
199
|
+
else
|
|
200
|
+
0
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def inside?(col)
|
|
205
|
+
@col_min <= col && col <= @col_max
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def store
|
|
209
|
+
record = 0x00EC # Record identifier
|
|
210
|
+
|
|
211
|
+
spid = @worksheet.object_ids.spid
|
|
212
|
+
|
|
213
|
+
# Number of objects written so far.
|
|
214
|
+
num_objects = @worksheet.images_size + @worksheet.charts_size
|
|
215
|
+
|
|
216
|
+
(0 .. count-1).each do |i|
|
|
217
|
+
if i == 0 && num_objects
|
|
218
|
+
spid, data = write_parent_msodrawing_record(count, @worksheet.comments_size, spid, vertices(i))
|
|
219
|
+
else
|
|
220
|
+
spid, data = write_child_msodrawing_record(spid, vertices(i))
|
|
221
|
+
end
|
|
222
|
+
length = data.bytesize
|
|
223
|
+
header = [record, length].pack("vv")
|
|
224
|
+
append(header, data)
|
|
225
|
+
|
|
226
|
+
store_obj_filter(num_objects + i + 1, col_min + i)
|
|
227
|
+
end
|
|
228
|
+
spid
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
private
|
|
232
|
+
|
|
233
|
+
def write_parent_msodrawing_record(num_filters, num_comments, spid, vertices)
|
|
234
|
+
# Write the parent MSODRAWIING record.
|
|
235
|
+
dg_length = 168 + 96 * (num_filters - 1)
|
|
236
|
+
spgr_length = 144 + 96 * (num_filters - 1)
|
|
237
|
+
|
|
238
|
+
dg_length += 128 * num_comments
|
|
239
|
+
spgr_length += 128 * num_comments
|
|
240
|
+
|
|
241
|
+
data = store_parent_mso_record(dg_length, spgr_length, spid)
|
|
242
|
+
spid += 1
|
|
243
|
+
data += store_child_mso_record(spid, *vertices)
|
|
244
|
+
spid += 1
|
|
245
|
+
[spid, data]
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def write_child_msodrawing_record(spid, vertices)
|
|
249
|
+
data = store_child_mso_record(spid, *vertices)
|
|
250
|
+
spid += 1
|
|
251
|
+
[spid, data]
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def store_parent_mso_record(dg_length, spgr_length, spid)
|
|
255
|
+
@worksheet.__send__("store_parent_mso_record", dg_length, spgr_length, spid)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def store_child_mso_record(spid, *vertices)
|
|
259
|
+
@worksheet.__send__("store_child_mso_record", spid, *vertices)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def vertices(i)
|
|
263
|
+
[
|
|
264
|
+
col_min + i, 0,
|
|
265
|
+
row_min, 0,
|
|
266
|
+
col_min + i + 1, 0,
|
|
267
|
+
row_min + 1, 0
|
|
268
|
+
]
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
#
|
|
272
|
+
# Write the OBJ record that is part of filter records.
|
|
273
|
+
# obj_id # Object ID number.
|
|
274
|
+
# col
|
|
275
|
+
#
|
|
276
|
+
def store_obj_filter(obj_id, col) #:nodoc:
|
|
277
|
+
record = 0x005D # Record identifier
|
|
278
|
+
length = 0x0046 # Bytes to follow
|
|
279
|
+
|
|
280
|
+
obj_type = 0x0014 # Object type (combo box).
|
|
281
|
+
data = '' # Record data.
|
|
282
|
+
|
|
283
|
+
sub_record = 0x0000 # Sub-record identifier.
|
|
284
|
+
sub_length = 0x0000 # Length of sub-record.
|
|
285
|
+
sub_data = '' # Data of sub-record.
|
|
286
|
+
options = 0x2101
|
|
287
|
+
reserved = 0x0000
|
|
288
|
+
|
|
289
|
+
# Add ftCmo (common object data) subobject
|
|
290
|
+
sub_record = 0x0015 # ftCmo
|
|
291
|
+
sub_length = 0x0012
|
|
292
|
+
sub_data = [obj_type, obj_id, options, reserved, reserved, reserved].pack('vvvVVV')
|
|
293
|
+
data = [sub_record, sub_length].pack('vv') + sub_data
|
|
294
|
+
|
|
295
|
+
# Add ftSbs Scroll bar subobject
|
|
296
|
+
sub_record = 0x000C # ftSbs
|
|
297
|
+
sub_length = 0x0014
|
|
298
|
+
sub_data = ['0000000000000000640001000A00000010000100'].pack('H*')
|
|
299
|
+
data += [sub_record, sub_length].pack('vv') + sub_data
|
|
300
|
+
|
|
301
|
+
# Add ftLbsData (List box data) subobject
|
|
302
|
+
sub_record = 0x0013 # ftLbsData
|
|
303
|
+
sub_length = 0x1FEE # Special case (undocumented).
|
|
304
|
+
|
|
305
|
+
# If the filter is active we set one of the undocumented flags.
|
|
306
|
+
|
|
307
|
+
if @worksheet.instance_variable_get(:@filter_cols)[col]
|
|
308
|
+
sub_data = ['000000000100010300000A0008005700'].pack('H*')
|
|
309
|
+
else
|
|
310
|
+
sub_data = ['00000000010001030000020008005700'].pack('H*')
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
data += [sub_record, sub_length].pack('vv') + sub_data
|
|
314
|
+
|
|
315
|
+
# Add ftEnd (end of object) subobject
|
|
316
|
+
sub_record = 0x0000 # ftNts
|
|
317
|
+
sub_length = 0x0000
|
|
318
|
+
data += [sub_record, sub_length].pack('vv')
|
|
319
|
+
|
|
320
|
+
# Pack the record.
|
|
321
|
+
header = [record, length].pack('vv')
|
|
322
|
+
|
|
323
|
+
append(header, data)
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def append(*args)
|
|
327
|
+
@worksheet.append(*args)
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
end
|