通过VB脚本实现PDM与EXCEL互转

        在软件开发过程中,很多时候都需要用需求文档中给出的表结构进行数据建模。若表数量、单位表字段数量较少还可以接受,一旦遇到十几张大表真的是心力交瘁。

        以下是本人整理改进后的两套VBS脚本,通过Power Designer工具中Script命令行执行脚本,实现PDM与Excel之间的模型互转,希望可以帮到大家!

Excel格式样例:

Excel -> PDM

'******************************************************************************
'* Purpose:  从Excel中读取信息创建PDM模型
'* Title:
'* Category: 
'* Author:   nisj	https://blog.csdn.net/nisjlvhudy/article/details/47176981
'* Created:  2015年7月31日
'* Use:      打开PDM,创建新的PDM,运行本脚本(Ctrl+Shift+X)
'*           Excel 格式要求
'*   |A     |B          |C          |D          |E      |F          |G          |H        |I    |J        |K      |
'*   主题域 |表注释 	|表英文名称 |表中文名称 |列名   |列中文名称 |列注释 	|数据类型 |主键 |是否为空 |默认值 |
'* Version:  2.0
'*
'* Comment:  Modified By Aikes On 2019-08-21
'*
'******************************************************************************
 
Option Explicit
 
' Model sheet中的列信息
CONST CELL_A="A" '主题域(Pachage)
CONST CELL_B="B" '表注释
CONST CELL_C="C" '表英文名称
CONST CELL_D="D" '表中文名称
CONST CELL_E="E" '列名
CONST CELL_F="F" '列中文名称
CONST CELL_G="G" '列注释
CONST CELL_H="H" '数据类型
CONST CELL_I="I" '是否主键
CONST CELL_J="J" '是否可空
CONST CELL_K="K" '默认值
 
CONST str_iskey="Y"
'表的所属者
CONST str_username="srv"
CONST isclear_columns = true  '是否先删除表的所有列,如果是false则不会删除excel中没有的列,如果是true,则会重新创建相应表的所有列
 
' get the current active model
DIM mdl ' 定义当前的模型
SET mdl = ActiveModel '通过全局参数获得当前的模型
 
IF (mdl IS NOTHING) THEN
   MsgBox "没有选择模型,请选择一个模型并打开"
ELSEIF NOT mdl.IsKindOf(PdPDM.cls_Model) THEN
   MsgBox "当前选择的不是一个物理模型(PDM)."
ELSE
 
'选择需要导入的Excel文件
' 打开Excel
DIM xlApp   '定义Excel对象
SET xlApp  = CreateObject("Excel.Application")
xlApp.DisplayAlerts = FALSE
DIM xlBook  '定义Excel Sheet
SET xlBook = xlApp.WorkBooks.Open("E:\import.xlsx")
xlApp.Visible = TRUE
 
output "开始从Excel创建模型"
Create_From_Excel(xlBook)
output "模型创建完成,开始关闭Excel"
 
SET xlBook=NOTHING
xlApp.Quit
SET xlApp=NOTHING
 
END IF
 
PRIVATE SUB Create_From_Excel(xlBook)
  DIM xlsheet
  DIM rowcount
  dim pkg
 
  FOR EACH xlsheet IN xlBook.WORKSHEETS
	rowcount = xlsheet.UsedRange.Cells.Rows.Count
	output "本Excel["+xlsheet.name+"]共有行数为:"+CSTR(rowcount)
	IF rowcount>1 THEN
	  '删掉包概念	可以根据所需自行调整  Modify By Aikes
	  'SET pkg = CreateOrReplacePackageByName( xlsheet.name , mdl)
	  Create_Model_From_Excel xlsheet,mdl 
	  SET xlsheet=NOTHING
	END IF
  NEXT
END SUB
 
