细品RibbonX(56):使用Visual Studio开发Excel商务应用程序(2)
资料整理来自于论坛
完整版下载地址:http://download.csdn.net/download/nodeman/10264659
Loading ...
让我们接着上文介绍,继续丰富已开发的应用程序。
下面,让应用程序执行更丰富的计算。例如,可能想计算一定范围内的抵押值,而不是单个值,以便为客户提供多种选择。在上例中,我们能够指导用户输入不同的值,执行相同的计算多次,然而这种方式往往会花费很多时间。因此,需要使用不同的方法使应用程序更好的执行任务。
较好的解决方案是使用对话框来输入计算范围,而使用对话框启动器来访问对话框。添加了对话框启动器的新界面如下图。
相应的XML代码如下:
<dialogBoxLauncher>
<buttonid="RedundantCalcsLaunch"
screentip="多重计算"
supertip="多次执行同一公式的计算."
onAction="DisplayRedundantCalc"/>
</dialogBoxLauncher>
要实现本例的功能,需要:
- 为每个等式创建不同的对话框,需要创建3个对话框。
- 代码必须区分不同的等式。
- 任何用于与用户交互的对话框需要与功能区中的信息相链接,功能区控件同样需要从对话框中更新。
- 代码对所需的ThisAddIn方法作多次调用,填充单元格区域中的单元格。
- 取决于你的需求,可以提供额外的信息,例如列标题和行标题,使输出更易理解。
设计对话框
本例限定用户选择两个范围,这样可以在表中显示输出。设计的“选择贷款范围”窗体如下图所示。
“选择年金范围”窗体设计如下图所示。
“选择有效利率范围”窗体设计如下图所示。
注:设计功能区的目的是减少复杂性。如果由于一些多余的设计选择而增加了更多的复杂性,那么用户将不会感受到使用功能区的任何好处。
创建计算代码
执行一次或多次计算实质上是相同的,但稍有不同。代码如下:
' 计算贷款金额并包括位置数据
Public Sub CalculatePMT(ByVal Rate As Double, ByVal NPer As Int32, ByVal PV As Int32, ByVal X As Int32, ByVal Y As Int32)
' 计算利率.
Dim PeriodicRate As Double = (Rate / 100) / 12
' 计算期数.
Dim Periods As Int32 = NPer * 12
' 执行计算.
Application.ActiveWindow.ActiveCell.Cells(X, Y) = _
"=PMT(" + PeriodicRate.ToString() + "," + _
Periods.ToString() + "," + PV.ToString() + ",0,0)"
Application.ActiveWindow.ActiveCell.Calculate()
End Sub
' 计算年金金额并包括位置数据.
Public Sub CalculateFV(ByVal Rate As Double, ByVal NPer As Int32, ByVal PMT As Int32, ByVal PV As Int32, ByVal X As Int32, ByVal Y As Int32)
' 计算利率.
Dim PeriodicRate As Double = (Rate / 100) / 12
' 计算期数.
Dim Periods As Int32 = NPer * 12
' 执行计算.
Application.ActiveWindow.ActiveCell.Cells(X, Y) = _
"=FV(" + PeriodicRate.ToString() + "," + _
Periods.ToString() + "," + PMT.ToString() + "," + _
PV.ToString() + ",0)"
Application.ActiveWindow.ActiveCell.Calculate()
End Sub
' 计算有效利率并包括数据位置.
Public Sub CalculateEFFECT(ByVal Rate As Double, ByVal X As Int32, ByVal Y As Int32)
' 计算利率.
Dim PeriodicRate As Double = (Rate / 100) / 12
' 执行计算.
Application.ActiveWindow.ActiveCell.Cells(X, Y) = _
"=EFFECT(" + PeriodicRate.ToString() + ",12)"
Application.ActiveWindow.ActiveCell.Calculate()
' 格式单元格.
Dim ThisRange As Excel.Range
ThisRange = Application.Cells(X, Y)
ThisRange.NumberFormat = "0.0000%"
End Sub
可以将上述代码与前文中相应的示例代码比较。最大的不同在于,添加了两个额外的位置参数,使得可以在任何位置放置输出的值。
定义对现有数据的链接
为功能区应用程序创建对话框时,需要创建对话框与合适的功能区控件的链接,否则两个元素将不同步并且应用程序会显示错误的数据。要创建链接,需要:
- 从功能区中获取信息
- 在功能区中设置信息
- 在XML中定义需要的回调
创建链接的XML代码如下:
<editBoxid="Rate"
label="有效利率"
onChange="GetRateText"
getText="SetRateText"/>
<dropDownid="Term"
label="期数"
getVisible="TermVisible"
getItemCount="TermCount"
getItemID="TermItemID"
getItemLabel="TermItemLabel"
onAction="GetSelectedTerm"
getSelectedItemIndex="SetSelectedTerm"/>
<editBoxid="Payment"
label="期初支付"
getVisible="PaymentVisible"
onChange="GetPaymentText"
getText="SetPaymentText"/>
<editBoxid="Amount"
getLabel="AmountLabel"
getVisible="AmountVisible"
onChange="GetAmountText"
getText="SetAmountText"/>
用于实现链接的属性取决于控件类型。大多数控件使用getText属性,从应用程序中提取信息并在控件中显示(例如,本例中的文本框);一些控件需要使用其它属性,例如本例中的getSelectedItemIndex属性。回调代码如下:
Public Function SetRateText(ByVal control As Office.IRibbonControl) As String
' 返回Rate变量的当前值.
Return Rate.ToString()
End Function
Public Function SetSelectedTerm(ByVal control As Office.IRibbonControl) As Int32
' 设置贷款项.
If CalcType = "Loan" Then
Select Case Term
Case 10
Return 0
Case 15
Return 1
Case 20
Return 2
Case 30
Return 3
End Select
End If
' 设置年金项.
If CalcType = "Annuity" Then
Select Case Term
Case 5
Return 0
Case 7
Return 1
Case 10
Return 2
Case 15
Return 3
Case 20
Return 4
End Select
End If
' 提供缺省的返回值.
Return 0
End Function
Public Function SetPaymentText(ByVal control As Office.IRibbonControl) As String
' 返回Payment变量的当前值.
Return Payment.ToString()
End Function
Public Function SetAmountText(ByVal control As Office.IRibbonControl) As String
' 返回Amount变量的当前值.
Return Amount.ToString()
End Function
执行更丰富的计算
对话框启动器dialogBoxLauncher仅有一个onAction属性,因此任何计算的开始点都是该属性指向的方法DisplayRedundantCalc。当然,由于每个等式都不相同,因此都需要采用某种方式单独实现调用。
Public Sub DisplayRedundantCalc(ByVal control As Office.IRibbonControl)
' 选择正确的过程.
Select Case CalcType
Case "Loan"
PerformLoanRangeCalc()
Case "Annuity"
PerformAnnuityRangeCalc()
Case "Effective Rate"
PerformEffectiveRateRangeCalc()
End Select
End Sub
代码根据所选择的项目不同,调用不同的对话框计算程序。
Private Sub PerformLoanRangeCalc()
' 创建对话框.
Dim ThisSelection As LoanRangeSelection = New LoanRangeSelection()
' 在对话框中添加已存在的变量.
ThisSelection.txtIntBeg.Text = Rate.ToString()
ThisSelection.txtIntEnd.Text = Rate.ToString()
ThisSelection.txtIntInc.Text = "1"
ThisSelection.cbTermBeg.Text = Term.ToString()
ThisSelection.cbTermEnd.Text = Term.ToString()
ThisSelection.txtLoanAmt.Text = Amount.ToString()
' 显示对话框并且如果用户单击确定则处理数据.
If ThisSelection.ShowDialog() = DialogResult.OK Then
' 转换数据值为Int32egers.
Rate = Int32.Parse(ThisSelection.txtIntBeg.Text)
Term = Int32.Parse(ThisSelection.cbTermBeg.Text)
Amount = Int32.Parse(ThisSelection.txtLoanAmt.Text)
' 创建本地变量,包括计算数据.
Dim EndRate As Int32 = Int32.Parse(ThisSelection.txtIntEnd.Text)
Dim IncRate As Int32 = Int32.Parse(ThisSelection.txtIntInc.Text)
Dim EndTerm As Int32 = Int32.Parse(ThisSelection.cbTermEnd.Text)
' 更新功能区中的值.
ribbon.InvalidateControl("Rate")
ribbon.InvalidateControl("Term")
ribbon.InvalidateControl("Amount")
' 添加初始标题.
Globals.ThisAddIn.SetHeading("利息", 1, 1)
' 执行计算.
Dim i As Int32
For i = Rate To EndRate
' 计算X和Y的位置值.
Dim X As Int32 = i + 2 - Rate
Dim Y As Int32 = 2
' 打印Int32erest利率.
Globals.ThisAddIn.SetHeading(i.ToString() + "%", X, 1)
' 使用一系列if语句确定年设置.
If Term = 10 And EndTerm >= 10 Then
' 执行计算.
Globals.ThisAddIn.CalculatePMT(i, 10, Amount, X, Y)
' 打印标题.
Globals.ThisAddIn.SetHeading("10年", 1, Y)
' 如果已经使用则增加Y.
Y = Y + 1
End If
If Term <= 15 And EndTerm >= 15 Then
' 执行计算.
Globals.ThisAddIn.CalculatePMT(i, 15, Amount, X, Y)
' 打印标题.
Globals.ThisAddIn.SetHeading("15年", 1, Y)
' 如果已经使用则增加Y.
Y = Y + 1
End If
If Term <= 20 And EndTerm >= 20 Then
' 执行计算.
Globals.ThisAddIn.CalculatePMT(i, 20, Amount, X, Y)
' 打印标题.
Globals.ThisAddIn.SetHeading("20年", 1, Y)
' 如果已经使用则增加Y.
Y = Y + 1
End If
If Term <= 30 And EndTerm >= 30 Then
' 执行计算.
Globals.ThisAddIn.CalculatePMT(i, 30, Amount, X, Y)
' 打印标题.
Globals.ThisAddIn.SetHeading("30年", 1, Y)
' 如果已经使用则增加Y.
Y = Y + 1
End If
Next
End If
End Sub
Private Sub PerformAnnuityRangeCalc()
' 创建对话框.
Dim ThisSelection As AnnuityRangeSelection = New AnnuityRangeSelection()
' 在对话框中添加已存在的变量.
ThisSelection.txtIntBeg.Text = Rate.ToString()
ThisSelection.txtIntEnd.Text = Rate.ToString()
ThisSelection.txtIntInc.Text = "1"
ThisSelection.cbTermBeg.Text = Term.ToString()
ThisSelection.cbTermEnd.Text = Term.ToString()
ThisSelection.txtLoanAmt.Text = Amount.ToString()
ThisSelection.txtPayment.Text = Payment.ToString()
' 显示对话框并且如果用户单击确定则处理数据.
If ThisSelection.ShowDialog() = DialogResult.OK Then
' 转换数据值为Int32egers.
Rate = Int32.Parse(ThisSelection.txtIntBeg.Text)
Term = Int32.Parse(ThisSelection.cbTermBeg.Text)
Amount = Int32.Parse(ThisSelection.txtLoanAmt.Text)
Payment = Int32.Parse(ThisSelection.txtPayment.Text)
' 创建本地变量以包含计算数据.
Dim EndRate As Int32 = Int32.Parse(ThisSelection.txtIntEnd.Text)
Dim IncRate As Int32 = Int32.Parse(ThisSelection.txtIntInc.Text)
Dim EndTerm As Int32 = Int32.Parse(ThisSelection.cbTermEnd.Text)
' 更新功能区中的值.
ribbon.InvalidateControl("Rate")
ribbon.InvalidateControl("Term")
ribbon.InvalidateControl("Amount")
ribbon.InvalidateControl("Payment")
' 添加初始标题.
Globals.ThisAddIn.SetHeading("利息", 1, 1)
' 执行计算.
Dim i As Int32
For i = Rate To EndRate
' 计算X和Y的位置值.
Dim X As Int32 = i + 2 - Rate
Dim Y As Int32 = 2
' 打印Int32erest利率.
Globals.ThisAddIn.SetHeading(i.ToString() + "%", X, 1)
' 使用一系列if语句决定年设置.
If Term = 5 And EndTerm >= 5 Then
' 执行计算.
Globals.ThisAddIn.CalculateFV(i, 5, Amount, Payment, X, Y)
' 打印标题.
Globals.ThisAddIn.SetHeading("5年", 1, Y)
' 如果已经使用则增加Y.
Y = Y + 1
End If
If Term <= 7 And EndTerm >= 7 Then
' 执行计算.
Globals.ThisAddIn.CalculateFV(i, 7, Amount, Payment, X, Y)
' 打印标题.
Globals.ThisAddIn.SetHeading("7年", 1, Y)
' 如果已经使用则增加Y.
Y = Y + 1
End If
If Term <= 10 And EndTerm >= 10 Then
' 执行计算.
Globals.ThisAddIn.CalculateFV(i, 10, Amount, Payment, X, Y)
' 打印标题.
Globals.ThisAddIn.SetHeading("10年", 1, Y)
' 如果已经使用则增加Y.
Y = Y + 1
End If
If Term <= 15 And EndTerm >= 15 Then
' 执行计算.
Globals.ThisAddIn.CalculateFV(i, 15, Amount, Payment, X, Y)
' 打印标题.
Globals.ThisAddIn.SetHeading("15年", 1, Y)
' 如果已经使用则增加Y.
Y = Y + 1
End If
If Term <= 20 And EndTerm >= 20 Then
' 执行计算.
Globals.ThisAddIn.CalculateFV(i, 20, Amount, Payment, X, Y)
' 打印标题.
Globals.ThisAddIn.SetHeading("20年", 1, Y)
' 如果已经使用则增加Y.
Y = Y + 1
End If
Next
End If
End Sub
Private Sub PerformEffectiveRateRangeCalc()
' 创建对话框.
Dim ThisSelection As EffectiveRateRangeSelection = New EffectiveRateRangeSelection()
' 在对话框中添加已存在的变量.
ThisSelection.txtIntBeg.Text = Rate.ToString()
ThisSelection.txtIntEnd.Text = Rate.ToString()
ThisSelection.txtIntInc.Text = "1"
' 显示对话框并且如果用户单击确定则处理数据.
If ThisSelection.ShowDialog() = DialogResult.OK Then
' 转换数据值为Int32egers.
Rate = Int32.Parse(ThisSelection.txtIntBeg.Text)
' 创建本地变量以包含计算数据.
Dim EndRate As Int32 = Int32.Parse(ThisSelection.txtIntEnd.Text)
Dim IncRate As Int32 = Int32.Parse(ThisSelection.txtIntInc.Text)
' 更新功能区中的值.
ribbon.InvalidateControl("Rate")
' 添加初始标题.
Globals.ThisAddIn.SetHeading("利息", 1, 1)
Globals.ThisAddIn.SetHeading("有效利率", 1, 2)
' 执行计算.
Dim i As Int32
For i = Rate To EndRate
' 计算X和Y位置值.
Dim X As Int32 = i + 2 - Rate
' 打印Int32erest利率.
Globals.ThisAddIn.SetHeading(i.ToString() + "%", X, 1)
' 执行计算.
Globals.ThisAddIn.CalculateEFFECT(i, X, 2)
Next
End If
End Sub
考虑数据识别需求
对输出结果添加有意义的标题。当执行多重计算时,为使数据意义明确,必须提供标题。代码如下:
Public Sub SetHeading(ByVal Heading As String, ByVal X As Int32, ByVal Y As Int32)
' 添加所需要的标题.
Application.ActiveWindow.ActiveCell.Cells(X, Y) = Heading
End Sub
现在,一切准备就绪。运行代码,在窗体中选择区域,输入相应数据,得到的输出结果如下图所示。