Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 仅根据请求重新计算自定义VBA函数_Excel_Vba_Oledb_User Defined Functions_Commandbutton - Fatal编程技术网

Excel 仅根据请求重新计算自定义VBA函数

Excel 仅根据请求重新计算自定义VBA函数,excel,vba,oledb,user-defined-functions,commandbutton,Excel,Vba,Oledb,User Defined Functions,Commandbutton,我的问题是: 我希望在电子表格中使用自定义功能区命令按钮或甚至简单的命令按钮来初始化OLEDB数据库连接,并更新/重新计算所有需要此类连接的关联用户定义函数,或我指定的函数。我不希望这些函数中的任何函数重新计算,除非单击特定按钮。我很难弄明白怎么做。请提供您的帮助或建议 有关我所做工作的详细信息,请参见下文: 我目前将数据存储在access数据库中,在excel中使用vba进行特定查询。我将每个datarequest例程嵌入到名为[fnc]的模块下的一组函数中。然后,我从excel电子表格中以用

我的问题是:

我希望在电子表格中使用自定义功能区命令按钮或甚至简单的命令按钮来初始化OLEDB数据库连接,并更新/重新计算所有需要此类连接的关联用户定义函数,或我指定的函数。我不希望这些函数中的任何函数重新计算,除非单击特定按钮。我很难弄明白怎么做。请提供您的帮助或建议

有关我所做工作的详细信息,请参见下文:

我目前将数据存储在access数据库中,在excel中使用vba进行特定查询。我将每个datarequest例程嵌入到名为[fnc]的模块下的一组函数中。然后,我从excel电子表格中以用户定义函数的形式访问它们。此处给出了一个示例:

 Function ValueV(mm As String, yy As String, qtable As String, qcode As String, compare_period As Integer, average_period As Integer, weight As Boolean) As Variant
 'Month Value Formula for Horizontal Data
 'mm - month value 2-digit
 'yy - year value 4-digit
 'qtable - query table name eg. "cpia"
 'qcode - query code for variable eg. "all0100"
 'avgperiod - lag periods to average in calculation eg. 3-avgperiods for quarterly measure, 1-avgperiod for point measure.
 'weight - boolean (true or false) value for weighting values given reference weight. Currently unsupported. Code should be extended to include this feature. (space holder for now)
  Dim lag_value As Variant
  Dim cur_value As Variant
  lag_value = 0
  cur_value = 0


     'STEP-A: Gets the initial Value average or not.
     '===============================================================
     If compare_period > 0 Then
     'Use this step to pickup initial value when compare_period <> 0 which requires a % change as opposed to a point value.
     'Average_period must be greater than or equal to one (1). One (1) represents the current month which is the same as a point value.
         lmm = fnc.lagdate(mm, yy, compare_period, "mm")                          'lag month (a single month for mValueH)
         lyy = fnc.lagdate(mm, yy, compare_period, "yy")                          'lag year (a single month for mValueH)
         smm = fnc.lagdate(mm, yy, compare_period + average_period - 1, "mm")     'dating backwards to account for average period
         syy = fnc.lagdate(mm, yy, compare_period + average_period - 1, "yy")     'dating backwards to account for average period
         'note, for smm & syy, the average period includes the lmm so we add back one (1)
         'eg. 3-mth average is not 3-lags but current and 2-lags.
         sdate1 = syy & fnc.numtext(smm)
         'start date for query (begining of lag value including average period)

         Set MyRecordset = New ADODB.Recordset
         MySql = sql.sqlVSers(lmm, lyy, qtable, qcode, sdate1)
         'MsgBox (MySql)
         MyRecordset.Open MySql, MyConnect, adOpenStatic, adLockReadOnly

         Do Until MyRecordset.EOF     'Loop to end and enter required values
         lag_value = lag_value + MyRecordset(qcode)
         MyRecordset.MoveNext
         Loop
         'Stop
         lag_value = lag_value / average_period
         MyRecordset.Close
     End If


     'STEP-B: Gets the current Value average or not.
     '===============================================================
         smm = fnc.lagdate(mm, yy, average_period - 1, "mm")           'dating backwards to account for average period
         syy = fnc.lagdate(mm, yy, average_period - 1, "yy")           'dating backwards to account for average period
         sdate1 = syy & fnc.numtext(smm)
         'start date for query (begining of lag value including average period)

         Set MyRecordset = New ADODB.Recordset
         MySql = sql.sqlVSers(mm, yy, qtable, qcode, sdate1)
         MyRecordset.Open MySql, MyConnect, adOpenStatic, adLockReadOnly

         Do Until MyRecordset.EOF     'Loop to end and enter required values
         cur_value = cur_value + MyRecordset(qcode)
         MyRecordset.MoveNext
         Loop

         cur_value = cur_value / average_period
         MyRecordset.Close


     'STEP-C: Calculates the Requested % Change or Point Value.
     '===============================================================
     If compare_period = 0 Then
         ValueV = cur_value
     Else
         ValueV = cur_value / lag_value * 100 - 100
     End If

 End Function
