Страницы: 1
RSS
VBA - Sub прерывается до завершения без видимой причины
 
Добрый день!

Я передал несколько переменных из Worksheet_Change Листа:
Код
Private Sub Worksheet_Change(ByVal zChange as Range)

...

Dim zRng As Range
Dim zRngCount As Integer
Dim zArr(1 to zRngCount - предположим, что она здесь уже определена как конкретное число)


Call zCall(zArr, zRng, zRngCount)

...
((после выполнения zCall - продолжается выполнение Worksheet_Change))

End Sub

в Sub отдельного модуля:
Код
Sub zCall(zArr, zRng As Range, zRngCount As Integer)

For i = 1 to zRngCount
zArr(i) = ((присваиваю некое значение из области zRng))
Next i

End Sub

В действительности, каждой из представленных переменных несколько десятков,
и для каждой производится не одна, а множество процедур в Sub'e (в частности - не один "For", а десятки).

Проблема в том, что выполнение zCall (вызванного из Worksheet_Change) непостижимым образом прерывается, прямо посреди одного из ничем не примечательных циклов. Даже сам цикл не завершается! Выполнение Worksheet_Change продолжается, но результаты "передачи" переменных получаются неверными.

Факты могу привести следующие:
- без переноса, код работает идеально (перенос потребовался из-за возникшей на днях "Procedure too large");
- прерывание происходит тем позже, чем меньше длина массива zRng (зависит от порядкового номера строки, изменение ячейки\ячеек которой инициировало Worksheet_Change); но если редактировать одну и ту же ячейку (при прочих равных условиях), прерывание происходит в одном и том же месте;
- часть кода, которую Sub "успевает" отработать полностью (до прерывания) - даёт верный результат;
- в режиме дебаггера видно, что на некоторых "не отработанных" массивах (при наведении курсором, уже после возвращения в Worksheet_Change) висит статус "Subscript out of range";
- прерывание (в Sub'e) происходит примерно на 240-280 строке кода;
- Sub после вызова из Worksheet_Change выполняется беспрерывно, не считая причины публикации вопроса: никаких других процедур не предусмотрено, никаких условий выхода \ вызова других процедур, ничего такого;
- Excel 2013, 32 bit, сборка стандартная: плагинов \ расширений нет;
- ни на одном этапе, никаких ошибок Excel при этом не выдаёт.

Может я не верно произвожу процедуру передачи? Но об этом можно судить из оформления метода Call.
Может у Sub'ов какое-то ограничение (ну там, не знаю, по количеству итераций)? Хотя я пробовал прогнать переданную таким же образом переменную через 30000 итераций в одном-единственном цикле: всё прошло успешно.

Странно то, что прерывание может произойти ПРЯМО посреди цикла! For i, Next i, Next, Next...
А потом - БАЦ! И не дойдя до следующего "Next" (не говоря про остальные строки кода), его выкинет обратно в Worksheet_Change. И так каждый раз, и зависит - такое впечатление - только от длины zRng (т.е., в разных случаях обрываются разные циклы; хотя все они идентичны: лишь порядковые номера у заполняемых массивов разные).

К сожалению, не могу привести код целиком.

2018.05.03
Товарищи, прошу простить грешного: ошибка оказалась моя личная.
Длина одного из массивов, используемых внутри цикла, была на 1цу меньше по сравнению с длиной цикла (это правильно, не вдаваясь в подробности, с точки зрения внутренней логики).
Уж не знаю, почему, но при передаче в модуль - это вызывало крах процедуры.
До передачи же (когда ещё не было ошибки "too large") - он, судя по всему, просто дальше продолжал.

Всем большое спасибо за участие! Ваши советы и опыт всегда мне очень помогали!

2018.05.24
А ещё это говно лечится простой резолюцией где-нибудь в начале процедуры
(или перед проблемным местом):
Код
On Error Resume Next
- ибо действует только в пределах процедуры, в отличие от Application.EnableEvents
(что логично, конечно, но всё равно вымораживает), и при разделении одной процедуры на несколько - соответственно, теряется; потому он, собственно, и "продолжал" до разделения.
Изменено: RazorBaze - 24.05.2018 10:02:50
 
Пожалуйста, сначала измените декларацию "zRngCount" из «Integer» на «Double», если будет работать измените из «Double» на «Long», и если будет работать, оставьте такой.

Есть ли какие-либо изменения в содержимом ячеек на листе с помощью «Worksheet_Change» и других макросов ?
Возможно, вам нужно использовать «EnableEvents = False / True» ?
У вас есть захват ошибок ?
Может быть, слишком много значений присвоено «zArr»?
Попробуйте ещё "Call zCall(zArr(), zRng, zRngCount)" значит "zArr()" с кронштейнами.
Изменено: ocet p - 02.05.2018 05:55:36
 
Цитата
RazorBaze написал:
Факты могу привести следующие:
лучшим фактом был бы файл с данными...
извините, потому что "факты" из вашего описания я воспринимаю просто как слова, а не факты, еще раз извините.
из приведенных фрагментов не видно чтобы между обьявлением (zRng As Range) в 5-й строке и передачей его в качестве параметра в 9-й строке (Call zCall(zArr, zRng, zRngCount)) переменная zRng получила хоть какое-то значение... похоже что в zCall в качестве zRng приходит Nothing
и... перестаньте "взывать" к процедурам с помощью Call  в ситуациях, где в этом нет особой необходимости (чтобы сработала процедура, достаточно написать ее имя и перечислить (через запятую) нужные ей параметры)
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Ігор Гончаренко, я просто думал так правильнее; ну типа как без принудительного Option Explicit: можно не объявлять и не типизировать простейшие переменные... а можно всё равно это всё делать, ну вроде потому что так правильнее. "Call" я из этой логики везде писал.

Значений действительно не видно, но пустых там нигде нет!
Подчёркиваю, что без разделения на процедуры, код работал идеально (вплоть до "too large").

Но вы и не обязаны угадывать причину: я лишь надеялся, что кто-то знающий увидит неочевидное для меня ограничение, вроде того же "too large", и оно окажется причиной.

ocet p, я так расстроился из-за всего этого, что удалил всё что сделал за вчера)))
сейчас воспроизведу: скажу, помогло ли.
 
