Your question is quite general and such not easy to answer. But, if I understand you right, you want to use special characters in your table head and you want to read them from your csv file.
The \csvautotabular
macro is intended for quick survey only and not for productive tables, since it is quite restricted. \csvreader
or \csvloop
are indented for normal usage.
To use the first line of a csv file as normal data line, you have to say no head
and also to give column count
since this first line is not read as pattern. Then, this line can be used as data line.
Still, there is and will be an important restriction: A line is not allowed to start with a backslash \
.
Now, here comes an example:
\begin{filecontents*}{test3.csv}
Wei\ss{}b\"ack,\textbf{bold},c
2,2,8
3,6,9
\end{filecontents*}
\documentclass{letter}
\usepackage[utf8]{inputenc}
\usepackage{csvsimple}
\begin{document}
\csvloop{
file=test3.csv,
no head, % no special treatment of first line
column count=3, % since no first line is given, tell about column count
before reading=\begin{tabular}{|l|l|l|}\hline,
command=\csvlinetotablerow,
late after line=\\,
late after first line=\\\hline,
late after last line=\\\hline,
after reading=\end{tabular}
}
\end{document}
This uses lua
function call to read the specific field in the CVS file. For example, given this CVS file in the directory
123,Poty city,Poti,red,-295731.42857144,617222.85714285
124,Lanchhuti city,Poti,red,-299217.14285715,647851.42857142
125,Ozurgeti city,Poti,red,-317217.14285715,648422.85714285
126,Samtredia city,Poti,red,-287502.85714287,672022.85714285
Then to insert, say the field located at row 2 and column 5, which is -299217.14285715
, and the field at row 1 and column 3, which is Poty city
in the Latex table, then the code is
\begin{tabular}{|l|l|l|l|l|}\hline
1 & \getField{1}{2} & 3 & 4 & 5 \\\hline
6 & 7 & 8 & \getField{2}{5} & 9 \\\hline
10 & 11 & 12 & 13 & 14 \\\hline
\end{tabular}
Which generates the table:
The full code is below. I googled lua code to parse CVS files, there are few on the net, I found one that worked and used it. There does not seem to be a build in API in lua itself for this. The CVS file is read automatically. The cvs file name is hardcoded in the code below. The latex file needs to be compiled with lualatex
not pdflatex
\documentclass[]{article}
\usepackage{luacode}
\begin{luacode*} -- CVS API: http://nocurve.com/simple-csv-read-and-write-using-lua/
local function split(str, sep)
fields={}
local matchfunc = string.gmatch(str, "([^"..sep.."]+)")
if not matchfunc then return {str} end
for str in matchfunc do
table.insert(fields, str)
end
return fields
end
function read(path, sep, tonum)
tonum = tonum or true
sep = sep or ','
local csvFile = {}
local file = assert(io.open(path, "r"))
for line in file:lines() do
fields = split(line, sep)
if tonum then -- convert numeric fields to numbers
for i=1,#fields do
fields[i] = tonumber(fields[i]) or fields[i]
end
end
table.insert(csvFile, fields)
end
file:close()
return csvFile
end
local m = read('./c.cvs') -- read file csv file to local matrix m
function getField(row,col) -- API to latex command below
tex.print(m[row][col])
end
\end{luacode*}
\newcommand\getField[2]{\directlua{getField(#1,#2) }}%
\begin{document}
\begin{table}[]
\centering
\caption{My example}
\begin{tabular}{|l|l|l|l|l|}\hline
1 & \getField{1}{2} & 3 & 4 & 5 \\\hline
6 & 7 & 8 & \getField{2}{5} & 9 \\\hline
10 & 11 & 12 & 13 & 14 \\\hline
\end{tabular}
\end{table}
\end{document}
Update
I figured why stop at just reading field? Why not add a Latex command to load the whole CVS file and convert it to a Latex table? This will be much more useful also. So here is a new implementation that loads a CVS file and makes a Latex table, all automatically. This will be useful for making reports and such.
The Latex command is called getCVS{"fileName"}
and used as follows
\begin{table}[]
\centering
\caption{My CVS file in a Latex table}
\getCVS{"c.cvs"}
\end{table}
Using the above CVS file, the table generated is
The full code is below
\documentclass[]{article}
\usepackage{luacode}
\begin{luacode*} -- CVS API http://nocurve.com/simple-csv-read-and-write-using-lua/
local function split(str, sep)
fields={}
local matchfunc = string.gmatch(str, "([^"..sep.."]+)")
if not matchfunc then return {str} end
for str in matchfunc do
table.insert(fields, str)
end
return fields
end
function read(path, sep, tonum)
tonum = tonum or true
sep = sep or ','
local csvFile = {}
local file = assert(io.open(path, "r"))
for line in file:lines() do
fields = split(line, sep)
if tonum then -- convert numeric fields to numbers
for i=1,#fields do
fields[i] = tonumber(fields[i]) or fields[i]
end
end
table.insert(csvFile, fields)
end
file:close()
return csvFile
end
function getCVS(fileName)
local m = read(fileName) -- read CVS file to matrix m
local nRow = #m
local nCol = #m[1]
tex.sprint("\\begin{tabular}{")
for j=1,nCol do
tex.sprint("|l")
end
tex.print("|}\\hline")
for i = 1,nRow do
for j = 1,nCol do
tex.sprint(m[i][j])
if j<nCol then tex.sprint("&") end
end
tex.print("\\\\ \\hline")
end
tex.print("\\end{tabular}")
end
\end{luacode*}
\newcommand\getCVS[1]{\directlua{getCVS(#1) }}%
\begin{document}
\begin{table}[]
\centering
\caption{My CVS file in a Latex table}
\getCVS{"c.cvs"}
\end{table}
\end{document}
Best Answer
An
expl3
implementation.Items in both csv files are stored in property lists, in the form
<row>@<column>
, emulating a two-dimensional array. Then a token list variable is built from the data so retrieved, where each cell containswhere the function is a wrapper around
\cellcolor
.