25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
# File 'lib/rubyXL/parser.rb', line 25
def parse(file_path, opts = {})
wb = Workbook.new([], file_path)
raise 'Not .xlsx or .xlsm excel file' unless @skip_filename_check ||
%w{.xlsx .xlsm}.include?(File.extname(file_path))
dir_path = File.join(File.dirname(file_path), Dir::Tmpname.make_tmpname(['rubyXL', '.tmp'], nil))
MyZip.new.unzip(file_path, dir_path)
files = {}
workbook_file = Nokogiri::XML.parse(File.open(File.join(dir_path,'xl','workbook.xml'),'r'))
rels_doc = Nokogiri::XML.parse(File.open(File.join(dir_path, 'xl', '_rels', 'workbook.xml.rels'), 'r'))
if(File.exist?(File.join(dir_path,'xl','sharedStrings.xml')))
shared_string_file = Nokogiri::XML.parse(File.open(File.join(dir_path,'xl','sharedStrings.xml'),'r'))
end
unless @data_only
wb.media = RubyXL::GenericStorage.new(File.join('xl', 'media')).binary.load_dir(dir_path)
wb.external_links = RubyXL::GenericStorage.new(File.join('xl', 'externalLinks')).load_dir(dir_path)
wb.external_links_rels = RubyXL::GenericStorage.new(File.join('xl', 'externalLinks', '_rels')).load_dir(dir_path)
wb.drawings = RubyXL::GenericStorage.new(File.join('xl', 'drawings')).load_dir(dir_path)
wb.drawings_rels = RubyXL::GenericStorage.new(File.join('xl', 'drawings', '_rels')).load_dir(dir_path)
wb.charts = RubyXL::GenericStorage.new(File.join('xl', 'charts')).load_dir(dir_path)
wb.chart_rels = RubyXL::GenericStorage.new(File.join('xl', 'charts', '_rels')).load_dir(dir_path)
wb.printer_settings = RubyXL::GenericStorage.new(File.join('xl', 'printerSettings')).binary.load_dir(dir_path)
wb.worksheet_rels = RubyXL::GenericStorage.new(File.join('xl', 'worksheets', '_rels')).load_dir(dir_path)
wb.macros = RubyXL::GenericStorage.new('xl').binary.load_file(dir_path, 'vbaProject.bin')
wb.theme = RubyXL::GenericStorage.new(File.join('xl', 'theme')).load_file(dir_path, 'theme1.xml')
core_file = Nokogiri::XML.parse(File.open(File.join(dir_path, 'docProps', 'core.xml'), 'r'))
wb.creator = core_file.css('dc|creator').children.to_s
wb.modifier = core_file.css('cp|last_modified_by').children.to_s
wb.created_at = core_file.css('dcterms|created').children.to_s
wb.modified_at = core_file.css('dcterms|modified').children.to_s
app_file = Nokogiri::XML.parse(File.open(File.join(dir_path, 'docProps', 'app.xml'), 'r'))
wb.company = app_file.css('Company').children.to_s
wb.application = app_file.css('Application').children.to_s
wb.appversion = app_file.css('AppVersion').children.to_s
end
styles_xml = Nokogiri::XML.parse(File.open(File.join(dir_path, 'xl', 'styles.xml'), 'r'))
defined_names = workbook_file.css('definedNames definedName')
wb.defined_names = defined_names.collect { |node| RubyXL::DefinedName.parse(node) }
wb.date1904 = workbook_file.css('workbookPr').attribute('date1904').to_s == '1'
wb.shared_strings_XML = shared_string_file.to_s
unless shared_string_file.nil?
sst = shared_string_file.css('sst')
wb.shared_strings.count_attr = sst.attribute('count').value.to_i
wb.shared_strings.unique_count_attr = sst.attribute('uniqueCount').value.to_i
shared_string_file.css('si').each_with_index { |node, i|
wb.shared_strings.add(node.css('t').inject(''){ |s, c| s + c.text }, i)
}
end
fills = styles_xml.css('fills fill')
wb.fills = fills.collect { |node| RubyXL::Fill.parse(node) }
colors = styles_xml.css('colors').first
if colors then
colors.element_children.each { |color_type_node|
wb.colors[color_type_node.name] ||= []
color_type_node.element_children.each { |color_node|
wb.colors[color_type_node.name] << RubyXL::Color.parse(color_node)
}
}
end
borders = styles_xml.css('borders border')
wb.borders = borders.collect { |node| RubyXL::Border.parse(node) }
fonts = styles_xml.css('fonts font')
wb.fonts = fonts.collect { |node| RubyXL::Font.parse(node) }
cell_styles = styles_xml.css('cellStyles cellStyle')
wb.cell_styles = cell_styles.collect { |node| RubyXL::CellStyle.parse(node) }
num_fmts = styles_xml.css('numFmts numFmt')
wb.num_fmts = num_fmts.collect { |node| RubyXL::NumFmt.parse(node) }
csxfs = styles_xml.css('cellStyleXfs xf')
wb.cell_style_xfs = csxfs.collect { |node| RubyXL::XF.parse(node) }
cxfs = styles_xml.css('cellXfs xf')
wb.cell_xfs = cxfs.collect { |node| RubyXL::XF.parse(node) }
wb.cell_xfs.each { |style|
id = style.font_id
wb.fonts[id].count += 1
id = style.fill_id
wb.fills[id].count += 1
id = style.border_id
wb.borders[id].count += 1 }
workbook_file.css('sheets sheet').each_with_index { |sheet_node, i|
sheet_rid = sheet_node.attributes['id'].value
sheet_file_path = rels_doc.css("Relationships Relationship[Id=#{sheet_rid}]").first.attributes['Target']
worksheet_xml = Nokogiri::XML.parse(File.read(File.join(dir_path, 'xl', sheet_file_path)))
parse_worksheet(wb, i, worksheet_xml, sheet_node.attributes['name'].value,
sheet_node.attributes['sheetId'].value )
}
FileUtils.remove_entry_secure(dir_path)
return wb
end
|