SuperMap sqlserver数据库中点数据集到AutoCAD文本的转换

转载请注明出处,谢谢合作

#!/usr/bin/env python
# -*- coding: cp936 -*-
'''
@brief 功能说明:
实现从supermap后台的mssql里点数据集到AutoCAD里文本型的转换。
要是改为多线程的效果可能会更好。但现在的处理量很小,用不着给自己找麻烦
@author 施峰<sf.cumt@163.com>
2011-10-4~2011-10-5
'''

import pyodbc
import logging
import comtypes.client
import numbers
import array
import re
import ConfigParser

def getconnect(db_type=None,db_arg=None):
    '''
    sql server:
        connector=pyodbc.connect('DRIVER={SQL SERVER};SERVER=LUOBO\\SQLEXPRESS;DATABASE=chengguuo')
    '''
    if db_type in ('MSSQL','JET'):
        try:
            connector = pyodbc.connect(db_arg)
        except :
            logging.error("数据库连接错误!")
            raise
        return connector

def getdrawscript(f=None):
    '''
    如果给定文件名则打开该CAD文件。
    如果没有给定文件名则认为待编辑的CAD文件已经打开。
    '''
    if not f:
        try:
            cad=comtypes.client.GetActiveObject('AutoCAD.Application') #这个可能有点问题
            cad.Visible=False
            drawingscript=cad.ActiveDocument
        except :
            logging.error("获得活动cad文件失败。请查看草稿文件是否已经打开,或请关闭除了草稿文件以外的所有cad文件。")
            raise
    else:
        try:
            cad=comtypes.client.CreateObject('AutoCAD.Application')
        except :
            logging.error("请确定本机上安装了autocad")
            raise
        try:
            drawingscript=cad.Documents.Open(f)
        except :
            logging.error("cad文件打开失败。")
            cad.Quit()
            raise
    return drawingscript

def getrows(sqlstring,connect=None,*args,**kargs):
    '''
    当返回大量记录时可以要占用大量内存空间
    >>> sqlstring = 'SELECT SmX,SmY,name FROM SMDTV_93'
    >>> connect = pyodbc.connect('DRIVER={SQL SERVER};SERVER=LUOBO\\SQLEXPRESS;DATABASE=chengguuo')
    >>> rows = getrows(sqlstring,connect)
    >>> isinstance(rows,list)
    True
    >>> row=rows[1]
    >>> isinstance(row[0],numbers.Real)
    True
    >>> isinstance(row[1],numbers.Real)
    True
    >>> isinstance(row[2],str)
    True
    '''
    cursor=connect.cursor()
    try:
        cursor.execute(sqlstring)
        rows = cursor.fetchall()
    except :
        logging.error("数据库进行sql查寻时出错")
        raise
    finally:
        connect.close()
    return rows # 返回引用,注意防止修改

def drawtext(x=None,y=None,text='什么都没有',draw=None,size=50):
    '''
    @brief 在cad里输入文字。
    >>> drawtext(x=36395514.9324,y=3250445.33498,text=r'\A1;T{\H0.7x;\S^3;}x',draw=getdrawscript('D:\\Drawing11.dwg')) == 0
    True
    '''
    if isinstance(x,numbers.Real) and isinstance(y,numbers.Real) and text: #无文字则不绘
        point=array.array('d',[x,y,0])
        try:
            ms=draw.ModelSpace #draw必须没有关闭
            #draw.ModelSpace.AddText(text,point,size) #单行文本
            ms.AddMText(point,size,text) #多行文本
        except:
            logging.error("绘制文字出错!")
            logging.error("\nx:%s\ny:%s\ntext:%s\npoint:%s\ndraw:%s\nms:\s"%(x,y,text,point,draw,ms))
            draw.Application.Quit()
            raise
        return 0
    return 1

def removesharp(text):
    '''
    @brief 去掉text中的表示supermap标签专题图上下标的特殊符号
    >>> removesharp("T#-3#=x")
    'T3x'
    >>> removesharp("J#-2#=S#+2")
    'J2S2'
    >>> removesharp("")
    ''
    >>> removesharp(None)
    ''
    '''
    if text:
        sharppattern=re.compile(r'#[+-=]')
        modifiedtext=sharppattern.sub(r"",text,count=0)
    else:
        modifiedtext=""
    return modifiedtext

def addchinesenote(test):
    pass


