Excel макрос переменная в адресе ячейки

 

SergeyU

Пользователь

Сообщений: 18
Регистрация: 01.01.1970

Hugo, Казанский — спасибо!  
Hugo — Ваш совет помог. Казанский, по Вашему варианту выдает ошибку:    
Run-time error ‘1004’:  
Application-defined or object-defined error  

  Юрий М, у меня есть файл со статистикой в виде: 1-й столбец — код продукта, 2-й столбец — наименование, 1-я строка — даты. На пересечении столбцов и дат — клиентский заказ по продукту на конкретную дату.  

  Я в свою очередь хочу вытягивать из данного закрытого файла часть статистики: данные по некоторой продукции на определенные даты. Забиваем в 1-й столбец нужные коды, в 1-ю строку нужные даты, запускаем макрос, который вытягивает нужные цифры из главного файла.  
Думал, как это сделать. Додумался только до способа вносить в ячейки формулы, а затем избавиться от формул, оставив только значения. Собственно вот что получилось:  

  Sub Макрос3()  
   Dim k As Integer, m As Integer  
   k = Cells(Rows.Count, 1).End(xlUp).Row  
   m = Cells(1, Columns.Count).End(xlToLeft).Column  
   MyPath = «C:Users…Desktop»  
   MyName = «Заказы.xls»  

         For i = 3 To m  
       If Cells(1, i) > 0 Then  
           For j = 2 To k  
               Cells(j, i).Select  
               ActiveCell.Formula = «=VLOOKUP(A» & j & «, ‘» & MyPath & «[» & MyName & «]31-й’!$A:$BZ, MATCH(» & Cells(1, i).Address & «,'» & MyPath & «[» & MyName & «]31-й’!$1:$1,0),0)»
           Next j  
       End If  
   Next i  
   Range(Cells(2, 3), Cells(k, m)).Select  
   Selection.Copy  
   Selection.PasteSpecial Paste:=xlPasteValues  

  End Sub

1 / 1 / 0

Регистрация: 18.01.2011

Сообщений: 15

1

Как указать адрес ячейки через переменную

15.06.2012, 01:18. Показов 57771. Ответов 31


Студворк — интернет-сервис помощи студентам

Нужно в («C5:C116») вместо С116 вставить переменну i, которая обозначает ячейку. Подскажите пожалуйста как это реализовать?



0



Alex77755

11482 / 3773 / 677

Регистрация: 13.02.2009

Сообщений: 11,145

15.06.2012, 01:37

2

Visual Basic
1
"C5:" & i

Подразумевается, что в i есть и буква



1



nnndaniil

1 / 1 / 0

Регистрация: 18.01.2011

Сообщений: 15

15.06.2012, 02:05

 [ТС]

3

я сам запутался =(
нужно что бы макрос работал только для тех ячеек, где есть значение. Я хотел следующим кодом определить последнюю ячейку, вывести адрес ячейки в переменную i. В коде указать i как границу для макроса.

Visual Basic
1
2
3
4
Dim lLastRow As Long
  Dim lLastCol As Long
     lLastRow = Cells(Rows.Count, 3).End(xlUp).Row
      lLastCol = Cells(3, Columns.Count).End(xlToLeft).Column

Подскажите пожалуйста, как это реализовать?

Добавлено через 10 минут

Visual Basic
1
Selection.AutoFill Destination:=Range("C5:" & lLastRow, lLastCol), Type:=xlFillDefault

вот тут выдает ошибку Method ‘Range’ of object’ _Global’ Failed



0



ikki

призрак

3261 / 889 / 119

Регистрация: 11.05.2012

Сообщений: 1,702

Записей в блоге: 2

15.06.2012, 04:51

4

Visual Basic
1
Range("C5", Cells(lLastRow, lLastCol))



1



skol13

369 / 78 / 6

Регистрация: 23.05.2012

Сообщений: 232

15.06.2012, 08:35

5

Цитата
Сообщение от nnndaniil
Посмотреть сообщение

нужно что бы макрос работал только для тех ячеек, где есть значение. Я хотел следующим кодом определить последнюю ячейку, вывести адрес ячейки в переменную i. В коде указать i как границу для макроса.

Если строки с данными идут без разрывов внутри, то я обычно пользую:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Public Function Разрыв(Лист, КонтрСтолбец, Optional СоСтроки As Integer)
'функция просматривает ячейки КонтрСтолбца и возвращает номер
'строки в которой найдена пустая ячейка (своеобразный EOF).
'Можно "искать" разрыв, начиная СоСтроки, иначе с первой
  Dim Строка  As Integer
  With Worksheets(Лист)
    If СоСтроки = 0 Then
        Строка = 1
    Else
        Строка = СоСтроки
    End If
 
    Do While .Cells(Строка, КонтрСтолбец).Value <> ""
        Разрыв = Строка
        Строка = Строка + 1
    Loop
  End With
End Function

Понятно что таким же образом, модифицировав макрос, можно найти крайний столбец.
Их пересечение даст крайнюю ячейку



1



735 / 203 / 11

Регистрация: 23.06.2011

Сообщений: 440

15.06.2012, 10:07

6

Range(Cells(i0, j0), Cells(i1,j1))
Где
i0 — номер строки левой верхней ячейки диапазона,
j0 — Номер столбца левой верхней ячейки диапазона,
i1 — номер строки правой нижней ячейки диапазона,
j1 — номер столбца правой нижней ячейки диапазона.



1



Dmitrii

2617 / 547 / 109

Регистрация: 21.03.2012

Сообщений: 1,051

15.06.2012, 10:26

7

Цитата
Сообщение от skol13
Посмотреть сообщение

…функция просматривает ячейки КонтрСтолбца и возвращает номер строки в которой найдена пустая ячейка (своеобразный EOF)…

А разве не проще для этой цели использовать метод SpecialCells?
Пример:

Visual Basic
1
Worksheets(1).Columns(1).Cells.SpecialCells(xlCellTypeBlanks).Item(1).Row



1



369 / 78 / 6

Регистрация: 23.05.2012

Сообщений: 232

15.06.2012, 10:47

8

Цитата
Сообщение от Dmitrii
Посмотреть сообщение

А разве не проще для этой цели использовать метод SpecialCells?

А если у вас данные идут не с первой строки?
Например несколько строк пропущенных, потом что-то типа шапки таблицы, в которой тоже не все ячейки заполнены?
Какую строку вернет ваш метод?
Правильно — первую строку в которой есть пустая ячейка в столбце поиска.
Но она будет далеко не последняя из строк с данными.

Добавлено через 12 минут
вообще конечно способов может быть туча и разных.
Который и как применить — все зависит от конкретных условий.
ТС дана куча ответов на его вопрос — что нибудь да пригодится



1



sulfur

200 / 98 / 2

Регистрация: 24.09.2011

Сообщений: 261

15.06.2012, 10:55

9

Цитата
Сообщение от nnndaniil
Посмотреть сообщение

я сам запутался =(
нужно что бы макрос работал только для тех ячеек, где есть значение.

я всегда делал так:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
With ОбластьТипаRange
Dim obLast as Range, obCurr as Range
set obLast = .Find("*", searchdirection:=xlPrevious)
if Not obLast is nothing then
set obCurr = obLast
do
set obCurr = .Find("*", after:=obCurr)
Call ОбработкаНайденнойЯчейки(obCurr)
loop obCurr.Address = obLast.Address
endif
end with

Там возникают проблемы, только если по ходу обработки удаляешь или вставляешь ячейки. Не помню этих тонкостей, но если кому надо будет…

Не по теме:

как тут в коде VB вставлять отступы? тэг[INDENT] не работает =/



1



Dmitrii

2617 / 547 / 109

Регистрация: 21.03.2012

Сообщений: 1,051

15.06.2012, 10:58

10

skol13, моя реплика относится не к задаче автора темы, а к Вашей функции.

Цитата
Сообщение от skol13
Посмотреть сообщение

А если у вас данные идут не с первой строки?..

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

Visual Basic
1
Worksheets(1).Range(Cells(СоСтроки, 1), Cells(65536, 1)).Cells.SpecialCells(xlCellTypeBlanks).Item(1).Row



1



369 / 78 / 6

Регистрация: 23.05.2012

Сообщений: 232

15.06.2012, 11:02

11

Цитата
Сообщение от sulfur
Посмотреть сообщение

Не по теме:
как тут в коде VB вставлять отступы? тэг[INDENT] не работает =/

Не по теме:

Я просто из макроса копирую код — все с отступами получается.
Правда я табулятором отступы в макросе привык делать — с пробелами может и не выходит — не знаю

Добавлено через 2 минуты

Цитата
Сообщение от Dmitrii
Посмотреть сообщение

Да ведь ничего же не мешает задать вместо целого столбца нужный диапазон.

Ну так функция то была написана или может быть даже откуда то выдернута в непонятно каком забытом году
Багаж знаний то растет.
А сейчас просто по привычке тащу ее из проекта в проект



1



200 / 98 / 2

Регистрация: 24.09.2011

Сообщений: 261

15.06.2012, 11:04

12

хотя со SpecialCells проще, оказывается =)



1



nnndaniil

1 / 1 / 0

Регистрация: 18.01.2011

Сообщений: 15

15.06.2012, 12:59

 [ТС]

13

Цитата
Сообщение от Gibboustooth
Посмотреть сообщение

Range(Cells(i0, j0), Cells(i1,j1))

Решил сделать по Вашему примеру, но теперь мне выдает ошибку в строке Selection.AutoFill Destination.
Вот собственно весь код, мне нужно до последней ячейки, в которой есть данные, столбца С- вставить формулу.

Visual Basic
1
2
3
4
5
6
7
8
Range("C5").Select
    ActiveCell.FormulaR1C1 = "=++RC[2]/RC[1]"
    Range("C5").Select
    
    Selection.AutoFill Destination:=Range(Cells(i5, j3), Cells(i200, j3)), Type:=xlFillDefault
    
    Range("C5:C200").Select
    ActiveWindow.SmallScroll Down:=200



0



735 / 203 / 11

Регистрация: 23.06.2011

Сообщений: 440

15.06.2012, 13:16

14

Цитата
Сообщение от nnndaniil
Посмотреть сообщение

Решил сделать по Вашему примеру, но теперь мне выдает ошибку в строке Selection.AutoFill Destination.

i и j перед числами не надо ставить. «0» и «1» в моих примерах — просто индексы. Надо было отформатировать:

Range(Cells(i0, j0), Cells(i1,j1))

Извинияюсь



1



1 / 1 / 0

Регистрация: 18.01.2011

Сообщений: 15

15.06.2012, 13:50

 [ТС]

15

Цитата
Сообщение от Gibboustooth
Посмотреть сообщение

i и j перед числами не надо ставить. «0» и «1» в моих примерах — просто индексы. Надо было отформатировать:

Range(Cells(i0, j0), Cells(i1,j1))

Извинияюсь

Поставил, все заработало, спасибо!
Но я рассчитывал на другой результат, что в этом диапазоне, он будет искать последнюю заполненную ячейку и вставлять формулу только до последней заполненной ячейки, а не для всего диапазона.
Подскажите пожалуйста, как это можно реализовать?



0



Gibboustooth

735 / 203 / 11

Регистрация: 23.06.2011

Сообщений: 440

15.06.2012, 14:25

16

Цитата
Сообщение от nnndaniil
Посмотреть сообщение

Но я рассчитывал на другой результат, что в этом диапазоне, он будет искать последнюю заполненную ячейку и вставлять формулу только до последней заполненной ячейки, а не для всего диапазона.
Подскажите пожалуйста, как это можно реализовать?

выбор последней заполненной ячейки на листе:

Visual Basic
1
Cells.Find("*", , , , xlByRows, xlPrevious)

Если нужно найти последнюю ячейку в определенном столбце:

Visual Basic
1
Columns(i).Find("*", , , , xlByRows, xlPrevious)

где i — номер столбца.

В вашем случае код будет выглядеть так:

Visual Basic
1
Selection.AutoFill Destination:=Range(Cells(5, 3), Columns(3).Find("*", , , , xlByRows, xlPrevious)), Type:=xlFillDefault



2



nnndaniil

1 / 1 / 0

Регистрация: 18.01.2011

Сообщений: 15

15.06.2012, 14:42

 [ТС]

17

Цитата
Сообщение от Gibboustooth
Посмотреть сообщение

В вашем случае код будет выглядеть так:

Visual Basic
1
Selection.AutoFill Destination:=Range(Cells(5, 3), Columns(3).Find("*", , , , xlByRows, xlPrevious)), Type:=xlFillDefault

Теперь на этой строчке

Visual Basic
1
Selection.AutoFill Destination:=

выдает ошибку, что метод AutoFill из класса Range завершен не верно.

Код сейчас такой:

Visual Basic
1
2
3
4
5
 Range("C5").Select
    ActiveCell.FormulaR1C1 = "=++RC[2]/RC[1]"
    Range("C5").Select
    Selection.AutoFill Destination:=Range(Cells(5, 3), Columns(3).Find("*", , , , xlByRows, xlPrevious)), Type:=xlFillDefault
Range("C5:C150").Select

В чем может быть ошибка?



0



призрак

3261 / 889 / 119

Регистрация: 11.05.2012

Сообщений: 1,702

Записей в блоге: 2

15.06.2012, 15:18

18

такую ошибку может выдавать только в одном случае — если Selection совпадает с Destination
конкретно для Вашего случая — все ячейки в столбце C ниже C5 — пустые.



2



1 / 1 / 0

Регистрация: 18.01.2011

Сообщений: 15

15.06.2012, 15:52

 [ТС]

19

Цитата
Сообщение от ikki
Посмотреть сообщение

такую ошибку может выдавать только в одном случае — если Selection совпадает с Destination
конкретно для Вашего случая — все ячейки в столбце C ниже C5 — пустые.

Точно!! Извините меня, за мою недальновидность.
У меня сначала макрос вставляет пустой столбце С, затем в него протягивается формула.
Можно сделать что бы формулу копировало до последней строки, в которой есть данные?
Например столбец B, строка 120 является последней, то что бы формулу в столбце С протянуло до 120 строки.



0



ikki

призрак

3261 / 889 / 119

Регистрация: 11.05.2012

Сообщений: 1,702

Записей в блоге: 2

15.06.2012, 16:02

20

попробуйте так:

Visual Basic
1
[c5].resize([b:b].Find("*", , , , xlByRows, xlPrevious).row-4,1).formular1c1= "=RC[2]/RC[1]"



2



Присвоение диапазона ячеек объектной переменной в VBA Excel. Адресация ячеек в переменной диапазона и работа с ними. Определение размера диапазона. Примеры.

Присвоение диапазона ячеек переменной

Чтобы переменной присвоить диапазон ячеек, она должна быть объявлена как Variant, Object или Range:

Dim myRange1 As Variant

Dim myRange2 As Object

Dim myRange3 As Range

Чтобы было понятнее, для чего переменная создана, объявляйте ее как Range.

Присваивается переменной диапазон ячеек с помощью оператора Set:

Set myRange1 = Range(«B5:E16»)

Set myRange2 = Range(Cells(3, 4), Cells(26, 18))

Set myRange3 = Selection

В выражении Range(Cells(3, 4), Cells(26, 18)) вместо чисел можно использовать переменные.

Для присвоения диапазона ячеек переменной можно использовать встроенное диалоговое окно Application.InputBox, которое позволяет выбрать диапазон на рабочем листе для дальнейшей работы с ним.

Адресация ячеек в диапазоне

К ячейкам присвоенного диапазона можно обращаться по их индексам, а также по индексам строк и столбцов, на пересечении которых они находятся.

Индексация ячеек в присвоенном диапазоне осуществляется слева направо и сверху вниз, например, для диапазона размерностью 5х5:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

Индексация строк и столбцов начинается с левой верхней ячейки. В диапазоне этого примера содержится 5 строк и 5 столбцов. На пересечении 2 строки и 4 столбца находится ячейка с индексом 9. Обратиться к ней можно так:

‘обращение по индексам строки и столбца

myRange.Cells(2, 4)

‘обращение по индексу ячейки

myRange.Cells(9)

Обращаться в переменной диапазона можно не только к отдельным ячейкам, но и к части диапазона (поддиапазону), присвоенного переменной, например,

обращение к первой строке присвоенного диапазона размерностью 5х5:

myRange.Range(«A1:E1»)

‘или

myRange.Range(Cells(1, 1), Cells(1, 5))

и обращение к первому столбцу присвоенного диапазона размерностью 5х5:

myRange.Range(«A1:A5»)

‘или

myRange.Range(Cells(1, 1), Cells(5, 1))

Работа с диапазоном в переменной

Работать с диапазоном в переменной можно точно также, как и с диапазоном на рабочем листе. Все свойства и методы объекта Range действительны и для диапазона, присвоенного переменной. При обращении к ячейке без указания свойства по умолчанию возвращается ее значение. Строки

MsgBox myRange.Cells(6)

MsgBox myRange.Cells(6).Value

равнозначны. В обоих случаях информационное сообщение MsgBox выведет значение ячейки с индексом 6.

Важно: если вы планируете работать только со значениями, используйте переменные массивов, код в них работает значительно быстрее.

Преимущество работы с диапазоном ячеек в объектной переменной заключается в том, что все изменения, внесенные в переменной, применяются к диапазону (который присвоен переменной) на рабочем листе.

Пример 1 — работа со значениями

Скопируйте процедуру в программный модуль и запустите ее выполнение.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

Sub Test1()

‘Объявляем переменную

Dim myRange As Range

‘Присваиваем диапазон ячеек

Set myRange = Range(«C6:E8»)

‘Заполняем первую строку

‘Присваиваем значение первой ячейке

myRange.Cells(1, 1) = 5

‘Присваиваем значение второй ячейке

myRange.Cells(1, 2) = 10

‘Присваиваем третьей ячейке

‘значение выражения

myRange.Cells(1, 3) = myRange.Cells(1, 1) _

* myRange.Cells(1, 2)

‘Заполняем вторую строку

myRange.Cells(2, 1) = 20

myRange.Cells(2, 2) = 25

myRange.Cells(2, 3) = myRange.Cells(2, 1) _

+ myRange.Cells(2, 2)

‘Заполняем третью строку

myRange.Cells(3, 1) = «VBA»

myRange.Cells(3, 2) = «Excel»

myRange.Cells(3, 3) = myRange.Cells(3, 1) _

& » « & myRange.Cells(3, 2)

End Sub

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

Пример 2 — работа с форматами

Продолжаем работу с тем же диапазоном рабочего листа «C6:E8»:

Sub Test2()

‘Объявляем переменную

Dim myRange As Range

‘Присваиваем диапазон ячеек

Set myRange = Range(«C6:E8»)

‘Первую строку выделяем жирным шрифтом

myRange.Range(«A1:C1»).Font.Bold = True

‘Вторую строку выделяем фоном

myRange.Range(«A2:C2»).Interior.Color = vbGreen

‘Третьей строке добавляем границы

myRange.Range(«A3:C3»).Borders.LineStyle = True

End Sub

Опять же, обратите внимание, что все изменения форматов в присвоенном диапазоне отобразились на рабочем листе, несмотря на то, что мы непосредственно с ячейками рабочего листа не работали.

Пример 3 — копирование и вставка диапазона из переменной

Значения ячеек диапазона, присвоенного переменной, передаются в другой диапазон рабочего листа с помощью оператора присваивания.

Скопировать и вставить диапазон полностью со значениями и форматами можно при помощи метода Copy, указав место вставки (ячейку) на рабочем листе.

В примере используется тот же диапазон, что и в первых двух, так как он уже заполнен значениями и форматами.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Sub Test3()

‘Объявляем переменную

Dim myRange As Range

‘Присваиваем диапазон ячеек

Set myRange = Range(«C6:E8»)

‘Присваиваем ячейкам рабочего листа

‘значения ячеек переменной диапазона

Range(«A1:C3») = myRange.Value

MsgBox «Пауза»

‘Копирование диапазона переменной

‘и вставка его на рабочий лист

‘с указанием начальной ячейки

myRange.Copy Range(«E1»)

MsgBox «Пауза»

‘Копируем и вставляем часть

‘диапазона из переменной

myRange.Range(«A2:C2»).Copy Range(«E11»)

End Sub

Информационное окно MsgBox добавлено, чтобы вы могли увидеть работу процедуры поэтапно, если решите проверить ее в своей книге Excel.

Размер диапазона в переменной

При получении диапазона с помощью метода Application.InputBox и присвоении его переменной диапазона, бывает полезно узнать его размерность. Это можно сделать следующим образом:

Sub Test4()

‘Объявляем переменную

Dim myRange As Range

‘Присваиваем диапазон ячеек

Set myRange = Application.InputBox(«Выберите диапазон ячеек:», , , , , , , 8)

‘Узнаем количество строк и столбцов

MsgBox «Количество строк = « & myRange.Rows.Count _

& vbNewLine & «Количество столбцов = « & myRange.Columns.Count

End Sub

Запустите процедуру, выберите на рабочем листе Excel любой диапазон и нажмите кнопку «OK». Информационное сообщение выведет количество строк и столбцов в диапазоне, присвоенном переменной myRange.

Хитрости »

1 Май 2011              225408 просмотров


Что такое переменная и как правильно её объявить?

Переменная — это некий контейнер, в котором VBA хранит данные. Если подробнее, то это как коробочка, в которую Вы можете положить что-то на хранение, а затем по мере необходимости достать. Только в данном случае в переменной мы храним число, строку или иные данные, которые затем можем извлекать из неё и использовать в коде по мере необходимости.

Для чего нужна переменная? Чтобы хранить значение и применить его позже в любой момент. Например, в ячейке А1 записана сумма, а нажатием на кнопку запускается обновление отчета. После обновления отчета сумма в А1 изменится. Необходимо сверить сумму до обновления с суммой после и в зависимости от этого сделать какое-либо действие. Переменная как раз позволит запомнить значение ячейки до того, как она обновится и использовать именно это значение после обновления.


  • Требования к переменным
  • Типы данных, хранимых в переменных
  • Как объявлять переменные
  • Как правильно назвать переменную
  • Пример использования переменных
  • Константы

В качестве имен переменных можно использовать символы букв и числа, но первой в имени переменной всегда должна быть буква. Не допускается использование точки, запятой, пробела и иных знаков препинания, кроме нижнего подчеркивания. Длина имени не должна превышать 254 символов. Так же нельзя использовать в качестве имен для переменных зарезервированные константы редактора VBA(например Sub, Msgbox, ubound, Date и т.п.). Так же для переменных неважен регистр букв.

 
Теперь рассмотрим основные декларированные в VBA

типы данных, которые можно хранить в переменных:

Тип данных Занимает байт в памяти Пределы значений
Byte 1 Целые числа от 0 до 255
Boolean 2 True или False
Integer 2 Целые числа от (-32768) до 32767
Long 4 Целые числа от (-2147483648) до 2147483647
Single 4 От (–3.402823Е+38) до (–1.401298Е-45) и от 1.401298Е-45 до 3.402823Е+38
Double 8 От ±1.79769313486232Е+308 до ±4.94065645841247Е-324
Decimal 12 От ±79228162514264337593543950335 без десятичных знаков до ±7,9228162514264337593543950335 с 28-ю знаками после запятой
Currency 8 От (–922337203685477.5808) до 922337203685477.5807
Date 8 От 01.01.100 до 31.12.9999(не надо путать с датами в Excel — 01.01.1900 до 31.12.9999)
String 10(+длина строки) От 0 до 65400 символов для фиксированных строк и чуть более 2 млрд. для строк переменной длины
Object 4 Любой объект
Array Определяется кол-вом и размером элементов
Variant от 16-ти Любой из встроенных типов данных

Как видно из таблицы больше всего памяти занимает Variant. Притом это если он хранит числовые данные. Если же такая переменная будет хранить данные строкового типа(текст), то размер занимаемой памяти будет измеряться уже начиная с 22 байт + длина строки, хранящейся в переменной. Чем больше памяти занимает переменная, тем дольше она инициализируется в памяти и тем медленнее код будет выполняться. Вот поэтому и важно явно задавать тип данных, хранимых в переменной — это называется объявить переменную.

Тип данных Decimal больше не используется, поэтому объявить переменную данного типа в VBA не получится — подобная попытка приведет к синтаксической ошибке. Для работы с данными типа Decimal переменную необходимо изначально объявить как Variant или вообще без типа (например Dim a), т.к. тип данных Variant используется в VBA по умолчанию и принимает любой тип данных.

Так же переменным можно назначать и другие типы данных, которых нет в таблице выше — это типы, которые поддерживаются объектной моделью приложений, к которым «подключен» VBA. Например, если зайти в VBA из Excel, то библиотека типов объектной модели Excel подключена по умолчанию и для переменных становится доступно множество типов этой объектной модели. Многие из них знакомы всем: Workbook, Worksheet, Range, Cells, Chart и т.д. Т.е. это книги, листы, ячейки, диаграммы. Типов много, почти на каждый объект и коллекцию. Рассматривать здесь все бессмысленно. Могу лишь привести пару строк кода:

Dim rRange as Range 'назначили переменной тип ячейка/диапазон
Set rRange = Range("A1") 'присвоили ссылку на ячейку A1 текущего листа

Про объявление переменных подробно написано чуть ниже.
А более подробно про обращение к диапазонам из VBA можно почитать в этой статье: Как обратиться к диапазону из VBA

как объявлять переменные

На самом деле все очень просто. Это делается при помощи операторов области действия: Dim, Public,Static и оператора присвоения типа As. Самый распространенный оператор — Dim. Его и возьмем в качестве примера. Синтаксис объявления:

[оператор области действия] Имя_переменной As [тип данных]

Очень частая ошибка при объявлении переменных, совершаемая начинающими изучать VBA:

Dim MyVar1, MyVar2, MyVar3 As Integer

Вроде бы исходя из логики всем переменным присвоен тип данных Integer. Но это ошибочное суждение. Тип Integer присвоен только последней переменной, к которой он «привязан» оператором AsMyVar3. Все остальные переменные имеют тип данных Variant. Т.е. если Вы не задаете каждой переменной свой тип хранимых данных явно(т.е. не указываете для неё тип данных через As), то VBA сам присваивает для такой переменной тип данных Variant, т.к. он может хранить любой тип данных. А вот так выглядит правильное присвоение типа данных:

Dim MyVar1 As Integer, MyVar2 As Integer, MyVar3 As Integer

Это и есть объявление переменных. Т.е. сначала идет оператор области действия (Dim, Public,Static), сразу за ним имя переменной, затем оператор As и тип.
Но это не все. Некоторые типы переменным можно присваивать еще короче — даже без оператора As:

Dim MyVar1%, MyVar2%, MyVar3%

Всего шесть типов, которые можно объявить подобным методом:
! — Single
# — Double
$ — String
% — Integer
& — Long
@ — Currency
На что стоит обратить внимание, при объявлении переменных подобным образом: между именем переменной и знаком типа не должно быть пробелов.
Я лично в большинстве статей предпочитаю использовать первый метод, т.е. полное указание типа. Это читабельнее и понятнее. В каких-то проектах могу использовать краткое указание, в общих(разработка в команде) — полное. В своих кодах Вы вправе использовать удобный Вам метод — ошибки не будет.

Теперь разберемся с операторами области действия(Dim, Public и Static):

  • Dim — данный оператор используется для объявления переменной, значение которой будет храниться только в той процедуре, внутри которой данная переменная объявлена. Во время запуска процедуры такая переменная инициализируется в памяти и использовать её значение можно внутри только этой процедуры, а по завершению процедуры переменная выгружается из памяти(обнуляется) и данные по ней теряются. Переменную, объявленную подобным образом еще называют локальной переменной. Однако с помощью данного оператора можно объявить переменную, которая будет доступна в любой процедуре модуля. Необходимо объявить переменную вне процедуры — в области объявлений(читать как первой строкой в модуле, после строк объявлений типа — Option Explicit). Тогда значение переменной будет доступно в любой процедуре лишь того модуля, в котором данная переменная была объявлена. Такие переменные называются переменными уровня модуля. Также для использования переменных во всех процедурах и функциях одного конкретного модуля можно использовать оператор Private. Но он в данном случае ничем не отличается от Dim, а пишется длиннее :) Плюс, Private нельзя использовать внутри процедуры или функции(только в области объявлений), что еще больше сужает её применимость. По сути чаще этот оператор применяется к функциям и процедурам(об этом см.ниже)
  • Static — данный оператор используется для объявления переменной, значение которой предполагается использовать внутри конкретной процедуры, но не теряя значения данной переменной по завершении процедуры. Переменные данного типа обычно используют в качестве накопительных счетчиков. Такая переменная инициализируется в памяти при первом запуске процедуры, в которой она объявлена. По завершении процедуры данные по переменной не выгружаются из памяти, но однако они не доступны в других процедурах. Как только Вы запустите процедуру с этой переменной еще раз — данные по такой переменной будут доступны в том виде, в котором были до завершения процедуры. Выгружается из памяти такая переменная только после закрытия проекта(книги с кодом).
  • Public — данный оператор используется для объявления переменной, значение которой будет доступно в любой процедуре проекта(в обычных модулях, модулях класса, модулях форм, модулях листов и книг). Переменная, объявленная подобным образом, должна быть объявлена вне процедуры — в области объявлений. Такая переменная загружается в память во время загрузки проекта(при открытии книги) и хранит значение до выгрузки проекта(закрытия книги). Использовать её можно в любом модуле и любой процедуре проекта. Важно: объявлять подобным образом переменную необходимо строго в стандартном модуле. Такие переменные называются переменными уровня проекта. В простонародье такие переменные еще называют глобальными(возможно из-за того, что раньше подобные переменные объявлялись при помощи оператора Global, который в настоящее время устарел и не используется).
    Для большего понимания того, где и как объявлять переменные уровня проекта два небольших примера.
    Неправильное объявление

    Option Explicit
     
    Sub main()
    Public MyVariable As String
    MyVariable = "Глобальная переменная"
    'показываем текущее значение переменной
    MsgBox MyVariable
    'пробуем изменить значение переменной
    Call sub_main
    'показываем измененное значение переменной
    MsgBox MyVariable
    End Sub
    'доп.процедура изменения значения переменной
    Sub ChangeMyVariable()
    MyVariable = "Изменили её значение"
    End Sub

    переменные не будут видны во всех модулях всех процедур и функций проекта, потому что:
    1. Оператор Public недопустим внутри процедуры(между Sub и End Sub), поэтому VBA при попытке выполнения такой процедуры обязательно выдаст ошибку — Invalid Attribut in Sub or Function.
    2. Даже если Public заменить на Dim — это уже будет переменная уровня процедуры и для других процедур будет недоступна.
    3. Т.к. объявление неверное — вторая процедура(ChangeMyVariable) ничего не знает о переменной MyVariable и естественно, не сможет изменить именно её.
    Правильное объявление

    'выше глобальных переменных и констант могут быть только декларации:
    Option Explicit     'принудительное объявление переменных
    Option Base 1       'нижняя граница объявляемых массивов начинается с 1
    Option Compare Text 'сравнение текста без учета регистра
    'глобальная переменная - первой строкой, выше всех процедур
    Public MyVariable As String
    'далее процедуры и функции
    Sub main()
        MyVariable = "Глобальная переменная"
        'показываем текущее значение переменной
        MsgBox MyVariable, vbInformation, "www.excel-vba.ru"
        'пробуем изменить значение переменной
        Call ChangeMyVariable
        'показываем измененное значение переменной
        MsgBox MyVariable, vbInformation, "www.excel-vba.ru"
    End Sub
    'доп.процедура изменения значения переменной
    Sub ChangeMyVariable()
        MyVariable = "Изменили её значение"
    End Sub

    Если при этом вместо Public записать Dim, то эта переменная будет доступна из всех функций и процедур того модуля, в котором записана, но недоступна для функций и процедур других модулей.
    Переменные уровня проекта невозможно объявить внутри модулей классов(ClassModule, ЭтаКнига(ThisWorkbook), модулей листов, модулей форм(UserForm) — подробнее про типы модулей: Что такое модуль? Какие бывают модули?)

  • Операторы области действия так же могут применяться и к процедурам. Для процедур доступен еще один оператор области действия — Private. Объявленная подобным образом процедура доступна только из того модуля, в котором записана и такая процедура не видна в диалоговом окне вызова макросов(Alt+F8)
  • 'процедура записана в Module1
    'эта процедура будет доступна для вызова исключительно из процедур в этом же модуле
    'но не будет доступна при вызове из других модулей
    Private Sub PrivateMain()
        MsgBox "Процедура может быть вызвана только из модуля, в котором записана", vbInformation, "www.excel-vba.ru"
    End Sub
    'другая процедура, записанная в этом же модуле
    Sub CallPrivate()
        Call PrivateMain
    End Sub
    'эта процедура записана в другом модуле - Module2
    'при попытке вызова этой процедурой получим ошибку
    ' Sub or Function not defined
    ' потому что процедура PrivateMain объявлена только для Module1
    Sub CallPrivate_FromModule1()
        Call PrivateMain
    End Sub

    При этом, если из Excel нажать сочетание клавиш Alt+F8, то в окне будут доступны только CallPrivate_FromModule1 и CallPrivate. Процедура PrivateMain будет недоступна.

Как правильно назвать переменную:

«Что самое сложное в работе программиста? — выдумывать имена переменным.» :-)А ведь придумать имя переменной тоже не так-то просто. Можно, конечно, давать им имена типа: a, d, f, x, y и т.д.(я сам иногда так делаю, но либо в простых кодах, либо для специального запутывания кода). Но стоит задуматься: а как Вы с ними будете управляться в большом коде? Код строк на 10 еще потерпит такие имена, а вот более крупные проекты — не советовал бы я в них оперировать такими переменными. Вы сами запутаетесь какая переменная как объявлена и какой тип данных может хранить и что за значение ей присвоено. Поэтому лучше всего давать переменным осмысленные имена и следовать соглашению об именовании переменных. Что за соглашение? Все очень просто: перед основным названием переменной ставится префикс, указывающий на тип данных, который мы предполагаем хранить в данной переменной. Про имеющиеся типы данных я уже рассказал выше. А ниже приведена примерная таблица соответствий префиксов типам данных:

Префикс Тип хранимых данных
b Boolean
bt Byte
i Integer
l Long
s Single
d Double
c Currency
dt Date
str String
obj Object
v Variant

Лично я немного для себя её переделал, т.к. некоторые обозначения мне кажутся скудными. Например Double я обозначаю как dbl, а Single как sgl. Это мне кажется более наглядным.

В чем еще плюс явного указания префикса данных. В VBA есть такие операторы как Def, при помощи которых можно указать тип данных по умолчанию для переменных, первая буква имени которых попадает в заданный в операторе диапазон. Например:

DefBool B
Sub test()
    Dim bCheck
End Sub

Автоматически переменной bCheck будет присвоен тип Boolean, т.к. она начинается с буквы b — регистр здесь не имеет значения(впрочем как в VBA в целом). Оператор Def задается в области объявления. Можно задать не одну букву, а целый диапазон букв:

DefBool B-C
Sub test()
    Dim bCheck, cCheck
End Sub

Но я считаю, что одной буквы для одного типа вполне достаточно. Можно задать сразу несколько операторов Def.

DefBool B
DefStr S
Sub test()
    Dim bCheck, sCheck
End Sub

Ниже приведен полный перечень операторов типов и данные, которые задает каждый из них:
DefBool — Задает тип Boolean
DefByte — Задает тип Byte
DefCur — Задает тип Currency
DefDate — Задает тип Date
DefDbl — Задает тип Double
DefInt — Задает тип Integer
DefLng — Задает тип Long
DefObj — Задает тип Object
DefSng — Задает тип Single
DefStr — Задает тип String
DefVar — Задает тип Variant
По умолчанию в VBA применена инструкция DefVar для всех букв(иначе говоря для всех переменных, которым не назначен тип данных явно через оператор As).

Ну и немаловажный момент это непосредственно осмысленное имя переменной. Имя переменной должно примерно отражать то, что в ней будет храниться. Например, Вы создаете отчет и Вам надо объявить две переменные: одна имя листа, другая имя книги. Можно было сделать так: str1, str2. Коротко, здорово. Но если подумать — и как можно понять, какая из этих переменных что хранит? Никак. Надо просматривать код и вспоминать, какой переменной какое значение было присвоено. Не совсем удобно, правда? А если бы Вы задали имена так: strBookName, strSheetName, то вроде как более понятно, что мы в них будем хранить. Это удобно не только вам самим при работе с кодом, но и другим людям, которые, возможно в будущем будут пользоваться Вашим кодом. Им будет удобнее читать код, если он будет оформлен грамотно, а переменные названы осмысленно. И не стоит экономить на длине имени — имя должно быть понятным. Без фанатизма, конечно :-). Хоть VBA и позволяет нам создавать переменные длиной до 254 символов, но читать такую переменную так же неудобно, как и с одним символом. Но здесь уже все зависит от Ваших предпочтений и фантазии.
Небольшое дополнение: лучше привыкать давать названия переменным на латинице(т.е. английский алфавит), т.к. для VBA английский язык «родной» и лучше использовать его.

