Copying last cell in a column and offsetting by 1 - excel

i have a code that copies an array of values from 1 sheet and pastes it in another now i want to offst the last populated row by 1 and delete the original row ie if the last row were L12:(entire row) it is pasted to L13 and row L12 is left empty.
Dim ws As Worksheet
Set ws = Worksheets("Pivot_WH calculations") 'change name as needed
With ws
'assumes data is in a "table" format with all data rows in column A and data columns in row 1
.Range("E2:J7").Copy _
Worksheets("WH Calc_new").Range("L" & .Rows.Count).End(xlUp).Offset(2)
.Range("E8:J8").Copy _
Worksheets("WH Calc_new").Range("L" & .Rows.Count).End(xlUp).Offset(2)
.Range("A2:A9").Copy _
Worksheets("WH Calc_new").Range("K" & .Rows.Count).End(xlUp).Offset(2)
End With
End Sub

The Function at the End will give you the last Row That is actually the last row used in the Worksheet.
For the offset you can change 2 to 3 or 4 or any other number you want to Offset in .Offset(Number_Here)
Try This:
Sub cdd()
Dim ws As Worksheet
Dim lst As Long
Set ws = Worksheets("Pivot_WH calculations") 'change name as needed
lst = LastRow(Worksheets("WH Calc_new"))
With ws
.Range("E2:J7").Copy Worksheets("WH Calc_new").Range("L" & lst).Offset(2)
.Range("E8:J8").Copy Worksheets("WH Calc_new").Range("L" & lst).Offset(2)
.Range("A2:A9").Copy Worksheets("WH Calc_new").Range("K" & lst).Offset(2)
End With
End Sub
Function LastRow(Sh As Worksheet)
On Error Resume Next
LastRow = Sh.Cells.Find(What:="*", _
After:=Sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).row
On Error GoTo 0
End Function

Related

Calculations across excel sheets using VBA

I am having problem with the following code.
I am trying to copy some data (as values) from one sheet to another (the data in the original sheet ("DAX NE3") is retrieved from a DAX database and the number of rows may vary depending on the date etc., so it has to copy all rows in every case). I have to take the two first columns (A and B) in "DAX NE3" and copy into column A and B in "Sheet4", but column C-F in "DAX NE3" has to be copied to column D-G in "Sheet4". All blank cells in the original data has to be equal to '0'. Furthermore I need to make a 'Share of part' in column C in 'Sheet4', so example C6=B6/sum(all B) and so on.
My Data when copying and pasting is all over the place. Can someone see why and please help?
Sub CopyData()
Dim m As Long
Dim rng As Range
Dim result As Variant
Dim firstvalue As Variant
Dim secondvalue As Variant
'Delete old data
Worksheets("Sheet4").Rows("6:" & Rows.Count).ClearContents
'Copy data from one sheet to another
On Error Resume Next
m = Worksheets("DAX NE3").Range("A:B").Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
If Err Then
MsgBox "No data to copy!", vbExclamation
Exit Sub
End If
On Error GoTo 0
Worksheets("DAX NE3").Range("A27:C" & m).Copy
Worksheets("Sheet4").Range("A6:C" & m + 1).Insert Shift:=xlShiftDown
Worksheets("Sheet4").Range("A6:C" & m + 1).PasteSpecial Paste:=xlPasteValues
Worksheets("DAX NE3").Range("A1").Copy Destination:=Worksheets("Sheet4").Range("A6").Resize(m)
Application.CutCopyMode = False
On Error Resume Next
m = Worksheets("DAX NE3").Range("B:F").Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
If Err Then
MsgBox "No data to copy!", vbExclamation
Exit Sub
End If
On Error GoTo 0
Worksheets("DAX NE3").Range("B27:G" & m).Copy
Worksheets("Sheet4").Range("C6:G" & m + 1).Insert Shift:=xlShiftDown
Worksheets("Sheet4").Range("C6:G" & m + 1).PasteSpecial Paste:=xlPasteValues
Worksheets("DAX NE3").Range("C1").Copy Destination:=Worksheets("Sheet4").Range("C6").Resize(m)
Application.CutCopyMode = False
'Change all Blank cells to '0'
Set rng = Sheets("Sheet4").Range("B6:B" & m)
Sheets("Sheet4").Activate
rng.Select
Selection.Replace What:="", Replacement:="0", LookAt:=xlWhole, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
'Calculate Share of portfolio %
firstvalue = Range("B6").Value
secondvalue = Range("B6" & Cells(Rows.Count, 2).End(xlUp).Row).Value > 0
m = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Worksheets("Sheet4").Range("C6:C" & m).Formula = firstvalue / secondvalue
End Sub

Find function in Excel VBA only refers to newly created sheet

