]> git.lyx.org Git - lyx.git/blob - lib/scripts/csv2lyx.py
ext_copy: bug when creating the error string.
[lyx.git] / lib / scripts / csv2lyx.py
1 # -*- coding: utf-8 -*-
2
3 # file csv2lyx.py
4 # This file is part of LyX, the document processor.
5 # Licence details can be found in the file COPYING.
6
7 # author Hartmut Haase
8 # author José Matos
9 # Full author contact details are available in file CREDITS
10
11 # This script reads a csv-table (file name.csv) and converts it into
12 # a LyX-table for versions 1.5.0 and higher (LyX table format 276).
13 # It uses Python's csv module for parsing.
14 # The original csv2lyx was witten by Antonio Gulino <antonio.gulino@tin.it>
15 # in Perl for LyX 1.x and modified for LyX table format 276 by the author.
16 #
17 import csv, unicodedata
18 import os, sys
19 import optparse
20
21 def error(message):
22     sys.stderr.write(message + '\n')
23     sys.exit(1)
24
25 header = """#csv2lyx created this file. For more info see http://www.lyx.org/
26 \\lyxformat 413
27 \\begin_document
28 \\begin_header
29 \\textclass article
30 \\use_default_options true
31 \\maintain_unincluded_children false
32 \\language english
33 \\language_package default
34 \\inputencoding auto
35 \\fontencoding global
36 \\font_roman default
37 \\font_sans default
38 \\font_typewriter default
39 \\font_default_family default
40 \\use_non_tex_fonts false
41 \\font_sc false
42 \\font_osf false
43 \\font_sf_scale 100
44 \\font_tt_scale 100
45
46 \\graphics default
47 \\default_output_format default
48 \\output_sync 0
49 \\bibtex_command default
50 \\index_command default
51 \\paperfontsize default
52 \\use_hyperref false
53 \\papersize default
54 \\use_geometry false
55 \\use_amsmath 1
56 \\use_esint 1
57 \\use_mhchem 1
58 \\use_mathdots 1
59 \\cite_engine basic
60 \\use_bibtopic false
61 \\use_indices false
62 \\paperorientation portrait
63 \\suppress_date false
64 \\use_refstyle 1
65 \\index Index
66 \\shortcut idx
67 \\color #008000
68 \\end_index
69 \\secnumdepth 3
70 \\tocdepth 3
71 \\paragraph_separation indent
72 \\paragraph_indentation default
73 \\quotes_language english
74 \\papercolumns 1
75 \\papersides 1
76 \\paperpagestyle default
77 \\tracking_changes false
78 \\output_changes false
79 \\html_math_output 0
80 \\html_css_as_file 0
81 \\html_be_strict false
82 \\end_header
83
84 \\begin_body
85
86 \\begin_layout Standard
87 \\begin_inset Tabular
88 <lyxtabular version="3" rows="%d" columns="%d">
89 <features tabularvalignment="middle">
90 """
91
92 cell = """<cell alignment="left" valignment="top" usebox="none">
93 \\begin_inset Text
94
95 \\begin_layout Plain Layout
96 %s
97 \\end_layout
98
99 \\end_inset
100 </cell>"""
101
102 footer = """</lyxtabular>
103
104 \\end_inset
105
106
107 \\end_layout
108
109 \\end_body
110 \\end_document
111 """
112
113 # processing command line options
114 # delegate this to standard module optparse
115 args = {}
116 args["usage"] = "Usage: csv2lyx [options] csvfile [file.lyx]"
117
118 args["description"] = """This script creates a LyX document containing a table created from a
119 comma-separated-value (CSV) file. The resulting LyX file can be opened
120 with LyX 1.5.0 or any later version.
121 If no options are given csv2lyx will try to infer the CSV type of the csvfile,
122 """
123 parser = optparse.OptionParser(**args)
124
125 parser.set_defaults(excel ='', column_sep = '')
126 parser.add_option("-e", "--excel", metavar ="CHAR",
127                   help = """CHAR corresponds to a CSV type:
128                        'e': Excel-generated CSV file
129                        't': Excel-generated TAB-delimited CSV file""")
130 parser.add_option("-s", "--separator", dest = "column_sep",
131                   help = """column separator
132                                        't' means Tab""")
133
134 group = optparse.OptionGroup(parser, "Remarks", """If your CSV file contains special characters (e. g. umlauts,
135    accented letters, etc.) make sure it is coded in UTF-8 (unicode).
136    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.""")
137 parser.add_option_group(group)
138
139 (options, args) = parser.parse_args()
140
141 # validate input
142 if len(args) == 1:
143     infile = args[0]
144     fout = sys.stdout
145 elif len(args) == 2:
146     infile = args[0]
147     fout = open(args[1], 'w')
148 else:
149     parser.print_help()
150     sys.exit(1)
151
152 if not os.path.exists(infile):
153         error('File "%s" not found.' % infile)
154
155 dialects = {'' : None, 'e' : 'excel', 't' : 'excel-tab'}
156 if options.excel not in dialects:
157     parser.print_help()
158     sys.exit(1)
159 dialect = dialects[options.excel]
160
161 # Set Tab, if necessary
162 if options.column_sep == 't':
163         options.column_sep = "\t"
164
165 # when no special column separator is given, try to detect it:
166 if options.column_sep and dialect :
167     reader = csv.reader(open(infile, "rU"), dialect = dialect, delimiter = options.column_sep)
168 else:
169     guesser = csv.Sniffer()
170     input_file = "".join(open(infile,'rU').readlines())
171     try:
172         dialect = guesser.sniff(input_file)
173         reader = csv.reader(open(infile, "rU"), dialect = dialect)
174     except:
175         # older versions (python < 2.5) of csv have problems (bugs)
176         # that is why we try harder to get a result, this should work on most cases
177         # as it assumes that the separator is a comma (the c in csv :-) )
178         try:
179             reader = csv.reader(open(infile, "rU"), dialect = dialect, delimiter = ',')
180         except:
181             reader = csv.reader(open(infile, "rU"), delimiter = ',')
182
183 # read input
184 num_cols = 1 # max columns
185 rows = []
186
187 for row in reader:
188     num_cols = max(num_cols, len(row))
189     rows.append(row)
190
191 num_rows = len(rows) # number of lines
192
193 # create a LyX file
194 #####################
195 # write first part
196 ####################
197 fout.write(header % (num_rows, num_cols))
198
199 #####################
200 # write table
201 ####################
202 for i in range(num_cols):
203         fout.write('<column alignment="left" valignment="top" width="0pt">\n')
204
205 for j in range(num_rows):
206     row = ['<row>']
207
208     ############################
209     # write contents of one line
210     ############################
211     for i in range(len(rows[j])):
212         row.append( cell % rows[j][i].replace('\\','\\backslash\n'))
213
214     # If row has less columns than num_cols fill with blank entries
215     for i in range(len(rows[j]), num_cols):
216         row.append(cell % " ")
217
218     fout.write("\n".join(row) + '\n</row>\n')
219
220 #####################
221 # write last part
222 ####################
223 fout.write(footer)
224 # close the LyX file
225 fout.close()