]> git.lyx.org Git - lyx.git/blob - lib/scripts/csv2lyx.py
#7894 explain the status column of mac bindings
[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 and 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         # older versions (python < 2.5) of csv have problems (bugs)
153         # that is why we try harder to get a result, this should work on most cases
154         # as it assumes that the separator is a comma (the c in csv :-) )
155         try:
156             reader = csv.reader(open(infile, "rb"), dialect = dialect, delimiter = ',')
157         except:
158             reader = csv.reader(open(infile, "rb"), delimiter = ',')
159
160 # read input
161 num_cols = 1 # max columns
162 rows = []
163
164 for row in reader:
165     num_cols = max(num_cols, len(row))
166     rows.append(row)
167
168 num_rows = len(rows) # number of lines
169
170 # create a LyX file
171 #####################
172 # write first part
173 ####################
174 fout.write(header % (num_rows, num_cols))
175
176 #####################
177 # write table
178 ####################
179 for i in range(num_cols):
180         fout.write('<column alignment="left" valignment="top" width="0pt">\n')
181
182 for j in range(num_rows):
183     row = ['<row>']
184
185     ############################
186     # write contents of one line
187     ############################
188     for i in range(len(rows[j])):
189         row.append( cell % rows[j][i].replace('\\','\\backslash\n'))
190
191     # If row has less columns than num_cols fill with blank entries
192     for i in range(len(rows[j]), num_cols):
193         row.append(cell % " ")
194
195     fout.write("\n".join(row) + '\n</row>\n')
196
197 #####################
198 # write last part
199 ####################
200 fout.write(footer)
201 # close the LyX file
202 fout.close()