Доброго времени суток, Планетяне! От проверки системных ограничений Excel'я решил вернуться к более рабочим вопросам. Прошу совета по проблеме. Итак: 1. Есть у меня базовый исполнительный макрос. Вообще он хранится в личной подключаемой надстройке, но в примере он помещён в книгу, вместе с предварительным макросом 2. Есть предварительный макрос. С его помощью я получаю 2 переменные (диапазон и разделитель) для последующей передачи их в исполнительный макрос 3. вопрос: как это грамотно сделать? Напрямую вызывать исполнительный макрос из предварительного не получается. Ни call, ни run… 4. Изменится ли (и как) порядок передачи переменных, если предварительный макрос находится в модуле книги, а исполнительный в личной надстройке и между ними настроена ссылочная связь, как мне подсказал уважаемый Казанский в этой теме?
Зачем мне это? Опять же - для удобства. Исполнительный макрос не меняется, выполняя одну и ту же работу. Меняются только переменные в нём: например в этом - это разделитель и диапазон. Иногда мне удобно их задать руками (для Selection, как в примере), а иногда онм задаются в составе другого большого макроса, одним из этапов которого будет являться этот.
'В выделенном диапазоне разбить содержимое ячеек по разделителю вниз в автоматически добавляемые строки
'Автор: webley
'Редактор: JayBhagavan
'Адаптация под сложный перенос и коррекция: JeyCi
'Тема на сайте: http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&FID=1&TID=80210&TITLE_SEO=80210-razbit-tekst-v-yacheyke-po-strokam-cherez-proizvolnyy-razdelitel#postform
'=====================================================================================================================================================================================
Option Explicit
Sub TextOnRowsInRange_BASE2()
Dim cl As Range, rngTOR As Range, rngTmp As Range
Dim strTmp$, DelimTOR$
Dim Arr() As String
Dim i&, n&, j&, k&, a&, max&
If DelimTOR = "" Then Exit Sub
If rngTOR.Columns.Count > 20 Or rngTOR.Rows.Count > 10000 Or rngTOR.Cells.Count > 100000 Then
MsgBox "Слишком много выделено!", vbExclamation, "Ошибка выделения"
Exit Sub
End If
Application.ScreenUpdating = 0
For i = rngTOR.Rows.Count To 1 Step -1
'===
max = 0
For j = 1 To rngTOR.Columns.Count
strTmp = rngTOR(i, j).Value & DelimTOR
Arr = Split(strTmp, DelimTOR)
a = UBound(Arr)
max = IIf(max > a, max, a)
Next
If max <= 1 Then GoTo nx
'===
rngTOR(i, 1).Offset(1, 0).Resize(max - 1).EntireRow.Insert Shift:=xlDown ', CopyOrigin:=xlFormatFromLeftOrAbove
For j = 1 To rngTOR.Columns.Count
With rngTOR(i, j)
If InStr(rngTOR(i, j), DelimTOR) Then
strTmp = .Value '& DelimTOR
Arr = Split(strTmp, DelimTOR)
a = UBound(Arr)
Set rngTmp = .Resize(a)
For k = 0 To a
rngTmp(k + 1, 1).Value = Arr(k)
Next k
End If
End With
Next j
'===
nx:
Next i
Application.ScreenUpdating = 1
End Sub
'=======================================================================================================================
Sub TextOnRowsInRange_Choose2()
Dim rngTOR As Range
Dim DelimTOR$
DelimTOR = InputBox("Введите символ-разделитель")
If DelimTOR = "10" Then DelimTOR = Chr(10) 'ввести "10" для использования в качестве разделителя "перенос строки"
Set rngTOR = Selection
Application.Run "TextOnRowsInRange_BASE2"
End Sub
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Не сочтите за ап))) Внутри одного модуля разобрался, "засунув" меняющиеся переменные (переменные переменные ) между Option Explicit и Sub'ом первого модуля — то есть, объявив их переменными уровня модуля. Совет взял отсюда… Теперь, как я понимаю, нужно экспериментировать со случаем из личной надстройки. Буду рад советам и продолжаю копать)
Код
Option Explicit
Dim rngTOR As Range
Dim DelimTOR$
Sub TextOnRowsInRange_BASE2()
Dim cl As Range, rngTmp As Range
Dim strTmp$
Dim Arr() As String
Dim i&, n&, j&, k&, a&, max&
If DelimTOR = "" Then Exit Sub
If rngTOR.Columns.Count > 20 Or rngTOR.Rows.Count > 10000 Or rngTOR.Cells.Count > 100000 Then
MsgBox "Слишком много выделено!", vbExclamation, "Ошибка выделения"
Exit Sub
End If
Application.ScreenUpdating = 0
For i = rngTOR.Rows.Count To 1 Step -1
'===
max = 0
For j = 1 To rngTOR.Columns.Count
strTmp = rngTOR(i, j).Value & DelimTOR
Arr = Split(strTmp, DelimTOR)
a = UBound(Arr)
max = IIf(max > a, max, a)
Next
If max <= 1 Then GoTo nx
'===
rngTOR(i, 1).Offset(1, 0).Resize(max - 1).EntireRow.Insert Shift:=xlDown ', CopyOrigin:=xlFormatFromLeftOrAbove
For j = 1 To rngTOR.Columns.Count
With rngTOR(i, j)
If InStr(rngTOR(i, j), DelimTOR) Then
strTmp = .Value '& DelimTOR
Arr = Split(strTmp, DelimTOR)
a = UBound(Arr)
Set rngTmp = .Resize(a)
For k = 0 To a
rngTmp(k + 1, 1).Value = Arr(k)
Next k
End If
End With
Next j
'===
nx:
Next i
Application.ScreenUpdating = 1
End Sub
'=======================================================================================================================
Sub TextOnRowsInRange_Choose2()
DelimTOR = InputBox("Введите символ-разделитель")
If DelimTOR = "10" Then DelimTOR = Chr(10) 'ввести "10" для использования в качестве разделителя "перенос строки"
Set rngTOR = Selection
Application.Run "TextOnRowsInRange_BASE2"
End Sub
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Кароч (инфу, как и ранее, взял у Дмитрия Щербакова на сайте) Вроде работает так: переменные нужно объявить в области объявлений (перед Sub) как Public, а не Dim в исполнительном макросе, что лежит в личной надстройке. Затем связать книгу и надстройку (ссылка в шапке) и вуаля))) не знаю, насколько стабильно, но с этим примером получилось. Подскажите, если тупанул где или подводные камни какие имеются, на что нужно обратить внимание и что учесть…
Вот ещё ссылка на официальные данные по этому вопросу от мелкомягких
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Доброго времени суток, Планетяне! Увидел, что из макроса в макрос переменные можно передавать в скобках, как в функции: Application.Run "Макрос(a,b,c,rng)". Подскажите пожалуйста как правильно это сделать и какие нюансы? Можно ли Optional, например, использовать и так далее…
Базовый макрос находится в личной надстройке. Вызываю его из модулей книг.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
В общем, то вопрос в чём? Как передать переменную из одного макроса в другой? Решений несколько: -Можно через глобальную переменную Public DelimTOR as String -Можно просто передать как вы выше указывали Call TextOnRowsInRange_BASE2(DelimTOR)
Sub TextOnRowsInRange_BASE2(DelimTOR) ------------------ End Sub -Ну или так с указанием точного модуля Макросы.TextOnRowsInRange_BASE2 (DelimTOR) Я обычно использую точное указание модуля, на случай если имена макросов могут повторяться. -Если Вы хотите запустить макрос вне надстройки, то-бишь перенести переменную в макрос, который находится в Вашей надстройке, то можно так: Application.Run "Надстройка.xlam!Макросы.TextOnRowsInRange_BASE2", DelimTOR
Sub TextOnRowsInRange_BASE2(DelimTOR) ------------------ End Sub Имена передаваемых аргументов могут быть другими, передаётся только их порядок, последовательность.
Мастерство программиста не в том, чтобы писать программы, работающие без ошибок. А в том, чтобы писать программы, работающие при любом количестве ошибок.
Jack Famous, очивидно, но, как говорил мой препод по математике, уметь доказывать: Макрос, или подпрограмм (Sub от Subroutine) отличается от функции только тем, что поcледняя возвращает значение плюс к тем что ей передали. Все остальные правила передачи аргументов остаются/
Надеюсь никого сильно не удивить, но угадайте, что выдадут три принта?
Код
Sub tt2()
B = 1
Call tt(B)
Debug.Print B
Debug.Print ttt(B)
Debug.Print BEnd SubSub tt(a)
a = a + 1
End Sub
sub tt(a)
a=a+1
end sub
Function ttt(a)
a = a + 1
ttt = a
End Function
То есть надо помнить, а иногда и пользоваться тем, что изменяя передавая параметр (аргумент) и изменив его, мы получаем измененное значение переменой и в родительском процессе.
Alemox, простите - не увидел вашего сообщения… Подробно, однако Application.Run "Надстройка.xlam!Макросы.TextOnRowsInRange_BASE2", DelimTOR — вот этот способ был нужен! Спасибо вам большое!
БМВ, спасибо вам большое! В коде что-то перепутано, но основное уяснил - буду пробовать!
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