文本概述: 本文描述了在实现汇率获取功能时,对现有方法(C#)的修改和转为Python的过程。作者解释了需要自定义获取二开外汇卖出价汇率的原因,并展示了通过修改SQL查询(使用StringBuilder拼接)来获取汇率的过程。该SQL查询从T_BD_RATE数据表中获取直接汇率或间接汇率,并通过UNION合并两个查询结果。同时,还展示了如何在Python中准备SQL查询参数(使用List[SqlParam]),执行查询,并处理查询结果。最后,给出了Python实现的完整代码示例,包括必要的库引用和函数定义。
当我在实现汇率时,本来可以直接引用
Kingdee.K3.FIN.App.Core中
CommonFunction的
GetExchangeRate(Context ctx, long iCurrencyFromID, long iCurrencyToID, long iRateTypeID, DateTime RateDate)
或是
GetExchangeBusRate(Context ctx, long iCurrencyFromID, long iCurrencyToID, long iRateTypeID, DateTime RateDate)
获取直接汇率
但是我要取一个二开的的外汇卖出价汇率
于是,自己修改了一下他的方法
(主要大头还是把C#转写为python的练习)
参数解释:
Context ctx 上下文
long iCurrencyFromID 目标币别
long iCurrencyToID 本位币别
long iRateTypeID 汇率类型(即期汇率、固定汇率等)
DateTime RateDate 取这个日期的汇率
StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine(string.Format(" select FExchangeRate,FNo=1 from {0} ", "T_BD_RATE")); stringBuilder.AppendLine(" where FForbidderID=0 and FRateTypeID=@RateTypeID "); stringBuilder.AppendLine(" and FCYForID=@CyForID and FCYToID=@CyToID "); stringBuilder.AppendLine(" and FBegDate <= @BegDate and FEndDate >= @EndDate and FFORBIDSTATUS = 'A' and FDOCUMENTSTATUS = 'C' "); stringBuilder.AppendLine(" Union "); stringBuilder.AppendLine(string.Format(" select FExchangeRate=FREVERSEEXRATE,FNo=2 from {0} ", "T_BD_RATE")); stringBuilder.AppendLine(" where FForbidderID=0 and FRateTypeID=@RateTypeID "); stringBuilder.AppendLine(" and FCYForID=@CyToID and FCYToID=@CyForID "); stringBuilder.AppendLine(" and FBegDate <= @BegDate and FEndDate >= @EndDate and FFORBIDSTATUS = 'A' and FDOCUMENTSTATUS = 'C' "); stringBuilder.AppendLine(" order by FNo"); 第一个问题就是,这段SQL代码是什么样意思? 变量解释: FExchangeRate 直接汇率 T_BD_RATE 汇率的数据表 FForbidderID 禁用者ID FRateTypeID 汇率类型 FCYForID 目标汇率币别 (外汇汇率) FCYToID 本位币币别 FBegDate 开始时间 FEndDate 结束时间 FREVERSEEXRATE 间接汇率 FFORBIDSTATUS 禁用状态 FDOCUMENTSTATUS 审核状态 代码解释: 在T_BD_RATE 汇率的数据表 中选出 FExchangeRate 直接汇率 FForbidderID 禁用者ID 为 0 FRateTypeID汇率类型为 @RateTypeID FCYForID目标汇率币别 为 @CyForID 并且 本位币币别为 @CyToID FBegDate 开始时间 小于等于 @BegDate 并且 FEndDate 结束时间 大于等于@EndDate FFORBIDSTATUS 禁用状态 为非禁用 FDOCUMENTSTATUS 审核状态 为 已审核 下一段sql代码基本一致,除了第一句选出的是 FREVERSEEXRATE 间接汇率 这里我并不明白为什么要这么做,再UNION, 我只用第一段SQL代码便可以实现取汇率了
写为python stringBuilder = StringBuilder() 创建一个StringBuilder的类,这里要注意引入clr.AddReference("System") from System.Text import * 这个类是来源于System.Text stringBuilder.AppendLine(" select FPRICE3 FROM T_BD_RATE ") stringBuilder.AppendLine("where FForbidderID=0 and FBEGDATE = @FBegDate ") stringBuilder.AppendLine("and FRATETYPEID = @FRateTypeId ") stringBuilder.AppendLine("and FCYTOID = @FCyToId") stringBuilder.AppendLine("and FCYFORID = @FCyForId and FFORBIDSTATUS = 'A' and FDOCUMENTSTATUS = 'C' ") 这里直接按照他原文照写 , FPRICE3是我需求中的卖出价汇率,各位替换成为自己的字段名
C# List<SqlParam> list = new List<SqlParam>(); list.Add(new SqlParam("@RateTypeID", DbType.Int64, iRateTypeID)); list.Add(new SqlParam("@CyForID", DbType.Int64, iCurrencyFromID)); list.Add(new SqlParam("@CyToID", DbType.Int64, iCurrencyToID)); list.Add(new SqlParam("@BegDate", DbType.DateTime, RateDate.Date)); list.Add(new SqlParam("@EndDate", DbType.DateTime, RateDate.Date)); 这段代码的解释: 创建一个SqlParam类型的List 并且在这个List中添加用于SQL查询的变量 Python List的使用需要 clr.AddReference("System.Collections") from System.Collections.Generic import * SqlParam: clr.AddReference('Kingdee.BOS') from Kingdee.BOS import * DbType: clr.AddReference("System.Data") from System.Data import * list = List[SqlParam]() #重点关注这里,在IronPython中使用中括号的方式声明泛型 list.Add(SqlParam("@FRateTypeId", DbType.Int64, 2)) list.Add(SqlParam("@FBegDate", DbType.DateTime, Date)) list.Add(SqlParam("@FCyToId", DbType.Int64, FRmbId)) list.Add(SqlParam("@FCyForId", DbType.Int64, FCurrencyId))
C# decimal result = 0m; using IDataReader dataReader = DBUtils.ExecuteReader(ctx, stringBuilder.ToString(), list); if (dataReader.Read()) { result = DBReaderUtils.GetValue<decimal>(dataReader, 0); } dataReader.Close(); return result; 代码解释: result是返回结果 使用ExecuteReader执行SQL语句,list是刚刚我么设定好的参数 如果,dataReader.Read()不为空 result结果就是GetValue(dataReader,索引为0) 为何索引为0,因为我们的SQL语句只会取出一个结果,所以固定位0就行 DBUtils引用: clr.AddReference('Kingdee.BOS.App') from Kingdee.BOS.App.Data import * DBReaderUtils引用: clr.AddReference('Kingdee.BOS') from Kingdee.BOS.Util import * Decimal: clr.AddReference("System") from System import * python: dataReader = IDataReader #重点,可以这样为这个接口赋值 dataReader = DBUtils.ExecuteReader(this.Context, stringBuilder.ToString(), list); result = 0.0 #将默认为decimal的值,而不是声明为0时的int值 if dataReader.Read(): result = DBReaderUtils.GetValue[Decimal](dataReader, 0) #重点!使用这种方法来声明泛型的结果 dataReader.Close() return result
整体就结束了,其中的python转换重点就是
StringBuilder stringBuilder = new StringBuilder();
List<SqlParam> list = new List<SqlParam>();
using IDataReader dataReader = DBUtils.ExecuteReader(ctx, stringBuilder.ToString(), list);
result = DBReaderUtils.GetValue<decimal>(dataReader, 0);
python整体代码:
import clr clr.AddReference("System") clr.AddReference("System.Collections") clr.AddReference("System.Data") clr.AddReference('Kingdee.BOS.App') clr.AddReference('Kingdee.BOS') from Kingdee.BOS.App.Data import * from System.Text import * from System import * from System.Collections.Generic import * from Kingdee.BOS import * from System.Data import * from Kingdee.BOS.Util import * #获取汇率 def Exchange(): stringBuilder = StringBuilder() string = String() FCurrency = this.View.Model.GetValue("FSellCurrencyId") #授信币别 if (FCurrency == None): return FCurrencyId = FCurrency["Id"] FRmb = this.View.Model.GetValue("FLocCurrencyId") #本位币 if (FRmb == None): return FRmbId = FRmb["Id"] Date = this.View.Model.GetValue("FSignDate") #日期 if (Date==None): return if FCurrencyId == FRmbId:#本位币等于授信币别的时候 汇率为1 this.Model.SetValue("FDealDateExcRate", 1.0) return stringBuilder.AppendLine(" select FPRICE3 FROM T_BD_RATE ") stringBuilder.AppendLine("where FForbidderID=0 and FBEGDATE = @FBegDate ") stringBuilder.AppendLine("and FRATETYPEID = @FRateTypeId ") stringBuilder.AppendLine("and FCYTOID = @FCyToId") stringBuilder.AppendLine("and FCYFORID = @FCyForId and FFORBIDSTATUS = 'A' and FDOCUMENTSTATUS = 'C' ") list = List[SqlParam]() list.Add(SqlParam("@FRateTypeId", DbType.Int64, 2)) list.Add(SqlParam("@FBegDate", DbType.DateTime, Date)) list.Add(SqlParam("@FCyToId", DbType.Int64, FRmbId)) list.Add(SqlParam("@FCyForId", DbType.Int64, FCurrencyId)) dataReader = IDataReader dataReader = DBUtils.ExecuteReader(this.Context, stringBuilder.ToString(), list); result = 0.0 if dataReader.Read(): result = DBReaderUtils.GetValue[Decimal](dataReader, 0) dataReader.Close() this.View.Model.SetValue("FDealDateExcRate", result) #汇率 this.View.InvokeFieldUpdateService("FDealDateExcRate",0) this.View.UpdateView("FDealDateExcRate") def DataChanged(e): if e.Field.Key.ToString().lower() == "FSignDate".lower(): Exchange() def AfterBindData(e): if this.Model.GetValue("FDealDateExcRate") == 0: Exchange()
如果没有选择日期就更新汇率值,把日期属性中的 立即触发值更新事件 勾选上
推荐阅读