Vba excel автонумерация строк

Автоматическая нумерация строк в Excel по порядку с помощью VBA

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

ручная нумерация строк

Вот так делается ручная нумерация строк

Но когда возникает необходимость делать эту процедуру часто, или ввиду обилия нескольких разделов и подразделов – ручная нумерация строк в таблице excel превращается в скучную рутинную работу. И гораздо приятнее написать макрос нумерации строк excel и наслаждаться результатом через долю секунды.

нумерация строк используя макрос vba

excel vba автоматическая нумерация строк

Работоспособный макрос нумерации строк в excel по порядку приведен ниже:


Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' Обновить нумерацию
If ActiveCell.Column = 10 And Cells(ActiveCell.Row, ActiveCell.Column).Value = "Обновить нумерацию" And ActiveCell.Row = 2 Then
' ссылка на лист книги в котором обновляем нумерацию
Set pr = Workbooks("planero-s-avtomaticheskoj-numeraciej-strok.xlsm").Worksheets("Проекты")
i = 0 ' для работоспособности цикла
j = 1 ' номер задачи
k = 1 ' номер подзадачи
' проходим вниз по странице до тех пор, пока есть записи в ячейке "B3" или "C3"
Do While pr.Range("B3").Offset(i, 0) > 0 Or pr.Range("D3").Offset(i, 0) > 0
' если ячейка "В3"+i содержит текст
If pr.Range("B3").Offset(i, 0) > 0 Then
' нумеруем ее
pr.Range("A3").Offset(i, 0) = j
' выделяем номер жирным
pr.Range("A3").Offset(i, 0).Font.Bold = True
' увеличиваем переменную j на единицу
j = j + 1
' обнуляем номер подзадачи
k = 1
' если ячейка "B3"+i пустая, следовательно мы имеем дело с подзадачей
Else
' если ячейка "D3"+i содержит текст
If pr.Range("D3").Offset(i, 0) > 0 Then
' нумеруем ее
pr.Range("C3").Offset(i, 0) = k
' увеличиваем номер подзадачи на единицу
k = k + 1
End If
End If
' увеличиваем i на +1 чтобы проверить следующию ячейку (расположенную ниже) на наличие записи
i = i + 1
Loop
' убираем курсор с кнопки
pr.Cells(ActiveCell.Row, ActiveCell.Column - 2).Select
End If
End Sub

Первым делом привязываем запуск макроса при нажатии на кнопку «Обновить нумерацию». Далее запускаем цикл и выполняем его до тех пор, пока ячейка B3 и D3 содержит текст. При этом последовательно перемещаемся к ниже идущим ячейкам от B3 и D3, используя Offset и переменную i: .offset(i, 0). Одновременно с этим, нумеруем задачи (если B3+i содержит текст) и подзадачи (если B3+i не содержит текст, при этом содержит текст D3+i). Ну и напоследок убираем курсор с кнопки «Обновить нумерацию».

Саму экселевсую книгу с макросом автоматической нумерации можно скачать по этой ссылке. На этом все. Остались вопросы – задавайте их в комментариях. С другими кейсами по автоматизации можно ознакомиться здесь.

Комментарии 2

© планеро.ru

Olya1985

32 / 2 / 0

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

Сообщений: 91

1

Макрос для автоматической нумерации строк

07.01.2011, 13:27. Показов 32903. Ответов 15

Метки нет (Все метки)


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

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

Visual Basic
1
2
3
4
5
6
7
Private Sub worksheet_change (byval target as range) 
 
For Each oCell In Range([D1], Cells(Rows.Count, "D")).Cells
    If Not IsEmpty(oCell) Then iCount = iCount + 1: oCell.Previous = iCount
Next
 
End Sub



0



Частенько бываю

749 / 330 / 42

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

Сообщений: 854

07.01.2011, 17:40

2

А чем же вас этот код не устраивает конкретно?



0



32 / 2 / 0

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

Сообщений: 91

07.01.2011, 17:42

 [ТС]

3

он зависает после нумерации первой строки…



0



Vlanib

Частенько бываю

749 / 330 / 42

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

Сообщений: 854

07.01.2011, 18:03

4

Естественно! Исправьте макрос следующим образом:

Visual Basic
1
2
3
4
5
6
7
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal target As Range)
Application.EnableEvents = False
For Each oCell In Range([D1], Cells(Rows.Count, "D")).Cells
    If Not IsEmpty(oCell) Then iCount = iCount + 1: oCell.Previous = iCount
Next
Application.EnableEvents = True
End Sub



0



32 / 2 / 0

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

Сообщений: 91

07.01.2011, 18:07

 [ТС]

5

Vlanib,

теперь строки не нумеруются…



0



Частенько бываю

749 / 330 / 42

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

Сообщений: 854

07.01.2011, 18:15

6

Скиньте ваш файлик.



0



32 / 2 / 0

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

Сообщений: 91

07.01.2011, 18:24

 [ТС]

7

файлик прилагаю



0



Частенько бываю

749 / 330 / 42

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

Сообщений: 854

07.01.2011, 18:30

8

Видимо не приложился…



0



32 / 2 / 0

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

Сообщений: 91

07.01.2011, 18:32

 [ТС]

9

еще раз попробую…



0



Частенько бываю

749 / 330 / 42

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

Сообщений: 854

07.01.2011, 18:56

10

Так, Оленька, давайте обстоятельно. В этом вашем посте вы просили перевести формулу на ВБА, что я и сделал дословно. Данная вами формула возвращает в ячейку количество аргументов в столбце «D». Если бы вы изначально правильно сформулировали задачу, то и вопросов было бы меньше.
Внимательно посмотрите где располагается макрос. Если нужно чтобы он работал только для конкретной страницй, то код нужно разместить в модуле листа, в событии его изменения. Макрос нумерует столбец А если в В есть значение.



1



32 / 2 / 0

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

Сообщений: 91

07.01.2011, 19:01

 [ТС]

11

Vlanib,

спасибо! только осталась еще одна проблема.. при удалении строки в столбце B номер все равно остается. при использовании же формулы он исчезает вместе с удаленным текстом. можно ли в макросе сделать также?



0



Vlanib

Частенько бываю

749 / 330 / 42

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

Сообщений: 854

07.01.2011, 19:25

12

Visual Basic
1
2
3
4
5
6
7
8
9
Application.EnableEvents = False
For Each oCell In Range([B1], Cells(ActiveSheet.UsedRange.Rows.Count, "B")).Cells
    If Not IsEmpty(oCell) Then
        iCount = iCount + 1
        oCell.Previous = iCount
    Else: oCell.Previous.Clear
    End If
Next
Application.EnableEvents = True



1



32 / 2 / 0

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

Сообщений: 91

07.01.2011, 20:26

 [ТС]

13

теперь отлично. спасибо!

Добавлено через 13 минут
Vlanib,

извиняюсь, но еще одна небольшая проблемка. последнее введенное значение не пронумеровывается. как можно это исправить?

Добавлено через 16 минут
Vlanib,

прошу мое предыдущее сообщение считать недействительным.

у меня овт еще вопрос. я не совсем понимаю для чего используется Application.EnableEvents = False или True. Не могли бы вы вкратце объяснить?

