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



Reply via email to