I have been racking my brain on a bug whereby VBA seems to be using the wrong sheet within a Find function. For purposes such as printing the name of the sheet and values within cells, VBA refers to the sheet I expect. But for the Find function, it reverts to the most recently created sheet and I cannot force a reference to any other sheet. Below is an example that illustrates the problem. The lastRow variable gets assigned based on the Find function from the newly created sheet (three row) whereas the sht variable refers to the five row sheet.
Option Explicit
Dim wb As Workbook
Sub start()
Set wb = ThisWorkbook
Call make5RowSheet
Call make3RowSheet
Call CountRows5RowSheet
End Sub
Sub CountRows5RowSheet()
Dim thing As Variant
Dim sht As Worksheet
Dim lastRow As Long
For Each thing In wb.Worksheets
If LCase(thing.Name) = LCase("five rows") Then Set sht = thing
Next thing
With sht
lastRow = Cells.Find(What:="*", _
After:=.Range("A1"), _ '!!! .range here should refer to five row sheet, but lastRow gets set to 3
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
End With
Debug.Print "sheet name: " & sht.Name 'prints "five rows" as expected
Debug.Print "Cell(3,3) value: " & sht.Cells(3, 1).Value 'blank, as expected
Debug.Print "cell(5,5) value: " & sht.Cells(5, 1).Value 'prints "foo", as expected
Debug.Print "last Row: " & lastRow 'prints 3, which is puzzling
End Sub
Sub make5RowSheet()
Dim sht As Worksheet
Set sht = wb.Worksheets.Add
sht.Name = "five rows"
sht.Cells(5, 1) = "foo"
End Sub
Sub make3RowSheet()
Dim sht As Worksheet
Set sht = wb.Worksheets.Add
sht.Name = "three rows"
sht.Cells(3, 1).Value = "foo"
End Sub
Here
With sht
lastRow = Cells.Find(What:="*", _
Cells is not tied to sht so it refers to the ActiveSheet
With sht
lastRow = .Cells.Find(What:="*", _
should fix things
Your Cells.Find will be executed on whatever sheet is active.
In your case, the last sheet that was created is three rows.
So to avoid this hassle, make sure you Activate the right sheet right before you Find.
sht.Activate ' move from (three rows) to (five rows)
With sht
lastRow = Cells.Find(What:="*", _
After:=.Range("A1"), _ '!!! .range here should refer to five row sheet, but lastRow gets set to 3
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
End With

Using Select Case with InStr for multiple named sheets

My first post here.....
I was able to search and find this code from Siddharth Rout which is the basis for what I want to do....append multiple sheets of data to a single data sheet. However I'm having trouble modifying it to fit my case. What I have below doesn't currently work......
Problem 1) How can I use Select Case InStr with multiple sheets (3) that do not have a common name such as "Legende" as the original poster had in her case.
Problem 2) In my case each sheet will have different columns that I need copied to the Tab_Appended sheet, Sheet1 will have x rows and I want column B, D, M, AR, etc and Sheet2 will have XXXX rows and I want to copy column B, D, N, AS, AT, etc for 15 sheets.
Credit to Siddharth Rout for this original code:
Sub SummurizeSheets()
Dim wsOutput As Worksheet
Dim ws As Worksheet
Dim wsOLr As Long, wsLr As Long
Application.ScreenUpdating = False
'~~> Set this to the sheet where the output will be dumped
Set wsOutput = Sheets("Tab_Appended")
With wsOutput
'~~> Get Last Row in "Tab_Appended" in Col A/M and Add 1 to it
wsOLr = .Range("A:M").Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row + 1
'~~> Loop through sheet
For Each ws In Worksheets
'~~> Check if the sheet name has Legende
'Select Case InStr(1, ws.Name, "Legende", vbTextCompare)
Select Case InStr(1, ws.Name, "Test2", vbTextCompare) + _
InStr(1, strData, "Test", vbTextCompare) + _
InStr(1, strData, "Sheet2", vbTextCompare)
'~~> If not then
Case 0
With ws
'~~> Get Last Row in the sheet
wsLr = .Range("A:M").Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row
'~~> Copy the relevant range
.Range("A2:M" & wsLr).Copy wsOutput.Range("A" & wsOLr)
'~~> Get Last Row AGAIN in "Tab_Appended" in Col A/B and Add 1 to it
wsOLr = wsOutput.Range("A:M").Find(What:="*", After:=wsOutput.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row + 1
End With
End Select
Next
End With
Application.ScreenUpdating = True
End Sub
Thanks,
Don

How to lock a column until it's last row with data

I have date mentioned in cell A1, ex - "May".
I am now trying to lock rows 2-last with column Z which mentions date of joining of each employee and compares it to A1.
If month of this cell Z is > A1 then I am trying to lock the row. Not sure what to do.
Below code doesnt help :
Sub Lockrow()
Dim DestSh As Worksheet
Dim lastrow As Long
Dim i As Integer
Set DestSh = Sheets("Consultant & Teacher")
With DestSh
'finds the last row with data on A column
lastrow = Range("A65536").End(xlUp).Row
'parse all rows
For i = 6 To lastrow
'if your conditions are met
If Month(.Cells(i, 26)) > Month(.Cells(1, 2)) Then
.Range("A" & i).EntireRow.Cells.Locked = True 'lock the row
End If
Next i
End With
End Sub
Is this what you are trying?
Sub Sample()
Dim DestSh As Worksheet
Dim lastrow As Long
'~~> Change this as applicable
Set DestSh = Sheets("Sheet1")
With DestSh
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lastrow = .Columns("A:C").Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
MsgBox "Insufficient rows"
Exit Sub
End If
.Unprotect "MyPassword"
.Cells.Locked = False
.Range("A6:C" & lastrow).Locked = True
.Protect "MyPassword"
End With
End Sub

VBA find and replace skipping some cells

I have a bit of code that finds blanks in a given column and replaces them with "BLANK", this has worked fine in the past and works for all of the sheets I am looking at bar one.
In the 'meter' sheet the whole column is blank, yet the find and replace fills all bar 6 of the blanks with no apparent pattern as below. I expect this could be another of my Monday morning 'user malfunction' errors but would appreciate any insight.
I am aware this would be better in a loop, which I will write once I've fixed the problem of it missing some blanks.
Cheers
Public Function FILL_blanks() '''' this searches for blanks
'in the columns in the raw data we are interested in and replaces
'them with BLANK there is a value assigned to BLANK in the flag matrix.
Dim LastRow_g As Long '''' HYDRANT, NODE ---->CHANGES LENGTH FOR EACH ASSET
Dim LastRow_j As Long ''''
Dim LastRow_bp As Long ''''
Dim WS_Count As Integer
Dim i As Integer
WS_Count = ActiveWorkbook.Worksheets.Count
For i = 1 To WS_Count
If ActiveWorkbook.Worksheets(i).Name = "hydrant" Then
Worksheets(i).Select
Range("g4").Select ' this will change j/g/bp only
LastRow_g = Range("g" & Rows.Count).End(xlUp).Row 'define the last row as all of the rows in DMA flag column
Range("r4:r" & LastRow_g).Select
'find and replace below
Selection.Replace What:="", Replacement:="BLANK", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
ElseIf ActiveWorkbook.Worksheets(i).Name = "meter" Then
Worksheets(i).Select
Range("j4").Select
LastRow_j = Range("j" & Rows.Count).End(xlUp).Row 'define the last row
Range("y4:y" & LastRow_j).Select
'find and replace below
Selection.Replace What:="", Replacement:="BLANK", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
I would use Sub here rather than Function because there doesn't seem to be a return. This code replaces blank cells in the columns specified above:
Option Explicit
Sub FillBlanks2() '''' this searches for blanks
Dim LastRow As Long '''' HYDRANT, NODE ---->CHANGES LENGTH FOR EACH ASSET
Dim Sheet As Worksheet
Dim TargetRange As Range
'loop through worksheets in this workbook
For Each Sheet In ThisWorkbook.Worksheets
If Sheet.Name = "hydrant" Then '<~ concerned with col G on hydrant sheet
With Sheet
LastRow = .Range("G" & .Rows.Count).End(xlUp).Row
Set TargetRange = .Range(.Cells(4, 7), .Cells(LastRow, 7))
End With
'apply replacement to the target range
TargetRange.Replace What:="", Replacement:="BLANK", LookAt:=xlWhole, SearchOrder:=xlByRows
ElseIf Sheet.Name = "meter" Then '<~ concerned with col J on hydrant sheet
With Sheet
LastRow = .Range("J" & .Rows.Count).End(xlUp).Row
Set TargetRange = .Range(.Cells(4, 10), .Cells(LastRow, 10))
End With
'apply replacement to the target range
TargetRange.Replace What:="", Replacement:="BLANK", LookAt:=xlWhole, SearchOrder:=xlByRows
End If
Next Sheet
End Sub
I adapted the code from Dan Wagner to account for cells that appear blank but actually have spaces in them. if the cells are only likely to contain a blank or one space then it is possible to use "" and " ".
However, I am sure there is a more elegant solution that accounts for all blank spaces. SpecialCells(xlCellTypeBlanks) is a possibility but it appears to be limited to a certain number of rows.
Sub FILL_blanks() '''' this searches for blanks
Dim LastRow As Long '''' HYDRANT, NODE ---->CHANGES LENGTH FOR EACH ASSET
Dim Sheet As Worksheet
Dim TargetRange As Range
Sheets("Sheet1").Select
LastRow = Range("a" & Rows.Count).End(xlUp).Row
Set TargetRange = Range("b4:b" & LastRow)
'apply replacement to the target range
'"" accounts for true blank cells (no spaces)
' "*" is a wildcard and accounts for one or more spaces
TargetRange.Replace What:="", replacement:="BLANK", LookAt:=xlWhole, SearchOrder:=xlByRows
TargetRange.Replace What:=" ", replacement:="BLANK", LookAt:=xlWhole, SearchOrder:=xlByRows
End Sub
Thanks again for your assistance

Resources