Добавлено через 6 минут
я что то порядком запуталась… последняя строка и правда не нумеруется……..



0



1904 / 781 / 31

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

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

07.01.2011, 22:41

14

EnableEvents, как следует из перевода, отключает или включает обработку событий приложения (т. е события могут либо игнорироваться, либо при возникновении событий могут вызываться соответствующие обработчики этих событий) http://support.microsoft.com/kb/213720

Не по теме:

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

я что то порядком запуталась

ВОЗМОЖНО, выполнение кода было остановлено пользователем между инструкциями Application.EnableEvents = False/True и события перестали обрабатываться вплоть до повторного открытия приложения



0



91 / 1 / 1

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

Сообщений: 2

09.01.2013, 11:15

15

Лучший ответ Сообщение было отмечено как решение

Решение

Уважаемый Vlanib Спасибо — Очень интересное решение , а можно дописать макрос чтоб в » A » счет шел с первой пустой ячейки ( так как обычно бывают шапки в таблицах — получится макрос на все случаи жизни



0



8 / 8 / 0

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

Сообщений: 159

20.02.2021, 14:05

16

Vlanib, а как переписать макрос, чтобы он нумеровал строку не по приницпу «количество столбцов выше+1», а «значение в предыдущей ячейке+1». У меня нумерация строк просто 10001, 10002..



0



Содержание

  1. Автоматическая нумерация строк в Excel по порядку с помощью VBA
  2. Сборник полезностей
  3. пятница, 1 февраля 2013 г.
  4. Excel VBA. На старт
  5. Основы
  6. Автоматическая нумерация строк таблицы
  7. Кнопки вставки и удаления строк
  8. Проверка листа на правильное заполнение
  9. Vba excel пронумеровать строки таблицы
  10. Vba excel пронумеровать строки таблицы

Автоматическая нумерация строк в Excel по порядку с помощью VBA

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

Вот так делается ручная нумерация строк

Но когда возникает необходимость делать эту процедуру часто, или ввиду обилия нескольких разделов и подразделов – ручная нумерация строк в таблице excel превращается в скучную рутинную работу. И гораздо приятнее написать макрос нумерации строк excel и наслаждаться результатом через долю секунды.

excel vba автоматическая нумерация строк

Работоспособный макрос нумерации строк в excel по порядку приведен ниже:

Первым делом привязываем запуск макроса при нажатии на кнопку «Обновить нумерацию». Далее запускаем цикл и выполняем его до тех пор, пока ячейка B3 и D3 содержит текст. При этом последовательно перемещаемся к ниже идущим ячейкам от B3 и D3, используя Offset и переменную i: .offset(i, 0) . Одновременно с этим, нумеруем задачи (если B3+i содержит текст) и подзадачи (если B3+i не содержит текст, при этом содержит текст D3+i). Ну и напоследок убираем курсор с кнопки «Обновить нумерацию».

Саму экселевсую книгу с макросом автоматической нумерации можно скачать по этой ссылке. На этом все. Остались вопросы – задавайте их в комментариях. С другими кейсами по автоматизации можно ознакомиться здесь.

Источник

Сборник полезностей

пятница, 1 февраля 2013 г.

Excel VBA. На старт

Основы

‘ в ячейку А1 пишем «add note» + значение ячейки B1
Cells(1,1).Value = «add note » & Cells(1,2).Value

For Each oCell In Range(«A1:A10»).Cells
‘обработка
oCell.Value = oCell.Row ‘ присвоили номер строки
Next

Public Function insertRow()
Dim position As Integer
‘.
insertRow = position ‘возвращаемое значение

После написания нескольких функций во встроенном редакторе, меня нешуточно заинтересовало, как перенести строку кода на следующую физическую строку. Если посреди строки кода нажать enter, кроме ошибки мы ничего не добьемся. Оказывается, надо использовать «_»:

If ActiveSheet.Index = 1 _
Or ActiveSheet.Index = 4 Then
‘ действия
End If

Нарочно и не придумаешь.

Помимо массивов, в VBA следует обратить внимание на коллекции. Работать с ними просто:

Dim сoll As New Collection
сoll .Add («элемент1») ‘добавляем элемент
сoll .Add («элемент2») ‘размер увеличивается динамически
‘ по умолчанию индекс начинается с 1, можно изменить
MsgBox ( сoll .Item(1)) ‘ элемент1
сoll . Remove (1) ‘ удаляем первый элемент
MsgBox ( сoll .Count) ‘выводим размер коллекции

Автоматическая нумерация строк таблицы

Это потому, что формула в строке А9 крайне смущена тем, что ссылается на удаленную ячейку. Поэтому если строки в таблице буду удаляться и добавляться, лучше сделать ссылку на ячейки другой страницы (=СТРОКА(Лист2!А1)).

Кнопки вставки и удаления строк

Само по себе добавление и удаление по имени кнопки сложности не представляет:

Private Sub InsertButton1_Click( position as Integer )
‘вставка строки перед строкой с номером position
Rows(position).Insert
End Sub

Private Sub DeleteButton1_Click()
Dim position as Integer
‘ ищем номер строки кнопки удаления
position = _ ActiveSheet.Shapes(Application.Caller).TopLeftCell.Row
‘ удаление кнопки
ActiveSheet.Shapes(Application.Caller).Delete
‘ удаление строки с номером position
Rows(position).Delete
End Sub

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

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

Проверка листа на правильное заполнение

В голову пришло два слегка костыльных способа решения (и честно говоря, если судить по форумам с обсуждением подобных проблем, кажется, что применительно к Excel по-другому их и не решишь).

Первый способ: в одном столбце, напротив каждой строки таблицы, формулой вычисляется, правильно ли заполнена строка. Тогда, проходясь по этому столбцу, мы можем сказать, в какой строке проблема. А при помощи условного форматирования проблемные ячейки могут подсвечиваться красным. Этого достаточно, если не надо точно знать, в какой ячейке проблема. При необходимости можно дальше обрабатывать эту строку по ячейкам. Способ хорош, если разные строки проверяются на разные условия (даже в рамках одной таблицы).

Источник

Vba excel пронумеровать строки таблицы

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

Private Sub worksheet_change (byval target as range)

For Each oCell In Range([D1], Cells(Rows.Count, «D»)).Cells
If Not IsEmpty(oCell) Then iCount = iCount + 1: oCell.Previous = iCount
Next

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

Этот макрос будет зависать после нумерации любой строки.

Почему?
Да потому, что вы не прислушиваетесь к советам.
Я вам уже говорил, что надо дописать в коде, чтобы не было зависаний:
http://programmersforum.ru/showpost. 53&postcount=2

но когда я это дописала, то нумерация вообще пропала.

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal target As Range)
Application.EnableEvents = False
For Each oCell In Range([D1], Cells(Rows.Count, «D»)).Cells
If Not IsEmpty(oCell) Then iCount = iCount + 1: oCell.Previous = iCount
Next
Application.EnableEvents = True
End Sub

Мы не видели ваш файл, не знаем, что и как там надо нумеровать, так что, извините, ответа вы вряд ли дождётесь.

Почитайте правила раздела — там есть рекомендация каждый раз выкладывать пример файла.