Цитата
RazorBaze написал: висит статус "Subscript out of range"
Вас вот это никак не напрягло? Зачем Вам отдельная переменная для счетчика цикла при переборе массива? Или Вы уверены, что Ваш zRngCount ВСЕГДА будет равен Ubound(zArr) ?
Код
Sub zCall(zArr, zRng As Range)
 
For i = 1 To UBound(zArr)
    zArr(i) = zRng(i)
Next i
 
End Sub


Изменено: Sanja - 02.05.2018 07:14:31
Согласие есть продукт при полном непротивлении сторон
 
Офф. Судя по Вашим темам, возникающим ошибкам типа 'too large', сотен строк кода в уже разнесенных процедурах, по нескольку ДЕСЯТКОВ циклов в каждой Вам нужно пересматривать всю логику работы Вашего кода.
Например циклы, типа Вашего
Код
For i = 1 To UBound(zArr)
    zArr(i) = zRng(i) 'присваиваю некоторое значение из диапазона zRng
Next i
можно заменить одной строкой
Код
    zArr = zRng.Value
ИМХО
Изменено: Sanja - 02.05.2018 07:26:23
Согласие есть продукт при полном непротивлении сторон
 
Sanja, на самом деле там должно быть Dim zArr(1 to zRngCount),
но VBA почему-то её не глотает (в смысле, даже когда она уже определена)) требует, чтобы было именно число; хотя с Ubound в других случаях работает).

Прикол в том, что если сперва объявить пустой массив Dim zArr(), то потом удастся скормить ему этот "zRngCount" путём Redim zArr(1 to zRngCount). Но я не стал распространяться (в примере исправил).

А по поводу логики... да нет, знаете, там всё предельно просто, просто очень много списков и комментариев.
49 списков для изменяемой ячейки. И сопутствующих процедур (т.е., различаются они только порядковыми номерами; а так - код был бы, грубо говоря, в 49 раз короче).

А списки нужны потому что я из каждого извлекаю функцию максимума.
Изменено: RazorBaze - 02.05.2018 07:31:40
 
Цитата
RazorBaze написал: VBA почему-то её не глотает
Так потому что на момент объявления в переменной zRngCount нечего нет.
Цитата
RazorBaze написал: нет знаете, там всё предельно просто
Да дело Ваше, я не настаиваю, хотя Вы сами понимаете, что
Цитата
RazorBaze написал: код был бы, грубо говоря, в 49 раз короче
Согласие есть продукт при полном непротивлении сторон
 
