VBA copy data from different sheets from row above where cell text "subtotal" - excel

Want to copy Data from Different worksheets to a sheet called
"Summary". Data needs to be copy from one Row above (where row has text
"subtotal") to Row/Column A2. Below is my VBA code, but getting error MESSAGE " Compiler error, Else without If ", not sure what i am missing.
please help me.
Sub CombineData()
Dim Sht As Worksheet
For Each Sht In ActiveWorkbook.Worksheets
If Sht.Name <> "Summary" And Left(Sht.Name, 1) = "1" Or Left(Sht.Name, 1) = "4" Or Left(Sht.Name, 1) = "6" Or Left(Sht.Name, 1) = "7" Then
Sht.Select
'LastRow = Range("A65536").End(xlUp).Row
Set MyRng = Range(Cells(1, "d"), Cells(Rows.Count, "d").End(xlUp))
For Each cell In MyRng
If cell.Value = "Subtotal" Then cell.Value = cell.Offset(-1, 0).Value
.Range("A2", "M&MyRng").Copy
Sheets("Summary").Select
Range("A65536").End(xlUp).Offset(1, 0).Select
ActiveSheet.Paste
Sht.Select
Range("p1").ClearContents
Else
End If
Next Sht
End Sub

Your code has some flaws.
Identation. Code inside Sub, For, If needs to be identated with tab or 4 spaces.
End. Each Sub has End Sub, each If as and End If, each For has and End For
Values. Instead of copying and pasting, you can set .Range() = new_value
String comparison. If cell.Value = "Subtotal" will fail if the user writes subtotal or SUBTOTAL. That is why I prefer to lowercase the cell value using LCase() function.
You may want to use the following code
Sub CombineData()
Dim Sht As Worksheet
'Identify Sheet called Summary
Dim wsSummary As Worksheet
Set wsSummary = ActiveWorkbook.Sheets("Summary")
For Each Sht In ActiveWorkbook.Worksheets
If Sht.Name <> "Summary" And (Left(Sht.Name, 1) = "1" Or Left(Sht.Name, 1) = "4" Or Left(Sht.Name, 1) = "6" Or Left(Sht.Name, 1) = "7") Then
For Each cell In Sht.UsedRange.Cells
If LCase(cell.Value) = "subtotal" Then
'Copy cell above subtotal to the last row in column A of Summary sheet
wsSummary.Range("A65536").End(xlUp).Offset(1, 0) = cell.Offset(-1, 0).Value
Sht.Range("p1") = cell.Offset(-1, 0).Value
End If
Next
End If
Next Sht
End Sub

Related

in Excel VBA why does my code not work with SpecialCells type visible and work without it?