Источник

Vba excel пронумеровать строки таблицы

= Мир MS Excel/Нумерация строк — Мир MS Excel

Войти через uID

Войти через uID

Модератор форума: китин, _Boroda_

Мир MS Excel » Вопросы и решения » Вопросы по VBA » Нумерация строк (Макросы Sub)

Нумерация строк

Гисер Дата: Пятница, 04.10.2013, 08:13 | Сообщение № 1

Есть такая проблема, не могу придумать как пронумеровать позиции
в общем есть такая табличка предположим

№, п/п Наименование Показатель, Макс. Периметр или Диаметр Материал Объем, м2 Цена Итого, руб.
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73

Число строк естественно меняется в зависимости от числа позиций. Как что бы перед наименованием проставить порядковый номер позиции.
Макрос выглядит так
[vba]

200?’200px’:»+(this.scrollHeight+5)+’px’);»> Sub Прямик_фас()
Application.ScreenUpdating = False

‘ Вставим наименование
Sheets(«прямоугольный с фас.»).Select
Range(«B1»).Select
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«B4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ Вставим показатель
Sheets(«прямоугольный с фас.»).Select
Range(«A2»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«C4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ вставим материал
Sheets(«прямоугольный с фас.»).Select
Range(«A7»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«D4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ Вставим объем
Sheets(«прямоугольный с фас.»).Select
Range(«F2»).Select
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«E4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ Вставим цену
Sheets(«прямоугольный с фас.»).Select
Range(«F24»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«G4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘Вставим итого
Application.ScreenUpdating = True
Sheets(«прямоугольный с фас.»).Select
Range(«E24»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«H4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets(«прямоугольный с фас.»).Select
Application.Cursor = xlDefault
End Sub

Есть такая проблема, не могу придумать как пронумеровать позиции
в общем есть такая табличка предположим

№, п/п Наименование Показатель, Макс. Периметр или Диаметр Материал Объем, м2 Цена Итого, руб.
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73

Число строк естественно меняется в зависимости от числа позиций. Как что бы перед наименованием проставить порядковый номер позиции.
Макрос выглядит так
[vba]

200?’200px’:»+(this.scrollHeight+5)+’px’);»> Sub Прямик_фас()
Application.ScreenUpdating = False

‘ Вставим наименование
Sheets(«прямоугольный с фас.»).Select
Range(«B1»).Select
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«B4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ Вставим показатель
Sheets(«прямоугольный с фас.»).Select
Range(«A2»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«C4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ вставим материал
Sheets(«прямоугольный с фас.»).Select
Range(«A7»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«D4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ Вставим объем
Sheets(«прямоугольный с фас.»).Select
Range(«F2»).Select
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«E4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ Вставим цену
Sheets(«прямоугольный с фас.»).Select
Range(«F24»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«G4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘Вставим итого
Application.ScreenUpdating = True
Sheets(«прямоугольный с фас.»).Select
Range(«E24»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«H4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets(«прямоугольный с фас.»).Select
Application.Cursor = xlDefault
End Sub

Сообщение Есть такая проблема, не могу придумать как пронумеровать позиции
в общем есть такая табличка предположим

№, п/п Наименование Показатель, Макс. Периметр или Диаметр Материал Объем, м2 Цена Итого, руб.
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73

Число строк естественно меняется в зависимости от числа позиций. Как что бы перед наименованием проставить порядковый номер позиции.
Макрос выглядит так
[vba]

Источник

Adblock
detector

 

Hashtag

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

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

#1

08.02.2019 15:48:43

Добрый день. Помогите создать нумерацию не пустых строк средствами VBA, без формул в ячейках. Нумерация должна начинаться с 7 строки в колонке B. При очистке строки нумерация в строке должна удаляться и продолжить нумерацию со следующей не пустой строки.
Имеющийся код начинает нумеровать с первой строки и не очищает значения с последующим продолжением нумерации.

Код
Application.EnableEvents = False
   RowMax = Cells.SpecialCells(xlCellTypeLastCell).Row
   ColMax = Cells.SpecialCells(xlCellTypeLastCell).Column
   n = 0
   For i = 1 To RowMax
      For j = 1 To ColMax
         If Not IsEmpty(Cells(i, j)) Then
            n = n + 1
            Cells(i, 2) = n
            Exit For
         End If
      Next j
   Next i
Application.EnableEvents = True

Прикрепленные файлы

  • Пример.xlsm (25.33 КБ)

 

Ігор Гончаренко

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

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

#2

08.02.2019 16:03:35

Код
Sub RenumB()
  Dim b As Range, c As Range, i&, r&
  For r = 1 To Cells.SpecialCells(xlCellTypeLastCell).Row
    If WorksheetFunction.CountBlank(Rows(r)) < Columns.Count Then If b Is Nothing Then Set b = Cells(r, 2) Else Set b = Union(b, Cells(r, 2))
  Next
  i = 1
  For Each c In b
    c = i: i = i + 1
  Next
End Sub

Программисты — это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!

 

vikttur

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

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

#3

08.02.2019 16:06:39

Цитата
Hashtag написал: не очищает значения с последующим продолжением нумерации

Событие листа…

 

Hashtag

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

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

#4

08.02.2019 19:33:11

Ігор Гончаренко
vikttur
Не удаляется нумерация в очищенной от записей строке. Также, при попытке очистить всю нумерацию выдает «Run-time error 424  Object required»? а в коде выделяется строка For Each c In b

Посмотрите, пожалуйста, что в коде не так?

Скрытый текст

Прикрепленные файлы

  • Пример2.xlsm (25.96 КБ)

Изменено: Hashtag08.02.2019 19:36:13

 

Vintic

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

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

#5

08.02.2019 19:44:16

Код
Sub num()
lr = Cells(Rows.Count, 3).End(xlUp).Row
Range(Cells(1, 1), Cells(lr, 1)).Clear
For i = 7 To lr
    If Application.WorksheetFunction.CountA(Rows(i)) <> 0 Then
        k = k + 1
        Cells(i, 1) = k
    End If
Next i
End Sub
 

Hashtag

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

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

Vintic
Почти работает! Но если очищать строку с конца списка, например, последнюю строку, то номер строки не удаляется.

 

Юрий М

Модератор

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

Контакты см. в профиле

Файл не смотрел… Попробуйте увеличить переменную номера последней строки на единичку:
lr = Cells(Rows.Count, 3).End(xlUp).Row +1

 

Vintic

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

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

#8

08.02.2019 21:25:38

Подлечил немного) Надеюсь сейчас все нормально

Код
Sub num()
lr = Cells(Rows.Count, 3).End(xlUp).Row
Range(Cells(1, 1), Cells(lr + 1, 1)).Clear
For i = 7 To lr
    If Application.WorksheetFunction.CountA(Rows(i)) <> 0 Then
        k = k + 1
        Cells(i, 1) = k
    End If
Next i
End Sub
 

Vintic

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

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

#9

08.02.2019 21:27:45

Цитата
Юрий М написал:
Попробуйте увеличить переменную номера последней строки на единичку

Спасибо, сделал почти так же

 

Hashtag

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

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

#10

08.02.2019 21:28:43

Юрий М

Цитата
lr = Cells(Rows.Count, 3).End(xlUp).Row +1

Если снизу очищать несколько строк, номера остаются кроме одного

 

см.вложение

Программисты — это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!

 

Hashtag

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

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

Vintic
Тоже самое. Если очищать несколько строк снизу, все номера напротив, кроме одного, остаются.

 

Hashtag

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

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

Ігор Гончаренко
В вашем примере ни один номер, к сожалению, автоматически не удаляется, вариант Vintic сейчас ближе всего к правде.

 

Юрий М

Модератор

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

Контакты см. в профиле

#14

08.02.2019 21:56:22

Цитата
Hashtag написал:
Если снизу очищать несколько строк

В каких ячейках (столбцах) Вы удаляете значения?

 

Hashtag

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

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

Юрий М
В этом примере очистите диапазон C18:F21 и C7:F10. Сверху номера автоматом удаляются, снизу — нет. Код от Vintic.

Изменено: Hashtag08.02.2019 22:04:01

 

skais675

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

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

 

Юрий М

Модератор

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

Контакты см. в профиле

#17

08.02.2019 22:37:52

Код
lr = Cells(Rows.Count, 1).End(xlUp).Row
 

Hashtag

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

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

skais675
Если снизу или сверху очищать строки, номера удаляются хорошо.
1.Но теперь если очищать снизу колонку C, номера удаляются, а должны удаляться только при полностью очищенной строке в диапазоне C:F.
2.При копировании кнопкой не происходит нумерация, если не заполнена ячейка C3, но должна происходить, даже если заполнена любая ячейка в диапазоне C:F.

 

ocet p

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

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

#19

09.02.2019 01:38:10

Пожалуйста, проверьте:

Код
Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim maks As Long, stk As Long, strk
    ReDim strk(1 To 5)
    For stk = 3 To 6
        strk(stk - 1) = Cells(Rows.Count, stk).End(xlUp).Row
    Next
    strk(1) = Cells(Rows.Count, 1).End(xlUp).Row
    maks = Application.Max(strk)
    If Intersect(Target, Range("c7:f" & maks)) Is Nothing Then Exit Sub
    Application.EnableEvents = False
    If maks <= 7 And Application.CountA(Range("c7:f7")) = 0 Then
        Range("a7").ClearContents: GoTo konets
    Else
        Range("a7:a" & maks).ClearContents
    End If
    strk = Empty
    stk = 0
    For Each strk In Range("c7:f" & maks).Rows
        If Application.CountA(strk) > 0 Then
            stk = stk + 1
            Range("a" & strk.Row).Value = stk
        End If
    Next
konets: Application.EnableEvents = True
End Sub
 

skais675

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

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

Ну раз такое дело, тогда так.

 

Hashtag

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

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

#21

09.02.2019 13:32:11

skais675
Все безупречно, спасибо вам огромное.
ocet p
Не удалось проверить ваш код, постоянно была ошибка в этом месте:

Код
If Intersect(Target, Range("c7:f" & maks)) Is Nothing Then

От себя хочу поблагодарить всех, кто отозвался решить эту задачу и внес свой вклад в ее разрешение, не оставили наедине с проблемой и довели дело до конца. Спасибо всем!

 

vikttur

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

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

#22

09.02.2019 13:39:15

Цитата
Hashtag написал: ocet p Не удалось проверить ваш код

Код в модуле листа? Нужно показать, тогда и на ошибку укажут.

 

Hashtag

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

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

#23

09.02.2019 14:16:43

vikttur

Цитата
Код в модуле листа? Нужно показать, тогда и на ошибку укажут.

Если в модуле листа, ошибку не выдает, но и нумерация не происходит.

Прикрепленные файлы

  • Пример4.xlsm (23.55 КБ)

 

vikttur

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

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

#24

09.02.2019 14:22:01

Код
Private Sub Worksheet_Change(ByVal Target As Range)
Application.ScreenUpdating = 0
Call num

Название процедуры указывает на то, что это — процедура отслеживания события листа (Worksheet_Change) — код должен быть в модуле листа.
Последняя показанная строка — переход к выпонению макроса  num. Да, он у Вас есть… но пустой.

По коду Worksheet_Change. Вы изменили предложенный макрос.

Код
 If Intersect(Target, Range("C3:F3")) Is Nothing Then Exit Sub

Если изменения произошли не в диапазоне C3:F3, уходим. Т.е. до проверки диапазона Range(«c7:f» & maks) никак не дойдет

Это вообще лишнее:

Код
  Application.EnableEvents = Truе 
  Application.EnableEvents = False
 

Юрий М

Модератор

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

Контакты см. в профиле

Hashtag, в #17 я предложил минимальную правку (к старым файлам), которая решала проблему.

 

Hashtag

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

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

#26

09.02.2019 17:06:07

vikttur
Вы правы, вариант от ocet p работает.

Прикрепленные файлы

  • Пример5.xlsm (22.1 КБ)

Here is my code to add line numbers in the VBE IDE. It is an improvement of the solution provided here by Excel MVP mikerickson. I have worked on this, because in some rare cases I have already met, VBE can’t enter in debug mode, for example when you have a .ReplaceLine method in your code. Indeed, you can’t enter in debug mode once it has been executed, so Erl might be usefully for debug (instead of Debug.Print). I have added several feature such as:

  • possibility to either add line numbers as labels: 10: Dim foo as bar or as single numbers seperated from code by a tab: 10 Dim foo as bar
  • possibility to add line numbers to End of procedures statements, and to match the indent of the procedure declaration lines to its End statement line once numberered. Or not.
  • possibility of add line numbers to empty lines or not
  • [WIP] possibility to add line numbers to a specific procedure in a module
  • [WIP] match all indentations of code lines with line numbers to match the indent of the last line indented. If last line is 200: End Sub, the line 30: With ActiveSheet will be re-indented as 30: ActiveSheet
  • [WIP] add of a VBE IDE command to directly make the calls with the current module/proc as a parameter
Public Enum vbLineNumbers_LabelTypes
    vbLabelColon    ' 0
    vbLabelTab      ' 1
End Enum

Public Enum vbLineNumbers_ScopeToAddLineNumbersTo
    vbScopeAllProc  ' 1
    vbScopeThisProc ' 2
End Enum

Sub AddLineNumbers(ByVal wbName As String, _
                   ByVal vbCompName As String, _
                   ByVal LabelType As vbLineNumbers_LabelTypes, _
                   ByVal AddLineNumbersToEmptyLines As Boolean, _
                   ByVal AddLineNumbersToEndOfProc As Boolean, _
                   ByVal Scope As vbLineNumbers_ScopeToAddLineNumbersTo, _
                   Optional ByVal thisProcName As String)

' USAGE RULES
' DO NOT MIX LABEL TYPES FOR LINE NUMBERS! IF ADDING LINE NUMBERS AS COLON TYPE, ANY LINE NUMBERS AS VBTAB TYPE MUST BE REMOVE BEFORE, AND RECIPROCALLY ADDING LINE NUMBERS AS VBTAB TYPE

    Dim i As Long
    Dim j As Long
    Dim procName As String
    Dim startOfProcedure As Long
    Dim lengthOfProcedure As Long
    Dim endOfProcedure As Long
    Dim strLine As String

    With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule
        .CodePane.Window.Visible = False

If Scope = vbScopeAllProc Then

        For i = 1 To .CountOfLines

            strLine = .Lines(i, 1)
            procName = .ProcOfLine(i, vbext_pk_Proc) ' Type d'argument ByRef incompatible ~~> Requires VBIDE library as a Reference for the VBA Project

            If procName <> vbNullString Then
                startOfProcedure = .ProcStartLine(procName, vbext_pk_Proc)
                bodyOfProcedure = .ProcBodyLine(procName, vbext_pk_Proc)
                countOfProcedure = .ProcCountLines(procName, vbext_pk_Proc)

                prelinesOfProcedure = bodyOfProcedure - startOfProcedure
                'postlineOfProcedure = ??? not directly available since endOfProcedure is itself not directly available.

                lengthOfProcedure = countOfProcedure - prelinesOfProcedure ' includes postlinesOfProcedure !
                'endOfProcedure = ??? not directly available, each line of the proc must be tested until the End statement is reached. See below.

                If endOfProcedure <> 0 And startOfProcedure < endOfProcedure And i > endOfProcedure Then
                    GoTo NextLine
                End If

                If i = bodyOfProcedure Then InProcBodyLines = True

                If bodyOfProcedure < i And i < startOfProcedure + countOfProcedure Then
                    If Not (.Lines(i - 1, 1) Like "* _") Then

                        InProcBodyLines = False

                        PreviousIndentAdded = 0

                        If Trim(strLine) = "" And Not AddLineNumbersToEmptyLines Then GoTo NextLine

                        If IsProcEndLine(wbName, vbCompName, i) Then
                            endOfProcedure = i
                            If AddLineNumbersToEndOfProc Then
                                Call IndentProcBodyLinesAsProcEndLine(wbName, vbCompName, LabelType, endOfProcedure)
                            Else
                                GoTo NextLine
                            End If
                        End If

                        If LabelType = vbLabelColon Then
                            If HasLabel(strLine, vbLabelColon) Then strLine = RemoveOneLineNumber(.Lines(i, 1), vbLabelColon)
                            If Not HasLabel(strLine, vbLabelColon) Then
                                temp_strLine = strLine
                                .ReplaceLine i, CStr(i) & ":" & strLine
                                new_strLine = .Lines(i, 1)
                                If Len(new_strLine) = Len(CStr(i) & ":" & temp_strLine) Then
                                    PreviousIndentAdded = Len(CStr(i) & ":")
                                Else
                                    PreviousIndentAdded = Len(CStr(i) & ": ")
                                End If
                            End If
                        ElseIf LabelType = vbLabelTab Then
                            If Not HasLabel(strLine, vbLabelTab) Then strLine = RemoveOneLineNumber(.Lines(i, 1), vbLabelTab)
                            If Not HasLabel(strLine, vbLabelColon) Then
                                temp_strLine = strLine
                                .ReplaceLine i, CStr(i) & vbTab & strLine
                                PreviousIndentAdded = Len(strLine) - Len(temp_strLine)
                            End If
                        End If

                    Else
                        If Not InProcBodyLines Then
                            If LabelType = vbLabelColon Then
                                .ReplaceLine i, Space(PreviousIndentAdded) & strLine
                            ElseIf LabelType = vbLabelTab Then
                                .ReplaceLine i, Space(4) & strLine
                            End If
                        Else
                        End If
                    End If

                End If

            End If

NextLine:
        Next i

ElseIf AddLineNumbersToEmptyLines And Scope = vbScopeThisProc Then

End If

        .CodePane.Window.Visible = True
    End With

End Sub

Function IsProcEndLine(ByVal wbName As String, _
                   ByVal vbCompName As String, _
                   ByVal Line As Long) As Boolean

With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule
    If Trim(.Lines(Line, 1)) Like "End Sub*" _
    Or Trim(.Lines(Line, 1)) Like "End Function*" _
    Or Trim(.Lines(Line, 1)) Like "End Property*" _
    Then IsProcEndLine = True
End With

End Function

Sub IndentProcBodyLinesAsProcEndLine(ByVal wbName As String, ByVal vbCompName As String, ByVal LabelType As vbLineNumbers_LabelTypes, ByVal ProcEndLine As Long)
    Dim procName As String
    Dim startOfProcedure As Long
    Dim endOfProcedure As Long

    With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule

        procName = .ProcOfLine(ProcEndLine, vbext_pk_Proc)
        bodyOfProcedure = .ProcBodyLine(procName, vbext_pk_Proc)
        endOfProcedure = ProcEndLine
        strEnd = .Lines(endOfProcedure, 1)

        j = bodyOfProcedure
        Do Until Not .Lines(j - 1, 1) Like "* _" And j <> bodyOfProcedure

            strLine = .Lines(j, 1)

            If LabelType = vbLabelColon Then
                If Mid(strEnd, Len(CStr(endOfProcedure)) + 1 + 1 + 1, 1) = " " Then
                    .ReplaceLine j, Space(Len(CStr(endOfProcedure)) + 1) & strLine
                Else
                    .ReplaceLine j, Space(Len(CStr(endOfProcedure)) + 2) & strLine
                End If
            ElseIf LabelType = vbLabelTab Then
                If endOfProcedure < 1000 Then
                    .ReplaceLine j, Space(4) & strLine
                Else
                    Debug.Print "This tool is limited to 999 lines of code to work properly."
                End If
            End If

            j = j + 1
        Loop

    End With
End Sub

Sub RemoveLineNumbers(ByVal wbName As String, ByVal vbCompName As String, ByVal LabelType As vbLineNumbers_LabelTypes)
    Dim i As Long
    With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule

        For i = 1 To .CountOfLines

            procName = .ProcOfLine(i, vbext_pk_Proc)

            If procName <> vbNullString Then

                If i = .ProcBodyLine(procName, vbext_pk_Proc) Then InProcBodyLines = True

                LenghtBefore = Len(.Lines(i, 1))
                If Not .Lines(i - 1, 1) Like "* _" Then
                    InProcBodyLines = False
                    .ReplaceLine i, RemoveOneLineNumber(.Lines(i, 1), LabelType)
                Else
                    If IsInProcBodyLines Then
                        ' do nothing
                    Else
                        .ReplaceLine i, Mid(.Lines(i, 1), RemovedChars_previous_i + 1)
                    End If
                End If
                LenghtAfter = Len(.Lines(i, 1))

                LengthBefore_previous_i = LenghtBefore
                LenghtAfter_previous_i = LenghtAfter
                RemovedChars_previous_i = LengthBefore_previous_i - LenghtAfter_previous_i

                If Trim(.Lines(i, 1)) Like "End Sub*" Or Trim(.Lines(i, 1)) Like "End Function" Or Trim(.Lines(i, 1)) Like "End Property" Then

                    LenOfRemovedLeadingCharacters = LenghtBefore - LenghtAfter

                    procName = .ProcOfLine(i, vbext_pk_Proc)
                    bodyOfProcedure = .ProcBodyLine(procName, vbext_pk_Proc)

                    j = bodyOfProcedure
                    strLineBodyOfProc = .Lines(bodyOfProcedure, 1)
                    Do Until Not strLineBodyOfProc Like "* _"
                        j = j + 1
                        strLineBodyOfProc = .Lines(j, 1)
                    Loop
                    LastLineBodyOfProc = j
                    strLastLineBodyOfProc = strLineBodyOfProc

                    strLineEndOfProc = .Lines(i, 1)
                    For k = bodyOfProcedure To j
                        .ReplaceLine k, Mid(.Lines(k, 1), 1 + LenOfRemovedLeadingCharacters)
                    Next k

                    i = i + (j - bodyOfProcedure)
                    GoTo NextLine

                End If
            Else
            ' GoTo NextLine
            End If
NextLine:
        Next i
    End With
End Sub

Function RemoveOneLineNumber(ByVal aString As String, ByVal LabelType As vbLineNumbers_LabelTypes)
    RemoveOneLineNumber = aString
    If LabelType = vbLabelColon Then
        If aString Like "#:*" Or aString Like "##:*" Or aString Like "###:*" Then
            RemoveOneLineNumber = Mid(aString, 1 + InStr(1, aString, ":", vbTextCompare))
            If Left(RemoveOneLineNumber, 2) Like " [! ]*" Then RemoveOneLineNumber = Mid(RemoveOneLineNumber, 2)
        End If
    ElseIf LabelType = vbLabelTab Then
        If aString Like "#   *" Or aString Like "##  *" Or aString Like "### *" Then RemoveOneLineNumber = Mid(aString, 5)
        If aString Like "#" Or aString Like "##" Or aString Like "###" Then RemoveOneLineNumber = ""
    End If
End Function

Function HasLabel(ByVal aString As String, ByVal LabelType As vbLineNumbers_LabelTypes) As Boolean
    If LabelType = vbLabelColon Then HasLabel = InStr(1, aString & ":", ":") < InStr(1, aString & " ", " ")
    If LabelType = vbLabelTab Then
        HasLabel = Mid(aString, 1, 4) Like "#   " Or Mid(aString, 1, 4) Like "##  " Or Mid(aString, 1, 4) Like "### "
    End If
End Function

Function RemoveLeadingSpaces(ByVal aString As String) As String
    Do Until Left(aString, 1) <> " "
        aString = Mid(aString, 2)
    Loop
    RemoveLeadingSpaces = aString
End Function

Function WhatIsLineIndent(ByVal aString As String) As String
    i = 1
    Do Until Mid(aString, i, 1) <> " "
        i = i + 1
    Loop
    WhatIsLineIndent = i
End Function

Function HowManyLeadingSpaces(ByVal aString As String) As String
    HowManyLeadingSpaces = WhatIsLineIndent(aString) - 1
End Function

You can make calls like this :

Sub AddLineNumbers_vbLabelColon()
    AddLineNumbers wbName:="EvaluateCall.xlsm", vbCompName:="ModLineNumbers_testDest", LabelType:=vbLabelColon, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbScopeAllProc
End Sub

Sub AddLineNumbers_vbLabelTab()
    AddLineNumbers wbName:="EvaluateCall.xlsm", vbCompName:="ModLineNumbers_testDest", LabelType:=vbLabelTab, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbScopeAllProc
End Sub

Sub RemoveLineNumbers_vbLabelColon()
    RemoveLineNumbers wbName:="EvaluateCall.xlsm", vbCompName:="ModLineNumbers_testDest", LabelType:=vbLabelColon
End Sub

Sub RemoveLineNumbers_vbLabelTab()
    RemoveLineNumbers wbName:="EvaluateCall.xlsm", vbCompName:="ModLineNumbers_testDest", LabelType:=vbLabelTab
End Sub

And as a reminder, here as some compile rules about about line numbers:

  • not allowed before a Sub/Function declaration statement
  • not allowed outside of a proc
  • not allowed on a line following a line continuation character «_» (underscore)
  • not allowed to have more than one label/line number per code line ~~> Existing labels other than line numbers must be tested otherwise a compile error will occur trying to force a line number.
  • not allowed to use characters that already have a special VBA meaning ~~> Allowed characters are [a-Z], [0-9], é, è, ô, ù, €, £, § and even «:» alone !
  • compiler will trim any space before a label ~~> So if there is a label, the first char of the line is the first char of the label, it cannot be a space.
  • appending a line number with a colon will result in having a space inserted between the «:» and the fist next char if there is none
  • when appending a line number with a tab/space, there must be at least one space between the last digit and the first next char, compiler won’t add it as it does for a label with a colon separator
  • the .ReplaceLine method will overide the compile rules without displaying any compile error as it does in design mode when selecting a new line or when manually relaunching compilation
  • the compiler is ‘quicker than the VBA environment/system’: for example, just after a line number with colon and without any space has been inserted with .ReplaceLine, if the .Lines property is called to get the new string, the space (between the colon character and the first character of the string) is already appended in that string !
  • it is not possible to enter debug mode after a .ReplaceLine has been called (from within or outside the module it is editting), not till the code is running, and execution reset.

Нумерация строк

Гисер

Дата: Пятница, 04.10.2013, 08:13 |
Сообщение № 1

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

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

Сообщений: 14


Репутация:

0

±

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


Excel 2010

Есть такая проблема, не могу придумать как пронумеровать позиции
в общем есть такая табличка предположим

№, п/п Наименование Показатель, Макс. Периметр или Диаметр Материал Объем, м2 Цена Итого, руб.
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73
Воздуховод прямоугольный 2200,00 Лист оц. 0,55 42,00 791,04 33223,73

Число строк естественно меняется в зависимости от числа позиций. Как что бы перед наименованием проставить порядковый номер позиции.
Макрос выглядит так
[vba]

Код

Sub Прямик_фас()
Application.ScreenUpdating = False

‘ Вставим наименование
Sheets(«прямоугольный с фас.»).Select
Range(«B1»).Select
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«B4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ Вставим показатель
Sheets(«прямоугольный с фас.»).Select
Range(«A2»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«C4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ вставим материал
Sheets(«прямоугольный с фас.»).Select
Range(«A7»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«D4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ Вставим объем
Sheets(«прямоугольный с фас.»).Select
Range(«F2»).Select
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«E4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘ Вставим цену
Sheets(«прямоугольный с фас.»).Select
Range(«F24»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«G4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
‘Вставим итого
Application.ScreenUpdating = True
Sheets(«прямоугольный с фас.»).Select
Range(«E24»).Select
Application.CutCopyMode = False
Selection.Copy
Sheets(«Ком.пред»).Select
Range(«H4»).Select
вниз
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets(«прямоугольный с фас.»).Select
Application.Cursor = xlDefault
End Sub

[/vba]

 

Ответить

ShAM

Дата: Пятница, 04.10.2013, 08:19 |
Сообщение № 2

Группа: Друзья

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

Сообщений: 1347


Репутация:

249

±

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


Excel 2010

в общем есть такая табличка предположим

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

 

Ответить

Гисер

Дата: Пятница, 04.10.2013, 13:06 |
Сообщение № 3

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

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

Сообщений: 14


Репутация:

0

±

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


Excel 2010

Как скажете, прошу прощения…

 

Ответить

SkyPro

Дата: Пятница, 04.10.2013, 13:13 |
Сообщение № 4

Группа: Друзья

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

Сообщений: 1206


Репутация:

255

±

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


2010

Гисер, ?
Вы можете ВНИМАТЕЛЬНО прочитать правила и составить нормальный пример с исходными данными, откуда и что нужно брать, что с этим делать и куда это вставить? Или вы полагаете, что это форум «битвы экстрасенсов» ?


skypro1111@gmail.com

 

Ответить

Wasilich

Дата: Пятница, 04.10.2013, 18:57 |
Сообщение № 5

Группа: Друзья

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

Сообщений: 1232


Репутация:

326

±

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


2003

Можно воспользоваться формулой в колонке А.

Код

=ЕСЛИ(B5=»»;»»;СТРОКА()-4)

Макросом так можно, (если угадал с копированием):

К сообщению приложен файл:

5472920.xls
(61.0 Kb)

 

Ответить

wild_pig

Дата: Пятница, 04.10.2013, 19:21 |
Сообщение № 6

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

Ранг: Обитатель

Сообщений: 516


Репутация:

97

±

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


2003, 2013

вариант от я

К сообщению приложен файл:

3238832.xls
(25.5 Kb)

 

Ответить

Гисер

Дата: Вторник, 08.10.2013, 12:16 |
Сообщение № 7

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

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

Сообщений: 14


Репутация:

0

±

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


Excel 2010

Объясняльшик из меня так себе, но нашлись понимающие люди) Огромное спасибо!

 

Ответить

Гисер

Дата: Пятница, 11.10.2013, 05:59 |
Сообщение № 8

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

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

Сообщений: 14


Репутация:

0

±

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


Excel 2010

[vba]

Код

Sub Гнутье()
PS = Sheets(«Ком.пред»).Range(«B» & Rows.Count).End(xlUp).Row + 1
With Sheets(«Гнутье»)
Sheets(«Ком.пред»).Range(«A» & PS) = PS — 4
Sheets(«Ком.пред»).Range(«B» & PS) = .Range(«A2») ‘ Вставим наименование
Sheets(«Ком.пред»).Range(«C» & PS) = .Range(«F5») ‘ Вставим показатель
Sheets(«Ком.пред»).Range(«D» & PS) = .Range(«A8») ‘ Вставим материал
Sheets(«Ком.пред»).Range(«E» & PS) = .Range(«E3») ‘ Вставим объем
Sheets(«Ком.пред»).Range(«G» & PS) = .Range(«F26») ‘ Вставим цену
Sheets(«Ком.пред»).Range(«H» & PS) = .Range(«E26») ‘ Вставим итого
End With
End Sub

[/vba]

Спасибо за макрос очень лаконично и правильно. Можно как то так же для диапазона написать.

Как будет выглядеть если не одну ячейку вставить нужно а диапазон A2:F5.?

 

Ответить

KuklP

Дата: Пятница, 11.10.2013, 06:26 |
Сообщение № 9

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

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

Сообщений: 2369


Репутация:

486

±

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


2003-2010

Народная мудрость гласит, что нет такой программы, к-рую нельзя было бы сократить, хотя бы на одну строку :)
[vba]

Код

Sub ВСТАВИТЬ()
       PS = Sheets(«Ком.пред»).Cells(Rows.Count, 2).End(xlUp)(2).Row
       With Sheets(«прямоугольный с фас.»)
           Sheets(«Ком.пред»).Range(«A» & PS & «:H» & PS) = _
           Array(PS — 4, .[b1], .[g4], .[a7], .[f2], .[f24], .[e26])
       End With
End Sub

[/vba] beer


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

Сообщение отредактировал KuklPПятница, 11.10.2013, 06:30

 

Ответить

Гисер

Дата: Пятница, 11.10.2013, 07:01 |
Сообщение № 10

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

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

Сообщений: 14


Репутация:

0

±

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


Excel 2010

KuklP, спасибо, но это на будущее) Переписывать все лень…сейчас бы выяснить вопрос как таким же образом написать для диапазона
A2:F5

 

Ответить

KuklP

Дата: Пятница, 11.10.2013, 07:42 |
Сообщение № 11

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

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

Сообщений: 2369


Репутация:

486

±

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


2003-2010

Я не понимаю, в чем тут сложность(не знаю задачи). Так и пишите:
[vba]

Код

[c27:h30] = [a2:f5].Value

[/vba]


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

 

Ответить

Гисер

Дата: Пятница, 11.10.2013, 07:43 |
Сообщение № 12

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

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

Сообщений: 14


Репутация:

0

±

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


Excel 2010

Сложнось в моем знании VBA)))

 

Ответить

Последнее время на работе занималась приведением excel-файлов к виду, при котором пользователь может допустить наименьшее количество ошибок при заполнении. До этого первый и последний раз я сталкивалась с visual basic в школе, причем не применительно к Ms Excel, поэтому потребовалось некоторое время на то, чтобы понять, как делать простые и, и тем более не очень, вещи. Эта статейка может помочь людям, оказавшимся в похожей ситуации, быстрее войти в курс дела. Демо-экселька прилагается.


Основы

Самый первый вопрос, который у меня возник, после того как вкладка «Разработчик» была добавлена (подробнее тут, например) и открыт встроенный vba-редактор, это куда собственно писать код. По умолчанию в книге есть модули страниц, модуль книги и один общий модуль. Существуют также модули формы и классов, но сейчас речь не о них. Все вполне логично: обработку событий на объекты страницы пишем в соответствующий лист страницы, обработку событий для книги — в модуль книги, а общие функции для всех листов — в общий модуль. При этом имеет смысл создать еще модули для отделения функционала по смыслу.

Также сразу возникает вопрос, а как элементарно обратиться к ячейке, найти ее значение и перезаписать его. Очень просто:

‘ в ячейку А1 пишем «add note» + значение ячейки B1
Cells(1,1).Value = «add note » & Cells(1,2).Value

For Each oCell In Range(«A1:A10»).Cells
     ‘обработка 
     oCell.Value = oCell.Row ‘ присвоили номер строки   
Next 

Моим следующим вопросом было каким образом вернуть значение из функции. В vba есть два типа функций: sub и function. Разница в том, что function как раз и умеет возвращать значение, для этого в коде функции надо написать ИмяФункции = возвращаемое_значение:

Public Function insertRow()
    Dim position As Integer
    ‘…
    insertRow = position ‘возвращаемое значение

End Function

После написания нескольких функций во встроенном редакторе, меня нешуточно заинтересовало, как перенести строку кода на следующую физическую строку. Если посреди строки кода нажать enter, кроме ошибки мы ничего не добьемся. Оказывается, надо использовать «_»:

If ActiveSheet.Index = 1 _
   Or ActiveSheet.Index = 4 Then
        ‘ действия
End If

Нарочно и не придумаешь.

Помимо массивов, в VBA следует обратить внимание на коллекции. Работать с ними просто:

Dim сoll As New Collection
сoll.Add («элемент1»)‘добавляем элемент
сoll.Add («элемент2»)‘размер увеличивается динамически
‘ по умолчанию индекс начинается с 1, можно изменить
MsgBox (сoll.Item(1)) элемент1
сoll.Remove (1) ‘ удаляем первый элемент
MsgBox (сoll.Count)‘выводим размер коллекции

Чтобы когда мы творим беспредел с нашим excel-файликом посредством vba, он предательски не корчился и напоказ не дергал строками и столбцами перед пользователем (например, при удалении и скрытии интервалов), можно отключать прорисовку:

Application.ScreenUpdating = False ‘ значение True включает

Автоматическая нумерация строк таблицы

Одной из первых моих мелких подзадач стала нумерация строк таблицы. Можно, конечно, при добавлении строки вставлять номер функцией, но хотелось по возможности чтобы это происходило само собой. Как выяснилось, нумеровать ячейки можно формулой =СТРОКА(ячейка), которая возвращает номер строки ячейки-параметра. Например, формула =СТРОКА(А1), вставленная в произвольную ячейку, выведет 1, строка =СТРОКА(А3) — цифру 3. 

Таким образом, при копировании формулы в следующую строку нумерация таблицы продолжится:

‘проставляем формулу нумерации

Range(«A7»).FormulaR1C1 = Range(«A6»).FormulaR1C1 

Если нужно также копировать формат ячейки, используется метод AutoFill.

Тут может возникнуть одна неприятность. Пусть наша последовательность ячеек с формулами начинается  не с первой строки, а например, с третьей. Тогда в третьей строке будет формула =Строка(А1), во второй — =Строка(А2), в 10 — =Строка(А10) и т.д. Тогда при удалении строки 6 формула в теперешней строке 9 выдаст ошибку «неверная ссылка». 

Это потому, что формула в строке А9 крайне смущена тем, что ссылается на удаленную ячейку. Поэтому если строки в таблице буду удаляться и добавляться, лучше сделать ссылку на ячейки другой страницы (=СТРОКА(Лист2!А1)).

Кнопки вставки и удаления строк

Также неочевидными оказались некоторые нюансы при вставке и удалении строк в таблице по нажатию на соответствующие кнопки (под таблицей будем понимать визуально выделенный  диапазон ячеек, содержащий связанные по смыслу данные). Например, у нас на листе есть две таблицы, у каждой есть кнопка «добавить строку». При добавлении для каждой строки появляется кнопка «удалить».

Само по себе добавление и удаление по имени кнопки сложности не представляет:

Private Sub InsertButton1_Click(position as Integer)
   ‘вставка строки перед строкой с номером position
   Rows(position).Insert
End Sub


Private Sub DeleteButton1_Click()
   Dim position as Integer
   ‘ ищем номер строки кнопки удаления
   position = _            ActiveSheet.Shapes(Application.Caller).TopLeftCell.Row  
   ‘ удаление кнопки
   ActiveSheet.Shapes(Application.Caller).Delete 
   ‘ удаление строки с номером position
   Rows(position).Delete
End Sub

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

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

Нам нужен уникальный идентификатор. Чтобы не заниматься генерацией уникальных хэшей, можно, например, использовать имяКнопки_номерСтроки_текущаяДата. 

newButtonId = «delButton» & insertedRowNumber & Now()

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

Проверка листа на правильное заполнение 

Задача состоит в том, чтобы при сохранении файла проверять содержимое ячеек на всех листах и если какие-то помеченные как обязательные остались незаполненными, выдавать предупреждение пользователю. Для визуального выделения в зависимости от результата проверки содержимого ячеек на соответствие требованиям в excel можно использовать условное форматирование. Казалось бы, все просто: если мы используем условное форматирование и незаполненные ячейки (или неправильно заполненные, которые мы не смогли проверить при вводе с помощью меню «проверка данных») подкрашиваем, например, красным, то при сохранении все что нам нужно сделать — пройтись по всем ячейкам и проверить их цвет.

Но проблема вот в чем — если мы берем colorIndex или color ячейки, нам возвращается исходный цвет, не тот, на который он изменился при помощи условного форматирования.

В голову пришло два слегка костыльных способа решения (и честно говоря, если судить по форумам с обсуждением подобных проблем, кажется, что применительно к Excel по-другому их и не решишь).

Первый способ: в одном столбце, напротив каждой строки таблицы, формулой вычисляется, правильно ли заполнена строка. Тогда, проходясь по этому столбцу, мы можем сказать, в какой строке проблема. А при помощи условного форматирования проблемные ячейки могут подсвечиваться красным. Этого достаточно, если не надо точно знать, в какой ячейке проблема. При необходимости можно дальше обрабатывать эту строку по ячейкам. Способ хорош, если разные строки проверяются на разные условия (даже в рамках одной таблицы).

usedRows = ActiveSheet.UsedRange.Rows.Count
usedCols = ActiveSheet.UsedRange.Columns.Count
‘ переводим последний столбец из цифры в букву
usedColsInNumb = Split(Cells(1, usedCols).Address, «$»)(1)

For Each cell In ActiveSheet.Range(«A1:» & usedColsInNumb & usedRows).Cells

   ‘ если колонка с результатом формулы проверки заполнена

   If Len(cell.Value) > 0 Then 

       ‘ если строка неправильно заполнена

       If cell.Value = «ЛОЖЬ» Then 

            ‘ сохраняем в массив, отражающий правильность 
            ‘ заполнения каждой строки
            notFilled(cell.Row) = True 

       End If

   End If

Next

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

For Each cell In Sheets(i).Range(«A2:» & usedColsInNumb & usedRows).Cells

    ‘ проверяем выделенные цветом ячейки на пустоту

    If cell.Interior.Color = Sheets(5).Cells(1, 6).Interior.Color   And Len(cell.Value) = 0 Then

        ‘ обработка незаполненной ячейки

    End If

Next

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

‘ ищем смежные с текущей ячейки в виде интервала, eg «A1:B10»

mergedInterv = Cells(cell.Row, cell.Column).MergeArea.Address(RowAbsolute:=False, ColumnAbsolute:=False)

‘ разбиваем адрес на первую и последнюю из смежных

splitAr = Split(mergedInt, «:»)

‘ если текущая ячейка входит в объединенные

If UBound(splitAr) = 1 Then 

      splitAr2 = Split(cell.Address, «$»)

      ‘ если первая из диапазона смежных равна текущей ячейке

      If splitAr(0) = splitAr2(1) & splitAr2(2) Then

          ‘ обработка незаполненной смежной ячейки

      End If

Else 

    ‘ если текущая ячейка не является смежной

End If

При нахождении последней используемой строки или столбца следует учесть, что если вы каким-то образом успели «поиспользовать» интервал (пусть даже выделили и очистили формат), то он все равно считается использованным. Придется удалить эти строки и столбцы.

Прилагаю демо-эксельку. Тестировалась в русифицированном MS Excel 2007.

Понравилась статья? Поделить с друзьями:
  • Vba excel автоматический запуск макроса
  • Vba excel vlookup пример
  • Vba excel type mismatch error 13 что
  • Vba excel автозапуск макроса
  • Vba excel vba tutorial