# Python 企业版工具方法速查

## 目录

| 章节 | 内容 |
|------|------|
| [一、读取单据数据包](#一读取单据数据包) | MetaDataServiceHelper / BusinessDataServiceHelper.Load / QueryServiceHelper |
| [二、保存/提交/审核单据](#二保存提交审核单据) | Save / Submit / Audit / DoNothing |
| [三、插件构建新单据](#三插件构建新单据) | 空白数据包法 / View 法 |
| [四、数据库操作](#四数据库操作) | ExecuteDataSet / ExecuteDynamicObject / Execute / ExecuteBatch / ExecuteStoreProcedure |
| [五、其他工具类](#五其他工具类) | 系统参数 / 用户参数 / 权限检查 |

---

## 一、读取单据数据包

### 引用

```python
clr.AddReference('Kingdee.BOS.ServiceHelper')
from Kingdee.BOS.ServiceHelper import *
clr.AddReference('Kingdee.BOS.Core')
from Kingdee.BOS.Core.SqlBuilder import *
from Kingdee.BOS.Core.Metadata import*
```

### MetaDataServiceHelper — 读取元数据

```python
formID = "PUR_PurchaseOrder"
meta = MetaDataServiceHelper.Load(this.Context, formID)                 # 读取单据元数据
meta2 = MetaDataServiceHelper.GetFormMetaData(this.Context, formID)     # 同上，另一种方法
```

### BusinessDataServiceHelper — 读取单据完整数据包

```python
pkIds = List[object]()
pkIds.Add(10001)

objType = meta.BusinessInfo.GetDynamicObjectType()      # 获取单据数据包对象类型

# 注意：修改基础资料字段时，不能用 GetDynamicObjectType()
# 应该用字段的 RefFormDynamicObjectType
# baseFld = this.BusinessInfo.GetField("字段标识")
# objType = baseFld.RefFormDynamicObjectType

# 读取多个单据
billObjs = BusinessDataServiceHelper.Load(this.Context, pkIds.ToArray(), objType)
# 读取单个单据
obj = BusinessDataServiceHelper.LoadSingle(this.Context, "10001", objType)
```

### QueryServiceHelper — 按需读取字段

```python
queryParam = QueryBuilderParemeter()
queryParam.FormId = formID
queryParam.BusinessInfo = meta.BusinessInfo

# 加入需要的字段
queryParam.SelectItems.Add(SelectorItemInfo(meta.BusinessInfo.GetForm().PkFieldName))  # 单据内码
queryParam.SelectItems.Add(SelectorItemInfo("FBillNo"))            # 单据编号
queryParam.SelectItems.Add(SelectorItemInfo("FSupplierId"))        # 供应商内码

# 取基础资料属性字段（写法特殊）
supplierName = SelectorRefItemInfo("FSupplierId.FName")
supplierName.PropertyName = "FSupplierId_FName"    # 字段名不能有"."，用"_"代替
queryParam.SelectItems.Add(supplierName)

# 设置过滤条件
entity = meta.BusinessInfo.GetEntity("单据体标识")
queryParam.FilterClauseWihtKey = "{0}_{1}={2}".format(entity.Key, entity.EntryPkFieldName, entryId)

# 执行查询
dataRows = QueryServiceHelper.GetDynamicObjectCollection(this.Context, queryParam)
for r in dataRows:
    billNoValue = r["BillNo"]  # PropertyName
```

## 二、保存/提交/审核单据

### 引用

```python
clr.AddReference('Kingdee.BOS')
from Kingdee.BOS.Orm.DataEntity import *
```

### Save — 保存

```python
ObjList = List[DynamicObject]()
ObjList.Add(billObjs[0])
# 传入操作代码"Save"，调用操作列表中操作类型=保存的操作
saveRslt = BusinessDataServiceHelper.Save(this.Context, meta.BusinessInfo, ObjList.ToArray(), None, "Save")

if saveRslt.IsShowMessage:
    OperationResultExt.MergeValidateErrors(saveRslt)
    for rst in saveRslt.OperateResult:
        msg = "{0}\r\n{1}".format(msg, rst.Message)
```

### Submit — 提交（不触发审批流）

```python
if saveRslt.SuccessDataEnity is not None:
    ids = List[object]()
    for newBillObj in saveResult.SuccessDataEnity:
        ids.Add(newBillObj["Id"])
    subRslt = BusinessDataServiceHelper.Submit(this.Context, meta.BusinessInfo, ids.ToArray(), "Submit", None)
```

### Audit — 审核

```python
if subRslt.IsSuccess:
    BusinessDataServiceHelper.Audit(this.Context, meta.BusinessInfo, ids.ToArray(), None)
```

### DoNothing — 空操作（可用于触发自动下推等）

```python
optCode = "DoNothing-AutoPush"    # 自定义空操作代码
PkIds = List[object]()
PkIds.Add("10001")
BusinessDataServiceHelper.DoNothing(this.Context, meta.BusinessInfo, PkIds.ToArray(), optCode, None)
```

## 三、插件构建新单据

### 方法①：构建空白数据包 → Save（不会触发界面服务）

```python
formID = "FIN_OTHERS"
meta = MetaDataServiceHelper.GetFormMetaData(this.Context, formID)
objType = meta.BusinessInfo.GetDynamicObjectType()

# 创建空白数据包
billObj = DynamicObject(objType)
billObj["Number"] = "Test001"
billObj["Name"] = "测试其他往来单位"

# 组织赋值
orgMeta = MetaDataServiceHelper.Load(this.Context, "ORG_Organizations")
orgId = "1"
createOrgFld = meta.BusinessInfo.GetField("FCreateOrgId")
useOrgFld = meta.BusinessInfo.GetField("FUseOrgId")
createOrgObj = BusinessDataServiceHelper.LoadSingle(this.Context, orgId, createOrgFld.RefFormDynamicObjectType)
useOrgObj = BusinessDataServiceHelper.LoadSingle(this.Context, orgId, useOrgFld.RefFormDynamicObjectType)
billObj["CreateOrgId"] = createOrgObj
billObj["CreateOrgId_Id"] = orgId
billObj["UseOrgId"] = useOrgObj
billObj["UseOrgId_Id"] = orgId

# 保存
saveList = List[DynamicObject]()
saveList.Add(billObj)
saveRslt = BusinessDataServiceHelper.Save(this.Context, meta.BusinessInfo, saveList.ToArray(), None, "Save")
```

### 方法②：构建 View → 操作数据包（会触发界面服务）

```python
clr.AddReference('Kingdee.BOS.Core')
clr.AddReference('Kingdee.BOS.ServiceHelper')
from Kingdee.BOS.Core.Metadata import *
from Kingdee.BOS.Core.Metadata.FormElement import *
from Kingdee.BOS.Core.Bill import *
from Kingdee.BOS.Core.DynamicForm import *
from Kingdee.BOS.Core.DynamicForm.PlugIn import *
from Kingdee.BOS.Core.DynamicForm.PlugIn.Args import *
from Kingdee.BOS.Core.DependencyRules import *   # 触发实体服务规则需要

def CreateOpenParameter(meta, ctx, billId):
    form = meta.BusinessInfo.GetForm()
    openParam = BillOpenParameter(form.Id, meta.GetLayoutInfo().Id)
    openParam.Context = ctx
    openParam.ServiceName = form.FormServiceName
    openParam.PageId = Guid.NewGuid().ToString()
    openParam.FormMetaData = meta
    openParam.Status = OperationStatus.ADDNEW if billId is None else OperationStatus.EDIT
    if billId is not None:
        openParam.PkValue = billId
    openParam.CreateFrom = CreateFrom.Default
    openParam.DefaultBillTypeId = ""
    openParam.SetCustomParameter("ShowConfirmDialogWhenChangeOrg", False)
    plugs = form.CreateFormPlugIns()
    openParam.SetCustomParameter(FormConst.PlugIns, plugs)
    args = PreOpenFormEventArgs(ctx, openParam)
    for plug in plugs:
        plug.PreOpenForm(args)
    return openParam

def CreateBillView(ctx, formId, billId):
    meta = MetaDataServiceHelper.Load(ctx, formId)
    tp = Type.GetType("Kingdee.BOS.Web.Import.ImportBillView,Kingdee.BOS.Web")
    billView = Activator.CreateInstance(tp)
    openParam = CreateOpenParameter(meta, ctx, billId)
    provider = meta.BusinessInfo.GetForm().GetFormServiceProvider()
    billView.Initialize(openParam, provider)
    return billView

def CreateBillObj():
    formID = "ORA_TestBill"
    meta = MetaDataServiceHelper.GetFormMetaData(this.Context, formID)
    billView = CreateBillView(this.Context, formID, None)
    billView.LoadData()
    dv = billView
    dv.SetItemValueByID("F_RBSU_OrgId", orgId, 0)
    dv.UpdateValue("FBillNo", 0, "Test001")
    dv.UpdateValue("F_RBSU_Remark", 0, "测试插件创建")

    newBillObj = billView.Model.DataObject
    entityKey = "FEntity"
    En = newBillObj[entityKey]
    En.Clear()
    i = 0
    billView.Model.CreateNewEntryRow(entityKey)
    dv.UpdateValue("F_RBSU_OrderNo", i, "订单号")
    dv.SetItemValueByID("F_RBSU_MaterialId", "物料ID", i)
    dv.SetItemValueByNumber("F_RBSU_StockId", "仓库编码", i)

    # 触发值更新事件
    dv.InvokeFieldUpdateService("F_RBSU_StockId", i)
    # 触发实体服务规则
    obj = BOSActionExecuteContext(dv)
    dataEntity = En[i]
    dv.RuleContainer.RaiseDataChanged("F_RBSU_MaterialId", dataEntity, obj)

    billView.InvokeFormOperation(FormOperationEnum.Close)
    billView.Close()
    billView.CommitNetworkCtrl()

    newBillList = List[DynamicObject]()
    newBillList.Add(newBillObj)
    saveRslt = BusinessDataServiceHelper.Save(this.Context, meta.BusinessInfo, newBillList.ToArray(), None, "Save")
    return newBillObj
```

## 四、数据库操作

### 引用

```python
clr.AddReference('System.Data')
clr.AddReference('Kingdee.BOS')
clr.AddReference('Kingdee.BOS.App')
from System.Data import *
from Kingdee.BOS import *
from Kingdee.BOS.App.Data import *
```

### SQL 拼接注意
`/*dialect*/` 为方言标识，前面不能有空格。没有方言标识的 SQL 必须满足 KSQL 语法。

```python
orgSQL = """/*dialect*/select org.FNUMBER, orgL.FNAME
from T_ORG_organizations org
inner join T_ORG_organizations_L orgL on org.FORGID = orgL.FORGID and orgL.FLocalEId = 2052
where OrgId = '{0}'""".format("1")
```

### ExecuteDataSet — 返回 DataSet

```python
ds = DBUtils.ExecuteDataSet(this.Context, orgSQL)
tab = ds.Tables[0]
for dr in tab.Rows:
    orgNum = dr["FNUMBER"]
    orgName = dr["FNAME"]
```

### ExecuteDynamicObject — 返回 DynamicObjectCollection

```python
dataRows = DBUtils.ExecuteDynamicObject(this.Context, orgSQL)
for dr in dataRows:
    orgNum = dr["FNUMBER"]
    orgName = dr["FNAME"]
```

### Execute — 执行更新，返回受影响行数

```python
updateSql = """/*dialect*/update T_ORG_organizations set FNUMBER='testOrg001' where OrgId='{0}'""".format("1")
x = DBUtils.Execute(this.Context, updateSql)
```

### ExecuteBatch — 批量执行

```python
sqlList = List[str]()
sqlList.Add(updateSql)
if sqlList.Count > 0:
    DBUtils.ExecuteBatch(this.Context, sqlList, sqlList.Count)
```

### ExecuteStoreProcedure — 执行存储过程

```python
ProcName = "Proc_SimpleReport_BillA"
lstParam = List[SqlParam]()
lstParam.Add(SqlParam("@P1", KDDbType.AnsiString, "AAA"))
lstParam.Add(SqlParam("@P2", KDDbType.AnsiString, "BBB"))
resutParas = DBUtils.ExecuteStoreProcedure(this.Context, ProcName, lstParam)
for dr in resutParas:
    paraName = dr.Name
    paraValue = dr.Value
```

## 五、其他工具类

### 读取系统参数

```python
clr.AddReference('Kingdee.BOS.App.Core')
from Kingdee.BOS.App.Core import *

orgs = List[Int64]()
orgs.Add(Int64.Parse("1"))
sysParaFormId = "XXX"       # 系统参数单据 FormId
paraName = "参数字段标识"    # 使用绑定实体属性标识

# 批量读取多个组织的参数（字典返回，orgId 为 key）
sysParaObjs = SystemParameterServiceHelper.GetParamter(this.Context, orgs, 0, sysParaFormId, paraName)
sysParaObj = sysParaObjs[orgId]

# 读取单个组织的参数
sysParaObj = SystemParameterServiceHelper.GetParamter(this.Context, orgId, 0, sysParaFormId, paraName)
```

### 读取用户选项参数

```python
formID = "PUR_PurchaseOrder"
meta = MetaDataServiceHelper.Load(this.Context, formID)
paraObjFormId = meta.BusinessInfo.GetForm().ParameterObjectId
formMeta = FormMetaDataCache.GetCachedFormMetaData(this.Context, paraObjFormId)

UserParaObj = UserParamterServiceHelper.Load(this.Context, formMeta.BusinessInfo,
    this.Context.UserId, paraObjFormId, "UserParameter")
# 修改后可保存
UserParamterServiceHelper.Save(this.Context, formMeta.BusinessInfo,
    UserParaObj, paraObjFormId, this.Context.UserId, "UserParameter")
```

### 权限检查

```python
clr.AddReference('Kingdee.BOS.Core')
from Kingdee.BOS.Core.Permission import *

businessObj = BusinessObject()
businessObj.Id = "PUR_PurchaseOrder"    # 单据 FormId
# 权限项 ID 查询：select a.FItemID from T_SEC_PermissionItem a where a.FNumber='BOS_AUDIT'
permissionItemId = "权限项ID"
iResult = PermissionServiceHelper.FuncPermissionAuth(this.Context, businessObj, permissionItemId)
if not iResult.Passed:
    raise Exception("对不起，您没有权限!")
```