0

我有一位使用 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 显示所有变量都已声明。

4

1 回答 1

0

由于我没有 2003 年(只有 2007 年),我希望这对你有用。

您可以做的是在公式栏中使用的每个函数的顶部使用“Application.Volatile”。这会将用户定义的函数标记为 volatile。每当在工作表的任何单元格中发生计算时,都必须重新计算 volatile 函数。只有当输入变量发生变化时,才会重新计算非易失函数。

public Function xx () as variant
  Application.Volatile(True)
  '
  'Your code
  '  
end function
于 2015-05-03T12:32:53.303 回答