Skip to content

Instantly share code, notes, and snippets.

@obikag
Created July 31, 2013 00:52
Show Gist options
  • Save obikag/6118422 to your computer and use it in GitHub Desktop.
Save obikag/6118422 to your computer and use it in GitHub Desktop.
Simple Lua Object that can read and modify a CSV file. Strings containing a comma (,) are not supported.
--Initialise
SimpleCSV = {}
SimpleCSV.__index = SimpleCSV
--Create new object
function SimpleCSV.new()
self = setmetatable({},SimpleCSV)
self.csv_table = {}
return self
end
--[[
Load CSV File into multidimensional table.
parmeter: filepath is the location of the csv file
returns: True is file exists and has been loaded
]]
function SimpleCSV:load_csvfile(filepath)
local file = io.open(filepath,"r")
if file then
for line in file:lines() do
local temp = {}
for item in string.gmatch(line,"[^,]*") do --does not work for strings containing ','
if item ~= "" then
item = item:gsub(",","")
item = item:gsub("^%s*(.-)%s*$", "%1") -- remove trailing white spaces
table.insert(temp,item)
end
end
table.insert(self.csv_table, temp)
end
else
print("Cannot open file: "..filepath)
return false
end
return true
end
--[[
Display csv file loaded into table
returns: None
]]
function SimpleCSV:display_csvfile()
if next(self.csv_table) ~= nil then
for rowCount = 1, #self.csv_table do
print(unpack(self.csv_table[rowCount]))
end
else
print("No CSV Table found!!")
end
end
--[[
Write to a CSV File from the multidimensional table.
parmeter: filepath is the location of the csv file
returns: None
]]
function SimpleCSV:write_csvfile(filepath)
local outfile = io.open(filepath,"w")
if outfile then
if next(self.csv_table) ~= nil then
for rowCount = 1, #self.csv_table do
row = self.csv_table[rowCount]
for i,item in pairs(row) do
if i ~= #row then
outfile:write(item..",")
else
outfile:write(item.."\n")
end
end
end
else
print("No CSV Table found!!")
end
else
print("Cannot write to file: "..filepath)
end
end
--[[
Displays the attribute in a particular row and column of the table
parameter: row is the row number in the table
parameter: column is the column number in the table
returns: string value of the attribute
]]
function SimpleCSV:get_attribute(row, column)
if next(self.csv_table) ~= nil then
if row > #self.csv_table or row < 0 then
print("Row is outside of allowed range")
else
row_attr = self.csv_table[row]
if column > #row_attr or column < 0 then
print("Column is outside of allowed range")
else
return row_attr[column]
end
end
else
print("No CSV Table found!!")
end
return "No Attribute found"
end
--[[
Changes a specific attribute in table to a given value
parameter: row is the row number in the table
parameter: column is the column number in the table
parameter: value is the attribute to be set
returns: True if value was sucessfully changed
]]
function SimpleCSV:set_attribute(row,column,value)
if next(self.csv_table) ~= nil then
if row > #self.csv_table or row < 0 then
print("Row is outside of allowed range")
else
row_attr = self.csv_table[row]
if column > #row_attr or column < 0 then
print("Column is outside of allowed range")
else
row_attr[column] = value
return true
end
end
else
print("No CSV Table found!!")
end
return false
end
--[[
Searches the table and gives the location of the first instance of a user-defined attribute
parameter: attr is the attribute given by the user
returns: the row and column of the defined attribute if found
]]
function SimpleCSV:find_attribute(attr)
if next(self.csv_table) ~= nil then
local rowIndex = 1
repeat
local columns = self.csv_table[rowIndex]
for columnIndex,item in pairs(columns) do
if string.lower(attr) == string.lower(item) then
return "Attribute \""..attr.."\" found in row "..rowIndex..", column "..columnIndex
end
end
rowIndex = rowIndex + 1
until rowIndex > #self.csv_table
return "Attribute: \""..attr.."\" not found"
else
print("No CSV Table found!!")
end
end
--[[
Searches the table and gives the row and column indexes of the first instance of a user-defined attribute
parameter: attr is the attribute given by the user
returns: the row and column indexes as a table
]]
function SimpleCSV:get_location(attr)
if next(self.csv_table) ~= nil then
local rowIndex = 1
repeat
local columns = self.csv_table[rowIndex]
for columnIndex,item in pairs(columns) do
if string.lower(attr) == string.lower(item) then
return {["row"]=rowIndex,["col"]=columnIndex}
end
end
rowIndex = rowIndex + 1
until rowIndex > #self.csv_table
return {["row"]=0,["col"]=0}
else
print("No CSV Table found!!")
end
end
--[[
Searches the table and gives the row and column indexes of all instances of a user-defined attribute
parameter: attr is the attribute given by the user
returns: the row and column indexes as a multidimensional table
]]
function SimpleCSV:get_locations(attr)
if next(self.csv_table) ~= nil then
local rowIndex = 1
local pos = {}
repeat
local columns = self.csv_table[rowIndex]
for columnIndex,item in pairs(columns) do
if string.lower(attr) == string.lower(item) then
table.insert(pos,{["row"]=rowIndex,["col"]=columnIndex})
end
end
rowIndex = rowIndex + 1
until rowIndex > #self.csv_table
return pos
else
print("No CSV Table found!!")
end
end
--[[
Adds a row to the end of the table
parameter: elements is the row to be added.
returns: true if row was sucessfully added to table
]]
function SimpleCSV:add_row(elements)
if next(self.csv_table) ~= nil then
local firstRow = self.csv_table[1]
if #elements == #firstRow then
table.insert(self.csv_table,elements)
return true
else
print("Number of columns do not match")
end
else
print("No CSV Table found!!")
end
return false
end
--[[
**********Test section**********
CSV file: test.csv
1, Tom, 34, Man, Electrician
2, Dan, 34, Man, Business Man
3, Stan, 34, Man, Programmer
4, Douglas, 34, Man, Shop Owner
5, Sarah, 34, Woman, Beautician
6, Joan, 34, Woman, Business Woman
7, Jenny, 34, Woman, Fashion Designer
8, Suzie, 34, Woman, Engineer
]]
--Start
csv = SimpleCSV.new() --Create object
csv:load_csvfile("test.csv") --Load File (true)
csv:display_csvfile()
--[[
Output:
1 Tom 34 Man Electrician
2 Dan 34 Man Business Man
3 Stan 34 Man Programmer
4 Douglas 34 Man Shop Owner
5 Sarah 34 Woman Beautician
6 Joan 34 Woman Business Woman
7 Jenny 34 Woman Fashion Designer
8 Suzie 34 Woman Engineer
]]
print(csv:get_attribute(1,2)) --Tom
print(csv:get_attribute(2,2)) --Dan
csv:set_attribute(2,2,"John")
print(csv:get_attribute(2,2)) --John
print(csv:find_attribute("Man")) --Attribute "Man" found in row 1, column 4
loc1 = csv:get_location("Man")
print("row = "..loc1.row.." , col = "..loc1.col) --row = 1 , col = 4
loc2 = csv:get_locations("Man")
for i,v in pairs(loc2) do
print("row => "..v.row.." , col => "..v.col)
end
--[[
Output:
row => 1 , col => 4
row => 1 , col => 4
row => 2 , col => 4
row => 3 , col => 4
row => 4 , col => 4
]]
newrow = {9,"Carol",44,"Woman","IT Professional"}
csv:add_row(newrow)
csv:display_csvfile()
--[[
Output:
1 Tom 34 Man Electrician
2 John 34 Man Business Man
3 Stan 34 Man Programmer
4 Douglas 34 Man Shop Owner
5 Sarah 34 Woman Beautician
6 Joan 34 Woman Business Woman
7 Jenny 34 Woman Fashion Designer
8 Suzie 34 Woman Engineer
9 Carol 44 Woman IT Professional
]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment