【发布时间】:2014-12-05 15:17:09
【问题描述】:
我有一位使用 Excel 2003 的同事。我在 .xla 插件中为他制作了一些自定义函数。他在加载项中自定义函数的路径问题上遇到了太多麻烦,所以我将自定义函数移到了工作簿中,他根据需要制作了该工作簿的副本。
当我将它发送给他时,从那时起每当我向他发送更新版本时,当他打开工作簿时,他发现所有使用自定义函数的公式都返回 #Value 错误。每次,同一个工作簿对我来说都很好,在 Excel 2003 中也是如此(我也有更高版本的 Excel,但我使用 2003 与他一起工作)。
然后,如果他重新计算,什么都不会发生。我让他尝试对等号进行搜索和替换,这通常会强制受影响的公式重新计算,但没有效果。我们能够让公式再次开始工作的唯一方法是手动激活单元格(F2,或单击公式栏中),然后按 Enter。我尝试了一个 VBA 循环来使用 SendKeys 发送 F2 然后输入,它在一些单元格上工作,但不是全部。
在与他一起工作了一段时间后,一些公式再次起作用,而一些公式仍在返回#Value,我让他保存工作簿并将其发送给我。如果我得到相同的行为,我希望在所有公式中看到#Value。但是相反,我看到对他来说工作正常的公式对我来说工作正常,而为他返回#Value 的公式对我来说也是一样的。因此,当他打开我发送的文件时,无论是什么使它们从正常工作变为返回#Value,对我来说似乎都没有发生,在同一个版本的 Excel 中。
知道为什么会这样吗?有任何故障排除建议吗?
更新:
有人要求我提供一个受影响的自定义函数示例。这是一个,“GetCompanyName”:
Option Explicit
Public Const APP_NAME As String = "Download Financials"
'TABLE NAME:
Public Const TABLE_INCOME_STATEMENT_ANNUAL As String = "_TABLE_INCOME_STATEMENT_ANNUAL_"
Public Const TABLE_BALANCE_SHEET_ANNUAL As String = "_TABLE_BALANCE_SHEET_ANNUAL_"
'LINE ITEM NAME:
Public Const ROW_TOTAL_REVENUE As String = "Total Revenue"
Public Const ROW_GROSS_PROFIT As String = "Gross Profit"
Public Const ROW_OPERATING_INCOME As String = "Operating Income"
'SPECIAL:
Public Const EXCHANGE_SYMBOL As String = "_EXCHANGE_SYMBOL_"
Public Const COMPANY_NAME As String = "_COMPANY_NAME_"
Public Const COMPANY_DESC_SHORT As String = "_COMPANY_DESCRIPTION_SHORT_"
Public Const DESC_SHORT_NA As String = "Short Company Description is not available."
Public Const COMPANY_DESC_LONG As String = "_COMPANY_DESCRIPTION_LONG_"
Public Const DESC_LONG_NA As String = "Long Company Description is not available."
Public Const DATE_ADD_INTERVAL_MINUTE As String = "n" 'm is month.
Public Const DATE_ADD_INTERVAL_SECOND As String = "s"
Public Const WEB_OUTPUT_FILE_NAME As String = "Output"
Public Const COLOR_SOFT_YELLOW As Long = 10092543
Public Const COLOR_DARK_RED As Long = 128
Public Const DOWNLOAD_STATUS_SUCCESS As String = "Success"
Public Const DOWNLOAD_STATUS_FAILURE As String = "Failure"
'shDownloadIndex (worksheet's codename):
Public Const COL_DOWNLOADINDEX_URL As Long = 1
Public Const COL_DOWNLOADINDEX_SHEETNAME As Long = 2
Public Const COL_DOWNLOADINDEX_TIME As Long = 3
Public iRowDownloadIndex As Long
Public rgDownloadIndexCell As Range, strDownloadIndexURL As String
Public wbCurrent As Workbook, shCurrent As Worksheet
Public shDownloadIndex As Worksheet
Public wbWeb As Workbook, shWeb As Worksheet
Public rgColA As Range
Public rgFind As Range
Public rgHeaderIncomeStatement As Range, rgRowHeaderIncomeStatement As Range
Public rgHeaderBalanceSheet As Range, rgRowHeaderBalanceSheet As Range
Public rgExchangeSymbol As Range, rgCompanyName As Range
Public rgDesc As Range, strDesc As String
Public iPosStart As Long, iPosEnd As Long, iPosTmp As Long, iPosCounter As Long, iLen As Long
Public rgTmpRow As Range, shTmpHeader As Range
Public iTmpRow As Long
Public dateLastCall As Date
Public bDownloadInProgress As Boolean
Public bCancelDownload As Boolean
Public Const COL_DOWNLOADINDEX_URL As Long = 1
Public Const COL_DOWNLOADINDEX_SHEETNAME As Long = 2
Public Const COMPANY_NAME As String = "_COMPANY_NAME_"
Public Function GetCompanyName(full_url As String) As Variant
Set wbCurrent = ActiveWorkbook: Set shCurrent = ActiveSheet
Set shDownloadIndex = SetDownloadIndexSheet(shDownloadIndex, wbCurrent, shCurrent)
Set rgDownloadIndexCell = shDownloadIndex.Columns(COL_DOWNLOADINDEX_URL).Find(What:=full_url, LookIn:=xlValues, LookAt:=xlPart, SearchDirection:=xlNext, MatchCase:=False)
strDownloadIndexURL = shDownloadIndex.Cells(rgDownloadIndexCell.Row, COL_DOWNLOADINDEX_SHEETNAME).Value
Set shWeb = wbCurrent.Worksheets(strDownloadIndexURL)
Set rgColA = shWeb.Columns(1).EntireColumn
Set rgFind = rgColA.Find(COMPANY_NAME, rgColA.Cells(1), xlValues, xlWhole, , xlNext, False)
Set rgCompanyName = rgFind.End(xlDown)
GetCompanyName = rgCompanyName.Value
End Function
Public Function SetDownloadIndexSheet(index_sheet As Worksheet, work_book As Workbook, after_sheet As Worksheet) As Worksheet
Dim shTmp As Worksheet, shDownloadIndex As Worksheet
Dim shActiveSheet As Worksheet
Dim bIndexSheetIsBad As Boolean
On Error GoTo CheckingIndexSheet
bIndexSheetIsBad = False 'init.
If Not index_sheet Is Nothing Then
If Not bIndexSheetIsBad Then
If index_sheet.Name = "DownloadIndex" Then
If Not bIndexSheetIsBad Then
Set SetDownloadIndexSheet = index_sheet
Exit Function
End If
End If
End If
End If
On Error GoTo GenErr
For Each shTmp In work_book.Worksheets
If shTmp.Name = "DownloadIndex" Then
Set shDownloadIndex = shTmp
Exit For
End If
Next shTmp
If shDownloadIndex Is Nothing Then
Set shActiveSheet = ActiveSheet
Set shDownloadIndex = work_book.Worksheets.Add(after:=after_sheet)
shDownloadIndex.Name = "DownloadIndex"
shDownloadIndex.Visible = xlSheetVisible
shActiveSheet.Activate
End If
Set SetDownloadIndexSheet = shDownloadIndex
Exit Function
CheckingIndexSheet:
If False Then
Resume
End If
bIndexSheetIsBad = True
Resume Next
GenErr:
If False Then
Resume
End If
End Function
更新 2:
在工作中我没有 Excel 2003,而是雇主只为我提供了 Excel 2007。我看到他的同一个工作簿在 Excel 2007 中打开正常;所有功能正常工作。昨晚在家和他通电话时已经很晚了,我们时间紧迫,我没有测试 2007 年、2010 年和 2013 年。
但是,他真的很讨厌 Ribbon,所以他仍然使用 Excel 2003。关于他可以在 Excel 2003 中做什么来解决这个问题的任何想法?
更新 3:
更新了代码以向 Ron 显示所有变量都已声明。
【问题讨论】:
-
举例说明返回#VALUE的函数代码。 ;)
-
嗨,Rory,我在上面添加了一个示例函数。
-
在“GetCompanyName”中,您有多个从未声明过的变量——这不是一个好习惯。此外,在将该变量设置为任何值之前,您正在尝试使用一个将该变量用作参数的函数来设置 shDownloadIndex。
-
嗨@RonRosenfeld,声明了ALL变量;我只是没有意识到有必要在这里展示它们。我在顶部有 Option Explicit,所以如果没有声明它们,我会得到一个编译错误。我更新了示例以显示所有变量都已声明。
-
嗨,@RonRosenfeld,关于您的陈述,“在您将该变量设置为任何值之前,您正在尝试使用一个使用该变量作为参数的函数来设置 shDownloadIndex。”:不正确。我只是检查它是否已经设置(并为当前正确的工作表设置),并在必要时重置它。如果它发现工作表一切正常,它会转到 Exit Function 行,尽管在这种情况下它确实将其设置为自身以避免将其变为 Nothing。除了这两个简单的功能之外,还有很多事情要做,我不会发布整个项目。
标签: vba excel excel-2003 excel-udf