利用VBA把PowerDesigner导出到Excel

代码如下,有需要的同学直接复制就可用:

Option Explicit
'-------------------------------------------------------------------------------
'作用:PowerDesigner导出到Excel
'
'作者: Lio5n
'
'时间: 2015-12-17
'
'版本: V1.0
'-------------------------------------------------------------------------------

'----------------------------------请按需设置-----------------------------------
CONST GEN_MENU    = "Y"                         '是否生成目录文件 [ Y-是 N-否 ]
CONST MENU_FILE   = "D:\File_Name.xlsx"         '目录文件路径
CONST GEN_TABLE   = "Y"                         '是否生成模型结构 [ Y-是 N-否 ]
CONST SHOW_DISTRIBUTION_KEYS  = "Y"             '是否显示分布键   [ Y-是 N-否 ]
'----------------------------------目录页设置-----------------------------------
CONST COL_TABLE_CODE = "C"                      '表英文名列
CONST COL_TABLE_NAME = "D"                      '表中文名列
CONST COL_DEAL_FLAG  = "E"                      '处理标志列
'-------------------------------------------------------------------------------
CONST BEG_ROW = 6                               '数据区域-开始行
CONST END_COL = "J"                             '数据区域-结束列
CONST MAX_TABLES = 1000                         '表数量上限

CONST DATA_TYPE_DATE_LEN      = 10              'DATE类型数据长度
CONST DATA_TYPE_TIMESTAMP_LEN = 19              'TIMESTAMP类型数据长度
CONST DATA_TYPE_INTEGER_LEN   = 12              'INTEGER类型数据长度

CONST D_COLOR_BLUE     = 16764057               '天蓝色
CONST D_COLOR_GREEN    = 13434828               '浅绿色
CONST D_COLOR_ORAGNE   = 49407                  '橙色

Dim mCR,mLF
mCR = Chr(10)       '换行
mLF = Chr(13)       '回车
'-------------------------------------------------------------------------------

'定义PDM
Dim mdl
Dim errCount, errString
errCount=0
Set mdl = ActiveModel
If ( mdl Is Nothing ) Then
    MsgBox "There is no Active Model"
Else
    If UCase(GEN_MENU) = "Y" Then
        createMenuSheet mdl         '生成目录
    End If

    If UCase(GEN_TABLE) = "Y" Then
        createTableSheet mdl        '根据目录生成表结构
    End If

    If errCount > 0 Then
        output "错误信息: " + errString
    End If
    MsgBox "处理完毕,共有"+Cstr(errCount)+"个错误!"
End If

