On Mon, 29 Oct 2001, Renaud MICHEL wrote:
> > csv2lyx was written by <[EMAIL PROTECTED]> and works pretty well. I can
> > mail my copy by request.
>
> If it is not too big (I guess it is not) could you mail it to the list.
I have got a copy from Guenter only 20 Kb and I attach in this mail to the
list...
Wayan
#! /usr/bin/perl
# csv2lyx
# Copyright (C) 2001 Antonio Gulino
# This program is free software; you can redistribute it and/or modify it under
# the term of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or any later version.
# RCS:
# $Date: 2001/10/10 16:10:23 $
# $Revision: 1.3 $
# $Source: /home/antonio/tesi/pl/csv2lyx,v $
# $Log: csv2lyx,v $
# Revision 1.3 2001/10/10 16:10:23 antonio
# Neue option --fontsize=-3|-2|-1|+1|+2|+3, welche die Gr�sse aller Zellen �ndert,
# aber nicht jene des Titels.
# --help eingef�hrt
# -L als alternative zu --lyxserver eingef�hrt
# --multicolumn als Alternative zu --colspan (weil LaTeX-Ausdruck, w�hrend colspan
Html-Ausdruck ist)
#
# Revision 1.2 2001/09/29 22:14:47 antonio
# usando --lyxserver il file temporaneo viene messo in /tmp
# Ho modificato la documentazione e introdotto la parte BUGS del pod
#
=head1 NAME
csv2lyx - converter from csv-file to a LyX table
=head1 DESCRIPTION
Converts a Comma Separated Value file to a float table in LyX format.
Good for LyX version 1.1.4fix1 and other. You can use it whit the LyX-server too.
=head1 HOW USE IT
=head2 Creating a LyX file
under Linux one of the follow (see also the many L<Options>):
antonio@bidone:~ > cat mycsvfile | csv2lyx > mytmptable.lyx
antonio@bidone:~ > cat mycsvfile | csv2lyx --output=mytmptable.lyx
antonio@bidone:~ > csv2lyx mycsvfile > mytmptable.lyx
antonio@bidone:~ > csv2lyx mycsvfile --output=mytmptable.lyx
antonio@bidone:~ > csv2lyx mycsvfile -o mytmptable.lyx
antonio@bidone:~ > csv2lyx mycsvfile --lyxserver
As default this will create a Float-Table in the LyX format, version 2.15 (used by
LyX-1.1.4fix1).
=head2 Using the created LyX file
=over 4
=item Include as external LyX file
as usal: Insert --> Include File --> Use Include (mytmptable.lyx)
=item Insert directly in your LyX document
as usal: Insert --> LyXfile (mytmptable.lyx)
=back
=head1 Options
-s or --separator="what you want"
-o or --output='A filename, please!'
-l or --label='A label for crossreference to the table'
-f or --fontsize=-3|-2|-1|+1|+2|+3
-c or --colspan="a pattern" or --multicolumn="a pattern"
-vl or --vlines
-hl or --hlines
-g or --grid
-b or --border
-h or --header='N'
-t or --title="A pretty title for a pretty table"
-L or --lyxserver
--nofloat
--help
=head2 --separator
-s or --separator="what you want"
default: "\t" for a tab-sep-value file
=head2 --output
-o or --output='A filename, please!'
default: STDOUT aka Screen. That mean, that you can use the pipe, if you want:
antonio@bidone > csv2lyx pippo.csv > pippo.lyx
is the same as
antonio@bidone > csv2lyx pippo.csv -o pippo.lyx
If you use L<"--lyxserver">, then --output is overwriten by a random filename.
=head2 -L or --lyxserver
With this option, you can past the table direct in the LyX-document that is open. At
the
place of the cursor. That mean, you have started LyX and opened a LyX-document.
That mean also, that this option is valid only where the lyxserver can be started:
*NIX, OS/2, but no Win32!
What's "lyxserver"? Good question. A partial, but simple answord is: go in your lyxrc,
and write the line
\serverpipe "~/.lyxpipe"
If you have problems, close LyX, rm ~/.lyxpipe.in and ~/.lyxpipe.out. Restart.
Better: look on the LyX-Documentation "Configuration.lyx".
=head2 --title
-t or --title="A pretty title for a pretty table"
default: inputfilename otherwise, when you use the pipe, "Title of the LyX table"
=head2 --label
-l or --label='A label for crossreference to the table'
=head2 --nofloat
If you don't want a Float-Table. In this case the options L<"--title"> and
L<"--label"> are ignored.
Default is Float-Table
=head2 --header
-h or --header='N'
--header is the same as --header='1'
the first N rows are the Header. Default: noheader
A line is made under the last row of the Header. If L<"--border">, L<"--grid"> or
L<"--hlines"> are
activated, then are two lines unter the last row of the Header.
=head2 --border
-b or --border
(a line around the table. Default: noborder)
=head2 --grid
-g or --grid
a line between each cell. include L<"--border">, L<"--vlines">, L<"--hlines">.
Default: nogrid
=head2 --hlines
-hl or --hlines
horizonal line between each row
=head2 --vlines
-vl or --vlines
vertical lines between each column
=head2 --colspan
-c or --colspan="a pattern"
Man kann, Zeile f�r Zeile angeben, ob die einzelne Werte �ber mehrere Spalten hinweg
verteilt werden sollen. Mit Zahlen gibt man an, wieviele Spalten ein Wert ... Wert
ist. Mit
dem Schr�gstrich (/), besser bekannt als 'slash', kann man die verschieden Zeilen
identifizieren.
Falls nicht gen�gend Spalten angegeben werden, werden automatisch soviele '1'
angeh�ngt, bis
die Sache stimmt. 'Leere' Zeilen werden ebenfalls automatisch mit '1' ausgef�llt. Hier
einige
Beispiele:
=over 4
=item --colspan="23" oder --colspan="23/////" oder --colspan="23/11111//// oder ...
+-------------+----------------------+
1 | 2 spalten | �ber 3 spalten |
+-----+-------+-----+--------+-------+
2 | | | | | |
=item --colspan="23/221" oder --colspan="23/22"
+-------------+----------------------+
1 | 2 spalten | �ber 3 spalten |
+-----+-------+-----+--------+-------+
2 | 2 spalten | 2 spalten | eine |
+-----+-------+-----+--------+-------+
3 | | | | | |
=item --colspan="23//221" oder --colspan="23/11111/221"
+-------------+----------------------+
1 | 2 spalten | �ber 3 spalten |
+-----+-------+-----+--------+-------+
2 | | | | | |
+-----+-------+-----+--------+-------+
3 | 2 spalten | 2 spalten | eine |
+-----+-------+-----+--------+-------+
4 | | | | | |
=item --colspan="/12/212" oder --colspan="11111/1211/212"
+-----+-------+-------+--------+-------+
1 | | | | | |
+-----+-------+-------+--------+-------+
2 |eine |�ber 2 spalten | | |
+-----+-------+-------+--------+-------+
3 | 2 spalten | eine | �ber 2 spalten |
+-----+-------+-------+--------+-------+
4 | | | | | |
=back
=head1 WILL COME (maybe)
Next features are:
=over 4
=item --format="|p{3cm}|c|"
formatting the column, with the same Syntax of LaTeX
=back
=head1 BUGS
Using L<"--lyxserver"> your data are on the C</tmp> directory. Maybe everybody can see
your data.
=head1 AUTHOR and COPYLEFT
Copyright (C) 2001, Antonio Gulino <[EMAIL PROTECTED]>
This program is free software; you can redistribute it and/or modify it under
the term of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or any later version.
=cut
###########################################################################################
# di default il separatore e' un tabulatore
use strict;
use Getopt::Long;
my $OPT_separator = "\t";
my $OPT_header = '-1';
my ($OPT_output, $OPT_title , $OPT_border, $OPT_nofloat,
$OPT_label,$OPT_grid,$OPT_hlines,$OPT_vlines, $OPT_colspan,
$OPT_lyxserver, $OPT_fontsize, $OPT_help
);
$OPT_help=1 unless @ARGV; # if no one option, then --help
&GetOptions( "separator|s=s" => \$OPT_separator,
"title|t=s" => \$OPT_title,
"output|o=s" => \$OPT_output,
"fontsize|f=s" => \$OPT_fontsize,
"header|h:i" => \$OPT_header,
"border|b" => \$OPT_border,
"nofloat" => \$OPT_nofloat,
"label|l=s" => \$OPT_label,
"grid|g" => \$OPT_grid,
"hlines|hl" => \$OPT_hlines,
"vlines|vl" => \$OPT_vlines,
"colspan|c|multicolumn=s" => \$OPT_colspan,
"lyxserver|L" => \$OPT_lyxserver,
"help" => \$OPT_help,
);
# if you use --help, then the other options are ignored
if ($OPT_help) {
print <<EOH
under Linux one of the follow (see also the many options):
antonio\@bidone:~ > cat mycsvfile | csv2lyx > mytmptable.lyx
antonio\@bidone:~ > cat mycsvfile | csv2lyx --output=mytmptable.lyx
antonio\@bidone:~ > csv2lyx mycsvfile > mytmptable.lyx
antonio\@bidone:~ > csv2lyx mycsvfile --output=mytmptable.lyx
antonio\@bidone:~ > csv2lyx mycsvfile -o mytmptable.lyx
antonio\@bidone:~ > csv2lyx mycsvfile --lyxserver
As default this will create a Float-Table in the LyX format, version 2.15 (used by
LyX-1.1.4fix1).
-s or --separator='what you want'
-o or --output='A filename, please!'
-l or --label='A label for crossreference to the table'
-f or --fontsize=-3|-2|-1|+1|+2|+3
-c or --colspan='a pattern' or --multicolumn='a pattern'
-vl or --vlines
-hl or --hlines
-g or --grid
-b or --border
-h or --header='N'
-t or --title='A pretty title for a pretty table'
--nofloat
--lyxserver
--help
EOH
;
die "(c) 2001, Antonio Gulino <antonio.gulino\@tin.it>\n"
}
# if you dont use the --output option, then the output is redirect to the STDOUT
(=screen)
# if --lyxserver, then --output='/tmp/csv2lyxRANDOM.tmp.lyx'
if ($OPT_lyxserver) {
my $random;
# $random = sprintf "%0.6d", rand(999999);
$OPT_output = sprintf "/tmp/csv2lyx%0.6d.tmp.lyx", rand(999999);
}
if ($OPT_output) {
open OUTPUT, ">$OPT_output" or die "Cannot write to file $OPT_output\n";
select OUTPUT;
}
#####
# I add '1' to $OPT_header, so if no OPT_header, then =0
# otherwise = numer of the rows that are included in "header"
$OPT_header++ if $OPT_header<1;
#####
# if $OPT_grid, then $OPT_hlines and $OPT_vlines and $OPT_border too
if ($OPT_grid) {
$OPT_hlines = '1';
$OPT_vlines = '1';
$OPT_border = '1';
}
##############################################################################
# in the first case, the data are in a file $inputFileName
# in the second case, the data comes from the pipe
# @csv have the data, in both case
my $inputFileName = shift;
my @csv;
if ($inputFileName) {
open CSV, $inputFileName or die "Cannot read file :$inputFileName\n";
@csv = <CSV>;
close CSV;
} else {
@csv = <>;
}
chomp(@csv);
###############
$OPT_title ||=$inputFileName?$inputFileName:'Title of the LyX table';
# vediamo quante righe ci sono
# how many row (=righe) are there?
my $righe = $#csv + 1;
# looking in $OPT_colspan, if I want change the default of colspans
# / idiot
# /121 first line default, second line=121, third, forth,...line = default
# /121/112 first line default, second line=121, third line=112, forth ... line =
default
# 22//112 first line=22, second line default, third line=112, forth ... line =
default
# 22/*/211 first line=22, second... line default, last line=211
# */211 all lines default, but last line=211
# / mean: next line
# after * mean: beginning by the bottom
my @colspan;
for (my $i=0; $i<$righe; $i++) {
last if $OPT_colspan eq ''; # do nothing if $OPT_colspan is empty
last if $OPT_colspan =~ /^\*/; # if the first charachter is a star,
# then I must begin by the bottom
next if $OPT_colspan =~ s/^\///; # if the first charachter is a slash, then go
to next line
if ($OPT_colspan =~ s/^([1-9]+)\/?//) {
$colspan[$i] = $1;
}
}
# here the code for the colspan beginning by the bottom
#
#
# adesso leggo l'intero array e creo una matrice: @matrix
# contemporaneamente calcolo il numero massimo di campi, per sapere quante colonne mi
servono
# now i read the whole array and put it into a matrix : @matrix
# at the same time i look how many column (=colonne) have the biggest row
my $col = 0;
my ($colonne, @matrix);
my $rn = 0;
foreach my $r (@csv) {
my @r = split $OPT_separator, $r;
my $sumcol;
foreach (split('',$colspan[$rn])) {
$sumcol += $_;
}
$colonne = $#r+1 - length($colspan[$rn]) + $sumcol
if $colonne <= $#r - length($colspan[$rn]) + $sumcol;
push @matrix, [@r];
$rn++;
}
# Default: each value have only one cell, over only one column . colspan = 1
my $rn = 0;
foreach (@matrix) {
my $sumcol;
foreach (split('',$colspan[$rn])) {
$sumcol += $_;
}
$colspan[$rn] .= '1' x ($colonne - $sumcol);
$rn++;
}
#########################################################################################
# adesso stampo il codice lyx. l'allineamento avviene a destra
# (immagino che di solito siano cifre)
# produco automaticamente una float table,
# versione funzionante per la 1.1.4fix1
# now I print the LyX format. Align=right (I think this is a matrix of numbers)
# dafault: a float table
my $insetLabel;
if ($OPT_label) {
$insetLabel = "\n\\begin_inset LatexCommand
\\label\{$OPT_label\}\n\n\\end_inset\n\n\n";
} else {$insetLabel=''}
my $insetFloat;
unless ($OPT_nofloat) {
$insetFloat = "\\begin_float tab\n\\layout Caption\n\n$OPT_title
$insetLabel\n\\layout Standard\n";
}
#####################
# print first part
####################
print <<LYX;
\#csv2lyx created this file
\\lyxformat 2.15
\\layout Standard
$insetFloat
\\align center \\LyXTable
multicol5
$righe $colonne 0 0 -1 -1 -1 -1
LYX
;
#####################
#### Horizontal Lines
#
# qui viene deciso se ci sono righe in alto o in basso di ciascuna riga
# se la prima cifra e' "1" allora c'e una linea in alto
# se la seconda cifra e' "1" allora c'e una linea in basso
# here I say if there are a border
# if the first number is "1", then a border on the top of the line
# if the second number is "1", then a border on the bottom of the line
my $rownumber = 0;
my ($top,$bottom);
foreach (@matrix) {
if ($rownumber < $OPT_header) {
$bottom = ($OPT_hlines or ($rownumber==$OPT_header-1))?1:0;
$top = (($rownumber==0) and $OPT_border)?1:0;
} elsif ($rownumber == $#matrix) { # this is the last row of the table
$top = ($OPT_hlines or $rownumber==$OPT_header)?1:0;
$bottom = $OPT_border?1:0;
} else {
$top =$OPT_hlines?1:0;
$bottom='0';
}
print "$top $bottom 0 0\n";
$rownumber++;
};
##### Vertical lines and align in each column
# adesso viene deciso il formato delle colonne
# se la prima cifra e' 2, allora allineamento a sinistra
# se la prima cifra e' 4, allora allineamento a destra
# now the align of the column
# if the first number is "2", then align=left
# if the first number is "4", then align=right
# if the second number is '1', then left=line else not
# if the third number is '1', then right=line else not
my $align = '4'; # default: align=right (I think it is a number)
my ($leftline,$rightline);
for (my $i=0; $i<$colonne; $i++) {
if ($i == 0) {
$leftline = ($OPT_border or $OPT_vlines)?1:0;
$rightline= '0';
} elsif ($i == $colonne-1) {
$leftline = ($OPT_vlines)?1:0;
$rightline= ($OPT_border or $OPT_vlines)?1:0;
} else {
$leftline =$OPT_vlines?1:0;
$rightline='0';
}
print "$align $leftline $rightline \"\" \"\"\n";
};
#########################################################
# adesso tocca alla formattazione delle singole celle.
# personalmente non ci capisco nulla e dunque faccio come ho trovato
# le celle della prima riga hanno delle informazioni supplementari che di fatto pare
riguardino
# tutta la colonna sottostante
# la primissima cella pare che abbia una formattazione ancora differente dalle altre
# now the format of each Cell
# I have make only a little "reverse engeneering", I think it's enough.
# le altre celle, riga per riga,
# the other cells, row by row,
for (my $j=0; $j<$righe; $j++) {
for (my $i=0; $i<$colonne; $i++) {
my $colspan = (&colspan($colspan[$j]))[$i];
my ($underline,$overline);
# a special format is for the multicolumn cells, in the header
if ($colspan eq '1' and $j<$OPT_header) {
# I look if the cell under the current cell have the same colspan
# this is the case, if the same calspan-pattern,
# beginning with 1 and the same number of'2'
my $diffColspan=0;
if ((&colspan($colspan[$j+1]))[$i] =~ /[01]/ and $j+1<$OPT_header) {
# how is the colspan of the actual cell ?
my $accs; # actual cell col span
for (my $c=$i+1; $c<$colonne; $c++) {
if ( (&colspan($colspan[$j]))[$c] ne '2') {
$accs = $c;
$c=$colonne;
}
}
$accs = $accs - $i;
# how is the colspan of the cell under the actual ?
my $uccs; # under cell col span
for (my $c=$i+1; $c<$colonne; $c++) {
if ( (&colspan($colspan[$j+1]))[$c] ne '2') {
$uccs = $c;
$c=$colonne;
}
}
$uccs = $uccs - $i;
# are the two cells the same colspan ?
$diffColspan = $accs - $uccs;
}
$underline = '1'; if ($diffColspan <= 0 and $j<$OPT_header-1) { $underline
= '0'}
$overline = '0'; if ($j==0 and ($OPT_border)) {$overline = '1'}
} else {
if ($OPT_grid and $j<$OPT_header) {
$underline = '1';
$overline = '1';
} else {
$underline = '0';
$overline = '0'; if ($OPT_border) {$overline = '1'}
}
}
print "$colspan 8 $overline $underline 0 0 0 \"\" \"\"\n";
}
}
# segue una riga vuota
# a empty line
print "\n";
######################################################################################
# adesso segue il contenuto dell celle, riga per riga
# mi raccomando di scrivere qualcosa anche per le celle non esistenti nel file
iniziale
# now the contents of each cell, row by row
# remember to put something in each cell
my %fontsize = (
'-3' => 'scriptsize',
'-2' => 'footnotesize',
'-1' => 'small',
'+1' => 'large',
'+2' => 'larger',
'+3' => 'largest'
);
for (my $j=0; $j<$righe; $j++) {
# for (my $i=0; $i<$colonne; $i++) {
for (my $i=0; $i<length($colspan[$j]); $i++) {
if ($fontsize{$OPT_fontsize}) {
print "\n\\size $fontsize{$OPT_fontsize}\n",$matrix[$j][$i],"\n\\size
default\n\n"
} else {
print $matrix[$j][$i],"\n";
}
unless ($j==$righe-1 and $i==$colonne-1) {print "\\newline\n"};
}
}
print "\\end_float\n\n" unless $OPT_nofloat;
print "\\the_end\n";
##########################################################################################
# using LyX-server
##########################################################################################
if ($OPT_lyxserver and $OPT_output =~ /^\/tmp\/csv2lyx\d{6}\.tmp\.lyx$/) {
close OUTPUT;
system("echo \"LYXCMD:csv2lyx:file-insert\" $OPT_output > ~/.lyxpipe.in");
# system("rm $OPT_output");
}
############################################################################################
# Subroutines are here
############################################################################################
sub colspan { # input a $string='111213', output an @array=qw(0 0 0 1 2 0 1 2 2)
my $mystring = shift; # = '111213'
my @mystring = split ('', $mystring); # = qw(1 1 1 2 1 3)
my @result;
foreach my $span (@mystring) {
if ($span == 1) {
push @result, '0';
} else {
push @result, '1';
for (my $i=2; $i<=$span; $i++) {
push @result, '2';
}
}
}
return @result
}
1