I am trying to make a macro that will look at a list on sheet 2 and look for the same value on sheet 1. If/when it finds it, it would delete the row on sheet 1. Then it would end at the bottem of sheet 2. Any advice would help, thank you!
The best way to do this is to loop through the values on sheet 2. On each value, check if it exists on sheet 1, and if so, delete that row.
The key is in how you structure your loop, and how you plan for the unexpected. How does your code handle if the same value is listed more than once on sheet 1? What if there are blank spots in sheet 1?
My advice is to use a built-in function such as the .Find method. This can skip over unexpected spaces, and it can easily be called multiple times. More info on this and other methods is found by pressing F1 in VBA editor, or you can look here.
As has been pointed out elsewhere, avoiding using .Select is also good practice.
To get you started, here is an outline of what's possible, looking at information in Sheet2 rows 1 through 3, and replacing those values in Sheet1 rows 1 through 10:
Public Sub delete_selected_rows()
'look at sheet2, A1 through A3 for search values
For Each search_value In Worksheets(2).Range("A1:A3")
'as long as there is something to delete...
Do While Not Worksheets(1).Range("A1:A10"). _
Find(search_value.Value, lookat:=xlWhole) Is Nothing
'...delete that row
Worksheets(1).Range("A1:A10").Find(search_value.Value, _
lookat:=xlWhole).EntireRow.Delete
Loop
Next
End Sub
Related
I have four table-formatted worksheets (A, B, C, and D) each with rows of different data beneath matching column headers. I'm trying to write a VBA macro to cut rows from one sheet and paste them into the bottom of another based on the value of a single cell in a given column. I know this has been done from one individual sheet to another and I found the basic code to do so. However, I wanted to modify that to apply across all the worksheets, account for multiple permutations of the same value, and avoid re-checking rows that are already/have been placed in their "proper" worksheet, i.e., all rows marked 'Archived' in all its various permutations in column 17 of their respective other worksheets get shuffled over to the 'D' worksheet once the word archived is typed into that cell and the enter key is pressed. I think I'm screwing up something basic here with the "<>" and "or" portions, but not sure how to fix them. I'm also not sure if it is better to link this command to the 'Enter' keystroke or just have it check the values automatically?
Sub MoveRows()
Dim k As String
a = Worksheets(k).Cells(Rows.Count,1).End(xlUp).Row
If Worksheet.Name <> "D" Then
For i = 2 To a Step -1
If Worksheets(k).Cell(i,17).Value = "Archived" or "archived" or "ARCHIVED" Then
Worksheets(k).Rows(i).Cut
Worksheets("D").Range("A1").End(xldown).Offset(1,0).Insert
End If
next i
Else 'do nothing'
End Sub
I need some help for my Excel sheet,
I have the first sheet and this is blank
and on the seconde sheet i have a list and in the column D i can change the value starts from 1.
And when i changed in the column a cell then it should copy the row to the first sheet.
thanks
Regards
It is not clear for me what you want to do. If you want VBA to copy the row automatically, you should go to the module of the corresponding Worksheet in the VBA editor (in the list of the Wroksheets on the left, just double-click the Worksheet to open up the module associated with it). After that, write an event handler:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 4 Then
ActiveSheet.Rows(Target.Row).Copy Worksheets("Sheet1").Rows(whichRowYouNeed)
End If
End Sub
you should also write a routine to determine the 'whichRowYouNeed'
It may be the end of the filled range on Worksheet1
Hey sorry for my bad statement, i try it again :)
The first sheet is blank,
The Second sheet is that:
When i add a number in column D then I want to copy this row, in that case row 8, copy to the first sheet starting from row 5.
I hope now it is better to understand
I am very new to VBA, and most of the times I manage to fit my needs by simple jury-rigging someone else's code - sometimes I also find exactly what I was looking for in answers to other people's questions. But right now it seems I can't figure out how to solve this problem (I tried asking in other excel forums, but with no result).
I'm working with very large data output files, which present all the variables I need to analyze scattered in sheets, in multiple workbooks. In order to statistically analyze these data files we often have to rearrange the output data into a more statistically friendly format.
What I'm trying to code is a Summary new sheet for each of the workbooks I need analyzed, which will be populated with a dynamic range copied from each of the sheets and pasted one below the other.
The difficulty resides in the fact that the range is not fixed: has a variable starting point as row in column "A", and a variable length (and thus a variable ending point, but always in Column "F").
So I would need to adapt a simple copy/paste code like the one I've been using for ages
Sub SummurizeSheets()
Dim ws As Worksheet
Application.ScreenUpdating = False
Sheets("Summary").Activate
For Each ws In Worksheets
If ws.Name <> "Summary" Then
ws.Range("A1:A2").Copy
ActiveSheet.Range("A65536").End(xlUp).Offset(1, 0).PasteSpecial Transpose:=True
End If
Next ws
End Sub
with a dynamic range starting in:
Column "A", row =(MATCH(Summary!$M$1;[SheetName]!A:A;0)
and ending in the last non-blank cell starting from the range-start point (which is effectively the last populated cell within the range belonging to the variable described in the Summary Column M1)
this last part looks like frankenstein's monster as:
MATCH(TRUE;INDEX(ISBLANK(INDIRECT(CONCATENATE(CONCATENATE("A";MATCH(Summary!$M$1;[SheetName]!A:A;0));":";"A100")));0;0);0)+ROW(INDIRECT(CONCATENATE("A";MATCH(Summary!$M$1;[SheetName]!A:A;0))))-1
which basically looks for the first blank cell in an arbitrary custom range, from the above-mentioned starting point to A100, and, once found, offsets the row number by (-1).
Finally, the question: how can I translate those two cell references into the ws.Range("xx:xx") above to have my old pal copy/paste do its job with the range I require?
If the output is a row number, just use Cells() in a combination with Range():
Range(Cells(ROW NUMBER, COLUMN NUMBER), Cells(ROW NUMBER2, COLUMN NUMBER2))
where the ROW NUMBER is the output of your frankenstein and the COLUMN NUMBER is obviously the number of the column. ROW NUMBER2 is the row number of your last row
I want to write a formula like =SUM(tab2!A:A) but instead use the column title of A which is say "count". How can I modify this to look more like: =SUM(tab2!"count")?
The reason I want to do this is because I copy and paste a spreadsheet from another source in tab2 and the column referring to "count" may be in a different column. I want the formula to give me the correct calculation as soon as I paste the new spreadsheet by automatically finding the column to sum up by title name.
I must be missing something because this seems like a very basic question and I can't find the answer anywhere...
Thanks for your help!
I like the idea of naming ranges proposed by #Doug, but if the issue is that you are dumping your data in [and you don't know in advance which column is going to be where] and would need to rename your range every time, there are other options - I suggest using OFFSET. OFFSET allows you to dynamically create a range, starting at a particular point and moving down/up / right/left for as many rows and columns as you determine.
In your case, you will need to combine that with a method for searching the columns to see which one says "Count". I am assuming that your column headings are always in row 1. If they aren't [or if they aren't always in row 2, or any row you know in advance]... you can get around that but then I'd recommend you try to make your data more uniform instead of creating unnecessary Excel workarounds.
In total your formula would look like this:
=SUM(OFFSET(A1,,MATCH("Count",1:1,0)-1,ROWS(A:A),1))
What this does is first determine which column the word "Count" is found in, in row 1. Then it subtracts 1 from that number - this now equals the number of columns to the right that it is, from column A. It uses offset to create a reference to that column, for all rows, and sums those rows together.
Check out the name manager for naming ranges :)
You didn't say whether you would consider a macro solution. If so, this may work.
If the sheet you are pasting into is Sheet2 and the sheet you want the result in is Sheet1, then this macro, if placed in the Worksheet_Activate event of Sheet1 will give you the result as soon as you click on the Sheet1 tab afetr pasting your data into Sheet2:
Private Sub Worksheet_Activate()
Dim r As Range
Dim rCol As Range
Dim rFound As Range
Dim ws As Worksheet
Dim lTotal As Long
Set ws = Sheet2
Set r = ws.Cells
Set rFound = r.Find("count")
If Not rFound Is Nothing Then
Set rCol = rFound.EntireColumn
lTotal = Application.WorksheetFunction.Sum(rCol)
End If
Cells(1, 1) = lTotal
End Sub
It does assume there is only one cell with the word "count" in it on Sheet2.
I've just got a quick one wondering if I can somehow alter the following snippet to include .End(xlToRight) instead of defining L6 (the result is the same).
Sub Test()
Dim LastCol As String
With Worksheets("Sheet1")
LastCol = .Cells(5, .Columns.Count).End(xlToLeft).Address
.Range(Range("A5"), LastCol).Copy
.Range("B5:L5", Range("B5:L5").Offset(LastRow - FirstRow, 0)).PasteSpecial xlPasteFormulas
.Range("B6", .Cells.SpecialCells(xlCellTypeLastCell)).Copy
.Range("B6").PasteSpecial xlPasteValues
End With
End Sub
Many thanks for any help :)
EDIT: updated pdw TonyDallimore (see response below)
Tony, the above code is the sum of what I've been trying to get working. Within the with statement, I'm looking to copy the contents of row 5, and paste them down to the nth row - which is defined by a list already present in columnA. The last line per your advice will then paste the values of all but the top row (r5) to preserve transparency for the user, while minimising file size.
The middle bit is the remaining 'work in progress', as L5 is not certain to be the farmost column.
Both questions
.End(xxx) is the same as Ctrl+Arrow from the keyboard and stops at the first cell that is different from the current cell. So if you start at a cell with a value it stops at a cell without a value or vice versa.
The trouble with starting top left and using xlDown and xlToRight is that it will stop at a blank cell in the middle of your table. Fine if you absolutely cannot have a blank cell in the middle, but XlUp or xlToLeft from bottom right are safer.
Question 1
Is your problem that .End(xxx).Column will return 12 and you do not know how to turn it into the letter "L"?
Is so, there are lots of choices. I think the easiest is to remember that
.Cells(6,Columns.Count).End(xlToLeft).Address
would return "$L$6".
Question 2
Does .Cells(1000, ColRange) represent the bottom right cell?
.Cells.SpecialCells(xlCellTypeLastCell) might be an easier option.