def sharp2mtext(text):
    '''
    >>> text1 = 'T#-3#=x'
    >>> text2 = 'J#-2#=S#+2'
    >>> text3 = None
    >>> sharp2mtext(text1) == '\\A1;T{\H0.7x;\\\\S^3;}x'
    True
    >>> #注意这是用的是repr()函数输出。
    >>> print sharp2mtext(text1)
    \A1;T{\H0.7x;\\S^3;}x
    >>> sharp2mtext(text2) == '\\A1;J{\H0.7x;\\S^2;}S{\H0.7x;\\S2^;}'
    True
    >>> sharp2mtext(text3) == ''
    True
    '''
    if not text:
        return ''
    else:
        ws=text.split('#')
        logging.info(ws)
        ws_conved=[]
        for w in ws[1:]:
            w_tem=''
            if w[0] == '+':
                w_tem = r'{\H0.7x;\S' + w[1:] + r'^;}'
            elif w[0] == '-':
                w_tem = r'{\H0.7x;\S^' + w[1:] + r';}'
            elif w[0] == '=':
                w_tem = w[1:]
            ws_conved.append(w_tem)
        text_conved = r'\A1;'+ws[0]+''.join(ws_conved)
        return text_conved

def main(*args,**kargs):
    '''
    >>> #main(filename="D:\\Drawing1.dwg",sqlstring="SELECT SmX,SmY,name FROM SMDTV_93")
    0
    >>> # main(filename="D:\\Drawing2.dwg",sqlstring="SELECT SmX,SmY,name FROM SMDTV_93") 失败,由于Drawing2.dwg还不存在
    >>> # 0
    >>> config = ConfigParser.ConfigParser()
    >>> config.read('dot2text.cfg')
    ['dot2text.cfg']
    >>> connectstring = config.get('APPLICATION','connectstring')
    >>> connectstring='DRIVER={SQL SERVER};SERVER=LUOBO\\SQLEXPRESS;DATABASE=chengguuo'
    >>> filename = config.get('APPLICATION','outputfile')
    >>> sqlstring = config.get('APPLICATION','sqlstring')
    >>> dbtype =config.get('APPLICATION','dbtype')
    >>> main(filename=filename,sqlstring=sqlstring,dbtype=dbtype,connectstring=connectstring)
    0
    '''
    try:
        filename=kargs['filename']
        sqlstring=kargs['sqlstring']
        dbtype=kargs['dbtype']
        connectstring=kargs['connectstring']
    except:
        logging.info("请给出正确的关键字参数")
        return 1
    if not filename:
        draw=getdrawscript()
    else:
        draw=getdrawscript(filename)

    try:
        layer=draw.Layers.Add("DOT_2_TEXT") #新增图层
        draw.ActiveLayer=layer
    except :
        logging.error("添加新图层出错")
        draw.Application.Quit()
        raise
    # 这里出过大bug,主要是异常的处理
    #try:
    #    dbconnect=getconnect(db_type=dbtype,db_arg=connectstring)
    #except:
    #    raise
    #finally:
    #    draw.Application.Quit()
    try:
        dbconnect=getconnect(db_type=dbtype,db_arg=connectstring)
    except:
        draw.Application.Quit()
        raise
    try:
        rows=getrows(sqlstring,dbconnect)
    except:
        return 1
    try:
        for row in rows:
            #drawtext(x=row[0],y=row[1],text=removesharp(row[2]),draw=draw)
            drawtext(x=row[0],y=row[1],text=sharp2mtext(row[2]),draw=draw)
        draw.save()
    except:
        logging.error("主函数中的drawtext操作出错")
        logging.error("drawtext:\nrow[0]:%s\nrow[1]:%s\nrow[2]:%s\n"%(row[0],row[1],row[2]))
        return 1
    draw.Application.Quit()
    return 0

if __name__ == "__main__":
    #filename = raw_input("请输入文件名\n") # D:\Drawing1.dwg
    #sqlstring = raw_input("***请不要误操作!***\n请输入查询语句。\n") # select SmX,SmY,name from SMDTV93
    config = ConfigParser.ConfigParser()
    config.read('dot2text.cfg')
    connectstring = config.get('APPLICATION','connectstring')
    filename = config.get('APPLICATION','outputfile')
    sqlstring = config.get('APPLICATION','sqlstring')
    dbtype =config.get('APPLICATION','dbtype')
    main(filename=filename,sqlstring=sqlstring,dbtype=dbtype,connectstring=connectstring)