'--------------------------------------------------------------------------------
'功能函数
'--------------------------------------------------------------------------------
PRIVATE SUB Create_Model_From_Excel(xlsheet,package)
	DIM Tab '定义数据表对象
	DIM col
	DIM tabcode
	DIM tabcode1
	DIM i
	DIM col_code
 
	FOR i=2 TO xlsheet.UsedRange.Cells.Rows.Count
		'判断是否需要创建新表对象
		tabcode1 = xlsheet.Range(CELL_C+CSTR(i)).Value
		IF tabcode1<>"" and tabcode<>tabcode1 THEN
			SET Tab=NOTHING 
			tabcode=tabcode1
			IF tabcode<>"" THEN
			    '判断表是否存在,如果不存在则创建,存在则直接返回表对象
				SET tab = CreateOrReplaceTableByCode(tabcode,package)
				'将表的所有列删除,如果需要重新创建表的列
				IF isclear_columns THEN
					DeleteTableColumns(tab)
				END IF
				'更新表的属性
				Tab.code=xlsheet.Range(CELL_C+CSTR(i)).Value
				Tab.name=xlsheet.Range(CELL_D+CSTR(i)).Value
				Tab.comment=xlsheet.Range(CELL_D+CSTR(i)).Value
				Tab.Description=xlsheet.Range(CELL_B+CSTR(i)).Value '注释
				'Tab.owner=FindUserByName(str_username)
				output "创建表模型OK:"+Tab.code+"——"+Tab.name
			END IF
		END IF
 
		IF NOT(Tab IS NOTHING) THEN '创建表的列
			col_code=xlsheet.Range(CELL_E+CSTR(i)).Value '列代码   	
			'判断是否已经存在列,不存在则创建
			SET col = CreateOrReplaceColumnByCode(col_code,Tab)
			'设置列属性
			col.code=xlsheet.Range(CELL_E+CSTR(i)).Value '列代码
			col.name=xlsheet.Range(CELL_F+CSTR(i)).Value '列名称
			col.comment=xlsheet.Range(CELL_F+CSTR(i)).Value '列注释
			col.Description=xlsheet.Range(CELL_G+CSTR(i)).Value '列注释
			col.DataType=xlsheet.Range(CELL_H+CSTR(i)).Value '列数据类型
			'列是否主键,如果是主键,则输出 Y
			IF CSTR(xlsheet.Range(CELL_I+CSTR(i)).Value)=str_iskey THEN
				col.primary= TRUE
			END IF
			'补充 J-是否为空标记、K-默认值  若已标记主键非空约束自动存在 不需要再次标记  Added By Aikes
			IF CSTR(xlsheet.Range(CELL_J+CSTR(i)).Value)=str_iskey and col.primary <> TRUE THEN
				col.Mandatory= TRUE	'是否为空标记
			END IF
			col.DefaultValue=xlsheet.Range(CELL_K+CSTR(i)).Value '默认值
			
			output "更新表模型的列OK:"+Tab.code+"——"+col.code+"--"+col.name
		END IF
	NEXT
 
END SUB
 
'--------------------------------------------------------------------------------
'功能函数
'--------------------------------------------------------------------------------
PRIVATE FUNCTION CreateOrReplacePackageByName(name,model)
	DIM pkg 'Table 对象
	SET pkg = FindPackageByName(name,model)
	IF pkg IS NOTHING THEN
	  SET pkg = model.Packages.CreateNew()
	  pkg.SetNameAndCode name, name
	  pkg.PhysicalDiagrams.Item(0).SetNameAndCode name, name
	END IF
	SET CreateOrReplacePackageByName = pkg
END FUNCTION
 
PRIVATE FUNCTION CreateOrReplaceTableByCode(code,package)
	DIM tab 'Table 对象
	SET tab = FindTableByCode(code,package)
	IF tab IS NOTHING THEN
	  SET tab = package.Tables.CreateNew()
	  tab.SetNameAndCode code, code
	END IF
	SET CreateOrReplaceTableByCode = tab
END FUNCTION
 
PRIVATE FUNCTION CreateOrReplaceColumnByCode(code,table)
	DIM col 'Table 对象
	SET col =FindColumnByCode(code,table) 
	IF col IS NOTHING THEN
	  SET col =table.Columns.CreateNew
	  col.SetNameAndCode code , code
	END IF
	SET CreateOrReplaceColumnByCode = col
END FUNCTION
 
PRIVATE FUNCTION FindPackageByName(name,model)
	DIM pkg 'Table 对象
	SET FindPackageByName = NOTHING
	FOR EACH pkg IN model.Packages
		IF NOT pkg.isShortcut THEN
			IF pkg.name =name THEN
				SET FindPackageByName=pkg
				Exit FOR
			END IF
		END IF
	NEXT
	
END FUNCTION
 
PRIVATE FUNCTION FindTableByName(name,package)
	DIM Tab1 'Table 对象
	SET FindTableByName = NOTHING
	FOR EACH Tab1 IN package.Tables
		IF NOT Tab1.isShortcut THEN
			IF Tab1.name =name THEN
				SET FindTableByName=Tab1
				Exit FOR
			END IF
		END IF
	NEXT
END FUNCTION
 
PRIVATE FUNCTION FindTableByCode(code,package)
	DIM Tab1 'Table 对象
	SET FindTableByCode = NOTHING
	FOR EACH Tab1 IN package.Tables
		IF NOT Tab1.isShortcut THEN
			'OUTPUT "循环表:"+Tab1.name
			IF Tab1.code =code THEN
				SET FindTableByCode=Tab1
				Exit FOR
			END IF
		END IF
	NEXT
END FUNCTION
 
