There’re some libraries dealing with Excel, but they didn’t work in some conditions. So I’ve just written the code for this.
ExcelData uses win32ole module. It means this work only on Windows and Excel needs to be installed.
There’s only a public class method Load returns row array. Each row consists of hash with column name and value string pair.
Load method requires minimum three parameters. Excel filename(excelFilename), sheet name(worksheetName) and first header column name(firstHeaderColumnName). ExcelData finds first row with first header column name and read cell from there. If empty cell is found(both row and column), it stops reading the file.
require 'win32ole' class ExcelData public def ExcelData.Load(excelFilename, worksheetName, firstHeaderColumnName, keySearcher = nil) xls = nil ws = nil excelData = [] begin xls = WIN32OLE.new('Excel.Application') xls.visible = false ws = xls.Workbooks.Open(excelFilename).Worksheets(worksheetName) excelData = _CollectData(ws, firstHeaderColumnName, keySearcher) rescue puts "Failed to open excel file : #{excelFilename}" ensure xls.quit if xls != nil end return excelData end private def ExcelData._FindFirstDataRowNum(worksheet, firstHeaderColumnName) rowNum = 1 while (true) row = worksheet.Range("a#{rowNum}") break if (row['Value'] != nil && row['Value'] == firstHeaderColumnName) rowNum += 1 end return rowNum + 1 end def ExcelData._FindLastDataRowNum(worksheet, firstDataRowNum) rowNum = firstDataRowNum while (true) row = worksheet.Range("a#{rowNum}") break if (row['Value'] == nil || row['Value'] == "") rowNum += 1 end return rowNum - 1 end def ExcelData._FindLastDataColChar(worksheet, headerDataRowNum) colChar = 'a' while (true) row = worksheet.Range("#{colChar}#{headerDataRowNum}") break if (colChar == 'z' || row['Value'] == nil || row['Value'] == "") colChar.succ! end return colChar end def ExcelData._CollectData(worksheet, firstHeaderColumnName, keySearcher) firstDataRowNum = _FindFirstDataRowNum(worksheet, firstHeaderColumnName) lastDataRowNum = _FindLastDataRowNum(worksheet, firstDataRowNum) lastDataColChar = _FindLastDataColChar(worksheet, firstDataRowNum - 1) puts "Collecting excel data : Total #{lastDataRowNum - firstDataRowNum + 1} rows ..." # Column Names colNames = [] row = worksheet.Range("a#{firstDataRowNum - 1}:#{lastDataColChar}#{firstDataRowNum - 1}") row.each do |cell| colNames << cell['Value'] end # Collect excel data excelData = [] for rowNum in firstDataRowNum..lastDataRowNum colIndex = 0 rowHash = {} row = worksheet.Range("a#{rowNum}:#{lastDataColChar}#{rowNum}") row.each do |cell| if (!cell['Value'].to_s.empty? && cell['Value'].to_s =~ /^[0-9.]+/) rowHash.store(colNames[colIndex], cell['Value'].to_i.to_s) elsif rowHash.store(colNames[colIndex], cell['Value'].to_s) end colIndex += 1 end excelData << rowHash keySearcher.store(rowHash[colNames[0]].to_s, excelData.length - 1) if keySearcher != nil print "." if excelData.length % 10 == 0 end puts return excelData end end
You can simply use this code like bellow.
xls = ExcelData.Load('myfile.xls', 'sheet1', 'ITEMID')