'-------------------------------------------------------------------------------
'生成目录
'   序号|模式名|表名|处理标志(Y/N)|中文表名|备注
'   处理标志默认全部为Y
'-------------------------------------------------------------------------------
sub createMenuSheet(mdl)

    Dim ExcelApp, ExcelBook, ExcelSheet

    Set ExcelApp = CreateObject("Excel.Application")
    ExcelApp.visible=FALSE
    Set ExcelBook = ExcelApp.Workbooks.Add
    Set ExcelSheet = ExcelBook.Sheets.Add
    ExcelSheet.Name = "目录"

    '目录标题栏
    With ExcelSheet
        '内容
        .Cells(1,"A").Value = "序号"
        .Cells(1,"B").Value = "模式名"
        .Cells(1,"C").Value = "表英文名"
        .Cells(1,"D").Value = "中文表名"
        .Cells(1,"E").Value = "处理标志(Y/N)"
        .Cells(1,"F").Value = "备注"

        '样式-居中
        .Rows(1).HorizontalAlignment = 3      '左右居中   5-填充,左对齐,不会覆盖右边的单元格
        .Rows(1).VerticalAlignment = 2        '上下居中
        '样式-宽高
        .Rows(1).RowHeight = 1/0.035          '高1厘米
        .Columns(1).ColumnWidth = 5           '宽,单位:字符
        .Columns(2).ColumnWidth = 6
        .Columns(3).ColumnWidth = 31
        .Columns(4).ColumnWidth = 41
        .Columns(5).ColumnWidth = 9
        .Columns(6).ColumnWidth = 21
        '样式-四周边框
        .Range("A1","F1").Borders(1).LineStyle = 1
        .Range("A1","F1").Borders(2).LineStyle = 1
        .Range("A1","F1").Borders(3).LineStyle = 1
        .Range("A1","F1").Borders(4).LineStyle = 1
        '样式-其他
        .Rows(1).WrapText = True              '自动换行
        .Range("A1","F1").Interior.Color = D_COLOR_BLUE   '背景色-天蓝色
        .Range("A1","F1").Font.Size = 10                '字体
        .Rows(1).Font.Bold = True             '粗体
    End With


    Dim rowCnt
    rowCnt = 2

    '生成表清单
    output "开始生成表清单..."
    ListObjects mdl,ExcelSheet,rowCnt       '遍历模型

    '样式-设置部分列为左右居中
    With ExcelSheet
        .Columns(1).HorizontalAlignment = 3      '左右居中
        .Columns(2).HorizontalAlignment = 3      '左右居中
        .Columns(5).HorizontalAlignment = 3      '左右居中
    End With

    '调整整个数据区域样式
    Dim rowEnd
    rowEnd = rowCnt-1                '最后一行行号
    With ExcelSheet.Range("A2","F"+Cstr(rowEnd))
        .Borders(1).LineStyle = 1                       '四周边框
        .Borders(2).LineStyle = 1
        .Borders(3).LineStyle = 1
        .Borders(4).LineStyle = 1
    End With
    ExcelSheet.Range("A1","F"+Cstr(rowEnd)).Font.Size = 10       '字体

    '按层名、表名排序
    ExcelApp.AddCustomList Array("ODM", "FDM", "ADM", "MDM", "PUBLIC")
    ExcelSheet.Sort.SortFields.Clear
    ExcelSheet.Sort.SortFields.Add ExcelSheet.Range("B2","B"+Cstr(rowEnd)), 0, 1, "ODM,FDM,ADM,DMD,PUBLIC", 0
    ExcelSheet.Sort.SortFields.Add ExcelSheet.Range("C2","C"+Cstr(rowEnd)), 0, 1, "", 0
    With ExcelSheet.Sort
        .SetRange ExcelSheet.Range("B1","F"+Cstr(rowEnd))
        .Header = 1
        .MatchCase = False
        .Apply
    End With

    '筛选
    ExcelApp.Selection.AutoFilter

    '冻结首行
    ExcelApp.ActiveWindow.SplitRow = 1          '
    ExcelApp.ActiveWindow.SplitColumn = 0       '
    ExcelApp.ActiveWindow.FreezePanes = True

    ExcelBook.SaveAs MENU_FILE
    ExcelBook.Close
    ExcelApp.Quit
    Set ExcelSheet = Nothing
    Set ExcelBook = Nothing
    Set ExcelApp = Nothing

    output "表清单生成完毕, 共 " + Cstr(rowCnt-2) + " 张表!"
    Exit Sub
End Sub


'遍历模型
Private Sub ListObjects(fldr,ExcelSheet,rowCnt)
    Dim obj
    For Each obj In fldr.children
        getTables fldr,obj,ExcelSheet,rowCnt
    Next

    Dim f
    For Each f In fldr.Packages
        ListObjects f,ExcelSheet,rowCnt
    Next
End Sub

'获取表清单
Private Sub getTables(CurrentFldr,CurrentObject,ExcelSheet,rowCnt)
    Dim col
    Dim colType
    If CurrentObject.IsKindOf(cls_Table) then
        ExcelSheet.Cells(rowCnt,"A").Value = rowCnt - 1
        If ( CurrentObject.Owner Is Nothing ) Then
            ExcelSheet.Cells(rowCnt,"B").Value = "PUBLIC"
        Else
            ExcelSheet.Cells(rowCnt,"B").Value = CurrentObject.Owner.Code
        End If
        ExcelSheet.Cells(rowCnt,"C").Value = CurrentObject.Code
        ExcelSheet.Cells(rowCnt,"D").Value = CurrentObject.Name
        ExcelSheet.Cells(rowCnt,"E").Value = "Y"
        ExcelSheet.Cells(rowCnt,"F").Value = ""
        rowCnt = rowCnt + 1
    else
        exit sub
    end if
End Sub