PRIVATE FUNCTION FindColumnByCode(code,tabobj)
	DIM col1 'Column 对象
	'OUTPUT "code:"+code
	SET FindColumnByCode = NOTHING
	FOR EACH col1 IN tabobj.Columns
		'OUTPUT "code2:"+col1.code
		IF col1.code =code THEN
			SET FindColumnByCode=col1
			EXIT FOR
		END IF
	NEXT
END FUNCTION
 
PRIVATE FUNCTION FindColumnByName(name,tabobj)
	DIM col1 'Column 对象
	'OUTPUT "codename:"+name
	SET FindColumnByName = NOTHING
	FOR EACH col1 IN tabobj.Columns
		IF col1.name =name THEN
			SET FindColumnByName=col1
			EXIT FOR
		END IF
	NEXT
END FUNCTION
 
PRIVATE FUNCTION FindDomainByName(dmname,mdl)
 
	DIM dm1 'Domain 对象
	SET FindDomainByName = NOTHING
 
	FOR EACH dm1 IN mdl.domains
		IF NOT dm1.isShortcut THEN
			IF dm1.name =dmname THEN
				SET FindDomainByName =dm1
				EXIT FOR
			END IF
		END IF
	NEXT
 
END FUNCTION
 
PRIVATE FUNCTION FindUserByName(username)
	DIM user1
	SET FindUserByName = NOTHING
	FOR EACH user1 IN mdl.users
		IF user1.name=username THEN
			SET FindUserByName=user1
			EXIT FOR
		END IF
	NEXT
 
END FUNCTION
 
' 删除表的所有列
PRIVATE SUB DeleteTableColumns(table)
  IF NOT table.isShortcut THEN  
   DIM col
   FOR EACH col IN table.columns  
  	'output "Column deleted :"+table.name
  	col.Delete
  	SET col = NOTHING
   NEXT
  END IF
END SUB

PDM - > Excel

'******************************************************************************
'* Purpose:  将模型Table等对象的描述信息导出到Excel中
'* Title:
'* Category: Export
'* Author:   nisj	https://blog.csdn.net/nisjlvhudy/article/details/47176981
'* Created:  2015年7月31日
'* Use:      打开PDM,创建新的PDM,运行本脚本(Ctrl+Shift+X)
'*           Excel 格式为
'* |A     |B          |C          |D          |E      |F          |G          |H        |I    |J        |K      |
'* 主题域 |表注释 	|表英文名称   |表中文名称 |列名   |列中文名称 |列注释     |数据类型 |主键 |是否为空 |默认值 |
'*
'* Version:  2.0
'*
'* Comment:  Modified By Aikes On 2019-08-21
'*
'******************************************************************************
Option Explicit
 
' Model sheet中的列信息
CONST CELL_A="A" '主题域(Pachage)
CONST CELL_B="B" '表注释
CONST CELL_C="C" '表英文名称
CONST CELL_D="D" '表中文名称
CONST CELL_E="E" '列名
CONST CELL_F="F" '列中文名称
CONST CELL_G="G" '列注释
CONST CELL_H="H" '数据类型
CONST CELL_I="I" '是否主键
CONST CELL_J="J" '是否可空
CONST CELL_K="K" '默认值
 
CONST str_iskey="Y"
 
DIM nb
'
' get the current active model
'
DIM mdl ' the current model
SET mdl = ActiveModel
IF (mdl IS NOTHING) THEN
   MsgBox "没有选择一个Model"
END IF
 
DIM fldr
SET Fldr = ActiveDiagram.Parent
 
DIM isMerage '是否需要合并表名称单元格
DIM isMulite 
isMulite = FALSE '是否不同的Package不同的sheet
DIM RQ
 
'RQ = MsgBox ("是否不同的Package不同的sheet?", vbYesNo + vbInformation,"确认")
'IF RQ= VbYes THEN
' isMulite= TRUE
'ELSE
' isMulite= FALSE
'END IF
 
' 创建新的Excel
DIM x1  '
SET x1 = CreateObject("Excel.Application")
x1.Workbooks.Add
x1.Visible = TRUE
 
ExportModelToExcel( fldr)
 
MsgBox "成功将 Models 导出到Excel中!"
 
