Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Регистрация
Войти
 
Страницы: 1
RSS
Диапазон в With, По мотивам ответа ZVI
 
В теме
http://www.planetaexcel.ru/?PAGE_NAME=message&FID=1&TID=46522&MID=386922#message386922
Цитата
ZVI пишет:
Нет, с этим здесь все в порядке, Range(Диапазон1, Диапазон2) задается только параметрами Диапазон1, Диапазон2, а они оба относятся к одному т и тому же листу одной и той же книги (не важно какой, активной или нет). В данном случае используется диапазон листа той книги, в которой написан код.
Сегодня пытал код
Код
   With sh
        Range(.Cells(13, 5).Address).Resize(UBound(larr), UBound(larr, 2)) = larr
        .Copy
        ActiveWorkbook.SaveAs Filename:=iPath & sh.Name & "_" & Replace(Date, ".", "_"), _
                              FileFormat:=51
         .Range(.Cells(13, 5).Address).Resize(UBound(larr), UBound(larr, 2)).ClearContents
     End With

Возник вопрос - почему без точки перед Range заполнение на листе происходит правильно, а без точки перед Range при очистке происходит очистка диапазона в активной книге, а не в той, где sh (и макрос).
 
Цитата
RAN пишет:
без точки перед Range заполнение на листе происходит правильно
ну так внутри этого Range у Cells ведь есть точка.  :)
а вот попробуй убрать её.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
После команды .Copy активным становится лист-копия. Соответственно, без точки при очистке происходит очистка диапазона листа-копии, а с точкой - диапазона листа sh.
Заполнение без точки перед Range происходит на активном в этот момент листе (который потом копируется).
 
Да я собственно всегда так и предполагал, и делал. Но смутил процитированный пост.
 
Цитата
RAN: ... Сегодня пытал код ...
Андрей, в той теме в выражении Range(Диапазон1, Диапазон2) под диапазоном подразумевался тип данных Range, а не текстовый адрес, как в приведенном Вами фрагменте кода. Проверьте - в коде сообщения #1 той темы тип данных был именно Range.

В Вашем коде замените в обоих случаях Range(.Cells(13, 5).Address) на Range(.Cells(13, 5)) или просто на .Cells(13, 5) и смысл вернется  :)
Изменено: ZVI - 17 Мар 2013 11:24:48 (Range(.Cells(13, 5)) выдаст ошибку (см.ниже))
Vladimir Zakharov
Microsoft MVP – Office Apps & Services
 
Когда-то на одном из форумов пытался эту тему развернуть и дал такой ответ:
По умолчанию для всех объектов родительским объектом является текущий объект(если он может быть использован в качестве родителя). Т.е. если для ячейки не указать явно лист, к которому она относится, в качестве родительского листа для неё будет использован текущий(за исключением случаев, когда код записан в модуле листа - тогда в качестве родителя будет использован лист, в котором записан код). В конструкциях типа Range(Cells(,),Cells(,)) Range является контейнером, в котором указываются ссылки на объекты, из которых и будет создана ссылка на непосредственно конечный объект.
Предположим, что активен "Лист1", а код запущен с листа "Итог".
Если запись будет вида
Sheets("Итог").Range(Cells(1,1),Cells(10,1))

это вызовет ошибку(контейнер и объекты внутри него не могут располагаться на разных листах), равно как и
Код
Sheets("Итог").Range(Cells(1,1),Sheets("Итог").Cells(10,1))


и
Код
Range(Cells(1, 1), Sheets("Итог").Cells(10, 1))


т.к. ссылки на объекты внутри контейнера относятся к разным листам.
А вот такие записи будут правильными:
Код
Sheets("Итог").Range(Sheets("Итог").Cells(1,1),Sheets("Итог").Cells(10,1))
Range(Sheets("Итог").Cells(1,1),Sheets("Итог").Cells(10,1))


Вторая запись не содержит ссылки на родителя для Range, но ошибки это не вызовет - т.к. если для контейнера ссылка не указана, а для двух объектов внутри контейнера родитель один - он будет применен и для самого контейнера.
Если запись будет вида Range("A1","A10"), то указывать ссылку на родителя внутри Range не обязательно - достаточно будет указать эту ссылку перед самим Range - Sheets("Итог").Range("A1","A10"), т.к. текстовое представление адреса внутри Range обязывает создать ссылку именно на родителя контейнера.

В примере:
Код
With Sheets("Итог").Range("E2:E" & Cells(Rows.Count, 1).End(xlUp).Row)
    .FormulaR1C1 = "=SUMIF(Лист1!C4,RC1,Лист1!C11)"
End With


Запись смешанная - и текстовое представление адреса ячейки и ссылка на объект Cells. В данном случае явную ошибку код не вызовет, но и работает не всегда так, как хотелось бы.
Sheets("Итог").Range("E2:E" - создается ссылка на столбец Е листа Итог. Но далее идет вычисление последней строки первого столбца. И вот как раз это вычисление происходит на основе объекта Cells, который не содержит в себе ссылки на родительский объект. А значит он будет вычислять последнюю строку исключительно для текущего листа(если код записан в стандартном модуле). Правильно было бы записать тогда так:
Код
With Sheets("Итог").Range("E2:E" & Sheets("Итог").Cells(Rows.Count, 1).End(xlUp).Row)
    .FormulaR1C1 = "=SUMIF(Лист1!C4,RC1,Лист1!C11)"
End With



Надеюсь, что мне удалось дать достаточно развернутый и доступный для понимания ответ.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Владимир, спасибо за разъяснения.
Просто периодически втыкаюсь (забываю).
Например в данном варианте Range(.Cells(13, 5))  не работает, работает Range(.Cells(13, 5), .Cells(13, 6)).
.Cells(13, 5), как ни странно работает, хотя в сочетании с Resize или Resize и Offset тоже вылетало с ошибкой.
 
Цитата
RAN:
... Range(.Cells(13, 5))  не работает
Вы правы, такая конструкция избыточна ( масло масленое :) ) и не работает. Нужно просто .Cells(13, 5)
Можно еще и Range(.Cells(13, 5).Address(External:=True)), хотя это неоптимально.
Vladimir Zakharov
Microsoft MVP – Office Apps & Services
 
Всем спасибо за разъяснения.

Опять глюк ответов.   :!: :(

Ответ Дмитрия вероятно был добавлен, когда я писал свой. Отправив ответ я его не увидел. Загланув в тему сейчас обнаружил.  :(
Страницы: 1
Читают тему (гостей: 1)
Наверх