Страницы: 1
RSS
Глюк Excel - не могу понять причину, 2 простейших, по сути одинаковых, цикла - на одном из них Excel молча закрывается
 
Есть файл со следующим кодом:

Код
' sh - кодовое имя листа

Sub test1()
    a = FIOarray1 ' Excel 2007 и 2010 молча закрываются, Excel 2003 зависает
End Sub

Sub test2()
    a = FIOarray2 ' все нормально работает
End Sub

Function FIOarray1() As Variant ' Excel глючит
    ' возвращает двумерный массив с фамилиями и примечаниями к ним
    Dim cell As Range, n&
    FIOarray1 = FIOrange.Resize(, 2).Value
    For Each cell In FIOrange.Cells
        n = n + 1: FIOarray1(n, 2) = cell.NoteText
    Next cell
End Function

Function FIOarray2() As Variant ' а вот так - работает
    ' возвращает двумерный массив с фамилиями и примечаниями к ним
    Dim cell As Range, n&: arr = FIOrange.Resize(, 2).Value
    For Each cell In FIOrange.Cells
        n = n + 1: arr(n, 2) = cell.NoteText
    Next cell
    FIOarray2 = arr
End Function


Function FIOrange() As Range
    Set FIOrange = sh.Range(sh.[b5], sh.Range("b" & sh.Rows.Count).End(xlUp))
End F unction


2 функции, которые делают одно и то же - возвращают двумерный массив (в первом столбце - значения ячеек, во втором - примечания к тем же ячейкам)

При запуске первой функции (которую я написал изначально) - Excel 2007 и 2010 закрываются без каких-либо уведомлений, а Excel 2003 зависает.

Что самое интересное: если в Excel 2003 во время выполнения первого кода нажать Ctrl + pause (остановить макрос), и продолжить выполнение в пошаговом режиме (нажимая F8), мы увидим, как Excel сходит с ума:
выполнение не всегда идет не как ожидается, а происходит перескакивание с одной строки кода на другую, в хаотичном порядке.

С точки зрения синтаксиса VBA, обе функции написаны верно.
Регулярно пишу подобные по методам работы функции - никогда проблем не было.

В чем причина столь странного поведения Excel?
 
Похоже понял причину - функция вызывает сама себя (рекурсия)

Проверял на этом:

Код
Function FIOarray() As Variant
    ' возвращает двумерный массив
    ReDim arr(1 To 10, 1 To 2)
    FIOarray = arr

    For i = 1 To 10
        For j = 1 To 2
            FIOarray(i, j) = Rnd()
        Next
    Next
End F unction


Но почему?

Если мы обращаемся к функции внутри неё же, вызов функции (рекурсия) происходит только в том случае, если вызов идёт СПРАВА от знака РАВНО
(например, x = FIOarray)

Тут же обращение к функции слева - это всегда работало как присвоение функции значения
(см. работающую функцию с последней строкой вида FIOarray2 = arr)


Или обращение к имени функции с параметрами ВСЕГДА вызывает рекурсивный вызов этой функции?
(может, в этом дело, раз при обращении без параметров все работает?)
Изменено: EducatedFool - 30.01.2013 08:40:42
 
Все верно делает VBA, Игорь.
Код
FIOarray(i, j) = Rnd()

здесь ты неявно вызываешь свою функцию. Если бы ты сначала прошелся по массиву arr, а затем назначал значение функции(как это обычно делается и сделано у тебя в функции FIOarray2) - все было бы хорошо. Но ты сначала назначил значения FIOarray = arr. Основной затык именно в том, что у тебя функция не объявлена как массив значений явно - у тебя тип Variant. И чтобы понять, что действительно можно присвоить значение функции как ты хочешь - VBA должен её вызвать для инициализации. А там опять цикл, и опять, и опять...
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
И чтобы понять, что действительно можно присвоить значение функции как ты хочешь - VBA должен её вызвать для инициализации
Спасибо, Дима.
Про инициализацию я как-то не подумал...
Действительно, в этом и причина, судя по всему.
 
Ну в общем, как-то так должно быть:
Код
Function FIOarray() As Variant
    ' возвращает двумерный массив
    Dim arr(1 To 10, 1 To 2)
    Dim i, j
Randomize
    For i = 1 To 10
        For j = 1 To 2
          arr(i, j) = Rnd()
        Next
    Next
     FIOarray = arr
End F unction
Изменено: Александр Моторин - 30.01.2013 10:01:03
 
Александр Моторин, у EducatedFool есть уже такая реализация - Function FIOarray2. Вопрос был именно в причинах такого поведения Excel в данной ситуации.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Как то странно работает здесь подсветка кода!?
Второй раз пытаюсь исправить, а всё равно ставит зачем-то пробелы лишние(в слове Function получилось Function F unction.
А после редактирования кода вообще согнало всё в оду строку. И код в любом случае получается не рабочий без редактирования
 
Да, обращение к имени функции со скобками всегда воспринимается как вызов функции с аргументами.
Даже если она определена без аргументов и как массив.
Поэтому в теле функции приходится вводить вспомогательную переменную-массив и работать с ним, а потом присваивать имени функции.
Страницы: 1
Наверх