In columns Bk and CB they both contain formula's that will result in a code. Now CB will also contain four codes and a remove statement which if they match with the cell in column BK in the same row then take the value from CB and paste over hence overriding the value in BK with that code and then paste it red.
the above should be done only on a filtered range though.
The ignore #N/A are in there as the overide column will error out on almost everyline except for when there is a code to overide.
This macro works perfectly without the visible cells statement at the end of my with range line but as soon as the visible cells statement is added the loop only goes up to #N/A and disregards the rest of the ElseIF statement.
Here is my code below:
Option Explicit
Sub Override()
Dim x As Workbook: Set x = ThisWorkbook
Dim rRange As Variant, fltrdRng As Range, aCell As Range, rngToCopy As Range
Dim ws As Worksheet
Dim LR As Long
Dim LR2 As Long
Dim SrchRng As Range, cel As Range
Dim mRow
mRow = 2
Set ws = x.Worksheets("Data")
LR = ws.Range("CB" & ws.Rows.Count).End(xlUp).Row
LR2 = ws.Range("BK" & ws.Rows.Count).End(xlUp).Row
'clears any filters on the sheet
ws.AutoFilterMode = False
' turns formula's to manual
Application.Calculation = xlManual
'copies down the formula in Column BK ignoring the last two rows as they have already been pasted over.
ws.Range("BK2:BK4 ").AutoFill Destination:=ws.Range("BK2:BK" & LR2 - 2)
'filters on N/A's and 10 as these are the codes we are interested in overiding
ws.Range("$A$1:$CB$1").AutoFilter Field:=19, Criteria1:=Array( _
"10", "N/A"), Operator:= _
xlFilterValues
' will loop through all cells in specified range and ignore any error's and #N/A's and will paste over the code overided in CB column to the BK column if conditions are met.
On Error Resume Next
While IsEmpty(ws.Range("CB" & mRow)) = False
With ws.Range("CB" & mRow).SpecialCells(xlCellTypeVisible)
If .Value = "#N/A" Then
ElseIf .Value = "1234" Then
.Offset(0, -17).Value = "1234"
.Offset(0, -17).Interior.Color = vbRed
ElseIf .Value = "1235" Then
.Offset(0, -17).Value = "1235"
.Offset(0, -17).Interior.Color = vbRed
ElseIf .Value = "1236" Then
.Offset(0, -17).Value = "1236"
.Offset(0, -17).Interior.Color = vbRed
ElseIf .Value = "Remove" Then
.Offset(0, -17).Value = "Remove"
.Offset(0, -17).Interior.Color = vbRed
ElseIf .Value = "1237" Then
.Offset(0, -17).Value = "1237"
.Offset(0, -17).Interior.Color = vbRed
End If
End With
mRow = mRow + 1
Wend
'turn Formula 's back to automatic
Application.Calculation = xlAutomatic
End Sub
With ws.Range("CB" & mRow).SpecialCells(xlCellTypeVisible)
Using SpecialCells on just one cell is problematic.
Instead, use it on the entire filtered column, like this, which will replace your entire While...Wend loop (by the way, While...Wend is obsolete):
On Error Resume Next
Dim visibleCells As Range
Set visibleCells = ws.Range("CB2:CB" & LR).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If visibleCells Is Nothing Then Exit Sub
Dim cell As Range
For Each cell In visibleCells
If Not IsError(cell.Value) Then
Select Case cell.Value
Case "1234", "1235", "1236", "1237", "Remove"
cell.Offset(0, -17).Value = cell.Value
cell.Offset(0, -17).Interior.Color = vbRed
End Select
End If
Next

VBA code to copy and paste specifc words in different cells to another worksheet

