Собственная функция Excel: Ошибка компиляции: Sub или Function не определены - PullRequest
0 голосов
/ 23 января 2019

У нас есть система, которая экспортирует данные IP-адреса всегда с трехзначными октетами.Я пытаюсь создать собственную функцию в Excel, чтобы удалить ненужные начальные нули с этих IP-адресов.У меня есть проверенная формула, которая выполняет это, но при попытке создать функцию я получаю ошибку компиляции: Sub или Function не определены.Любая помощь будет оценена.

формула, которая работает:

=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE("@." & TRIM(A2), ".0", "."), ".0", "."), "@.", "") 

например, если ячейка A2 содержит 010.110.009.254, эта формула приводит к 10.110.9.254

Public Function IPFix(IP)
IPFix = Substitute(Substitute(Substitute("@." & Trim(IP), ".0", "."), ".0", "."), "@.", "")
End Function

Я ожидаю, что =IPFix (A2) приведет к правильному формату IP без начальных нулей.Однако я просто получаю эту ошибку компиляции.

Ответы [ 2 ]

0 голосов
/ 23 января 2019

VBA размещен в Excel, но он совершенно различен: VBA ничего не знает о функциях листа Excel.По крайней мере, не изначально.

Итак, Substitute нигде не определено - то же самое для VLookup и многих других функций рабочего листа.Некоторые функции VBA имеют то же имя (или похожее имя), что и функции листа Excel, и ведут себя по-разному .

Стандартная библиотека VBA имеет Stringsмодуль, который предоставляет ряд специализированных String функций (некоторые из которых также существуют как функции рабочего листа, например, =LEFT против Left и Left$).

As Том правильно указывает , стандартная библиотека VBA, которая эквивалентна Substitute функции Excel, - это Replace - функция, определенная в модуле VBA.Strings, которую вы можете изучить, нажав F2 , чтобы вызвать VBE Обозреватель объектов :

VBE object browser showing definition for VBA.Strings.Replace

Поскольку все эти функции имеют глобальную область действия, у вас нет для их полной квалификации;вот почему и как вы можете легально написать Debug.Print Replace(string1, string2).Но знайте, что вы всегда можете набрать VBA. и получить IntelliSense для просмотра списка доступных функций - VBA.Strings.Replace работает, как и VBA.Replace, или просто Replace:

Public Function IPFix(ByVal IP As String) As String
    IPFix = VBA.Strings.Replace(VBA.Strings.Replace(VBA.Strings.Replace("@." & Trim(IP), ".0", "."), ".0", "."), "@.", "")
End Function

Теперь это многословно.Однако преимущество заключается в том, что теперь, если ваш проект VBA определяет функцию Replace, места, которые вызывают VBA.Strings.Replace или VBA.Replace, будут по-прежнему вызывать эту функцию вместо вашей пользовательской функции VBAProject.Module1.Replace, поскольку ссылка на идентификатор в VBAвсегда разрешается компилятором, начиная с наименьшей доступной области видимости: так что пользовательская функция может существовать в пользовательском модуле и «скрывать» или «скрывать» функцию стандартной библиотеки VBA (или любую другую функцию, определенную в любой другой библиотеке ссылочных типов).

И наконец, обратите внимание, что для случаев, когда вам действительно необходимо вызвать фактическую функцию рабочего листа, вы можете сделать это из объектной модели Excel - здесь с помощью блока With для сокращения словоблудия:

Public Function IPFix(ByVal IP As String) As String
    With Application.WorksheetFunction
        IPFix = .Substitute(.Substitute(.Substitute("@." & Trim(IP), ".0", "."), ".0", "."), "@.", "")
    End With
End Function

Функции рабочего листа, вызываемые следующим образом, будут работать точно так же, как их действительные аналоги;таким образом, вы можете использовать Index, Match, VLookup и множество других функций рабочего листа с помощью стандартного вызова члена VBA с ранним связыванием, который вызовет стандартную ошибку времени выполнения VBA, заданную недопустимымАргументы.

Вы также можете вызывать их с поздним связыванием непосредственно с объектом Application - в этом случае недопустимые аргументы не будут вызывать ошибку, но возвратят one - точно так же, как они это делают в реальных рабочих листах (например, #VALUE!) - если вы хотите вернуть это значение ошибки рабочего листа, ваша функция должна вернуть Variant (неявное, как у вас, или явное, как указано ниже), потому чтоError - это тип данных VBA, который не может быть приведен к значению String, поэтому при возвращении присваивается несоответствие типов ошибка:

Public Function IPFix(ByVal IP As String) As Variant
    With Application
        IPFix = .Substitute(.Substitute(.Substitute("@." & Trim(IP), ".0", "."), ".0", "."), "@.", "")
    End With
End Function

Обратите внимание, что, посколькуэти вызовы с поздним связыванием , они разрешаются только во время выполнения, что означает, что вы должны быть очень осторожны с опечатками;вы также не получите никаких IntelliSense или "быстрой информации о параметрах", чтобы помочь при вводе.

0 голосов
/ 23 января 2019

Заменить Substitute на Replace для функции VBA

Public Function IPFix(IP)
    IPFix = Replace(Replace(Replace("@." & Trim(IP), ".0", "."), ".0", "."), "@.", "")
End Function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...