#!/usr/bin/env pythonw
"""
Convert some VBA code to VB.NET
"""
__author__ = 'Martin Blais <blais@furius.ca>'
# This file is distributed under the GNU General Public License (GPLv3).
# See http://www.gnu.org/licenses/gpl.txt for details.

import sys, re
import Tkinter, Tkconstants, tkFileDialog

# You need to install win32com.
from win32com.client import Dispatch


replacements = [
    (r'\#', ' As Double'),
    (r'\&', ' As Int32'),
    (r'\bLong\b', 'Int32'),
    (r'\bVariant\b', 'Double()'),
    (r'\bSqr\b', 'Sqrt'),
    ]


Type_StdModule = 1

def read_excel_modules(fn):
    """ Read all the code modules from an Excel XLS file and return a mapping of
    module-name to VBA source code."""
    app = Dispatch("Excel.Application")
    app.Workbooks.Open(fn)
    app.Visible = 0
    codes = {}
    for wbook in app.Workbooks:
        i = 0
        for vbcomp in wbook.VBProject.VBComponents:
            if vbcomp.Type != Type_StdModule:
                continue
            i += 1
            mod = vbcomp.CodeModule
            codes[mod.Name] = mod.Lines(1, mod.CountOfLines)
    app.Quit()
    app.Visible = 0 # see note 2
    del app
    return codes



def main():
    import optparse
    parser = optparse.OptionParser(__doc__.strip())
    opts, args = parser.parse_args()

    if not args:
        # Read filenames.
        options = {
            'defaultextension': '.xls',
            'filetypes': [('all files', '.*'),
                          ('vba files', '.vba'),
                          ('Excel files', '.xls')],
            ## 'initialdir': 'C:\\',
            'initialfile': '',
            ## 'parent': root
            'title': 'This is a title',
            }
        fn = tkFileDialog.askopenfilename(**options)
        ## fn = tkFileDialog.askopenfile(mode='r', **options)
        if not fn:
            sys.exit(1)
        else:
            assert re.match('.*\.(vba|xls)$', fn, re.I)
    elif len(args) == 1:
        fn, = args
    else:
        parser.error("Supply the input filename to process.")



    # Read the inputs, either code modules or VBA source files.
    if re.match('.*\.xls$', fn, re.I):
        codes = read_excel_modules(fn)
    else:
        codes = {fn.replace('.vba', ''): open(fn).read()}

    # Process and output the modified file.
    nchanges = 0
    for filename, code in codes.iteritems():
        for from_, to_ in replacements:
            code, n = re.subn(from_, to_, code)
            nchanges += n

        ofilename = filename + '.dna'
        print 'Writing to %s' % ofilename
        outf = open(ofilename, 'w')
        outf.write(code)
        outf.close()
        print '%d changes made.' % nchanges


if __name__ == '__main__':
    main()