'-------------------------------------------------------------------------------
'根据目录生成表结构,每个表一个Sheet。
'-------------------------------------------------------------------------------
sub createTableSheet(mdl)

    Dim ExcelApp, ExcelBook, ExcelSheet, ExcelMenu
    Dim rowIdx, menuIdx
    Dim tableCnt, colCnt
    Dim tableNum
    Dim tableCode, tableName, tableOwner, tableFlag
    tableCnt = 0
    tableNum = 0

    '当用户指定目录文件时,重定义输出文件,以免生成过程中出错,或对输出结果不满意时,需要重新恢复目录文件。
    Dim InputFile, OutputFile
    InputFile = MENU_FILE
    If UCase(GEN_MENU) = "N" Then
        OutputFile = Mid(InputFile, 1, InstrRev(InputFile,".")-1) + "_out" + Mid(InputFile, InstrRev(InputFile,"."))
    Else
        OutputFile = InputFile
    End If

    '读取目录文件
    Set ExcelApp = CreateObject("Excel.Application")
    ExcelApp.visible=FALSE
    Set ExcelBook = ExcelApp.Workbooks.Open(MENU_FILE)
    Set ExcelMenu = ExcelBook.Sheets("目录")
    menuIdx = ExcelMenu.Index

    For rowIdx = 2 To MAX_TABLES+2
        If ExcelMenu.Cells(rowIdx, "A").Value = "" Then
            Exit For
        Else
            tableNum = tableNum + 1
        End If

        '获取表信息
        tableOwner = ExcelMenu.Cells(rowIdx, "B").Value
        tableCode = ExcelMenu.Cells(rowIdx, COL_TABLE_CODE).Value
        tableName = ExcelMenu.Cells(rowIdx, COL_TABLE_NAME).Value
        tableFlag = ExcelMenu.Cells(rowIdx, COL_DEAL_FLAG).Value

        If UCase(tableFlag) = "Y" AND ( Len(tableCode)>0 OR Len(tableName)>0 ) Then     '处理标志非Y则跳过

            '检查表是否存在
            Dim iFlag
            iFlag = 0
            checkTable mdl,ExcelSheet,tableCode,tableName,iFlag

            '表存在则继续处理
            If iFlag = 1 Then

                tableCnt = tableCnt + 1

                '创建Sheet页
                Set ExcelSheet = ExcelBook.Sheets.Add(,ExcelBook.Sheets(menuIdx))       '在目录后面插入,第一个参数为空
                ExcelSheet.Name = tableCode

                output "["+Cstr(tableCnt)+"] "+tableCode

                '添加自定义名称  范围-工作簿
                ExcelBook.Names.Add tableOwner+"."+tableCode,"="+ExcelMenu.Name+"!R"+Cstr(rowIdx)+"C3"       'R=row C=col R2C3=$2$3=C2

                '生成表头
                With ExcelSheet
                    '第一行
                    .Cells(1,"A").Value = "<<返回目录"
                    '超链接,指向自定义名称
                    .Hyperlinks.Add ExcelSheet.Range("A1"),"",tableOwner+"."+tableCode,"",ExcelSheet.Cells(1,"A").Value
                    '超链接,直接定位到单元格,但这样的话,如果目标单元格发生变化,就跳错了。
                    '.Hyperlinks.Add ExcelSheet.Range("A1"),"",ExcelMenu.Name+"!C"+Cstr(rowIdx),"",ExcelSheet.Cells(1,"A").Value

                    '第二行
                    .Cells(2,"A").Value = "英文名"
                    .Range("B2","C2").Merge
                    .Cells(2,"B").Value = tableCode

                    .Cells(2,"D").Value = "模式名"
                    .Cells(2,"E").Value = tableOwner

                    '第三行
                    .Cells(3,"A").Value = "中文名"
                    .Range("B3","E3").Merge
                    .Cells(3,"B").Value = tableName

                    '第四行
                    .Cells(4,"A").Value = "描述"
                    .Range("B4","E4").Merge

                    '设置样式-表头
                    .Range("A2","A4").Interior.Color = D_COLOR_GREEN  '背景色-浅绿色
                    .Range("A2","A4").Font.Bold = True              '粗体
                    .Range("A2","A4").HorizontalAlignment = 3       '左右居中

                    .Cells(2,"D").Interior.Color = D_COLOR_GREEN      '背景色-浅绿色
                    .Cells(2,"D").Font.Bold = True                  '粗体
                    .Cells(2,"D").HorizontalAlignment = 3           '左右居中

                    .Range("A1","E4").Font.Size = 10                '字体
                    .Range("A2","E4").Borders(1).LineStyle = 1      '四周边框
                    .Range("A2","E4").Borders(2).LineStyle = 1
                    .Range("A2","E4").Borders(3).LineStyle = 1
                    .Range("A2","E4").Borders(4).LineStyle = 1

                    '第五行-标题栏
                    .Cells(5,"A").Value = "序号"
                    .Cells(5,"B").Value = "字段中文名"
                    .Cells(5,"C").Value = "字段英文名"
                    .Cells(5,"D").Value = "字段类型"
                    .Cells(5,"E").Value = "数据长度"
                    .Cells(5,"F").Value = "主键"
                    .Cells(5,"G").Value = "非空"
                    .Cells(5,"H").Value = "分布键"
                    .Cells(5,"I").Value = "说明"
                    .Cells(5,"J").Value = "备注"

                    '设置样式-第五行-标题栏
                    With .Range("A5","J5")
                        .Interior.Color = D_COLOR_BLUE  '背景色-天蓝色
                        .Font.Bold = True               '粗体
                        .HorizontalAlignment = 3        '左右居中
                        .Font.Size = 10                 '字体
                        .Borders(1).LineStyle = 1       '四周边框
                        .Borders(2).LineStyle = 1
                        .Borders(3).LineStyle = 1
                        .Borders(4).LineStyle = 1
                    End With

                End With

                '生成字段内容
                colCnt=0
                getColumns mdl,ExcelSheet,tableCode,colCnt

                '调整整个数据区域样式
                Dim rowEnd
                rowEnd = colCnt+BEG_ROW-1       '最后一行行号
                With ExcelSheet.Range("A"+Cstr(BEG_ROW),END_COL+Cstr(rowEnd))
                    .Borders(1).LineStyle = 1    '四周边框
                    .Borders(2).LineStyle = 1
                    .Borders(3).LineStyle = 1
                    .Borders(4).LineStyle = 1
                End With
                ExcelSheet.Range("A"+Cstr(BEG_ROW),END_COL+Cstr(rowEnd)).Font.Size = 10              '字体-整个数据区域

                ExcelSheet.Range("A"+Cstr(BEG_ROW),"A"+Cstr(rowEnd)).HorizontalAlignment = 3     '左右居中-序号
                ExcelSheet.Range("F"+Cstr(BEG_ROW),"H"+Cstr(rowEnd)).HorizontalAlignment = 3     '左右居中-主键、非空、分布键

                '创建目录中的超链接
                ExcelMenu.Hyperlinks.Add ExcelMenu.Range(COL_TABLE_CODE+Cstr(rowIdx)),"",ExcelSheet.Name+"!A1","",ExcelSheet.Name
                ExcelMenu.Range(COL_TABLE_CODE+Cstr(rowIdx)).Font.Size = 10
                '更新目录中的表中文名
                ExcelMenu.Range(COL_TABLE_NAME+Cstr(rowIdx)).Value = tableName

                '设置宽度
                With ExcelSheet
                    .Columns("A:H").EntireColumn.AutoFit    '前8列-自适应
                    .Columns(9).ColumnWidth = 30            '说明   宽,单位:字符
                    .Columns(10).ColumnWidth = 10           '备注
                End With

                '拆分冻结单元格
                ExcelApp.ActiveWindow.SplitRow = BEG_ROW-1  '
                ExcelApp.ActiveWindow.SplitColumn = 5       '
                ExcelApp.ActiveWindow.FreezePanes = True

                '是否显示分布键
                If UCase(SHOW_DISTRIBUTION_KEYS) <> "Y" Then
                    ExcelSheet.Columns(8).Delete             '删除分布键列
                End If
            End If
        End If
    Next

    '设置目录页为活动页面,效果:打开EXCEL时,首页为目录页面
    ExcelMenu.Activate

    '筛选处理标志为Y的记录
    ExcelMenu.Range("$A$1:$"+COL_DEAL_FLAG+"$"+Cstr(tableNum)).AutoFilter Asc(COL_DEAL_FLAG)-Asc("A")+1,"=Y"

    ExcelBook.SaveAs OutputFile         '另存为输出文件
    ExcelBook.Close
    ExcelApp.Quit
    Set ExcelMenu  = Nothing
    Set ExcelSheet = Nothing
    Set ExcelBook  = Nothing
    Set ExcelApp   = Nothing

    output "输出文件为:[" + OutputFile + "]"
    Exit Sub
