Oleg Пользователь Сообщений: 112 |
Добрый день, коллеги, |
LVL Пользователь Сообщений: 903 |
#2 03.07.2014 10:03:11
Не верное утверждение. Redim не удаляет элементы, он изменяет размер массива, при чем только по последней(!) размерности. Вообще именно удалить «строку» массива будет проблематично (если вообще возможно), но проблему можно решить по другому. Допустим так — скопировать в другой массив только нужные строки.
Изменено: LVL — 03.07.2014 10:05:01 |
||||
Oleg Пользователь Сообщений: 112 |
LVL, спасибо, в коде разобрался. Единственное что озадачило — я думал в массивах с 0, а не с 1 элемента идет счет если задавать так redim (5), а не так redim (1 to 5). |
JeyCi Пользователь Сообщений: 3357 |
#4 04.07.2014 11:13:34
создать пустой массив и в него перекинуть нужное — всегда быстрее чем перезаписывать все строки в нём со смещением… Изменено: JeyCi — 04.07.2014 11:13:44 чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах) |
||
LVL Пользователь Сообщений: 903 |
#5 04.07.2014 11:30:15
По умолчанию да, но в зависимости от ситуации можно считать и от одного, в самом начале модуля пишите Option Base 1 и отсчёт будет начинаться с 1. Соответственно это справедливо при инициализации массива, если явно не указаны его границы. |
||
Мотя Пользователь Сообщений: 3218 |
Навеяло… Изменено: Мотя — 04.07.2014 11:41:50 |
Максим Зеленский Пользователь Сообщений: 4646 Microsoft MVP |
#7 04.07.2014 11:42:24
Читайте внимательно. Строки двумерного массива — это первая размерность, столбцы — вторая. Вы можете изменять только вторую размерность, т.е. столбцы. Можете извратиться и транспонировать массив, если это уже так необходимо, тогда вторым измерением станут строки F1 творит чудеса |
||
Hugo Пользователь Сообщений: 23249 |
Вот сколько пишу макросы — никогда не нужно было удалять строку из двумерного массива… Зачем? Изменено: Hugo — 04.07.2014 11:52:09 |
Skif-F Пользователь Сообщений: 181 |
#9 04.07.2014 12:41:15
А где написано, что первое измерение — это строки, а второе — столбцы? Тут каждый решает сам. В крайнем случае, можно сделать как-то так:
Если не принципиальна последовательность данных (строк), то можно переместить последнюю на место удаляемой и удалить освободившееся место. Если же операция часто выполняемая, то следует менять алгоритм, минимизируя перемещения и удаления строк. Изменено: Skif-F — 04.07.2014 12:49:15 |
||||
Максим Зеленский Пользователь Сообщений: 4646 Microsoft MVP |
#10 04.07.2014 17:02:50
да нет, конечно нигде, но, если не ошибаюсь, по умолчанию, при загоне данных с листа, создается двумерный массив, где первое измерение — строки, а второе — столбцы. F1 творит чудеса |
||
- Remove From My Forums
-
Question
-
Does anyone know how to delete a row r in an nxm array in VBA (not an EXCEL array)? I want to expunge a bad record if one column is bad.
Answers
-
We can use the Excel array to help us remove a row in the VBA array. Say the VBA arrray is 50 down by 100 across and we want to remove row #7:
Sub RowKiller()
Dim StartArray(1 To 50, 1 To 100) As Long
Dim EndArrayk = 1
For i = 1 To 50
For j = 1 To 100
StartArray(i, j) = k
k = k + 1
Next
NextRange(«A1:CV50») = StartArray
Range(«A7»).EntireRow.Delete
EndArray = Range(«A1:CV49»)End Sub
The last three lines do all the work.
gsnu201111
-
Edited by
Saturday, November 5, 2011 8:41 PM
typo -
Marked as answer by
danishani
Sunday, January 29, 2012 8:42 PM
-
Edited by
-
Thanks Gary, but unfortunately I have to use a Function, not a Sub. My Row and Col indicies are integers. The reason that I can’t use a Sub is that I have to pass arguments to the procedure. this is not conenient with a Sub. I pass,
among other things, the EXCEL array and make a copy of it in the vba, and then work on that.I guess this is a new discussion related to the other one where you wanted a function to change the worksheet environment.
If your data are already in Excel, there’s probably no need to do this work in VBA. Use Excel’s built-in features: Filtering / Advanced Filtering / PivotTables / Data Query / formulas.
Excel already has a host of features. Leverage them and let Excel do the heavy lifting.
Tushar Mehta (Technology and Operations Consulting)
www.tushar-mehta.com (Excel and PowerPoint add-ins and tutorials)
Microsoft MVP Excel 2000-Present-
Marked as answer by
danishani
Sunday, January 29, 2012 8:42 PM
-
Marked as answer by
First, let me say categorically that there is nothing wrong with loops — they certainly have their place!
Recently we were presented with the below situation:
400000 | Smith, John| 2.4 | 5.66| =C1+D1
400001 | Q, Suzy | 4.6 | 5.47| =C2+D2
400002 | Schmoe, Joe| 3.8 | 0.14| =C3+D3
Blank | | | | #VALUE
Blank | | | | #VALUE
The OP wanted to delete rows where Column A is blank, but there is a value in Column E.
I suggest that this is an example where we could make use of SpecialCells and a temporary Error Column to identify the rows to be deleted.
Consider that you might add a column H to try and identify those rows; in that row you could use a formula like below:
=IF(AND(A:A="",E:E<>""),"DELETE THIS ROW","LEAVE THIS ROW")
now, it is possible get that formula to put an error in the rows where I test returns True. The reason we would do this is a feature of Excel called SpecialCells.
In Excel select any empty cell, and in the formula bar type
=NA()
Next, hit F5 or CTRL+G (Go to… on the Edit menu) then click the Special button to show the SpecialCells dialog.
In that dialog, click the radio next to ‘Formulas’ and underneath, clear the checkboxes so that only Errors is selected. Now click OK
Excel should have selected all the cells in the worksheet with an Error (#N/A) in them.
The code below takes advantage of this trick by creating a formula in column H that will put an #N/A in all the rows you want to delete, then calling SpecialCells to find the rows, and clear (delete) them…
Sub clearCells()
'
Dim sFormula As String
'
' this formula put's an error if the test returns true,
' so we can use SpecialCells function to highlight the
' rows to be deleted!
Create a formula that will return #NA when the formula returns TRUE
sFormula = "=IF(AND(A:A="""",E:E<>""""),NA(),"""")"
Put that formula in Column H, to find the rows that are to be deleted…
Range("H5:H" & Range("E65536").End(xlUp).Row).Formula = sFormula
Now use SpecialCells to highlight the rows to be deleted:
Range("H5:H" & Range("E65536").End(xlUp).Row).SpecialCells(xlCellTypeFormulas, xlErrors).entirerow.select
This line of code would highlight just Column A by using OFFSET in case instead of deleting the entire row, you wanted to put some text in, or clear it
Range("H5:H" & Range("E65536").End(xlUp).Row).SpecialCells(xlCellTypeFormulas, xlErrors).Offset(0, -7).select
and the below line of code will delete thhe entire row because we can
Range("H5:H" & Range("E65536").End(xlUp).Row).SpecialCells(xlCellTypeFormulas, xlErrors).EntireRow.Delete shift:=xlup
' clean up the formula
Range("H5:H" & Range("E65536").End(xlUp).Row).Clear
'
End Sub
BTW, it’s also possible WITH A LOOP if you really want one
One more thing, before Excel 2010 there was a limit of 8192 rows (I think because this feature went all the way back to 8-bit versions of Excel maybe)
The VBA legend Ron de Bruin (on whose website I first picked up this technique, among others) has something to say about this
Philip
In this Article
- Delete Entire Row or Column
- Delete Multiple Rows or Columns
- Delete Blank / Empty Rows
- Delete Row if Cell is Blank
- Delete Row Based on Cell Value
- More Delete Row and Column Examples
- Delete Duplicate Rows
- Delete Table Rows
- Delete Filtered Rows
- Delete Rows in Range
- Delete Selected Rows
- Delete Last Row
- Delete Columns by Number
This tutorial will demonstrate different ways to delete rows and columns in Excel using VBA.
Delete Entire Row or Column
To delete an entire row in VBA use this line of code:
Rows(1).Delete
Notice we use the Delete method to delete a row.
Instead of referencing the Rows Object, you can reference rows based on their Range Object with EntireRow:
Range("a1").EntireRow.Delete
Similarly to delete an entire column, use these lines of code:
Columns(1).Delete
Range("a1").EntireColumn.Delete
Delete Multiple Rows or Columns
Using the same logic, you can also delete multiple rows at once:
Rows("1:3").Delete
or columns:
Columns("A:C").Delete
Notice here we reference the specific row and column numbers / letters surrounded by quotations.
Of course, you can also reference the EntireRow of a range:
Range("a1:a10").EntireRow.Delete
Note: The examples below only demonstrate deleting rows, however as you can see above, the syntax is virtually identically to delete columns.
Delete Blank / Empty Rows
This example will delete a row if the entire row is blank:
Sub DeleteRows_EntireRowBlank()
Dim cell As Range
For Each cell In Range("b2:b20")
If Application.WorksheetFunction.CountA(cell.EntireRow) = 0 Then
cell.EntireRow.Delete
End If
Next cell
End Sub
It makes use of the Excel worksheet function: COUNTA.
Delete Row if Cell is Blank
This will delete a row if specific column in that row is blank (in this case column B):
Range("b3:b20").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Delete Row Based on Cell Value
This will loop through a range, and delete rows if a certain cell value in that row says “delete”.
Sub DeleteRowswithSpecificValue()
Dim cell As Range
For Each cell In Range("b2:b20")
If cell.Value = "delete" Then
cell.EntireRow.Delete
End If
Next cell
End Sub
More Delete Row and Column Examples
VBA Coding Made Easy
Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
Learn More
Delete Duplicate Rows
This code will delete all duplicate rows in a range:
Range("b2:c100").RemoveDuplicates Columns:=2
Notice we set Columns:=2. This tells VBA to check both the first two columns of data when considering if rows are duplicates. A duplicate is only found when both columns have duplicate values.
If we had set this to 1, only the first row would’ve been checked for duplicate values.
Delete Table Rows
This code will delete the second row in a Table by referencing ListObjects.
ThisWorkbook.Sheets("Sheet1").ListObjects("list1").ListRows(2).Delete
Delete Filtered Rows
To delete only rows that are visible after filtering:
Range("b3:b20").SpecialCells(xlCellTypeVisible).EntireRow.Delete
VBA Programming | Code Generator does work for you!
Delete Rows in Range
This code will delete all rows in range:
Range("a1:a10").EntireRow.Delete
Delete Selected Rows
This code will delete all selected rows:
Selection.EntireRow.Delete
Delete Last Row
This will delete the last used row in column B:
Cells(Rows.Count, 2).End(xlUp).EntireRow.Delete
By changing 2 to 1, you can delete the last used row in column A, etc.:
Cells(Rows.Count, 1).End(xlUp).EntireRow.Delete
Delete Columns by Number
To delete a column by it’s number, use a code like this:
Columns (2).Delete
Удаление «пустых строк» из массива
Удаление «пустых строк» из диапазона ячеек при помощи макроса
Function DeleteBlankRows(ByVal arr As Variant, ByVal col As Long) As Variant ' осуществляет удаление пустых строк из массива ' получает в качестве параметров исходный массив, и номер столбца, ' по которому определяется, является ли строка постой ' возвращает новый массив (с меньшей размерностью по вертикали) If Not IsArray(arr) Then MsgBox "Это не массив!", vbCritical: Exit Function If col > UBound(arr, 2) Then MsgBox "Нет такого столбца в массиве!", vbCritical: Exit Function If col < LBound(arr, 2) Then MsgBox "Нет такого столбца в массиве!", vbCritical: Exit Function Dim iCount As Long ' кол-во непустых строк For i = LBound(arr) To UBound(arr) iCount = iCount - (arr(i, col) <> "") Next i ReDim narr(LBound(arr, 1) To iCount + LBound(arr, 1) - 1, LBound(arr, 2) To UBound(arr, 2)) iCount = LBound(narr) ' счётчик записей For i = LBound(arr, 1) To UBound(arr, 1) If arr(i, col) <> "" Then For j = LBound(arr, 2) To UBound(arr, 2) narr(iCount, j) = arr(i, j) Next j iCount = iCount + 1 End If Next i DeleteBlankRows = narr End Function
Sub ПримерИспользования() On Error Resume Next arr = [a1:d15] ' считываем значения ячеек диапазона [a1:d15] в массив arr ' получаем массив arr2, в 5-м столбце которого нет пустых значений arr2 = DeleteBlankRows(arr, 5) [f1:z111].Clear ' очищаем диапазон ячеек [f1:z111] на листе ' вставляем массив без пустых строк обратно на лист [f1].Resize(UBound(arr2, 1), UBound(arr2, 2)).Value = arr2 End Sub
- 30174 просмотра
Не получается применить макрос? Не удаётся изменить код под свои нужды?
Оформите заказ у нас на сайте, не забыв прикрепить примеры файлов, и описать, что и как должно работать.
i fell into a case where clearing the entire array failed with dim/redim :
having 2 module-wide arrays, Private inside a userform,
One array is dynamic and uses a class module, the other is fixed and has a special type.
Option Explicit
Private Type Perso_Type
Nom As String
PV As Single 'Long 'max 1
Mana As Single 'Long
Classe1 As String
XP1 As Single
Classe2 As String
XP2 As Single
Classe3 As String
XP3 As Single
Classe4 As String
XP4 As Single
Buff(1 To 10) As IPicture 'Disp
BuffType(1 To 10) As String
Dances(1 To 10) As IPicture 'Disp
DancesType(1 To 10) As String
End Type
Private Data_Perso(1 To 9, 1 To 8) As Perso_Type
Dim ImgArray() As New ClsImage 'ClsImage is a Class module
And i have a sub declared as public to clear those arrays (and associated run-time created controls) from inside and outside the userform like this :
Public Sub EraseControlsCreatedAtRunTime()
Dim i As Long
On Error Resume Next
With Me.Controls 'removing all on run-time created controls of the Userform :
For i = .Count - 1 To 0 Step -1
.Remove i
Next i
End With
Err.Clear: On Error GoTo 0
Erase ImgArray, Data_Perso
'ReDim ImgArray() As ClsImage ' i tried this, no error but wouldn't work correctly
'ReDim Data_Perso(1 To 9, 1 To 8) As Perso_Type 'without the erase not working, with erase this line is not needed.
End Sub
note : this last sub was first called from outside (other form and class module) with Call FormName.SubName
but had to replace it with Application.Run FormName.SubName
, less errors, don’t ask why…