]> git.lyx.org Git - lyx.git/blobdiff - lib/scripts/csv2lyx.py
de/Additional: revise extra features section.
[lyx.git] / lib / scripts / csv2lyx.py
index fe8ba275c79984adb4f0704862c5bd5695d4c680..27063235c9040f4ff1fdaecaa463733b8aa2d0f0 100644 (file)
@@ -1,4 +1,3 @@
-#! /usr/bin/env python
 # -*- coding: utf-8 -*-
 
 # file csv2lyx.py
 # Licence details can be found in the file COPYING.
 
 # author Hartmut Haase
-
+# author José Matos
 # Full author contact details are available in file CREDITS
 
 # This script reads a csv-table (file name.csv) and converts it into
 # a LyX-table for versions 1.5.0 and higher (LyX table format 276).
+# It uses Python's csv module for parsing.
 # The original csv2lyx was witten by Antonio Gulino <antonio.gulino@tin.it>
 # in Perl for LyX 1.x and modified for LyX table format 276 by the author.
 #
-
-
-import os, re, string, sys, unicodedata
+import csv, unicodedata
+import os, sys
+import optparse
 
 def error(message):
     sys.stderr.write(message + '\n')
     sys.exit(1)
 
-# processing command line options
-if len(sys.argv) == 1 or sys.argv[1] == '--help':
-    print '''Usage:
-   csv2lyx [options] mycsvfile mytmptable.lyx
-
-This script creates a LyX document containing a table
-from a comma-separated-value file. The LyX file has format 276
-and can be opened with LyX 1.5.0 and newer.
-
-Options:
-   -s separator    column separator, default is Tab
-   --help          usage instructions
-
-Remarks:
-   If your .csv file contains special characters (e. g. umlauts,
-   accented letters, etc.) make sure it is coded in UTF-8 (unicode).
-   Else LyX will loose some cell contents.'''
-    sys.exit(0)
-
-# print len(sys.argv), sys.argv
-separator = '\t'
-infile = ""
-if len(sys.argv) == 3:
-       infile = sys.argv[1]
-       outfile = sys.argv[2]
-elif len(sys.argv) == 5:
-       infile = sys.argv[3]
-       outfile = sys.argv[4]
-       if sys.argv[1] == '-s':
-               separator = sys.argv[2]
-
-if not os.path.exists(infile):
-       error('File "%s" not found.' % infile)
-# read input
-finput = open(infile, 'r')
-rowcontent = finput.readlines()
-finput.close()
-num_rows = len(rowcontent) # number of lines
-# print 'num_rows ', num_rows
-i = 0
-num_cols = 1 # max columns
-while i < num_rows:
-       # print len(rowcontent[i]), '   ', rowcontent[i]
-       num_cols = max(num_cols, rowcontent[i].count(separator) + 1)
-       i += 1
-# print num_cols
-
-fout = open(outfile, 'w')
-#####################
-# write first part
-####################
-fout.write("""#csv2lyx created this file
-\lyxformat 276
+header = """#csv2lyx created this file. For more info see http://www.lyx.org/
+\\lyxformat 413
 \\begin_document
 \\begin_header
 \\textclass article
+\\use_default_options true
+\\maintain_unincluded_children false
+\\language english
+\\language_package default
 \\inputencoding auto
+\\fontencoding global
 \\font_roman default
 \\font_sans default
 \\font_typewriter default
 \\font_default_family default
+\\use_non_tex_fonts false
 \\font_sc false
 \\font_osf false
 \\font_sf_scale 100
 \\font_tt_scale 100
+
 \\graphics default
+\\default_output_format default
+\\output_sync 0
+\\bibtex_command default
+\\index_command default
 \\paperfontsize default
+\\use_hyperref false
 \\papersize default
 \\use_geometry false
 \\use_amsmath 1
-\\use_esint 0
+\\use_esint 1
+\\use_mhchem 1
+\\use_mathdots 1
 \\cite_engine basic
 \\use_bibtopic false
+\\use_indices false
 \\paperorientation portrait
+\\suppress_date false
+\\use_refstyle 1
+\\index Index
+\\shortcut idx
+\\color #008000
+\\end_index
 \\secnumdepth 3
 \\tocdepth 3
 \\paragraph_separation indent
-\\defskip medskip
+\\paragraph_indentation default
+\\quotes_language english
 \\papercolumns 1
 \\papersides 1
 \\paperpagestyle default
 \\tracking_changes false
 \\output_changes false
+\\html_math_output 0
+\\html_css_as_file 0
+\\html_be_strict false
 \\end_header
 
 \\begin_body
-\\begin_layout Standard
-\\align left 
 
+\\begin_layout Standard
 \\begin_inset Tabular
-\n""")
-fout.write('<lyxtabular version="3" rows=' + str(num_rows) + ' columns=' + str(num_cols) + ' >\n')
-fout.write('<features>\n')
+<lyxtabular version="3" rows="%d" columns="%d">
+<features tabularvalignment="middle">
+"""
+
+cell = """<cell alignment="left" valignment="top" usebox="none">
+\\begin_inset Text
+
+\\begin_layout Plain Layout
+%s
+\\end_layout
+
+\\end_inset
+</cell>"""
+
+footer = """</lyxtabular>
+
+\\end_inset
+
+
+\\end_layout
+
+\\end_body
+\\end_document
+"""
+
+# processing command line options
+# delegate this to standard module optparse
+args = {}
+args["usage"] = "Usage: csv2lyx [options] csvfile [file.lyx]"
+
+args["description"] = """This script creates a LyX document containing a table created from a
+comma-separated-value (CSV) file. The resulting LyX file can be opened
+with LyX 1.5.0 or any later version.
+If no options are given csv2lyx will try to infer the CSV type of the csvfile,
+"""
+parser = optparse.OptionParser(**args)
+
+parser.set_defaults(excel ='', column_sep = '')
+parser.add_option("-e", "--excel", metavar ="CHAR",
+                  help = """CHAR corresponds to a CSV type:
+                      'e': Excel-generated CSV file
+                      't': Excel-generated TAB-delimited CSV file""")
+parser.add_option("-s", "--separator", dest = "column_sep",
+                  help = """column separator
+                                      't' means Tab""")
+
+group = optparse.OptionGroup(parser, "Remarks", """If your CSV file contains special characters (e. g. umlauts,
+   accented letters, etc.) make sure it is coded in UTF-8 (unicode).
+   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.""")
+parser.add_option_group(group)
+
+(options, args) = parser.parse_args()
+
+# validate input
+if len(args) == 1:
+    infile = args[0]
+    fout = sys.stdout
+elif len(args) == 2:
+    infile = args[0]
+    fout = open(args[1], 'w')
+else:
+    parser.print_help()
+    sys.exit(1)
+
+if not os.path.exists(infile):
+       error('File "%s" not found.' % infile)
+
+dialects = {'' : None, 'e' : 'excel', 't' : 'excel-tab'}
+if options.excel not in dialects:
+    parser.print_help()
+    sys.exit(1)
+dialect = dialects[options.excel]
+
+# Set Tab, if necessary
+if options.column_sep == 't':
+       options.column_sep = "\t"
+
+# when no special column separator is given, try to detect it:
+if options.column_sep and dialect :
+    reader = csv.reader(open(infile, "rU"), dialect = dialect, delimiter = options.column_sep)
+else:
+    guesser = csv.Sniffer()
+    input_file = "".join(open(infile,'rU').readlines())
+    try:
+        dialect = guesser.sniff(input_file)
+        reader = csv.reader(open(infile, "rU"), dialect = dialect)
+    except:
+        # older versions (python < 2.5) of csv have problems (bugs)
+        # that is why we try harder to get a result, this should work on most cases
+        # as it assumes that the separator is a comma (the c in csv :-) )
+        try:
+            reader = csv.reader(open(infile, "rU"), dialect = dialect, delimiter = ',')
+        except:
+            reader = csv.reader(open(infile, "rU"), delimiter = ',')
+
+# read input
+num_cols = 1 # max columns
+rows = []
+
+for row in reader:
+    num_cols = max(num_cols, len(row))
+    rows.append(row)
+
+num_rows = len(rows) # number of lines
+
+# create a LyX file
+#####################
+# write first part
+####################
+fout.write(header % (num_rows, num_cols))
+
 #####################
 # write table
 ####################
-i = 0
-while i < num_cols:
+for i in range(num_cols):
        fout.write('<column alignment="left" valignment="top" width="0pt">\n')
-       i += 1
-j = 0
-while j < num_rows:
-       fout.write('<row>\n')
-       row = str(rowcontent[j])
-       row = string.split(row,separator)
-       #print j, ': ' , row
-############################
-# write contents of one line
-############################
-       i = 0
-       while i < num_cols:
-               fout.write("""<cell alignment="left" valignment="top" usebox="none">
-\\begin_inset Text
-\\begin_layout Standard\n""")
-               fout.write(row[i])
-               fout.write('\\end_layout\n\\end_inset\n</cell>\n')
-               i += 1
-       fout.write('</row>\n')
-       j += 1
+
+for j in range(num_rows):
+    row = ['<row>']
+
+    ############################
+    # write contents of one line
+    ############################
+    for i in range(len(rows[j])):
+        row.append( cell % rows[j][i].replace('\\','\\backslash\n'))
+
+    # If row has less columns than num_cols fill with blank entries
+    for i in range(len(rows[j]), num_cols):
+        row.append(cell % " ")
+
+    fout.write("\n".join(row) + '\n</row>\n')
+
 #####################
 # write last part
 ####################
-fout.write("""</lyxtabular>
-\\end_inset
-\\end_layout
-\\end_body
-\\end_document\n""")
+fout.write(footer)
+# close the LyX file
 fout.close()