'--------------------------------------------------------------------------------
'功能函数:将模型导出到Sheet页【 MODEL 】
'--------------------------------------------------------------------------------
PRIVATE FUNCTION ExportModelToExcel(folder)
    '如果是每个package导出到不同的sheet页面,则采用folder的名称作为sheet页名称,否则使用"MODEL"作为sheet页名称
  IF isMulite THEN
    IF folder.Tables.count>0 THEN
	  AddExcelSheet(folder.name)
    END IF
  ELSE
    AddExcelSheet("MODEL")		
  END IF
  '写sheet页的第一行表头
  WriteExcelModelHead
 
  DIM nStart
  DIM nEnd
 
  DIM tabobj '定义数据表对象
  
  nb=2
  isMerage=TRUE
  '开始循环处理所有的folder
  FOR EACH tabobj IN folder.Tables
    IF NOT tabobj.isShortcut THEN '快捷方式不处理
	  '合并表的单元格A、B、C
      IF isMerage THEN  '合并表的单元格A、B、C
        nStart=nb '合并起始行
        nEnd=nb+tabobj.Columns.count-1 '合并结束行
		IF nStart<>nEnd THEN
          '合并单元格
          x1.Range(CELL_A+CSTR(nStart)+":"+CELL_A+CSTR(nEnd)).SELECT
          x1.Selection.Merge
          x1.Range(CELL_B+CSTR(nStart)+":"+CELL_B+CSTR(nEnd)).SELECT
          x1.Selection.Merge
		END IF
 
        '将主题域、表名称、表注释填写到合并后单元格中
        x1.Range(CELL_A+CSTR(nb)).Value = folder.name   '主题域
        x1.Range(CELL_B+CSTR(nb)).Value = Rtf2Ascii(tabobj.description)   '表注释
      END IF
 
      '开始循环列兵输出信息
      DIM colobj '定义列对象
      FOR EACH colobj IN tabobj.Columns
		'写表的信息
        x1.Range(CELL_C+CSTR(nb)).Value = tabobj.code    '表英文名称
        x1.Range(CELL_D+CSTR(nb)).Value = tabobj.name    '表英文名称
		
        '写列的信息
        x1.Range(CELL_E+CSTR(nb)).Value = colobj.code    '列名
        x1.Range(CELL_F+CSTR(nb)).Value = colobj.name    '列中文名称
		x1.Range(CELL_G+CSTR(nb)).Value = Rtf2Ascii(colobj.Description) '列注释
        x1.Range(CELL_H+CSTR(nb)).Value = colobj.DataType    '数据类型
		
        '列是否主键,如果是主键,则输出 Y
        IF colobj.primary THEN
          x1.Range(CELL_I+CSTR(nb)).Value = "Y"
        END IF
		
		'补充是否为空、默认值两列   Modify By Aikes
		'列是否允许为空,则输出 Y
        IF colobj.Mandatory THEN
          x1.Range(CELL_J+CSTR(nb)).Value = "Y"
        END IF
		
		x1.Range(CELL_K+CSTR(nb)).Value = colobj.DefaultValue    '默认值
		
        nb = nb+1  '行号加1
      NEXT
    END IF
  NEXT
 
  '对子包进行递归,如果不使用递归只能取到第一个模型图内的表
  DIM subfolder
  FOR EACH subfolder IN folder.Packages
    ExportModelToExcel(subfolder) 
  NEXT
 
END FUNCTION
 
'--------------------------------------------------------------------------------
'功能函数:添加一个Sheet页
'--------------------------------------------------------------------------------
PRIVATE SUB AddExcelSheet(sheetname)
  x1.Sheets.Add
  x1.ActiveSheet.Name=sheetname
END SUB
 
'--------------------------------------------------------------------------------
'功能函数:写Excel的第一行信息
'--------------------------------------------------------------------------------
PRIVATE SUB WriteExcelModelHead()
   x1.Range(CELL_A+"1").Value = "主题域"
   x1.Range(CELL_B+"1").Value = "表注释"
   x1.Range(CELL_C+"1").Value = "表英文名称"
   x1.Range(CELL_D+"1").Value = "表中文名称"
   x1.Range(CELL_E+"1").Value = "列名"
   x1.Range(CELL_F+"1").Value = "列中文名称"
   x1.Range(CELL_G+"1").Value = "列注释"
   x1.Range(CELL_H+"1").Value = "数据类型"
   x1.Range(CELL_I+"1").Value = "主键"
   x1.Range(CELL_J+"1").Value = "是否为空"
   x1.Range(CELL_K+"1").Value = "默认值"
   
   '设置字体
   x1.Columns(CELL_A+":"+CELL_K).SELECT
   WITH x1.Selection.Font
        .Name = "宋体"
        .Size = 10
   END WITH
 
   '设置首行可过滤,背景颜色为灰色,字体粗体
   x1.Range(CELL_A+"1:"+CELL_K+"1").SELECT
   x1.Selection.AutoFilter
   x1.Selection.Interior.ColorIndex = 15
   x1.Selection.Font.Bold = TRUE
   '设定首行固定
   x1.Range(CELL_A+"2").SELECT
   x1.ActiveWindow.FreezePanes = TRUE
 
END SUB

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aikes902

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值