Небольшой пример использования переменных в кодах:
Sub main()
'объявляем переменные с назначением конкретных типов
'As String - текст
'As Long   - целое число
Dim sAddress As String, sNewAddress As String, sShName As String
Dim lRow As Long
Dim rRange as Range 'назначили переменной тип ячейка/диапазон
 
'присвоили переменной rRange ссылку на текущую выделенную ячейку
Set rRange = Selection
'меняем выделение - выделяем ячейку D9
Range("D9").Select
'назначаем переменной адрес выделенных ячеек
sAddress = Selection.Address
'назначаем переменной lRow значение первой строки выделенной области
lRow = Selection.Row
'показываем сообщение
MsgBox "Адрес выделенной области: " & sAddress, vbInformation, "www.excel-vba.ru"
MsgBox "Номер первой строки: " & lRow, vbInformation, "www.excel-vba.ru"
'назначаем другой переменной значение адреса ячейки A1
sNewAddress = "A1"
'выделяем ячейку, заданную переменной sNewAddres
Range(sNewAddress).Select
MsgBox "Адрес выделенной области: " & sNewAddress, vbInformation, "www.excel-vba.ru"
'выделяем изначально выделенную ячейку, используя переменную rRange
rRange.Select
MsgBox "Адрес выделенной области: " & rRange.Address, vbInformation, "www.excel-vba.ru"
'задаем значение переменной
sShName = "excel-vba"
'переименовываем активный лист на имя, заданное переменной
ActiveSheet.Name = sShName
End Sub

