楼主 apolloh |
让我们接着上文介绍,继续丰富已开发的应用程序。 下面,让应用程序执行更丰富的计算。例如,可能想计算一定范围内的抵押值,而不是单个值,以便为客户提供多种选择。在上例中,我们能够指导用户输入不同的值,执行相同的计算多次,然而这种方式往往会花费很多时间。因此,需要使用不同的方法使应用程序更好的执行任务。 较好的解决方案是使用对话框来输入计算范围,而使用对话框启动器来访问对话框。添加了对话框启动器的新界面如下图。
相应的XML代码如下:
- <dialogBoxLauncher>
- <button id="RedundantCalcsLaunch"
- screentip="多重计算"
- supertip="多次执行同一公式的计算."
- onAction="DisplayRedundantCalc"/>
- </dialogBoxLauncher>
要实现本例的功能,需要: 为每个等式创建不同的对话框,需要创建3个对话框。代码必须区分不同的等式。任何用于与用户交互的对话框需要与功能区中的信息相链接,功能区控件同样需要从对话框中更新。代码对所需的ThisAddIn方法作多次调用,填充单元格区域中的单元格。取决于你的需求,可以提供额外的信息,例如列标题和行标题,使输出更易理解。设计对话框 本例限定用户选择两个范围,这样可以在表中显示输出。设计的“选择贷款范围”窗体如下图所示。
“选择年金范围”窗体设计如下图所示。
“选择有效利率范围”窗体设计如下图所示。
注:设计功能区的目的是减少复杂性。如果由于一些多余的设计选择而增加了更多的复杂性,那么用户将不会感受到使用功能区的任何好处。 创建计算代码 执行一次或多次计算实质上是相同的,但稍有不同。代码如下: [/code] ' 计算贷款金额并包括位置数据 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[/code]
可以将上述代码与前文中相应的示例代码比较。最大的不同在于,添加了两个额外的位置参数,使得可以在任何位置放置输出的值。 定义对现有数据的链接 为功能区应用程序创建对话框时,需要创建对话框与合适的功能区控件的链接,否则两个元素将不同步并且应用程序会显示错误的数据。要创建链接,需要: 从功能区中获取信息在功能区中设置信息在XML中定义需要的回调创建链接的XML代码如下:
- <editBox id="Rate"
- label="有效利率"
- onChange="GetRateText"
- getText="SetRateText"/>
- <dropDown id="Term"
- label="期数"
- getVisible="TermVisible"
- getItemCount="TermCount"
- getItemID="TermItemID"
- getItemLabel="TermItemLabel"
- onAction="GetSelectedTerm"
- getSelectedItemIndex="SetSelectedTerm"/>
- <editBox id="Payment"
- label="期初支付"
- getVisible="PaymentVisible"
- onChange="GetPaymentText"
- getText="SetPaymentText"/>
- <editBox id="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
现在,一切准备就绪。运行代码,在窗体中选择区域,输入相应数据,得到的输出结果如下图所示。
|