а вот и ключик
Цитата
49 списков для каждой строки
предполагаю, что в итоге все можно написать, ну... не в 49, а раз в 45 короче, чем написано сейчас
достаточно описать задачу, которую решаете, а не проблемы, с которыми столкнулись при реализации уже принятым способом
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Ігор Гончаренко, у меня строки сгруппированы между собой, множество строк; от 1го до 7го уровня. Я их называю "паренты" и "киндеры".

Мне с детства хотелось, чтобы у каждой строки было два "адреса" (в специальных столбцах): в первый - подтягивались бы "имена" всех "киндеров", если они есть ("имя" - это тоже ячейка одного из столбцов); а в другой - "имена" всех "парентов", если они есть.

Понятно, что при каждом изменении, или перемещении (одной; нескольких строк) все эти адреса должны пересчитываться.

Далее, есть ячейка, которые ВСЕ эти имена собирает, сцеплением.
Ну и когда ты фильтруешь строки по столбцу с ячейками, куда сцеплены все имена - ты видишь не только то, что ищешь, но и всё то, что с ним связано.

И чтобы нагрузка была минимальной - составляю массивы из значений, и с ними работаю.

Освоил, блин, программирование)) вот, второй месяц мучаюсь.

Строго говоря, код работает идеально, но только для постоянно убывающих уровней.
Поэтому списков теперь не 7, а 49.
Вот-вот бы закончил. И тут - ограничения, блин.
Изменено: RazorBaze - 02.05.2018 07:50:04
 
нормально, все ще впереди, я учусь программировать уже более 30 лет
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Покажите файл-пример с Вашими "киндер-сюрпризами' - очень уж интересно посмотреть на 'идеально работающий' код длиной в тысячи строк
Согласие есть продукт при полном непротивлении сторон
 
RazorBaze, ReDim zArr(1 to zRngCount). Диапазоны шерстите на том-же листе, на котором стоит обработчик событий? Если да, то при включенных событиях ваш мега код будет вызван пару десятков раз, а потом Excel поймет, что вы накосячили и прервет работу обработчика. Собственно об этом писали выше.

П.С.: Если не секрет, то какие космические расчеты вы проводите?
 
Anchoret, события у меня отключены, конечно.
Расчёты произвожу такие, что у моих строк уровень группировки задаётся соответственно значению ячейки в одной из колонок (собственно, событие Worksheet_Change). Далее, он находит все ячейки (в этой колонке со "значениями уровней") выше и ниже отредактированной, и разбивает их на списки: отдельный для всех "единиц", "двоек", "троек" и т.д. (массивы). Тогда функция максимума такого массива (при определённых условиях) будет означать, что редактируемая строка вложена (через группировку) в ту, на которую указывает функция максимума.
И если этих "максимумов" несколько (из разных списков), и если они идут по убыванию (соответственно порядковым номерам) - значит, все они вложены друг в друга, от наименьшей к наибольшей.

Sanja, я буду рад однажды поделиться со всеми интересующимимся, но в ближайшие несколько лет это будет означать нарушение неких договорённостей с моей стороны. Я не могу этого сделать.
На подготовку файла примера у меня ушло бы не меньше одного рабочего дня, что тоже нецелесообразно.

Пока не проверял советы ocet p: лучше, думаю, просплюсь сперва))

vikttur, не думаю, что кто-либо рискнул бы потратить своё время на решение незнакомых ему проблем. Тем более опираясь на их описание.
Изменено: RazorBaze - 03.05.2018 03:23:55
 
Цитата
RazorBaze написал: На подготовку файла примера у меня ушло бы не меньше одного рабочего дня, что тоже нецелесообразно.
Целесообравзнее отнимать чужое время, тратить его на догадки-допущения?
 
RazorBaze, понятнее не стало) Но все еще жива уверенность, что все это можно было сделать раз в двадцать компактнее.
 
RazorBaze, из опыта форумного. Чем больше тумана напускает автор, тем ближе к "выедененому яйцу" секреты и "суперпуперность" кода. Не в обиду, но так оно обычно получается. И по Вашему описанию в первом сообщении как-то думается, что слишком уж замудрено Вы логику построили.

Совет. Потратить свое драгоценное время, составить пример. Часто при составлении примера ошибка проявляется и становится понятной. Это тоже из собственного опыта.
В файл не нужно копировать все модули - только те коды, которые приводят к ошибке. С наличием примера помощь эффективнее.
Страницы: 1
Наверх