I have a code that will copy and paste a whole row in worksheet called "Raw Data". If cells in Range $D$1:D have a value of "Thomas Xiong", then it will paste the whole row of everything under that value to another worksheet called "WIP".
What I am trying to do is be able to create a code that will be able to find multiple words. For example, "Thomas Xiong" and the word "Assigned" and be able to copy and paste that whole line from the worksheet "Raw Data" into another worksheet.
Also with the code I have now, it will copy and paste the whole rows but there are spaces in between each cell row in the other worksheet.
The code I have now:
Sub Test()
Dim Cell As Range
With Sheets("Raw Data")
' loop column C untill last cell with value (not entire column)
For Each Cell In .Range("D1:D" & .Cells(.Rows.Count, "D").End(xlUp).Row)
If Cell.Value = "Thomas Xiong" Then
' Copy>>Paste in 1-line (no need to use Select)
.Rows(Cell.Row).copy Destination:=Sheets("WIP").Rows(Cell.Row)
'.Range("C1:C", "A", "B", "D", "F" & Cell.Row).copy
End If
Next Cell
For Each Cell In .Range("C1:C" & .Cells(.Rows.Count, "C").End(xlUp).Row)
If Cell.Value = "Assigned" Then
' Copy>>Paste in 1-line (no need to use Select)
.Rows(Cell.Row).copy Destination:=Sheets("WIP").Rows(Cell.Row)
'.Range("C1:C", "A", "B", "D", "F" & Cell.Row).copy
End If
Next Cell
End With
End Sub
The problem is you are using the row of the cells you are copying in your destination sheet. You want to use a separate counter that you increment every time you paste something on e given row:
Sub Test()
Dim Cell As Range
Dim myRow as long
myRow = 2
With Sheets("Raw Data")
' loop column C untill last cell with value (not entire column)
For Each Cell In .Range("D1:D" & .Cells(.Rows.Count, "D").End(xlUp).Row)
If Cell.Value = "Thomas Xiong" Then
' Copy>>Paste in 1-line (no need to use Select)
.Rows(Cell.Row).copy Destination:=Sheets("WIP").Rows(myRow)
myRow = myRow + 1
End If
Next Cell
For Each Cell In .Range("C1:C" & .Cells(.Rows.Count, "C").End(xlUp).Row)
If Cell.Value = "Assigned" Then
' Copy>>Paste in 1-line (no need to use Select)
.Rows(Cell.Row).copy Destination:=Sheets("WIP").Rows(myRow)
myRow = myRow + 1
End If
Next Cell
End With
End Sub
What's not clear (to me at least) is if you want to only find rows where the value in column D is "Thomas Xiong" and the value in column C is "Assigned", in which case you want to have something like this:
Sub Test()
Dim Cell As Range
Dim myRow as long
myRow = 2
With Sheets("Raw Data")
For Each Cell In .Range("C1:C" & .Cells(.Rows.Count, "C").End(xlUp).Row)
If Cell.Value = "Assigned" and Cell.Offset(0,1).Value = "Thomas Xiong" Then
' Copy>>Paste in 1-line (no need to use Select)
.Rows(Cell.Row).copy Destination:=Sheets("WIP").Rows(myRow)
myRow = myRow + 1
End If
Next Cell
End With
End Sub
To loop through a list of names (which I will assume to be in range A1:A10 in a worksheet called "myNames") something like this should work:
Sub Test()
Dim Cell as Range
Dim NameCell as Range
Dim myRow as Long
myRow = 2
With Sheets("Raw Data")
For each NameCell in Worksheet("myNames").Range("A1:A10)
For Each Cell In .Range("C1:C" & .Cells(.Rows.Count, "C").End(xlUp).Row)
If Cell.Value = "Assigned" and Cell.Offset(0,1).Value = NameCell.Value Then
.Rows(Cell.Row).copy Destination:=Sheets("WIP").Rows(myRow)
myRow = myRow + 1
Exit For
End If
Next Cell
Next NameCell
End With
End Sub

VBA - How to insert a row and divide data into groups?

I use the code below to copy my data from one sheet to another.
Sub Copypastemeddata()
Dim wb As Workbook
Dim ws As Worksheet
Dim sourceCell As Range
Dim targetSheet As Worksheet
Dim StartRow As Integer
Application.ScreenUpdating = False
Application.CopyObjectsWithCells = False
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Opgørsel")
Set sourceCell = ws.Range("D3") 'Cell with sheet names for copying to
StartRow = 1 'Destination row on targetSheet
With ws
Set targetSheet = wb.Worksheets(sourceCell.Text)
.Range("A1").CurrentRegion.Copy
targetSheet.Range("A" & StartRow).Insert Shift:=xlDown
targetSheet.Columns.AutoFit
End With
Application.CutCopyMode = 0
Application.ScreenUpdating = True
Application.CopyObjectsWithCells = True
End Sub
In the sheet I'm copying, i want to insert a row every time the value under cell "tykkelse [m]" is different and divide it under the same row if the value is the same for multiple copies.
Thanks.
below provides a possible solution:
Sub solved()
Set findfirst = Sheet1.Range("H:H").Find("tykkelse [m]")
currentvalue = findfirst.Offset(1, 0).Value
findfirst.Offset(-1, 0).EntireRow.Insert xlDown
With Range(Cells(findfirst.Row - 2, 1), Cells(findfirst.Row - 2, 14))
.Merge
.Value = currentvalue
End With
Set findfirst = Sheet1.Range("H:H").Find("tykkelse [m]")
Set findsecond = Sheet1.Range("H:H").FindNext(After:=findfirst)
Do While Intersect(findsecond, findfirst) Is Nothing
If findsecond.Offset(1, 0).Value <> currentvalue Then
currentvalue = findsecond.Offset(1, 0).Value
findsecond.Offset(-1, 0).EntireRow.Insert xlDown
With Range(Cells(findsecond.Row - 2, 1), Cells(findsecond.Row - 2, 14))
.Merge
.Value = currentvalue
End With
End If
Set findsecond = Sheet1.Range("H:H").FindNext(findsecond)
Loop
End Sub
First, we find the first occurrence of "tykkelse [m]":
Then we store the value associated to this occurrence, and insert the row above and merge (color and alignment still to be added)
We find first occurrence again, because it has shifted, and we need it for the check below. We loop over each occurrence in column H and check if we had them all by comparing it to the first occurrence.
For each occurrence, we check if the value underneath has changed; if so, we apply the same manipulations.

Hiding row if cell equals next visible cell

I am trying to write a macro that hides the row if the cell value equals the next visible cell in that column and loops through the whole column. I have read that SpecialCells(xlCellTypeVisible) only works up to 8192 cells and my spreadsheet has 15,000 rows.
I have tried something like this but want to restrict it to only visible cells
Sub Test()
For i = 7 To 15258
If Range("P" & i).Value = Range("P" & i + 1).Value Then
Rows(i).Hidden = True
End If
Next i
End Sub
I have tried to search for a solution but haven't been able to find one yet.
Thanks!
I'd be surprised if this couldn't be optimized just a little bit, but it will work for what you are needing.
You can follow the comments within the code itself to kind of get a sense of what it's doing, but in a nutshell, you are using a For...Next statement to loop through your visible cells. For each visible cell, you will search for the next visible cell and then check to see if that matches. If it does, you add that cell to a special range that tracks all the rows to hide at the end of the code, then hide it.
Sub Test()
Dim ws As Worksheet, lookupRng As Range, rng As Range, lstRow As Long
Set ws = ThisWorkbook.Worksheets(1)
lstRow = 15258
Set lookupRng = ws.Range("P7:P" & lstRow)
Dim rngToHide As Range, i As Long
For Each rng In lookupRng.SpecialCells(xlCellTypeVisible)
Application.StatusBar = "Checking row " & rng.Row & " for matches."
For i = rng.Row + 1 To lstRow 'Loop through rows after rng
If Not ws.Rows(i).Hidden Then 'Check if row is hidden
If rng.Value = ws.Cells(i, "P") Then 'check if the non-hidden row matches
If rngToHide Is Nothing Then 'Add to special range to hide cells
Set rngToHide = ws.Cells(i, "P")
Else
Set rngToHide = Union(rngToHide, ws.Cells(i, "P"))
End If
End If
Exit For 'Exit the second For statement
End If
Next i
Next rng
Application.StatusBar = "Hiding duplicate rows"
If Not rngToHide Is Nothing Then rngToHide.EntireRow.Hidden = True
Application.StatusBar = False
End Sub

modify code to start copy from under a cell named "Sales organization"

Below code is for retrieving header data from first sheet (starting in cell A1) then copying range from second row.
I would like to modify this to retrieve header date from first sheet: it is the row starting with Cell containing value "Sales organization", then copy the range from all sheet starting from under the header (Cell containing value "Sales organization") into sheet Master.
Can someone please help me to modify it so?
Many thanks!
Sub CopyFromWorksheets()
Dim wrk As Workbook
Dim sht As Worksheet
Dim trg As Worksheet
Dim rng As Range
Dim colCount As Integer
Set wrk = ActiveWorkbook
For Each sht In wrk.Worksheets
If sht.Name = "Master" Then
MsgBox "There is a worksheet called as 'Master'." & vbCrLf & _
"Please remove or rename this worksheet since 'Master' would be" & _
"the name of the result worksheet of this process.", vbOKOnly + vbExclamation, "Error"
Exit Sub
End If
Next sht
Application.ScreenUpdating = False
Set trg = wrk.Worksheets.Add(After:=wrk.Worksheets(wrk.Worksheets.Count))
trg.Name = "Master"
Set sht = wrk.Worksheets(1)
colCount = sht.Cells(1, 255).End(xlToLeft).Column
With trg.Cells(1, 1).Resize(1, colCount)
.Value = sht.Cells(1, 1).Resize(1, colCount).Value
.Font.Bold = True
End With
For Each sht In wrk.Worksheets
If sht.Index = wrk.Worksheets.Count Then
Exit For
End If
Set rng = sht.Range(sht.Cells(2, 1), sht.Cells(65536, 1).End(xlUp).Resize(, colCount))
trg.Cells(65536, 1).End(xlUp).Offset(1).Resize(rng.Rows.Count, rng.Columns.Count).Value = rng.Value
Next sht
trg.Columns.AutoFit
Application.ScreenUpdating = True
End Sub
You can use WorksheetFunction.MATCH to find the column of interest - after that, copying the column should be easy:
theColumn = WorksheetFunction.MATCH("Sales organization", Range("1:1"), 0)
which will find the first column in the first row that has exactly Sales organization in it.
Reference: http://msdn.microsoft.com/en-us/library/office/ff835873.aspx
update if there is a chance that there is no cell with "Sales organization" in it, you might want to trap this - since it would generate an error (as pointed out by D_Bester). Something like this:
theColumn = -1 ' set an "impossible" value
' - it will get overwritten by a successful call to MATCH
On Error Resume Next ' ignore error in the next line and keep going
theColumn = WorksheetFunction.MATCH("Sales organization", Range("1:1"), 0)
On Error GoTo 0 ' turn error handling off again
if theColumn > 0 Then
' do whatever you were planning - you found a match
Else
' do something else, since you didn't find a match...
End If

Resources