Просмотреть пошагово выполнение данного кода поможет статья: Отлов ошибок и отладка кода VBA
Важно! Назначение значений переменным задается при помощи знака равно(=). Однако, есть небольшой нюанс: для переменных типа Object(а так же других объектных типов(Workbook, Worksheet, Range, Cells, Chart и т.п.)) присвоение идет при помощи ключевого оператора Set:

'присвоили переменной rRange ссылку на текущую выделенную ячейку
Set rRange = Selection

это так же называется присвоением ссылки на объект. Почему именно ссылки? Все просто: при помещении в переменную непосредственно ячейки или диапазона(Set var = Range(«A1») или Set rRange = Selection) нет никакого запоминания самой ячейки. В переменную помещается лишь ссылка на эту ячейку(можете считать, что это как ссылка в формулах) со всеми вытекающими: такое назначение не запоминает свойства ячейки до или после — в переменной хранится ссылка на конкретную ячейку и доступ есть исключительно к свойствам ячейки на текущий момент. Чтобы запомнить для этой ячейки значение, цвет или даже адрес (а так же и другие свойства) до её изменения и применить запомненное даже после изменения/перемещения самой ячейки — необходимо запоминать в переменные именно свойства ячейки:

Sub main()
    Dim val, l_InteriorColor As Long, l_FontColor As Long
    Dim rRange As Range 'назначили переменной тип ячейка/диапазон
 
    'присвоили переменной rRange ссылку на активную ячейку
    Set rRange = ActiveCell
    'запоминаем свойства ячейки
    val = rRange.Value                      'значение
    l_InteriorColor = rRange.Interior.Color 'цвет заливки
    l_FontColor = rRange.Font.Color         'цвет шрифта
    'копируем другую ячейку и вставляем на место активной
    ActiveSheet.Range("D1").Copy rRange
 
    'проверяем, что rRange теперь имеет совершенно другие свойста - как у D1
    MsgBox "Значение rRange: " & rRange.Value & vbNewLine & _
           "Цвет заливки rRange: " & rRange.Interior.Color & vbNewLine & _
           "Цвет шрифта rRange: " & rRange.Font.Color & vbNewLine, vbInformation, "www.excel-vba.ru"
 
    'назначаем свойства из сохраненных в переменных
    rRange.Value = val                      'значение
    rRange.Interior.Color = l_InteriorColor 'цвет заливки
    rRange.Font.Color = l_FontColor         'цвет шрифта
 
    'проверяем, что rRange возвращены параметры до копирования
    MsgBox "Значение rRange: " & rRange.Value & vbNewLine & _
           "Цвет заливки rRange: " & rRange.Interior.Color & vbNewLine & _
           "Цвет шрифта rRange: " & rRange.Font.Color & vbNewLine, vbInformation, "www.excel-vba.ru"