函数ValueV(mm为字符串,yy为字符串,qtable为字符串,qcode为字符串,compare_period为整数,average_period为整数,weight为布尔值)作为变量
'水平数据的月值公式
'mm-月份值2位
'年-年值4位
'qtable-查询表名称,例如“cpia”
'qcode-变量的查询代码,例如“all0100”
'平均周期-计算中的平均滞后期,例如季度测量为3-平均周期,点测量为1-平均周期。
'权重-给定参考权重的权重值的布尔值(真或假)。目前不支持。应扩展代码以包含此功能。(暂时保留空格)
作为变量的Dim lag_值
Dim cur_值作为变量
滞后值=0
cur_值=0
'步骤A:获取初始值是否为平均值。
'===============================================================
如果比较周期>0,则
'当比较周期0时,使用此步骤拾取初始值,该周期需要与点值相对的%变化。
'平均_周期必须大于或等于一(1)。一(1)表示与分值相同的当前月份。
lmm=fnc.lagdate(mm,yy,比较周期,“mm”)滞后月(Mvalue为一个月)
lyy=fnc.滞后日期(mm,yy,比较周期,“yy”)'滞后年(mValueH为一个月)
smm=fnc.lagdate(mm,yy,比较周期+平均周期-1,“mm”)追溯到平均周期
syy=fnc.lagdate(mm,yy,比较周期+平均周期-1,“yy”)追溯到平均周期
注意,对于smm&syy,平均周期包括lmm,因此我们加回一(1)
“例如,3个月的平均值不是3个滞后,而是当前和2个滞后。
sdate1=syy&fnc.numtext(smm)
'查询的开始日期(滞后值的开始,包括平均周期)
Set MyRecordset=New ADODB.Recordset
MySql=sql.sqlVSers(lmm、lyy、qtable、qcode、sdate1)
'MsgBox(MySql)
MyRecordset.Open MySql、MyConnect、adOpenStatic、adLockReadOnly
直到MyRecordset.EOF'循环结束并输入所需的值
滞后值=滞后值+我的记录集(qcode)
MyRecordset.MoveNext
环
“停
滞后值=滞后值/平均周期
我的记录集。关闭
如果结束
'步骤B:获取当前值是否为平均值。
'===============================================================
smm=fnc.lagdate(mm,yy,平均周期-1,“mm”)追溯到平均周期
syy=fnc.lagdate(mm,yy,平均周期-1,“yy”)'追溯到平均周期
sdate1=syy&fnc.numtext(smm)
'查询的开始日期(滞后值的开始,包括平均周期)
Set MyRecordset=New ADODB.Recordset
MySql=sql.sqlVSers(mm,yy,qtable,qcode,sdate1)
MyRecordset.Open MySql、MyConnect、adOpenStatic、adLockReadOnly
直到MyRecordset.EOF'循环结束并输入所需的值
cur_值=cur_值+MyRecordset(qcode)
MyRecordset.MoveNext
环
电流值=电流值/平均周期
我的记录集。关闭
'步骤C:计算请求的%更改或分值。
'===============================================================
如果比较周期=0,则
ValueV=当前值
其他的
ValueV=当前值/滞后值*100-100
如果结束
端函数
由于我完全绕过了子例程的使用,到数据库的连接目前是作为工作簿助手例程完成的,如下所示

Private Sub Workbook_AfterSave(ByVal Success As Boolean)
Dim filePath
filePath = ThisWorkbook.Path
If Right$(filePath, 1) <> "\" Then filePath = filePath & "\"
MyConnect = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & filePath & "rsdata.accdb;"
End Sub
Private子工作簿_AfterSave(ByVal Success作为布尔值)
暗文件路径
filePath=ThisWorkbook.Path
如果右$(filePath,1)“\”则filePath=filePath&“\”
MyConnect=“Provider=Microsoft.ACE.OLEDB.12.0;”_
“数据源=”&filePath&“rsdata.accdb;”
端接头
问题是,这个更新过程不太理想。理想情况下,我想在菜单栏中放置一个自定义按钮(单击它时),该按钮将连接到数据库并重新计算给定工作表或工作簿中使用的所有用户定义函数

请提供您的建议,或者指出以前在哪里做过类似的事情

提前谢谢。
JR.

您正试图将
UDF
用于他们不打算做的事情。设计它们的目的是使其行为与其他单元格公式一样,并在Excel决定需要时进行计算

你有两个选择

  • 重新设计应用程序,使其不使用
    UDF
    (IMO是最好的方法)
  • 修改您的
    UDF
    s,使其仅对您指定的触发器作出响应,例如单击按钮(我认为这是一个错误的想法)

如何重新设计以避免
UDF
,取决于您的OP中未披露的因素

您正在尝试使用
UDF