spreadsheet_export_refi 0.0.0
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/lib/spreadsheet_export_refi.rb +401 -0
- metadata +123 -0
@@ -0,0 +1,401 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spreadsheet_cache_manager_refi'
|
4
|
+
require 'file_cache_manager_refi'
|
5
|
+
require 'minival_refi'
|
6
|
+
require 'minilang_refi'
|
7
|
+
require 'template_refi'
|
8
|
+
|
9
|
+
|
10
|
+
#myreq "#{$intern_base_path}/ss_db_cache_manager.rb"
|
11
|
+
#myreq "#{$intern_base_path}/text_file_cache_manager.rb"
|
12
|
+
#myreq "#{$intern_base_path}/minival.rb"
|
13
|
+
#myreq "#{$intern_base_path}/minilang.rb"
|
14
|
+
#myreq "#{$intern_base_path}/template.rb"
|
15
|
+
|
16
|
+
$minival_parser = MinivalGrammarParser.new
|
17
|
+
|
18
|
+
class SsExport
|
19
|
+
@@special_col_labels = ['ACTIVE','INSTRUCTION','FILE','SHEET','EXPORT','PARAMS','IGNORE']
|
20
|
+
@@dont_duplicate_from_super_map = ['INSTRUCTION','FILE','SHEET','IGNORE','PARAMS']
|
21
|
+
|
22
|
+
|
23
|
+
# \#placeholder_name_example#"
|
24
|
+
# \-a_function_name(a_minival_string)"
|
25
|
+
@@replace_functions = {
|
26
|
+
"nothing" => proc{|context,minival|
|
27
|
+
next ""
|
28
|
+
},
|
29
|
+
# file can only open files in subdirectories
|
30
|
+
# TODO security stuff
|
31
|
+
"read_file" => proc{|context,minival|
|
32
|
+
if(minival[0].is_a?(String))
|
33
|
+
text = context.text_file_cache_manager.get_text(minival[0])
|
34
|
+
next text
|
35
|
+
else
|
36
|
+
dparn('W1001',"read_file - could not open file because minival was not a string")
|
37
|
+
next nil
|
38
|
+
end
|
39
|
+
},
|
40
|
+
"current_spreadsheet_file_pathname" => proc{|context,minival|
|
41
|
+
next context.ss_pn
|
42
|
+
},
|
43
|
+
#"current_template_file_pathname" => proc{|context,minival|
|
44
|
+
# next context.current_file_info[:pn]
|
45
|
+
#},
|
46
|
+
"catch" => proc{|context,minival|
|
47
|
+
catch_name = minival[0]
|
48
|
+
if(catch_name.is_a?(String))
|
49
|
+
res = context.var_map[catch_name]
|
50
|
+
if res==nil
|
51
|
+
dput
|
52
|
+
dparn 1012,"catch could not find '#{catch_name}' in var_map"
|
53
|
+
res = ''
|
54
|
+
end
|
55
|
+
next res
|
56
|
+
else
|
57
|
+
dparn(1002,"catch - could not open file because minival was not a string")
|
58
|
+
next nil
|
59
|
+
end
|
60
|
+
},
|
61
|
+
"minilang_eval" => proc{|context,minival|
|
62
|
+
next context.minilang_env.run_str(minival[0])
|
63
|
+
},
|
64
|
+
}
|
65
|
+
|
66
|
+
def self.call_replace_function(context,name,minival_str)
|
67
|
+
fun = @@replace_functions[name]
|
68
|
+
return nil unless fun
|
69
|
+
minival = Minival.new(minival_str)
|
70
|
+
return nil unless minival.valid
|
71
|
+
return fun.call(context,minival)
|
72
|
+
end
|
73
|
+
|
74
|
+
attr_reader :ss_pn
|
75
|
+
attr_reader :var_map
|
76
|
+
|
77
|
+
def initialize(p={})
|
78
|
+
@instructions = {
|
79
|
+
"insert" => self.method(:insert_instruction),
|
80
|
+
"delegate" => self.method(:delegate_instruction),
|
81
|
+
"do" => self.method(:do_instruction),
|
82
|
+
"select" => self.method(:select_instruction),
|
83
|
+
}
|
84
|
+
@ss_pn = p[:ss_pn] || nil
|
85
|
+
@sheet_name = p[:sheet_name] || dperr(1008,'a sheetname must be specified')
|
86
|
+
@output_file = p[:output_file] || dperr(1009,'no output file specified')
|
87
|
+
@transpose = p[:transpose] || false
|
88
|
+
@ss_db_cache_manager = p[:ss_db_cache_manager] || SsDbCacheManager.new({default_db_pa: './cache/'})
|
89
|
+
@template_pa_prefix = p[:template_pa_prefix]
|
90
|
+
@text_file_cache_manager = p[:text_file_cache_manager] || TextFileCacheManager.new()
|
91
|
+
#@export_type = p[:export_type] || dperr(1010,'no export type specified')
|
92
|
+
@export_type = p[:export_type] || $Log.tlog({id: 'err1010'})
|
93
|
+
@super_var_map = p[:super_var_map] || {}
|
94
|
+
@subs = p[:subs] || dperr(1011,'no subsitutions passed to ss_export')
|
95
|
+
@var_map = {}
|
96
|
+
@ss_db_cache = @ss_db_cache_manager.get_ss_db_cache(@ss_pn)
|
97
|
+
@sheet = @ss_db_cache.get_sheet(@sheet_name)
|
98
|
+
@minilang_env = MinilangEnv.new(self, {export_type: @export_type} )
|
99
|
+
@loops = []
|
100
|
+
if(@sheet == nil)
|
101
|
+
# TODO make check for sheet_names
|
102
|
+
dperr('E1003',"no sheet: #{$st[:sheet]}#{@sheet_name}#{$st[:error]} in #{$st[:ss_file]}#{@ss_pn}\nsheets available are:#{@spreadsheet_cache.get_sheet_names.inspect}")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
def process
|
106
|
+
#dputi "to #{$st[:ss_file]}#{@ss_pn}#{$st[:std]}" << reset << ":#{$st[:sheet]}#{@sheet_nam}"
|
107
|
+
#dputi
|
108
|
+
#dpit ''
|
109
|
+
get_sheet_dims
|
110
|
+
read_headers()
|
111
|
+
@on_sheet_exit_add = ''
|
112
|
+
process_instructions()
|
113
|
+
write @on_sheet_exit_add
|
114
|
+
#dput
|
115
|
+
$Log.tlog({id: 'newline'})
|
116
|
+
#dpun
|
117
|
+
end
|
118
|
+
def write text
|
119
|
+
@subs[:write].each{|r,s|
|
120
|
+
text = text.gsub(r,s)
|
121
|
+
}
|
122
|
+
@output_file.write text
|
123
|
+
end
|
124
|
+
def read_headers()
|
125
|
+
#dputi "#{$st[:whisper]}K - read column labels"
|
126
|
+
first = @sheet_dims[:col][:min]
|
127
|
+
last = @sheet_dims[:col][:max]
|
128
|
+
@header_cols = get_row(1).inject({}){|memo,(k,v)| memo[v.value.to_s] = k ; memo }
|
129
|
+
#dpun
|
130
|
+
end
|
131
|
+
def get_sheet_dims
|
132
|
+
sheet_dims = @sheet.get_dims
|
133
|
+
if(@transpose)
|
134
|
+
sheet_dims = {
|
135
|
+
col: sheet_dims[:row],
|
136
|
+
row: sheet_dims[:col],
|
137
|
+
}
|
138
|
+
end
|
139
|
+
@sheet_dims = sheet_dims
|
140
|
+
end
|
141
|
+
def process_row(row_i)
|
142
|
+
@cur_row = row_i
|
143
|
+
if(is_row_active(row_i))
|
144
|
+
instruction_str = get_instruction(row_i)
|
145
|
+
process_instruction(instruction_str,row_i)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
def consume_after_last_row
|
149
|
+
write @after_last_row
|
150
|
+
@after_last_row = ''
|
151
|
+
end
|
152
|
+
def process_rows_from from
|
153
|
+
last_row = @sheet_dims[:row][:max]
|
154
|
+
from.upto(last_row) do |row_i|
|
155
|
+
process_row(row_i)
|
156
|
+
end
|
157
|
+
consume_after_last_row
|
158
|
+
end
|
159
|
+
def process_instructions()
|
160
|
+
@after_last_row = ''
|
161
|
+
process_rows_from(2)
|
162
|
+
@loops.each{|l|
|
163
|
+
#pp l
|
164
|
+
from = l[:from]
|
165
|
+
ary = l[:ary]
|
166
|
+
l_var_name = l[:l_var_name]
|
167
|
+
while !ary.empty?
|
168
|
+
@minilang_env.set_l(l_var_name,ary.shift)
|
169
|
+
process_rows_from(from)
|
170
|
+
end
|
171
|
+
}
|
172
|
+
end
|
173
|
+
def get_cell(row_i,col_i)
|
174
|
+
return @sheet.get_cell(row_i,col_i,@transpose)
|
175
|
+
end
|
176
|
+
def get_instruction(row_i)
|
177
|
+
return get_cell(row_i,@header_cols['INSTRUCTION']).value
|
178
|
+
end
|
179
|
+
def is_row_active(row_i)
|
180
|
+
active_col_i = @header_cols['ACTIVE']
|
181
|
+
if(active_col_i == nil)
|
182
|
+
$Log.tlog( {id: 'err1402'} )
|
183
|
+
#dperr(402,"no column named 'ACTIVE' - this column is mandatory")
|
184
|
+
end
|
185
|
+
is_active_str = get_cell(row_i,active_col_i).value
|
186
|
+
if(is_active_str.is_a?(String))
|
187
|
+
if(is_active_str == "NO")
|
188
|
+
$Log.tlog( {id: 'info1403'} )
|
189
|
+
return false
|
190
|
+
elsif(is_active_str == "YES")
|
191
|
+
ex_i = @header_cols['EXPORT']
|
192
|
+
ex_range = nil
|
193
|
+
if ex_i == nil
|
194
|
+
return true # missing EXPORT column defaults to active
|
195
|
+
else
|
196
|
+
ex_range = get_cell(row_i,ex_i).value
|
197
|
+
end
|
198
|
+
if (("*" == ex_range) or (@export_type == ex_range)) # EXPORT type matches
|
199
|
+
return true
|
200
|
+
else # 'EXPORT' must be something we are not interested in
|
201
|
+
return false
|
202
|
+
end
|
203
|
+
else
|
204
|
+
dperr(404,"'ACTIVE' has invalid value: #{is_active_str}\n(valid values are the strings 'YES' and 'NO')")
|
205
|
+
end
|
206
|
+
else # not ''.class
|
207
|
+
dperr(403,"'ACTIVE' has invalid value/type (row:#{row_i} col:#{active_col_i}) value:'#{is_active_str}' value.class:'#{is_active_str.class}' last row:#{@sheet.get_last_row.to_s} (valid values are the strings 'YES' and 'NO')")
|
208
|
+
end
|
209
|
+
return false
|
210
|
+
end
|
211
|
+
def process_instruction(instruction_type,row_i)
|
212
|
+
# TODO add warnings
|
213
|
+
@debug_row_i = row_i
|
214
|
+
@var_map = @super_var_map.dup()
|
215
|
+
@@dont_duplicate_from_super_map.each{|col_label|
|
216
|
+
@var_map.delete(col_label)
|
217
|
+
}
|
218
|
+
row = get_row(row_i)
|
219
|
+
@header_cols.each_pair{|col_label,col_i|
|
220
|
+
@var_map[col_label] = eval_var(row[col_i].value)
|
221
|
+
}
|
222
|
+
inst_p = @instructions[instruction_type]
|
223
|
+
if(inst_p)
|
224
|
+
inst_p.call(row_i)
|
225
|
+
else
|
226
|
+
$Log.tlog( {id: 'err1302', ss_pn: @ss_pn, sheet_name:@sheet_name, row_i: row_i} )
|
227
|
+
#dperr('E302',"invalid instruction - spreadsheet:'#{$st[:ss_file]}#{@ss_pn}#{$st[:error]} sheet:#{$st[:sheet]}#{@sheet_name}#{$st[:error]} row:#{$st[:num]}#{row_i}")
|
228
|
+
end
|
229
|
+
end
|
230
|
+
def get_row(row_i)
|
231
|
+
return @sheet.get_row(row_i,@transpose)
|
232
|
+
end
|
233
|
+
|
234
|
+
def do_instruction(row_i)
|
235
|
+
$Log.tlog({id: 'info1125_do_instruction'})
|
236
|
+
params = get_params(row_i)
|
237
|
+
@minilang_env.set_var_map @var_map
|
238
|
+
@minilang_env.run_str(params[:do])
|
239
|
+
text = @minilang_env.consume_text
|
240
|
+
if params[:on_exit]
|
241
|
+
@on_sheet_exit_add << text
|
242
|
+
else
|
243
|
+
write text
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def select_instruction(row_i)
|
248
|
+
$Log.tlog( {id: 'info1123_select_instruction'} )
|
249
|
+
end
|
250
|
+
|
251
|
+
def create_loop(l_var_name,ary)
|
252
|
+
# TODO
|
253
|
+
# set l_var to ary.shift
|
254
|
+
@minilang_env.set_l(l_var_name,ary.shift)
|
255
|
+
@loops.push({from:(@cur_row+1),ary:ary,l_var_name:l_var_name})
|
256
|
+
|
257
|
+
#@creator.create_loop(l_var_name,ary)
|
258
|
+
#@loops.
|
259
|
+
|
260
|
+
end
|
261
|
+
def read_file pn
|
262
|
+
if pn == ''
|
263
|
+
return ''
|
264
|
+
end
|
265
|
+
return @text_file_cache_manager.get_text("#{@template_pa_prefix}#{pn}")
|
266
|
+
end
|
267
|
+
def insert_instruction(row_i)
|
268
|
+
print 'i'
|
269
|
+
#if(row_i <= 12 || row_i % 20 == 0)
|
270
|
+
# print "r#{row_i} "
|
271
|
+
#end
|
272
|
+
params = get_params(row_i)
|
273
|
+
do_expression = params[:do]
|
274
|
+
template_text = ''
|
275
|
+
filename = @var_map['FILE']
|
276
|
+
#template_text = @text_file_cache_man.get_text("#{@template_pa_prefix}#{filename}")
|
277
|
+
template_text = read_file(filename)
|
278
|
+
text = template_text.gsub(/(\\)#(.*?)#/){
|
279
|
+
v = @var_map[$2]
|
280
|
+
if(v.is_a? String)
|
281
|
+
next v
|
282
|
+
else
|
283
|
+
dparn(304,"placeholder not in @var_map ('#{$2}')")
|
284
|
+
next "XXX WARN 304 @var_map[#{$2}].is_a? was not a string" # replace placeholder with error message
|
285
|
+
end
|
286
|
+
}
|
287
|
+
if params[:on_exit]
|
288
|
+
@on_sheet_exit_add << text
|
289
|
+
elsif params[:after_last_row]
|
290
|
+
@after_last_row << text
|
291
|
+
else
|
292
|
+
write text
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def delegate_instruction(row_i)
|
297
|
+
@debug_row_i = row_i
|
298
|
+
params = get_params(row_i)
|
299
|
+
p2_ss_pn = eval_mvar('FILE')
|
300
|
+
p2_sheet_name = eval_mvar('SHEET')
|
301
|
+
transpose_str = params[:transpose]
|
302
|
+
transpose = false
|
303
|
+
|
304
|
+
$Log.tlog({id: 'info1124_delegate_instruction', ss_pn: @ss_pn, sheet_name: @sheet_name, row_i: row_i, p2_ss_pn: p2_ss_pn, p2_sheet_name: p2_sheet_name})
|
305
|
+
$Log.indent
|
306
|
+
|
307
|
+
#dputi "delegate from #{$st[:ss_file]}#{@ss_pn}#{$st[:std]}" << reset << ":#{$st[:sheet]}#{@sheet_name}:#{$st[:num]}#{row_i}" << reset << " to #{$st[:ss_file]}#{p2_ss_pn}#{$st[:std]}" << reset << ":#{$st[:sheet]}#{p2_sheet_name}"
|
308
|
+
if(transpose_str)
|
309
|
+
if(transpose_str == 'true')
|
310
|
+
transpose = true
|
311
|
+
elsif(transpose_str == 'false')
|
312
|
+
# ok
|
313
|
+
else
|
314
|
+
dparn(401,"delegate_instruction - value for transpose is neither 'true' nor 'false' (defaulting to false) - value is: #{transpose_str}")
|
315
|
+
end
|
316
|
+
end
|
317
|
+
se = SsExport.new({
|
318
|
+
ss_pn: p2_ss_pn,
|
319
|
+
sheet_name: p2_sheet_name,
|
320
|
+
output_file: @output_file,
|
321
|
+
transpose: transpose,
|
322
|
+
ss_db_cache_manager: @ss_db_cache_manager,
|
323
|
+
template_pa_prefix: @template_pa_prefix,
|
324
|
+
text_file_cache_manager: @text_file_cache_manager,
|
325
|
+
export_type: @export_type,
|
326
|
+
super_var_map: @var_map,
|
327
|
+
subs: @subs,
|
328
|
+
})
|
329
|
+
se.process()
|
330
|
+
#dpun
|
331
|
+
$Log.undent
|
332
|
+
#dput "done with: #{$st[:ss_file]}#{p2_ss_pn}#{$st[:std]}" << reset << ":#{$st[:sheet]}#{p2_sheet_name}"
|
333
|
+
$Log.tlog({id:'info1060',p2_ss_pn:p2_ss_pn,p2_sheet_name:p2_sheet_name})
|
334
|
+
end
|
335
|
+
def eval_mvar(col_label)
|
336
|
+
unless @var_map.has_key?(col_label)
|
337
|
+
dperr(1007,"no column named:'#{col_label}'")
|
338
|
+
end
|
339
|
+
str = @var_map[col_label]
|
340
|
+
if(str.is_a? String)
|
341
|
+
str = str.gsub(/\\_/,'')
|
342
|
+
return eval_var(str)
|
343
|
+
else
|
344
|
+
dparn(406,"")
|
345
|
+
return 'XXX - WARN 406'
|
346
|
+
end
|
347
|
+
end
|
348
|
+
def eval_var(var)
|
349
|
+
if(var.class == Fixnum)
|
350
|
+
return var.to_s
|
351
|
+
elsif(var.class == Bignum)
|
352
|
+
return var.to_s
|
353
|
+
end
|
354
|
+
|
355
|
+
if(var.class != String)
|
356
|
+
dparn('W601',"var from db is of class:'#{var.class.to_s}'")
|
357
|
+
return "XXX WARN 601 - var from db is of class:'#{var.class.to_s}'"
|
358
|
+
end
|
359
|
+
if(var == '')
|
360
|
+
dperr(1372,"empty cell #{$st[:ss_file]}#{@ss_pn}:#{$st[:sheet]}#{@sheet_name}:#{$st[:num]}#{@debug_row_i}")
|
361
|
+
end
|
362
|
+
var = var.gsub(/\\_/,'')
|
363
|
+
unless var.index("\\-")
|
364
|
+
return var
|
365
|
+
end
|
366
|
+
t = Template.new(var)
|
367
|
+
parts = t.get_parts
|
368
|
+
ret_var = ''
|
369
|
+
parts.each{|part|
|
370
|
+
if(part.is_a? FunctionCall)
|
371
|
+
r = @@replace_functions[part.name].call(self,part.args)
|
372
|
+
ret_var << r
|
373
|
+
elsif(part.is_a? String)
|
374
|
+
ret_var << part
|
375
|
+
end
|
376
|
+
}
|
377
|
+
return ret_var.strip
|
378
|
+
end
|
379
|
+
def get_params(row_i)
|
380
|
+
params_str = @var_map['PARAMS']
|
381
|
+
params = {}
|
382
|
+
if(params_str == nil)
|
383
|
+
elsif(params_str.is_a? String)
|
384
|
+
pr = Minival.new(params_str)
|
385
|
+
if(pr.valid)
|
386
|
+
params = pr.get_value
|
387
|
+
else
|
388
|
+
pr.report_errors
|
389
|
+
dperr(311,"invalid 'PARAMS' ? - value: '#{params_str}' (row:#{row_i})")
|
390
|
+
end
|
391
|
+
else
|
392
|
+
dperr 310,"params_str not nil and not string (params_str.class:#{params_str.class.to_s})"
|
393
|
+
end
|
394
|
+
|
395
|
+
if(params.class != {}.class)
|
396
|
+
dparn(303,"failed to parse minival (row:#{row_i} column:'PARAMS')")
|
397
|
+
params = {'WARN'=>'303'}
|
398
|
+
end
|
399
|
+
return params
|
400
|
+
end
|
401
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spreadsheet_export_refi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 0.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Robert Fey
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-07-26 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: spreadsheet_cache_manager_refi
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - "="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 1
|
31
|
+
- 0
|
32
|
+
version: 0.1.0
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: file_cache_refi
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - "="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
- 0
|
46
|
+
- 1
|
47
|
+
version: 0.0.1
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: minilang_refi
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - "="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
- 0
|
61
|
+
- 1
|
62
|
+
version: 0.0.1
|
63
|
+
type: :runtime
|
64
|
+
version_requirements: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: template_refi
|
67
|
+
prerelease: false
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - "="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
- 1
|
76
|
+
- 0
|
77
|
+
version: 0.1.0
|
78
|
+
type: :runtime
|
79
|
+
version_requirements: *id004
|
80
|
+
description: ""
|
81
|
+
email: feyrob@gmail.com
|
82
|
+
executables: []
|
83
|
+
|
84
|
+
extensions: []
|
85
|
+
|
86
|
+
extra_rdoc_files: []
|
87
|
+
|
88
|
+
files:
|
89
|
+
- lib/spreadsheet_export_refi.rb
|
90
|
+
has_rdoc: true
|
91
|
+
homepage: http://rubygems.org/gems/spreadsheet_export_refi
|
92
|
+
licenses: []
|
93
|
+
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
requirements: []
|
116
|
+
|
117
|
+
rubyforge_project: nowarning
|
118
|
+
rubygems_version: 1.3.7
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: create documents with instructions in spreadsheets
|
122
|
+
test_files: []
|
123
|
+
|