End Sub

'检查表是否存在
Sub checkTable(mdl,ExcelSheet,tableCode,tableName,iFlag)
    Dim tb

    If Len(tableCode) > 0 Then
        set tb = mdl.FindChildByCode(tableCode,cls_Table)
        If ( tb Is Nothing ) Then
            output "未找到表[" + tableCode + "]"
            errString = errString + mLF + "未找到表[" + tableCode + "]"
            errCount  = errCount + 1
        Else
            iFlag = 1
            tableName = tb.Name
        End If
    Else
        set tb = mdl.FindChildByName(tableName,cls_Table)
        If ( tb Is Nothing ) Then
            output "未找到表[" + tableName + "]"
            errString = errString + mLF + "未找到表[" + tableName + "]"
            errCount  = errCount + 1
        Else
            iFlag = 1
            tableCode = tb.Code
        End If
    End If

End Sub

'生成字段
Sub getColumns(mdl,ExcelSheet,tableCode,colCnt)

    Dim tb, col, rowIdx
    set tb = mdl.FindChildByCode(tableCode,cls_Table)           '在模型中查找目标表
    If ( tb Is Nothing ) Then
        output "未找到表[" + tableCode + "]"
        errString = errString + mLF + "未找到表[" + tableCode + "]"
        errCount  = errCount + 1
    End If

    Dim colDistributionKeys, dKeys, iKeys, iKeysFlag         '分布键
    Dim tPhysicalOptions, iIdx1, iIdx2, sStr1, sStr2
    iKeysFlag = 0
    If Len(tb.PhysicalOptions) > 0 Then
        tPhysicalOptions = Replace(UCase(tb.PhysicalOptions), mLF, "")      '去换行
        iIdx1 = Instr(tPhysicalOptions, "DISTRIBUTED")                          'DISTRIBUTED在字符串中的位置
        If iIdx1 > 0 Then
            sStr1 = Mid(tPhysicalOptions, iIdx1)                                '从distributed开始的子串
            sStr2 = Mid(sStr1, 1, Instr(sStr1, ")")-1)                          'distributed by (...  没有")"
            colDistributionKeys = Mid(sStr2, Instr(sStr2, "(")+1)               '分布键子串,有多个的话逗号分隔
            dKeys = Split( colDistributionKeys, "," )                           '拆分成数组
            iKeys = ubound(dKeys)                                               '数组最大下标
            iKeysFlag = 1
        End If
    End If

    rowIdx = 5
    For Each col In tb.Columns
        rowIdx = rowIdx + 1
        colCnt = colCnt + 1

        '单元格-中英文表名、数据类型、长度
        ExcelSheet.Cells(rowIdx,"A").Value = colCnt
        ExcelSheet.Cells(rowIdx,"B").Value = col.Name
        ExcelSheet.Cells(rowIdx,"C").Value = col.Code
        ExcelSheet.Cells(rowIdx,"D").Value = col.DataType
        ExcelSheet.Cells(rowIdx,"E").Value = col.Length

        '截取字段类型
        Dim colType, strPair
        If Len(col.DataType) > 0 Then
            strPair = Split( col.DataType, "(" )
            colType = strPair(0)
        Else
            colType = ""
            output "表[" + tableCode + "] 字段["+ col.Name + "] 类型为空!"
            errString = errString + mLF + "表[" + tableCode + "] 字段["+ col.Name + "] 类型为空!"
            errCount  = errCount + 1
        End If

        '根据字段类型,获取数据长度,CHAR类型的PDM自带长度,不需另外处理
        If UCase(colType) = "DATE" Then
            ExcelSheet.Cells(rowIdx,"E").Value = DATA_TYPE_DATE_LEN
        End If
        If UCase(colType) = "TIMESTAMP" Then
            ExcelSheet.Cells(rowIdx,"E").Value = DATA_TYPE_TIMESTAMP_LEN
        End If
        If UCase(colType) = "INTEGER" Then
            ExcelSheet.Cells(rowIdx,"E").Value = DATA_TYPE_INTEGER_LEN
        End If
        If UCase(colType) = "DECIMAL" Or UCase(colType) = "NUMERIC" Then '20150728 新增NUMERIC判断
            Dim str1, str2, colLen
            str1 = Split( strPair(1), ")" )     '截取括号内的值,如15,2或8
            str2 = Split( str1(0), "," )        '截取总长度
            colLen = str2(0)
            ExcelSheet.Cells(rowIdx,"E").Value = Cint(colLen)+2
        End If

        '单元格-主键
        If col.Primary = true Then
            ExcelSheet.Cells(rowIdx,"F").Value = "Y"
        End If

        '单元格-非空
        If col.Mandatory = true Then
            ExcelSheet.Cells(rowIdx,"G").Value = "Y"
        End If

        '单元格-分布键
        If iKeysFlag = 1 Then
            Dim keyIdx
            For keyIdx = 0 To iKeys
                If col.Code = Trim(dKeys(keyIdx)) Then
                    ExcelSheet.Cells(rowIdx,"H").Value = "Y"
                    Exit For
                End If
            Next
        End If

        '单元格-说明
        ExcelSheet.Cells(rowIdx,"I").Value = col.Comment
    Next

    Exit Sub
End Sub

 

posted @ 2015-12-17 13:31  Lio5n  阅读(1169)  评论(1编辑  收藏  举报