End Sub

Это так же распространяется на все другие объекты. Т.е. те переменные, значения которым назначаются через оператор Set.
Для других же типов Set не нужен и в переменную значение заносится без этих нюансов.


Константы

Так же есть и иной вид «переменных» — константы. Это такая же переменная, только(как следует из её названия) — она не может быть изменена во время выполнения кода, т.к. является величиной постоянной и значение её назначается только один раз — перед выполнением кода.

Const sMyConst As String = "Имя моей программы"

Константам могут быть назначены данные тех же типов, что и для переменных, за исключением типа Object, т.к. Object это всегда ссылка на объект, который как правило обладает «динамическими»(т.е. обновляющимися) свойствами. А изменение для констант недопустимо.
Для дополнительной области видимости/жизни констант используется только Public. Если область видимости не указана, то константа будет доступна только из того модуля, в котором объявлена. Здесь обращаю внимание на то, что Dim уже не используется, т.к. Dim это идентификатор только для переменных. Пару важных отличий объявления констант от объявления переменных:

  • при объявлении константы необходимо обязательно указывать явно, что это константа ключевым словом Const
  • сразу в момент объявления необходимо назначить константе значение: = «Имя моей программы»

Во всем остальном объявление и применение констант идентично объявлению переменных. Коротко приведу пару примеров.
Если константа объявлена внутри процедуры:

