]> git.lyx.org Git - lyx.git/blob - lib/scripts/csv2lyx.py
csv2lyx.py: I haven't contributed something to the actual file version
[lyx.git] / lib / scripts / csv2lyx.py
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 # file csv2lyx.py
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
7
8 # author Hartmut Haase
9 # author José Matos
10 # Full author contact details are available in file CREDITS
11
12 # This script reads a csv-table (file name.csv) and converts it into
13 # a LyX-table for versions 1.5.0 and higher (LyX table format 276).
14 # It uses Python's csv module for parsing.
15 # The original csv2lyx was witten by Antonio Gulino <antonio.gulino@tin.it>
16 # in Perl for LyX 1.x and modified for LyX table format 276 by the author.
17 #
18 import csv, unicodedata
19 import os, sys
20 import optparse
21
22 def error(message):
23     sys.stderr.write(message + '\n')
24     sys.exit(1)
25
26 header = """#csv2lyx created this file
27 \lyxformat 276
28 \\begin_document
29 \\begin_header
30 \\textclass article
31 \\inputencoding auto
32 \\font_roman default
33 \\font_sans default
34 \\font_typewriter default
35 \\font_default_family default
36 \\font_sc false
37 \\font_osf false
38 \\font_sf_scale 100
39 \\font_tt_scale 100
40 \\graphics default
41 \\paperfontsize default
42 \\papersize default
43 \\use_geometry false
44 \\use_amsmath 1
45 \\use_esint 0
46 \\cite_engine basic
47 \\use_bibtopic false
48 \\paperorientation portrait
49 \\secnumdepth 3
50 \\tocdepth 3
51 \\paragraph_separation indent
52 \\defskip medskip
53 \\papercolumns 1
54 \\papersides 1
55 \\paperpagestyle default
56 \\tracking_changes false
57 \\output_changes false
58 \\end_header
59
60 \\begin_body
61
62 \\begin_layout Standard
63 \\align left
64 \\begin_inset Tabular
65 <lyxtabular version="3" rows="%d" columns="%d">
66 <features>
67 """
68
69 cell = """<cell alignment="left" valignment="top" usebox="none">
70 \\begin_inset Text
71
72 \\begin_layout Standard
73 %s
74 \\end_layout
75
76 \\end_inset
77 </cell>"""
78
79 footer = """</lyxtabular>
80
81 \\end_inset
82
83
84 \\end_layout
85
86 \\end_body
87 \\end_document
88 """
89
90 # processing command line options
91 # delegate this to standard module optparse
92 args = {}
93 args["usage"] = "Usage: csv2lyx [options] csvfile [file.lyx]"
94
95 args["description"] = """This script creates a LyX document containing a table created from a
96 comma-separated-value (CSV) file. The resulting LyX file can be opened
97 with LyX 1.5.0 or any later version.
98 If no options are given csv2lyx will try to infer the CSV type of the csvfile,
99 """
100 parser = optparse.OptionParser(**args)
101
102 parser.set_defaults(excel='', column_sep='')
103 parser.add_option("-e", "--excel", metavar="CHAR",
104                   help="""CHAR corresponds to a CSV type:
105                        'e': Excel-generated CSV file
106                        't': Excel-generated TAB-delimited CSV file""")
107 parser.add_option("-s", "--separator", dest="column_sep",
108                   help= """column separator
109                                        't' means Tab""")
110
111 group = optparse.OptionGroup(parser, "Remarks", """If your CSV file contains special characters (e. g. umlauts,
112    accented letters, etc.) make sure it is coded in UTF-8 (unicode).
113    Else LyX will loose some cell contents. If your CSV file was not written according to the "Common Format and MIME Type for Comma-Separated Values (CSV) Files" (http://tools.ietf.org/html/rfc4180) there may be unexpected results.""")
114 parser.add_option_group(group)
115
116 (options, args) = parser.parse_args()
117
118 # validate input
119 if len(args) == 1:
120     infile = args[0]
121     fout = sys.stdout
122 elif len(args) ==2:
123     infile = args[0]
124     fout = open(args[1], 'w')
125 else:
126     parser.print_help()
127     sys.exit(1)
128
129 if not os.path.exists(infile):
130         error('File "%s" not found.' % infile)
131
132 dialects = {'' : None, 'e' : 'excel', 't' : 'excel-tab'}
133 if options.excel not in dialects:
134     parser.print_help()
135     sys.exit(1)
136 dialect= dialects[options.excel]
137
138 # Set Tab, if necessary
139 if options.column_sep == 't':
140         options.column_sep = "\t"
141
142 # when no special column separator is given, try to detect it:
143 if options.column_sep or dialect :
144     reader = csv.reader(open(infile, "rb"), dialect= dialect, delimiter=options.column_sep)
145 else:
146     guesser = csv.Sniffer()
147     input_file = "".join(open(infile,'rb').readlines())
148     try:
149         dialect = guesser.sniff(input_file)
150         reader = csv.reader(open(infile, "rb"), dialect= dialect)
151     except:
152         reader = csv.reader(open(infile, "rb"), dialect= dialect, delimiter=',')
153
154 # read input
155 num_cols = 1 # max columns
156 rows = []
157
158 for row in reader:
159     num_cols = max(num_cols, len(row))
160     rows.append(row)
161
162 num_rows = reader.line_num # number of lines
163
164 # create a LyX file
165 #####################
166 # write first part
167 ####################
168 fout.write(header % (num_rows, num_cols))
169
170 #####################
171 # write table
172 ####################
173 for i in range(num_cols):
174         fout.write('<column alignment="left" valignment="top" width="0pt">\n')
175
176 for j in range(num_rows):
177     row = ['<row>']
178
179     ############################
180     # write contents of one line
181     ############################
182     for i in range(len(rows[j])):
183         row.append( cell % rows[j][i])
184
185     # If row has less columns than num_cols fill with blank entries
186     for i in range(len(rows[j]), num_cols):
187         row.append(cell % " ")
188
189     fout.write("\n".join(row) + '\n</row>\n')
190
191 #####################
192 # write last part
193 ####################
194 fout.write(footer)
195 # close the LyX file
196 fout.close()