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