excel_to_code 0.0.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/README +41 -0
- data/bin/excel_to_c +63 -0
- data/bin/excel_to_ruby +9 -0
- data/src/commands.rb +2 -0
- data/src/commands/excel_to_c.rb +858 -0
- data/src/commands/excel_to_ruby.rb +620 -0
- data/src/compile.rb +2 -0
- data/src/compile/c.rb +5 -0
- data/src/compile/c/compile_to_c.rb +62 -0
- data/src/compile/c/compile_to_c_header.rb +26 -0
- data/src/compile/c/compile_to_c_unit_test.rb +42 -0
- data/src/compile/c/excel_to_c_runtime.c +2029 -0
- data/src/compile/c/map_formulae_to_c.rb +184 -0
- data/src/compile/c/map_sheet_names_to_c_names.rb +19 -0
- data/src/compile/c/map_values_to_c.rb +85 -0
- data/src/compile/c/map_values_to_c_structs.rb +37 -0
- data/src/compile/ruby.rb +3 -0
- data/src/compile/ruby/compile_to_ruby.rb +33 -0
- data/src/compile/ruby/compile_to_ruby_unit_test.rb +28 -0
- data/src/compile/ruby/excel_to_ruby_runtime.rb +1 -0
- data/src/compile/ruby/map_formulae_to_ruby.rb +95 -0
- data/src/compile/ruby/map_sheet_names_to_ruby_names.rb +19 -0
- data/src/compile/ruby/map_values_to_ruby.rb +65 -0
- data/src/excel.rb +5 -0
- data/src/excel/area.rb +93 -0
- data/src/excel/excel_functions.rb +84 -0
- data/src/excel/excel_functions/abs.rb +14 -0
- data/src/excel/excel_functions/add.rb +18 -0
- data/src/excel/excel_functions/and.rb +30 -0
- data/src/excel/excel_functions/apply_to_range.rb +17 -0
- data/src/excel/excel_functions/average.rb +12 -0
- data/src/excel/excel_functions/choose.rb +18 -0
- data/src/excel/excel_functions/cosh.rb +9 -0
- data/src/excel/excel_functions/count.rb +9 -0
- data/src/excel/excel_functions/counta.rb +8 -0
- data/src/excel/excel_functions/divide.rb +23 -0
- data/src/excel/excel_functions/excel_equal.rb +20 -0
- data/src/excel/excel_functions/excel_if.rb +8 -0
- data/src/excel/excel_functions/excel_match.rb +51 -0
- data/src/excel/excel_functions/find.rb +39 -0
- data/src/excel/excel_functions/iferror.rb +10 -0
- data/src/excel/excel_functions/index.rb +48 -0
- data/src/excel/excel_functions/left.rb +12 -0
- data/src/excel/excel_functions/less_than.rb +26 -0
- data/src/excel/excel_functions/less_than_or_equal.rb +26 -0
- data/src/excel/excel_functions/max.rb +12 -0
- data/src/excel/excel_functions/min.rb +12 -0
- data/src/excel/excel_functions/mod.rb +15 -0
- data/src/excel/excel_functions/more_than.rb +26 -0
- data/src/excel/excel_functions/more_than_or_equal.rb +26 -0
- data/src/excel/excel_functions/multiply.rb +24 -0
- data/src/excel/excel_functions/negative.rb +12 -0
- data/src/excel/excel_functions/not_equal.rb +19 -0
- data/src/excel/excel_functions/number_argument.rb +30 -0
- data/src/excel/excel_functions/pi.rb +7 -0
- data/src/excel/excel_functions/pmt.rb +16 -0
- data/src/excel/excel_functions/power.rb +18 -0
- data/src/excel/excel_functions/round.rb +13 -0
- data/src/excel/excel_functions/rounddown.rb +14 -0
- data/src/excel/excel_functions/roundup.rb +17 -0
- data/src/excel/excel_functions/string_join.rb +19 -0
- data/src/excel/excel_functions/subtotal.rb +13 -0
- data/src/excel/excel_functions/subtract.rb +18 -0
- data/src/excel/excel_functions/sum.rb +8 -0
- data/src/excel/excel_functions/sumif.rb +7 -0
- data/src/excel/excel_functions/sumifs.rb +74 -0
- data/src/excel/excel_functions/sumproduct.rb +32 -0
- data/src/excel/excel_functions/vlookup.rb +49 -0
- data/src/excel/formula_peg.rb +238 -0
- data/src/excel/formula_peg.txt +45 -0
- data/src/excel/reference.rb +56 -0
- data/src/excel/table.rb +108 -0
- data/src/excel_to_code.rb +7 -0
- data/src/extract.rb +13 -0
- data/src/extract/check_for_unknown_functions.rb +20 -0
- data/src/extract/extract_array_formulae.rb +23 -0
- data/src/extract/extract_formulae.rb +36 -0
- data/src/extract/extract_named_references.rb +38 -0
- data/src/extract/extract_relationships.rb +10 -0
- data/src/extract/extract_shared_formulae.rb +23 -0
- data/src/extract/extract_shared_strings.rb +20 -0
- data/src/extract/extract_simple_formulae.rb +18 -0
- data/src/extract/extract_table.rb +24 -0
- data/src/extract/extract_values.rb +29 -0
- data/src/extract/extract_worksheet_dimensions.rb +11 -0
- data/src/extract/extract_worksheet_names.rb +10 -0
- data/src/extract/extract_worksheet_table_relationships.rb +10 -0
- data/src/extract/simple_extract_from_xml.rb +19 -0
- data/src/rewrite.rb +10 -0
- data/src/rewrite/ast_copy_formula.rb +42 -0
- data/src/rewrite/ast_expand_array_formulae.rb +180 -0
- data/src/rewrite/rewrite_array_formulae.rb +71 -0
- data/src/rewrite/rewrite_array_formulae_to_arrays.rb +18 -0
- data/src/rewrite/rewrite_cell_references_to_include_sheet.rb +56 -0
- data/src/rewrite/rewrite_formulae_to_ast.rb +24 -0
- data/src/rewrite/rewrite_merge_formulae_and_values.rb +18 -0
- data/src/rewrite/rewrite_relationship_id_to_filename.rb +22 -0
- data/src/rewrite/rewrite_shared_formulae.rb +38 -0
- data/src/rewrite/rewrite_values_to_ast.rb +28 -0
- data/src/rewrite/rewrite_whole_row_column_references_to_areas.rb +90 -0
- data/src/rewrite/rewrite_worksheet_names.rb +20 -0
- data/src/simplify.rb +16 -0
- data/src/simplify/count_formula_references.rb +58 -0
- data/src/simplify/identify_dependencies.rb +56 -0
- data/src/simplify/identify_repeated_formula_elements.rb +37 -0
- data/src/simplify/inline_formulae.rb +77 -0
- data/src/simplify/map_formulae_to_values.rb +157 -0
- data/src/simplify/remove_cells.rb +18 -0
- data/src/simplify/replace_arrays_with_single_cells.rb +27 -0
- data/src/simplify/replace_blanks.rb +58 -0
- data/src/simplify/replace_common_elements_in_formulae.rb +19 -0
- data/src/simplify/replace_formulae_with_calculated_values.rb +21 -0
- data/src/simplify/replace_indirects_with_references.rb +44 -0
- data/src/simplify/replace_named_references.rb +82 -0
- data/src/simplify/replace_ranges_with_array_literals.rb +54 -0
- data/src/simplify/replace_shared_strings.rb +49 -0
- data/src/simplify/replace_table_references.rb +71 -0
- data/src/simplify/replace_values_with_constants.rb +47 -0
- data/src/simplify/simplify_arithmetic.rb +54 -0
- data/src/util.rb +2 -0
- data/src/util/not_supported_exception.rb +2 -0
- data/src/util/try.rb +9 -0
- metadata +207 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
formula := space? expression+
|
2
|
+
expression = string_join | comparison | arithmetic | thing
|
3
|
+
thing = function | array | brackets | any_reference | string | percentage | number | boolean | prefix | named_reference
|
4
|
+
argument = expression | null
|
5
|
+
function := /[A-Z]+/ `'(' space argument? (space `',' space argument)* space `')'
|
6
|
+
brackets := `'(' space expression+ space `')'
|
7
|
+
array := `'{' space row ( space `';' space row )* space `'}'
|
8
|
+
row := basic_type ( space `',' space basic_type )*
|
9
|
+
basic_type = string | percentage | number | boolean
|
10
|
+
string_join := (arithmetic | thing) (space `"&" space (arithmetic | thing))+
|
11
|
+
arithmetic := thing (space operator space thing)+
|
12
|
+
comparison := (arithmetic | thing) space comparator space (arithmetic | thing)
|
13
|
+
comparator := '>=' | '<=' | '<>' | '>' | '<' | '='
|
14
|
+
string := `'"' /(""|[^"])*/ `'"'
|
15
|
+
any_reference = external_reference | any_internal_reference
|
16
|
+
any_internal_reference = table_reference | local_table_reference | sheet_reference | sheetless_reference
|
17
|
+
percentage := /[-+]?[0-9]+\.?[0-9]*/ `'%'
|
18
|
+
number := /[-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?/
|
19
|
+
operator := '+' | '-' | '/' | '*' | '^'
|
20
|
+
external_reference := /\[\d+\]!?/ any_internal_reference
|
21
|
+
table_reference := table_name `'[' (range_structured_reference | complex_structured_reference | simple_structured_reference) `']'
|
22
|
+
local_table_reference := `'[' (range_structured_reference | complex_structured_reference | overly_structured_reference | simple_structured_reference) `']'
|
23
|
+
table_name = /[.a-zA-Z0-9_]+/
|
24
|
+
range_structured_reference = /\[[^\u005d]*\],\[[^\u005d]*\]:\[[^\u005d]*\]/
|
25
|
+
complex_structured_reference = /\[[^\u005d]*\],\[[^\u005d]*\]/
|
26
|
+
overly_structured_reference = `'[' simple_structured_reference `']'
|
27
|
+
simple_structured_reference = /[^\u005d]*/
|
28
|
+
named_reference := /[#a-zA-Z][\w_.!]+/
|
29
|
+
sheet_reference := (single_quoted_string | /[a-zA-Z0-9][\w_.]+/) `'!' (sheetless_reference | named_reference)
|
30
|
+
single_quoted_string = `"'" /[^']*/ `"'"
|
31
|
+
sheetless_reference = column_range | row_range | area | cell
|
32
|
+
column_range := column `':' column
|
33
|
+
row_range := row_number `':' row_number
|
34
|
+
area := reference `':' reference
|
35
|
+
cell := reference
|
36
|
+
row_number = /\$?\d+/
|
37
|
+
column = /\$?[A-Za-z]{1,3}/
|
38
|
+
reference = /\$?[A-Za-z]{1,3}\$?[0-9]+(?![0-9A-Za-z_])/
|
39
|
+
boolean = boolean_true | boolean_false
|
40
|
+
boolean_true := `'TRUE'
|
41
|
+
boolean_false := `'FALSE'
|
42
|
+
prefix := /[-+]/ thing
|
43
|
+
space = `/[ \n]*/
|
44
|
+
null := &','
|
45
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class Reference < String
|
2
|
+
|
3
|
+
# This is so that we only have one instance for a given reference
|
4
|
+
@@references_for_text ||= Hash.new do |hash,text|
|
5
|
+
hash[text] = reference = Reference.new(text)
|
6
|
+
reference
|
7
|
+
end
|
8
|
+
|
9
|
+
# This is so that we only have one instance of a given reference specified by its variables
|
10
|
+
def Reference.for(text)
|
11
|
+
@@references_for_text[text]
|
12
|
+
end
|
13
|
+
|
14
|
+
# This caches the calculation for turning column letters (e.g., AAB) into column numbers (e.g., 127)
|
15
|
+
@@column_number_for_column ||= Hash.new do |hash,letters|
|
16
|
+
number = letters.downcase.each_byte.to_a.reverse.each.with_index.inject(0) do |memo,byte_with_index,c|
|
17
|
+
memo + ((byte_with_index.first - 96) * (26**byte_with_index.last))
|
18
|
+
end
|
19
|
+
hash[letters] = number
|
20
|
+
@@column_letters_for_column_number[number] = letters.upcase
|
21
|
+
number
|
22
|
+
end
|
23
|
+
|
24
|
+
# This caches the calculation for turning column numbers (e.g., 127) into column letters (e.g., AAB)
|
25
|
+
@@column_letters_for_column_number ||= Hash.new do |hash,number|
|
26
|
+
letters = (number-1).to_i.to_s(26)
|
27
|
+
letters = (letters[0...-1].tr('1-9a-z','abcdefghijklmnopqrstuvwxyz') + letters[-1,1].tr('0-9a-z','abcdefghijklmnopqrstuvwxyz')).gsub('a0','z').gsub(/([b-z])0/) { $1.tr('b-z','a-y')+"z" }
|
28
|
+
letters.upcase!
|
29
|
+
hash[number] = letters
|
30
|
+
@@column_number_for_column[letters] = number
|
31
|
+
letters
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :excel_row_number, :excel_column_number, :excel_column, :excel_row
|
35
|
+
|
36
|
+
def calculate_excel_variables
|
37
|
+
return if @excel_variables_calculated
|
38
|
+
self =~ /(\$)?([A-Za-z]{1,3})(\$)?([0-9]+)/
|
39
|
+
@excel_fixed_column, @excel_column, @excel_fixed_row, @excel_row = $1, $2, $3, $4
|
40
|
+
@excel_row_number = @excel_row.to_i
|
41
|
+
@excel_column_number = @@column_number_for_column[@excel_column]
|
42
|
+
@excel_variables_calculated = true
|
43
|
+
end
|
44
|
+
|
45
|
+
def offset(rows,columns)
|
46
|
+
calculate_excel_variables
|
47
|
+
new_column = @excel_fixed_column ? @excel_column : @@column_letters_for_column_number[@excel_column_number + columns]
|
48
|
+
new_row = @excel_fixed_row ? @excel_row : @excel_row_number + rows
|
49
|
+
Reference.new([@excel_fixed_column,new_column,@excel_fixed_row,new_row].join)
|
50
|
+
end
|
51
|
+
|
52
|
+
def unfix
|
53
|
+
gsub("$","")
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/src/excel/table.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
require_relative '../excel'
|
2
|
+
require_relative '../util'
|
3
|
+
|
4
|
+
class Table
|
5
|
+
|
6
|
+
attr_accessor :name
|
7
|
+
|
8
|
+
def initialize(name,worksheet,reference,number_of_total_rows,*column_name_array)
|
9
|
+
@name, @worksheet, @area, @number_of_total_rows, @column_name_array = name, worksheet, Area.for(reference), number_of_total_rows.to_i, column_name_array.map { |c| c.strip.downcase }
|
10
|
+
@area.calculate_excel_variables
|
11
|
+
@data_area = Area.for("#{@area.excel_start.offset(1,0)}:#{@area.excel_finish.offset(-@number_of_total_rows,0)}")
|
12
|
+
end
|
13
|
+
|
14
|
+
def reference_for(table_name,structured_reference,calling_worksheet,calling_cell)
|
15
|
+
raise NotSupportedException.new("Local table reference not supported in #{structured_reference.inspect}") unless table_name
|
16
|
+
case structured_reference
|
17
|
+
when /\[#Headers\],\[(.*?)\]:\[(.*?)\]/io
|
18
|
+
column_number_start = @column_name_array.find_index($1.strip.downcase)
|
19
|
+
column_number_finish = @column_name_array.find_index($2.strip.downcase)
|
20
|
+
return ref_error unless column_number_start && column_number_finish
|
21
|
+
ast_for_area @area.excel_start.offset(0,column_number_start), @area.excel_start.offset(0,column_number_finish)
|
22
|
+
when /\[#Totals\],\[(.*?)\]:\[(.*?)\]/io
|
23
|
+
column_number_start = @column_name_array.find_index($1.strip.downcase)
|
24
|
+
column_number_finish = @column_name_array.find_index($2.strip.downcase)
|
25
|
+
return ref_error unless column_number_start && column_number_finish
|
26
|
+
ast_for_area @area.excel_start.offset(@area.height,column_number_start), @area.excel_start.offset(@area.height,column_number_finish)
|
27
|
+
when /\[#This Row\],\[(.*?)\]:\[(.*?)\]/io
|
28
|
+
r = Reference.for(calling_cell)
|
29
|
+
r.calculate_excel_variables
|
30
|
+
row = r.excel_row_number
|
31
|
+
column_number_start = @column_name_array.find_index($1.strip.downcase)
|
32
|
+
column_number_finish = @column_name_array.find_index($2.strip.downcase)
|
33
|
+
return ref_error unless column_number_start && column_number_finish
|
34
|
+
ast_for_area @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number_start), @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number_finish)
|
35
|
+
when /\[#Headers\],\[(.*?)\]/io
|
36
|
+
column_number = @column_name_array.find_index($1.strip.downcase)
|
37
|
+
return ref_error unless column_number
|
38
|
+
ast_for_cell @area.excel_start.offset(0,column_number)
|
39
|
+
when /\[#Totals\],\[(.*?)\]/io
|
40
|
+
column_number = @column_name_array.find_index($1.strip.downcase)
|
41
|
+
return ref_error unless column_number
|
42
|
+
ast_for_cell @area.excel_start.offset(@area.height,column_number)
|
43
|
+
when /\[#This Row\],\[(.*?)\]/io
|
44
|
+
r = Reference.for(calling_cell)
|
45
|
+
r.calculate_excel_variables
|
46
|
+
row = r.excel_row_number
|
47
|
+
column_number = @column_name_array.find_index($1.strip.downcase)
|
48
|
+
return ref_error unless column_number
|
49
|
+
ast_for_cell @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number)
|
50
|
+
when /#Headers/io
|
51
|
+
if calling_worksheet == @worksheet && @data_area.includes?(calling_cell)
|
52
|
+
r = Reference.for(calling_cell)
|
53
|
+
r.calculate_excel_variables
|
54
|
+
ast_for_cell "#{r.excel_column}#{@area.excel_start.excel_row_number}"
|
55
|
+
else
|
56
|
+
ast_for_area @area.excel_start.offset(0,0), @area.excel_start.offset(0,@area.width)
|
57
|
+
end
|
58
|
+
when /#Totals/io
|
59
|
+
if calling_worksheet == @worksheet && @data_area.includes?(calling_cell)
|
60
|
+
r = Reference.for(calling_cell)
|
61
|
+
r.calculate_excel_variables
|
62
|
+
ast_for_cell "#{r.excel_column}#{@area.excel_finish.excel_row_number}"
|
63
|
+
else
|
64
|
+
ast_for_area @area.excel_start.offset(@area.height,0), @area.excel_start.offset(@area.height,@area.width)
|
65
|
+
end
|
66
|
+
when /#Data/io, ""
|
67
|
+
ast_for_area @data_area.excel_start, @data_area.excel_finish
|
68
|
+
when /#All/io, ""
|
69
|
+
ast_for_area @area.excel_start, @area.excel_finish
|
70
|
+
when /#This Row/io
|
71
|
+
r = Reference.for(calling_cell)
|
72
|
+
r.calculate_excel_variables
|
73
|
+
row = r.excel_row_number
|
74
|
+
ast_for_area "#{@area.excel_start.excel_column}#{row}", "#{@area.excel_finish.excel_column}#{row}"
|
75
|
+
else
|
76
|
+
if calling_worksheet == @worksheet && @data_area.includes?(calling_cell)
|
77
|
+
r = Reference.for(calling_cell)
|
78
|
+
r.calculate_excel_variables
|
79
|
+
row = r.excel_row_number
|
80
|
+
column_number = @column_name_array.find_index(structured_reference.strip.downcase)
|
81
|
+
return ref_error unless column_number
|
82
|
+
ast_for_cell @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number)
|
83
|
+
else
|
84
|
+
column_number = @column_name_array.find_index(structured_reference.strip.downcase)
|
85
|
+
return ref_error unless column_number
|
86
|
+
ast_for_area @area.excel_start.offset(1,column_number), @area.excel_start.offset(@area.height - @number_of_total_rows,column_number)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def ast_for_area(start,finish)
|
92
|
+
[:sheet_reference,@worksheet,[:area,start,finish]]
|
93
|
+
end
|
94
|
+
|
95
|
+
def ast_for_cell(ref)
|
96
|
+
[:sheet_reference,@worksheet,[:cell,ref]]
|
97
|
+
end
|
98
|
+
|
99
|
+
def ref_error
|
100
|
+
[:error,"#REF!"]
|
101
|
+
end
|
102
|
+
|
103
|
+
def includes?(sheet,reference)
|
104
|
+
return false unless @worksheet == sheet
|
105
|
+
@area.includes?(reference)
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
data/src/extract.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'extract/check_for_unknown_functions'
|
2
|
+
require_relative "extract/extract_array_formulae"
|
3
|
+
require_relative "extract/extract_formulae"
|
4
|
+
require_relative "extract/extract_relationships"
|
5
|
+
require_relative "extract/extract_shared_formulae"
|
6
|
+
require_relative "extract/extract_shared_strings"
|
7
|
+
require_relative "extract/extract_simple_formulae"
|
8
|
+
require_relative "extract/extract_values"
|
9
|
+
require_relative "extract/extract_worksheet_dimensions"
|
10
|
+
require_relative "extract/extract_worksheet_names"
|
11
|
+
require_relative "extract/extract_named_references"
|
12
|
+
require_relative "extract/extract_worksheet_table_relationships"
|
13
|
+
require_relative "extract/extract_table"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative '../compile/ruby/map_formulae_to_ruby'
|
2
|
+
|
3
|
+
class CheckForUnknownFunctions
|
4
|
+
|
5
|
+
attr_accessor :settable
|
6
|
+
|
7
|
+
def self.rewrite(*args)
|
8
|
+
self.new.rewrite(*args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def check(input,output)
|
12
|
+
self.settable ||= lambda { |ref| false }
|
13
|
+
input.lines do |line|
|
14
|
+
line.scan(/\[:function, "(.*?)"/).each do |match|
|
15
|
+
output.puts $1 unless MapFormulaeToRuby::FUNCTIONS.has_key?($1)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'extract_formulae'
|
2
|
+
|
3
|
+
class ExtractArrayFormulae < ExtractFormulae
|
4
|
+
|
5
|
+
attr_accessor :array_range
|
6
|
+
|
7
|
+
def start_formula(type,attributes)
|
8
|
+
return unless type == 'array' && attributes.assoc('ref')
|
9
|
+
@array_range = attributes.assoc('ref').last
|
10
|
+
@parsing = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def write_formula
|
14
|
+
return false if @formula.empty?
|
15
|
+
output.write @ref
|
16
|
+
output.write "\t"
|
17
|
+
output.write @array_range
|
18
|
+
output.write "\t"
|
19
|
+
output.write @formula.join
|
20
|
+
output.write "\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative 'simple_extract_from_xml'
|
2
|
+
|
3
|
+
class ExtractFormulae < SimpleExtractFromXML
|
4
|
+
|
5
|
+
attr_accessor :ref, :formula
|
6
|
+
|
7
|
+
def start_element(name,attributes)
|
8
|
+
if name == 'c'
|
9
|
+
@ref = attributes.assoc('r').last
|
10
|
+
elsif name == "f"
|
11
|
+
type = attributes.assoc('t')
|
12
|
+
@formula = []
|
13
|
+
start_formula( type && type.last, attributes)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def start_formula(type,attributes)
|
18
|
+
# Should be overriden in sub classes
|
19
|
+
end
|
20
|
+
|
21
|
+
def write_formula
|
22
|
+
# Should be overriden in sub classes
|
23
|
+
end
|
24
|
+
|
25
|
+
def end_element(name)
|
26
|
+
return unless parsing && name == "f"
|
27
|
+
self.parsing = false
|
28
|
+
write_formula
|
29
|
+
end
|
30
|
+
|
31
|
+
def characters(string)
|
32
|
+
return unless parsing
|
33
|
+
@formula.push(string)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'simple_extract_from_xml'
|
2
|
+
|
3
|
+
class ExtractNamedReferences < SimpleExtractFromXML
|
4
|
+
|
5
|
+
attr_accessor :sheet_names
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
super
|
9
|
+
@sheet_names = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def start_element(name,attributes)
|
13
|
+
if name == "sheet"
|
14
|
+
sheet_names << attributes.assoc('name').last
|
15
|
+
elsif name == "definedName"
|
16
|
+
@parsing = true
|
17
|
+
sheet = attributes.assoc('localSheetId')
|
18
|
+
if sheet
|
19
|
+
output.write sheet_names[sheet.last.to_i]
|
20
|
+
end
|
21
|
+
output.write "\t"
|
22
|
+
output.write attributes.assoc('name').last
|
23
|
+
output.write "\t"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def end_element(name)
|
28
|
+
return unless name == "definedName"
|
29
|
+
self.parsing = false
|
30
|
+
output.putc "\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
def characters(string)
|
34
|
+
return unless parsing
|
35
|
+
output.write string
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative 'simple_extract_from_xml'
|
2
|
+
|
3
|
+
class ExtractRelationships < SimpleExtractFromXML
|
4
|
+
|
5
|
+
def start_element(name,attributes)
|
6
|
+
return false unless name == "Relationship"
|
7
|
+
output.puts "#{attributes.assoc('Id').last}\t#{attributes.assoc('Target').last}"
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'extract_formulae'
|
2
|
+
|
3
|
+
class ExtractSharedFormulae < ExtractFormulae
|
4
|
+
|
5
|
+
attr_accessor :shared_range
|
6
|
+
|
7
|
+
def start_formula(type,attributes)
|
8
|
+
return unless type == 'shared' && attributes.assoc('ref')
|
9
|
+
@shared_range = attributes.assoc('ref').last
|
10
|
+
@parsing = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def write_formula
|
14
|
+
return if @formula.empty?
|
15
|
+
output.write @ref
|
16
|
+
output.write "\t"
|
17
|
+
output.write @shared_range
|
18
|
+
output.write "\t"
|
19
|
+
output.write @formula.join
|
20
|
+
output.write "\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'simple_extract_from_xml'
|
2
|
+
|
3
|
+
class ExtractSharedStrings < SimpleExtractFromXML
|
4
|
+
|
5
|
+
def start_element(name,attributes)
|
6
|
+
self.parsing = true if name == "si"
|
7
|
+
end
|
8
|
+
|
9
|
+
def end_element(name)
|
10
|
+
return unless name == "si"
|
11
|
+
self.parsing = false
|
12
|
+
output.putc "\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
def characters(string)
|
16
|
+
return unless parsing
|
17
|
+
output.write string.gsub("\n","")
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'extract_formulae'
|
2
|
+
|
3
|
+
class ExtractSimpleFormulae < ExtractFormulae
|
4
|
+
|
5
|
+
def start_formula(type,attributes)
|
6
|
+
return if type
|
7
|
+
@parsing = true
|
8
|
+
end
|
9
|
+
|
10
|
+
def write_formula
|
11
|
+
return if @formula.empty?
|
12
|
+
output.write @ref
|
13
|
+
output.write "\t"
|
14
|
+
output.write @formula.join
|
15
|
+
output.write "\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'simple_extract_from_xml'
|
2
|
+
|
3
|
+
class ExtractTable < SimpleExtractFromXML
|
4
|
+
|
5
|
+
attr_accessor :worksheet_name
|
6
|
+
|
7
|
+
def initialize(worksheet_name = nil)
|
8
|
+
super()
|
9
|
+
@worksheet_name = worksheet_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def start_element(name,attributes)
|
13
|
+
if name == "table"
|
14
|
+
output.write "#{attributes.assoc('displayName').last}\t#{@worksheet_name}\t#{attributes.assoc('ref').last}\t#{attributes.assoc('totalsRowCount').try(:last) || 0}"
|
15
|
+
elsif name == "tableColumn"
|
16
|
+
output.write "\t#{attributes.assoc('name').last}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def end_element(name)
|
21
|
+
return unless name == "table"
|
22
|
+
output.putc "\n"
|
23
|
+
end
|
24
|
+
end
|