Sub TestConst()
    Const sMyConst As String = "Имя моей программы"
    MsgBox sMyConst 'показываем сообщение с именем программы
End Sub

то она не может быть использована в другой процедуре:

Sub TestConst()
    Const sMyConst As String = "Имя моей программы"
    MsgBox sMyConst 'показываем сообщение с именем программы
End Sub
Sub TestConst2()
    MsgBox sMyConst 'вызовет ошибку Variable not defined
End Sub

Чтобы использовать одну константу во всех процедурах модуля(того, в котором она объявлена), необходимо объявить её в области объявлений:

Const sMyConst As String = "Имя моей программы"
Sub TestConst()
    MsgBox sMyConst 'показываем сообщение с именем программы
End Sub
Sub TestConst2()
    MsgBox sMyConst 'уже не вызовет ошибку Variable not defined
End Sub

Чтобы использовать одну константу во всех процедурах проекта(книги), необходимо объявить её как Public:

Public Const sMyConst As String = "Имя моей программы"
Sub TestConst()
    MsgBox sMyConst 'показываем сообщение с именем программы
End Sub
Sub TestConst2()
    MsgBox sMyConst 'не вызовет ошибку Variable not defined, даже если процедура в другом модуле
End Sub

Подробнее можно прочитать выше — как я уже писал для констант применяются те же правила, что и для переменных.

