В приложении Excel все данные как правило находятся в ячейках на листах, с которыми макросы работают как с базой данных. Поэтому, начинающему программисту VBA важно понимать как читать значения из ячейки Excel в переменные или массивы и, наоборот, записывать какие-либо значения на лист в ячейки.
Обращение к конкретной ячейке
Прежде чем читать или записывать значение в ячейке, нужно определиться с тем, как можно указать какая именно ячейка нам необходима.
Полный путь к ячейке A1 в Книге1 на Листе1 можно записать двумя вариантами:
- С помощью Range
- С помощью Cells
Пример 1: Обратиться к ячейке A3 находящейся в Книге1 на Листе1
Workbooks("Книга1.xls").Sheets("Лист1").Range("A3") ' Обратиться к ячейке A3
Workbooks("Книга1.xls").Sheets("Лист1").Cells(3, 1) ' Обратиться к ячейке в 3-й строке и 1-й колонке (A3)
Однако, как правило, полный путь редко используется, т.к. макрос работает с Книгой, в которой он записан и часто на активном листе. Поэтому путь к ячейке можно сократить и написать просто:
Пример 2: Обратиться к ячейке A1 в текущей книге на активном листе
Range("A1")
Cells(1, 1)
Если всё же путь к книге или листу необходим, но не хочется его писать при каждом обращении к ячейкам, можно использовать конструкцию With End With. При этом, обращаясь к ячейкам, необходимо использовать в начале «.» (точку).
Пример 3: Обратиться к ячейке A1 и B1 в Книге1 на Листе2.
With Workbooks("Книга1").Sheets("Лист2")
' Вывести значение ячейки A1, которая находится на Листе2
MsgBox .Range("A1")
' Вывести значение ячейки B1, которая находится на Листе2
MsgBox .Range("B1")
End With
Так же, можно обратиться и к активной (выбранной в данный момент времени) ячейке.
Пример 4: Обратиться к активной ячейке на Листе3 текущей книги.
Application.ActiveCell ' полная запись ActiveCell ' краткая запись
Чтение значения из ячейки
Есть 3 способа получения значения ячейки, каждый из которых имеет свои особенности:
- Value2 — базовое значение ячейки, т.е. как оно хранится в самом Excel-е. В связи с чем, например, дата будет прочтена как число от 1 до 2958466, а время будет прочитано как дробное число. Value2 — самый быстрый способ чтения значения, т.к. не происходит никаких преобразований.
- Value — значение ячейки, приведенное к типу ячейки. Если ячейка хранит дату, будет приведено к типу Date. Если ячейка отформатирована как валюта, будет преобразована к типу Currency (в связи с чем, знаки с 5-го и далее будут усечены).
- Text — визуальное отображение значения ячейки. Например, если ячейка, содержит дату в виде «число месяц прописью год», то Text (в отличие от Value и Value2) именно в таком виде и вернет значение. Использовать Text нужно осторожно, т.к., если, например, значение не входит в ячейку и отображается в виде «#####» то Text вернет вам не само значение, а эти самые «решетки».
По-умолчанию, если при обращении к ячейке не указывать способ чтения значения, то используется способ Value.
Пример 5: В ячейке A1 активного листа находится дата 01.03.2018. Для ячейки выбран формат «14 марта 2001 г.». Необходимо прочитать значение ячейки всеми перечисленными выше способами и отобразить в диалоговом окне.
MsgBox Cells(1, 1) ' выведет 01.03.2018 MsgBox Cells(1, 1).Value ' выведет 01.03.2018 MsgBox Cells(1, 1).Value2 ' выведет 43160 MsgBox Cells(1, 1).Text ' выведет 01 марта 2018 г. Dim d As Date d = Cells(1, 1).Value2 ' числовое представление даты преобразуется в тип Date MsgBox d ' выведет 01.03.2018
Пример 6: В ячейке С1 активного листа находится значение 123,456789. Для ячейки выбран формат «Денежный» с 3 десятичными знаками. Необходимо прочитать значение ячейки всеми перечисленными выше способами и отобразить в диалоговом окне.
MsgBox Range("C1") ' выведет 123,4568
MsgBox Range("C1").Value ' выведет 123,4568
MsgBox Range("C1").Value2 ' выведет 123,456789
MsgBox Range("C1").Text ' выведет 123,457р.
Dim c As Currency
c = Range("C1").Value2 ' значение преобразуется в тип Currency
MsgBox c ' выведет 123,4568
Dim d As Double
d = Range("C1").Value2 ' значение преобразуется в тип Double
MsgBox d ' выведет 123,456789
При присвоении значения переменной или элементу массива, необходимо учитывать тип переменной. Например, если оператором Dim задан тип Integer, а в ячейке находится текст, при выполнении произойдет ошибка «Type mismatch». Как определить тип значения в ячейке, рассказано в следующей статье.
Пример 7: В ячейке B1 активного листа находится текст. Прочитать значение ячейки в переменную.
Dim s As String
Dim i As Integer
s = Range("B1").Value2 ' успех
i = Range("B1").Value2 ' ошибка
Таким образом, разница между Text, Value и Value2 в способе получения значения. Очевидно, что Value2 наиболее предпочтителен, но при преобразовании даты в текст (например, чтобы показать значение пользователю), нужно использовать функцию Format.
Запись значения в ячейку
Осуществить запись значения в ячейку можно 2 способами: с помощью Value и Value2. Использование Text для записи значения не возможно, т.к. это свойство только для чтения.
Пример 8: Записать в ячейку A1 активного листа значение 123,45
Range("A1") = 123.45
Range("A1").Value = 123.45
Range("A1").Value2 = 123.45
Все три строки запишут в A1 одно и то же значение.
Пример 9: Записать в ячейку A2 активного листа дату 1 марта 2018 года
Cells(2, 1) = #3/1/2018# Cells(2, 1).Value = #3/1/2018# Cells(2, 1).Value2 = #3/1/2018#
В данном примере тоже запишется одно и то же значение в ячейку A2 активного листа.
Визуальное отображение значения на экране будет зависеть от того, какой формат ячейки выбран на листе.
Обращение к ячейке на листе Excel из кода VBA по адресу, индексу и имени. Чтение информации из ячейки. Очистка значения ячейки. Метод ClearContents объекта Range.
Обращение к ячейке по адресу
Допустим, у нас есть два открытых файла: «Книга1» и «Книга2», причем, файл «Книга1» активен и в нем находится исполняемый код VBA.
В общем случае при обращении к ячейке неактивной рабочей книги «Книга2» из кода файла «Книга1» прописывается полный путь:
|
Workbooks(«Книга2.xlsm»).Sheets(«Лист2»).Range(«C5») Workbooks(«Книга2.xlsm»).Sheets(«Лист2»).Cells(5, 3) Workbooks(«Книга2.xlsm»).Sheets(«Лист2»).Cells(5, «C») Workbooks(«Книга2.xlsm»).Sheets(«Лист2»).[C5] |
Удобнее обращаться к ячейке через свойство рабочего листа Cells(номер строки, номер столбца), так как вместо номеров строк и столбцов можно использовать переменные. Обратите внимание, что при обращении к любой рабочей книге, она должна быть открыта, иначе произойдет ошибка. Закрытую книгу перед обращением к ней необходимо открыть.
Теперь предположим, что у нас в активной книге «Книга1» активны «Лист1» и ячейка на нем «A1». Тогда обращение к ячейке «A1» можно записать следующим образом:
|
ActiveCell Range(«A1») Cells(1, 1) Cells(1, «A») [A1] |
Точно также можно обращаться и к другим ячейкам активного рабочего листа, кроме обращения ActiveCell, так как активной может быть только одна ячейка, в нашем примере – это ячейка «A1».
Если мы обращаемся к ячейке на неактивном листе активной рабочей книги, тогда необходимо указать этот лист:
|
‘по основному имени листа Лист2.Cells(2, 7) ‘по имени ярлыка Sheets(«Имя ярлыка»).Cells(3, 8) |
Имя ярлыка может совпадать с основным именем листа. Увидеть эти имена можно в окне редактора VBA в проводнике проекта. Без скобок отображается основное имя листа, в скобках – имя ярлыка.
Обращение к ячейке по индексу
К ячейке на рабочем листе можно обращаться по ее индексу (порядковому номеру), который считается по расположению ячейки на листе слева-направо и сверху-вниз.
Например, индекс ячеек в первой строке равен номеру столбца. Индекс ячеек во второй строке равен количеству ячеек в первой строке (которое равно общему количеству столбцов на листе, зависящему от версии Excel) плюс номер столбца. Индекс ячеек в третьей строке равен количеству ячеек в двух первых строках плюс номер столбца. И так далее.
Для примера, Cells(4) та же ячейка, что и Cells(1, 4). Используется такое обозначение редко, тем более, что у разных версий Excel может быть разным количество столбцов и строк на рабочем листе.
По индексу можно обращаться к ячейке не только на всем рабочем листе, но и в отдельном диапазоне. Нумерация ячеек осуществляется в пределах заданного диапазона по тому же правилу: слева-направо и сверху-вниз. Вот индексы ячеек диапазона Range(«A1:C3»):
Обращение к ячейке Range("A1:C3").Cells(5) соответствует выражению Range("B2").
Обращение к ячейке по имени
Если ячейке на рабочем листе Excel присвоено имя (Формулы –> Присвоить имя), то обращаться к ней можно по присвоенному имени.
Допустим одной из ячеек присвоено имя – «Итого», тогда обратиться к ней можно – Range("Итого").
Запись информации в ячейку
Содержание ячейки определяется ее свойством «Value», которое в VBA Excel является свойством по умолчанию и его можно явно не указывать. Записывается информация в ячейку при помощи оператора присваивания «=»:
|
Cells(2, 4).Value = 15 Cells(2, 4) = 15 Range(«A1») = «Этот текст записываем в ячейку» ActiveCell = 28 + 10*36 |
Вместе с числами и текстом можно использовать переменные. Примеры здесь и ниже приведены для активного листа. Для неактивных листов дополнительно необходимо указывать имя листа, как в разделе «Обращение к ячейке».
Чтение информации из ячейки
Считать информацию из ячейки в переменную можно также при помощи оператора присваивания «=»:
|
Sub Test() Dim a1 As Integer, a2 As Integer, a3 As Integer Range(«A3») = 6 Cells(2, 5) = 15 a1 = Range(«A3») a2 = Cells(2, 5) a3 = a1 * a2 MsgBox a3 End Sub |
Точно также можно обмениваться информацией между ячейками:
|
Cells(2, 2) = Range(«A4») |
Очистка значения ячейки
Очищается ячейка от значения с помощью метода ClearContents. Кроме того, можно присвоить ячейке значение нуля. пустой строки или Empty:
|
Cells(10, 2).ClearContents Range(«D23») = 0 ActiveCell = «» Cells(5, «D») = Empty |
$begingroup$
I have an Excel Worksheet consisting of two columns, one of which is filled with strings and the other of which is empty. I would like to use VBA to assign the value of the cells in the empty column based on the value of the adjacent string in the other column.
Dim regexAdmin As Object
Set regexAdmin = CreateObject("VBScript.RegExp")
regexAdmin.IgnoreCase = True
regexAdmin.Pattern = "Admin"
Dim i As Integer
For i = 1 To 10 'let's say there is 10 rows
Dim j As Integer
For j = 1 To 2
If regexAdmin.test(Cells(i, j).Value) Then
Cells(i, j + 1).Value = "Exploitation"
End If
Next j
Next i
The problem is that when using this loop for a big amount of data, it takes way too long to work and, most of the time, it simply crashes Excel.
Does anyone know a better way of doing this?
Jamal
34.8k13 gold badges132 silver badges236 bronze badges
asked Aug 7, 2014 at 13:03
$endgroup$
0
$begingroup$
The short answer is:
Don’t use vba, use a formula. In particular, a combination of IF and SEARCH.
=IF(SEARCH($A1,"Admin")>0,"Exploitation","")
But this is code review, so let’s do that anyway.
-
Regex is slow. It seems that you’re only using it for it’s case insensitivity. Given that, you can directly compare cell values by using
StrCompwith thevbTextCompareoption. (useful article on StrComp) -
iandjare typically used for loop counters, butrowandcolmake more sense in this case.
Here is what this could could look like:
Dim row As Integer
For row = 1 To 10 'let's say there is 10 rows
Dim col As Integer
For col = 1 To 2
If StrComp("Admin",Cells(row, col).Value,vbTextCompare) Then
Cells(row, col + 1).Value = "Exploitation"
End If
Next col
Next row
answered Aug 7, 2014 at 16:07
RubberDuckRubberDuck
30.8k6 gold badges68 silver badges172 bronze badges
$endgroup$
$begingroup$
I would think that simple string comparison would be much faster than Regex.
Dim pattern as string
pattern = "Admin"
Dim i As Integer
For i = 1 To 10 'let's say there is 10 rows
Dim j As Integer
For j = 1 To 2
If Cells(i, j) = pattern Then
Cells(i, j + 1) = "Exploitation"
End If
Next j
Next i
answered Aug 7, 2014 at 18:29
PerryJPerryJ
1913 bronze badges
$endgroup$
1
$begingroup$
May I suggest a 50% reduction in runtime/effort?
Dim row As Integer
For row = 1 To 10 'let's say there is 10 rows
If StrComp("Admin",Cells(row, 1).Value,vbTextCompare) Then
Cells(row, 2).Value = "Exploitation"
End If
Next row
Did nobody notice that the OP talks about «checking ONE column, writing to the NEXT adjacent», really? Why loop columns then? The second pass would only check either an empty cell or one with «Exploitation» in it.
Alex L
5,7272 gold badges24 silver badges68 bronze badges
answered Jun 20, 2015 at 18:07
user1016274user1016274
6145 silver badges9 bronze badges
$endgroup$
$begingroup$
In B1:
=if(upper(A1)="ADMIN","Exploitation","")
Then just fill it down. This is case insensitive.
This auto fill can be done two ways, either interactively in the worksheet, or programmatically:
Interactively: Excel has an autofill feature. With B1 selected and that formula put in, just double click the fill handle, which is the tiny square in the bottom right corner of cell when it’s selected. Excel will intelligently copy the formula down to the end of the contiguous range that has data. Meaning if A1-A256 has data with no blanks, it’ll autofill to B256. Alternatively, if there are blanks, scroll to the bottom and select B256 (or whatever the end is). Then Ctrl + Shift + Up arrow to select the range leading to B1, and Ctrl+D to copy it down (think d= ditto)
Using VBA… if you must do this programmatically: with the formula containing cell as your selection:
Selection.AutoFill Destination:=Range("B1:B19")
There’s other options available for autofill to do a few cool tricks. Can copy a literal value instead of a formula, or also fill a series based on a pattern. You can also set custom patterns for it to recognize, such as lines of business you commonly repeat in stuff or cities you have retail locations in, etc.
rolfl
97.1k17 gold badges214 silver badges417 bronze badges
answered Sep 14, 2015 at 21:49
Gary RitterGary Ritter
3893 silver badges4 bronze badges
$endgroup$
1
$begingroup$
Wow. Just reading through the first couple of lines got me wondering:
- Why the late-binding?
- Why use a regex at all?
@ckuhn203 already addressed the naming in his answer, but I find this:
Dim i As Integer For i = 1 To 10 'let's say there is 10 rows
Turned into that:
Dim row As Integer
For row = 1 To 10 'let's say there is 10 rows
…Doesn’t need the comment anymore.
I would like to use VBA to assign the value of the cells in the empty column based on the value of the adjacent string in the other column.
I think that’s [mis|ab]using VBA: Excel itself is very good at dealing with assigning cell values based on other cells’ values.
regexAdmin.Pattern = "Admin"
I think that’s [mis|ab]using regex: if your pattern is just a plain word, you’re most probably trying to kill a mosquito with a bazooka. Wrong tool for the job here.
answered Aug 7, 2014 at 16:18
Mathieu GuindonMathieu Guindon
74.9k17 gold badges189 silver badges460 bronze badges
$endgroup$
$begingroup$
Whenever you are accessing the Range object it should be done with a single read/write operation.
Prior to entering the for loop you should read the entire range that you are looking to work with.
data = Range(Cells(1,1), Cells(10,2)).Value
Now you can work with the data:
For i = 1 To 10 'let's say there is 10 rows
Dim j As Integer
For j = 1 To 2
If regexAdmin.test(data(i, j)) Then
data(i, j + 1) = "Exploitation"
End If
Next j
Next i
Finally write the data back to excel:
Range(Cells(1,1), Cells(10,2)).Value = data
answered Jun 20, 2015 at 5:26
$endgroup$
$begingroup$
Combining all the other answers together, made it case insensitive like the regex in the original, removed the need to specify how many rows and declaring all the variables because Option Explicit avoids so many errors in vba
Option Explicit
Sub checkForExploit()
Dim row As Integer
Dim data() As Variant
Dim datarange As Range
Set datarange = Range("A1:B10")
data = datarange.Value
For row = 1 To UBound(data, 1)
If LCase(data(row, 1)) = "admin" Then
data(row, 2) = "Exploitation"
End If
Next row
datarange.Value = data
End Sub
answered Dec 20, 2019 at 15:27
$endgroup$
0
|
xlgrgrc Пользователь Сообщений: 3 |
Всем доброго времени суток. Ввожу первоначальные данные в Excel. (Прикрепленный документ Исходные данные). Нажимаю кнопку «выполнить». Данные вбиваются в 2 документа в соответствующие места, каждый сохраняется под своим именем в нужном месте, оригинал в своей папке. Так же 1 копия документа выделяется и копируется в Word, сохраняется куда нужно. Private Sub Ok_Click() Тоесть теперь у меня есть уже готовый документ Word (Постановление) и мне нужно прикрепленного документ «Исходные данные» вставить в ворд в определенные места Вместо XXX1 нужные данные. Вопросы. В школе хорошо кодил на бейсике (олимпиады) сейчас занимаюсь AutoIT (скрипты). Нужен совет. Либо ссылка на подробное описание лексики VBa. Заранее спасибо! |
|
xlgrgrc Пользователь Сообщений: 3 |
|
|
Sub Макрос1() ‘ Range(«A1»).Select — выбрать ячейку A1 Как теперь переключиться на Word? |
|
|
Юрий М Модератор Сообщений: 60570 Контакты см. в профиле |
1. Не нужно Select: Range(«A1»).Copy Если переменной, то: Переменная=Range(«A1»).value <BR>2. У нас работает поиск: http://yandex.ru/sitesearch?text=%EE%F2%EA%F0%FB%F2%FC+%E4%EE%EA%F3%EC%E5%ED%F2+word&searchid=84804&web=0&lr=22 |
|
Так с переменной ппонял. Получилось. Ошибка была что копировал и получался пробел x = Лист 1.Cells(1, 1) в Лист1. Про поиск в курсе но задавал вопрос Excel в ворд. Прочитал много даже пример открытия чистого Word видел . Щас перечитаю ещё. ))) Спасибо что отозвался ))) |
|
|
xlgrgrc Пользователь Сообщений: 3 |
Решил задачу на примере вот этого http://www.planetaexcel.ru/forum.php?thread_id=19286 Юрий М — спасибо большое ) Очень благодарен. Вот код что получился в итоге — может кому пригодиться… Sub Макрос1() Dim sOM As String, sDocNum As String sOM = «G:. ШаблоныПостановление.doc» ‘sOM = Range(«B9»).Value End Sub Код берет из Excel данные ячеек и вставляет их в закладки в Word. Когда получилось оказалось всё проще чем думал. Если что то вот адрес страницы в контакте — http://vkontakte.ru/popov_sergey_vladimirovich |
|
У меня ещё вопрос возник. Итогом этого макроса является открытый документ Word. Ни как не получается его сохранить и закрыть или макроса Excel/ Пишу .Close закрывается Окно Excel откуда был запущен макрос. А как мне дать команду Ворду что бы он сохранился куда нужно и закрылся ? |
|
|
Hugo Пользователь Сообщений: 23249 |
Могу такую цитату предложить — вроде всё есть: Private Sub start_DblClick(Cancel As Integer) |
|
Ага спасибо ) Только что получилось, зашел как раз поделиться тоже ))) Sub Макрос1() xNp = Range(«B2»).Value sOM = «G:. ШаблоныПостановление.doc» xxData = xData & » № » & xNp dc1.SaveAs «G:. ШаблоныПостановление1.doc» dc1.Close Set dc1 = Nothing End Sub Принцип понял ) И ошибку понял ))) |
|
|
Юрий М Модератор Сообщений: 60570 Контакты см. в профиле |
В Word есть такая штука, как СЛИЯНИЕ. Может его задействовать? |
|
Да Юра читал про неё даже пробовал. Но на сколько я понял — слияние больше подходит для формирование документа из списка: рассылка поздравлений и т.д. где перебирается весь список в цикле и вставляется в нужные места. У меня же это делает 1 раз и трижды пересохраняется документ. Моя ошибка была с переменными. Щас не помню, но есть сообщение на этом форуме в котором расписана структура документа ворд и эксель. Я его читал раз 6 и только к вечеру понял как то реализовано на VBA … Вообщем, очень благодарен всем за помощь ) Форум что наде!!! |
|
|
Как это элементарно, но давно не рабоитала в Exce, многое забыла. Что бы мы делали без инета? Спасибо |
|
|
Guest Гость |
#13 12.12.2012 10:58:20 спасибо, большое. Инфо мне пригодилось |
Небольшая памятка по работе с макросами VBA Excel. Для вставки в код, измените название листа и диапазон ячеек на свой.
Добавить текст к значениям (в данном случае добавить слово «add» в начале ячеек):
1 2 3 |
For Each c In Worksheets("list1").Range("F7:F44").Cells c.Value = "add" + CStr(c.Value) Next |
Добавить к значениям текст из соседней ячейки справа:
1 2 3 |
For Each c In Worksheets("list1").Range("F7:F44").Cells c.Value = CStr(c.Value) + " " + c.Cells(1, 2).Value Next |
Вывести строку обрезанную до 6 символов:
1 2 3 |
For Each c In Worksheets("list1").Range("J3:J175").Cells c.Value = Left(c.Value, 6) Next |
Убрать все после первого пробела:
1 2 3 4 5 6 |
For Each c In Worksheets("list1").Range("J3:J175").Cells c.Value = CStr(c.Value) + " " spacePos = inStr(1, c.Value, " ") artLen = spacePos - 1 c.Value = Left(c.Value, artLen) Next |
Убрать все до первого пробела, затем убрать пробелы в начале строки:
1 2 3 4 5 |
For Each c In Worksheets("list1").Range("D2:D79").Cells spacePos = InStr(1, c.Value, " ") c.Value = Mid(c.Value, spacePos) c.Value = LTrim(c.Value) Next |
Если здесь нет нужного вам макроса, посмотрите ещё часть 2.