Также см.:
Variable not defined или что такое Option Explicit и зачем оно нужно?
Что такое модуль? Какие бывают модули?
Что такое макрос и где его искать?
Отлов ошибок и отладка кода VBA


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам



Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

Адрес ячейки с переменной

Cudass

Дата: Среда, 25.09.2013, 05:50 |
Сообщение № 1

Группа: Пользователи

Ранг: Новичок

Сообщений: 19


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

Добрый день.
Наверное сразу оговорюсь что я новичек в среде VBA, VB проходили в базовом курсе института, но мало что помнится ))
В общем тут такой момент. По работе нужно сделать пару макросов, но они все однотипные.
Итак нужно расчитать число по формуле =D10-(D10*10%)-(E10*1,5%) и занести его в С10. Но при условии что в А10 находится определенный текст. Быстренько накидал примерный код:[vba]

Код

Sub macros1()
Dim i As Long
For i = 2 To 2000
If Cells(i, 1).Text = «Вывоз и утилизация ТБО» Then
Cells(i, 3).FormulaLocal = «=D10-(D10*10%)-(E10*1,5%)»
End If
Next i
End Sub

[/vba]Собственно вот в чем вопрос, как внедрить переменную вместо D10 и Е10 и т.д. ибо записей очень много

Сообщение отредактировал CudassСреда, 25.09.2013, 05:51

 

Ответить

KuklP

Дата: Среда, 25.09.2013, 07:07 |
Сообщение № 2

Группа: Проверенные

Ранг: Старожил

Сообщений: 2369


Репутация:

486

±

Замечаний:
0% ±


2003-2010

Код

«=RC[1]-(RC[1]*10%)-(RC[2]*1.5%)»

А еще я бы не перебирал в цикле ячейки, а использовал бы метод range.find или формулу листа match.


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728

 

Ответить

Cudass

Дата: Среда, 25.09.2013, 08:06 |
Сообщение № 3

Группа: Пользователи

Ранг: Новичок

Сообщений: 19


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

KuklP, спасибо большое )) пробовал этот вариант но, забыл указать .FormulaR1C1, теперь же всё хорошо ! ещё раз спасибо !

 

Ответить

KuklP

Дата: Среда, 25.09.2013, 08:17 |
Сообщение № 4

Группа: Проверенные

Ранг: Старожил

Сообщений: 2369


Репутация:

486

±

Замечаний:
0% ±


2003-2010

Не обязательно. Так тоже работает, можете убедиться:
[vba]

Код

[c10].Formula = «=RC[1]-(RC[1]*10%)-(RC[2]*1.5%)»

[/vba]


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728

 

Ответить

Вопрос такой мне надо связать переменную с адресом ячейки то есть так она читает:

i = «C4»
z = 1
    Range(i).Select
ActiveCell.FormulaR1C1 = «1»

  но мне надо чтобы 4 и С в С4 было числом которое я могу изменить например на z а не только на конкретное число
Например мне надо выбрать ячейку
«С(z)»
или «(С+z)4»


Не очень вас понял, но может так?

Sub Макрос1()
Dim iRow As Long, iCol As Long

    iRow = 5
    iCol = 7
    Cells(iRow, iCol).Select
End Sub

Кстати, чтобы ввести данные в ячейку, необязательно её выделять, т.е.

Cells(iRow, iCol) = 1

Разрабатываю макросы под заказ.
Email: MacrosForYou собака yandex точка ru


Да то что надо
Огромное Спасибо


Понравилась статья? Поделить с друзьями:
  • Excel макрос перевод в строку
  • Excel макрос перебор ячеек в столбце
  • Excel макрос перебор строк
  • Excel макрос очистки ячеек по условию
  • Excel макрос очистить столбец