I am working on a code that performs a certain number of steps on different reports. The reports contain different number or rows every time and in some cases , the reports also contain a hidden row below the last row with data. My code works fine on reports that have a hidden row but it does not work well on reports that do not have a hidden row. For the reports that do not have a hidden row, it leaves one row blank.
It works well until I define LR2. I would like to define LR2 in so that it does not consider the hidden row as a row containing data so that my code works uniformly on reports containing hidden row as well as not containing hidden row. Please see the image of the file that has a hidden row. In this case, row number 64 is hidden but in some cases there are no hidden rows below the grey row which is supposed to be the last row. Please assist me writing a single code to work for both scenarios
Dim LR2 As Long
LR2 = ActiveSheet.UsedRange.Rows.Count - 2
ActiveSheet.Range("A6:A" & LR2).Copy ActiveSheet.Range("B6:B" & LR2)
Application.CutCopyMode = False
ActiveSheet.Range("B6:B" & LR2).Select
Selection.Replace What:="-", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2```
UsedRange is not always a reliable to find the last row, so try something like this:
Sub Tester()
Dim ws As Worksheet, rng As Range
Dim lr As Long
Set ws = ActiveSheet
lr = LastUsedRow(ws)
If ws.Rows(lr).Hidden Then lr = lr - 1 'skip last row if hidden
Set rng = ws.Range("A6:A" & lr)
Debug.Print "copying", rng.Address
rng.Copy rng.Offset(0, 1) 'copy to colB
rng.Offset(0, 1).Replace What:="-", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2
End Sub
'find the last used row on a worksheet
Function LastUsedRow(ws As Worksheet)
Dim f As Range
Set f = ws.Cells.Find(What:="*", After:=ws.Range("A1"), _
LookAt:=xlPart, LookIn:=xlFormulas, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
If Not f Is Nothing Then LastUsedRow = f.Row 'otherwise zero
End Function
Related
Good Day,
I had found a solution that looks at a table, but the file I am trying to delete the last 2 rows for is just a worksheet. The code I am referring to is,
Dim wsR2 As Worksheet
Set wsR2 = ThisWorkbook.Sheets("Journal")
Dim LastRow As Long
LastRow = wsR2.ListObjects("xJrnl").DataBodyRange.Rows.Count
wsR2.ListObjects("xJrnl").ListRows(LastRow).Delete
I'm not sure how to edit the above code to be used for a simple worksheet rather than a table. My sheet name is "Sheet1" Any assistance is appreciated.
The hardest part of your task is to reliably find the last row on the sheet. There are several ways, each with its own advantages and disadvantages. One of the solutions is below (a fragment of the solution from Find last row, column or last cell is used - I recommend reading it).
Option Explicit
Sub Del2lastRows()
Dim sh As Worksheet, LastCell As Range
Set sh = ThisWorkbook.Sheets("Sheet1")
Set LastCell = sh.Cells.Find(what:="*", _
After:=sh.Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If LastCell.Row > 1 Then
LastCell.Offset(-1).Resize(2).EntireRow.Delete
End If
' reset find dialog after using LastRow()
sh.Cells.Find what:="", _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False
End Sub
I am attempting to have a macro insert a column on sheet "Runs", and then paste information from sheet "Templates" onto the newly inserted column on a specific Row. I have named the range for row four as "Eight", however, info from templates is pasted onto column A, Row 4, and not the newly inserted column.
Set myWorksheet = Worksheets("Runs")
myFirstColumnT = myWorksheet.Cells.Find( _
What:="TS", _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
myLastColumnT = myWorksheet.Cells.Find( _
What:="TE", _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
For iCounter = myLastColumnT To (myFirstColumnT + 1) Step -100000000
myWorksheet.Columns(iCounter).Insert
Sheets("Templates").Select
Range("B2:B16").Copy
Sheets("Runs").Select
With Columns(iCounter).Select
Range("eight").PasteSpecial
End With
Next iCounter
The issue is your With doesn't actually do anything and if it did your Range doesn't reference it.
I've removed your loop, it has such a massive step it isn't actually looping anything. Also you don't need a loop for this.
I removed the .column from your .finds because that will cause an error if it fails, I also added in some error checking for if (when) it doesn't find anything.
I removed all instances of .Select because they aren't necessary.
Dim myworksheet As Worksheet
Dim myfirstcolumnt As Range
Dim mylastcolumnt As Range
Dim newcol As Long
Set myworksheet = Worksheets("Runs")
'I'm assuming you need this for a reason other than the loop, otherwise you can remove it
Set myfirstcolumnt = myworksheet.Cells.Find( _
What:="TS", _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious)
If myfirstcolumnt Is Nothing Then
MsgBox "TS not found"
Exit Sub
End If
Set mylastcolumnt = myworksheet.Cells.Find( _
What:="TE", _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious)
If mylastcolumnt Is Nothing Then 'Avoiding errors
MsgBox "TE not found"
Exit Sub
End If
newcol = mylastcolumnt.Column + 1 'No need to loop to find the column you're making
myworksheet.Columns(newcol).Insert 'use the new column index to add the column
Sheets("Templates").Range("b2:b16").Copy
myworksheet.Cells(4, newcol).PasteSpecial 'We know it's going in row 4 and we have the new column index now
If you want to use your named range you can do myworksheet.Cells(myworksheet.range("Eight").Row, newcol)... Though I suggest changing the name, a range called "Eight" pointing to Row 4 isn't very clear.
Trying to copy data from one Excel spreadsheet to another (from New_data to report).
In the New_data spreadsheet I find the second time System (hence why I start the search below the first one at N21) appears then I need to copy all data below it from columns b - k until I hit blank cells. How do I get the amount of rows to only capture filled cells?
Range("B584:K641") needs to be dynamic.
Sub CopyWorkbook()
Range("N21").Select
Cells.Find(What:="system", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
Range("B584:K641").Select
Selection.Copy
Application.WindowState = xlNormal
Windows("report.xlsx").Activate
Range("A2").Select
ActiveSheet.Paste
Windows("new_data.csv"). _
Activate
End Sub
Try the next code please. It should be very fast (if I correctly understood where to be searched for 'system', starting with what...). The code assumes that "new_data.csv" is the csv workbook name. If not, you must use its real name when defining shCSV sheet:
Sub CopyWorkbook()
Dim shR As Worksheet, shCSV As Worksheet, lastRow As Long, systCell As Range, arr
Set shR = Workbooks("report.xlsx").ActiveSheet 'use here the sheet you need to paste
'it should be better to use the sheet name.
'No need to have the respective sheet activated at the beginning
Set shCSV = Workbooks("new_data.csv").Sheets(1) 'csv file has a single sheet, anyhow
lastRow = shCSV.Range("B" & rows.count).End(xlUp).row
Set systCell = shCSV.Range("B21:B" & lastRow).Find(What:="system", _
After:=shCSV.Range("B21"), LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False)
If systCell Is Nothing Then MsgBox "No 'sytem' cell has been found...": Exit Sub
arr = shCSV.Range(systCell, shCSV.Range("K" & lastRow)).Value
shR.Range("A2").Resize(UBound(arr), UBound(arr, 2)).Value = arr
End Sub
Try:
Sub test()
Dim LR As Long
Dim Ini As Long
LR = Range("B" & Rows.Count).End(xlUp).Row 'last non empty row in column B
Ini = Application.WorksheetFunction.Match("system", Range("N21:N" & LR), 0) + 20 'position of system after n21
Range("B" & Ini & ":K" & LR).Copy
'''rest of your code to paste
End Sub
Note that this code is searching word system only in column N. If it's somewhere else, you'll need to adapt the MATCH function
I set a range to equal the filtered range and start a loop to count how many none empty cells occur until the first empty cell in column B.
Sub CopyWorkbook()
ThisWorkbook.Sheets("new_data").Activate
Range("N21").Select
Dim rng As Range
Set rng = Cells.Find(What:="system", After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
Dim i As Double
i = rng.Row
Do Until ThisWorkbook.Sheets("new_data").Range("B" & i) = vbNullString
i = i + 1
Loop
i = i - 1
Range("B" & rng.Row & ":K" & i).Select
Selection.Copy
Application.WindowState = xlNormal
Windows("report.xlsx").Activate
Range("A2").Select
ActiveSheet.Paste
Windows("new_data.csv").Activate
End Sub
I found a Stack Overflow question that was helpful in finding an answer. Find cell address
I have two sheets:
Database
Macro sheet: It has a row with dates that will be the headings of a table after the macro.
Objective: In the macro sheet take the value of the first date and look for its position in the database sheet. Then, in the database sheet, copy the entire column corresponding to the previously copied date.
I understand that the code should look something like this:
Sheets("Macro").Select
Range("K3").Select
Selection.Copy
Sheets("Database").Select
Cells.Find(What:=Selection.PasteSpecial xlValues, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("Macro").Select
ActiveSheet.Paste
This code does not work, because the search part is not done well, I will appreciate some correction
Something along these lines.
Read this to learn the advantages of not using Select or Activate.
When using Find, always check first that your search term is found to avoid an error. For example, you cannot activate a cell that does not exist.
Sub x()
Dim r As Range
With Sheets("Database")
Set r = .Cells.Find(What:=Sheets("Macro").Range("K3").Value, lookAt:=xlPart, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not r Is Nothing Then
Range(r, r.End(xlDown)).Copy Sheets("Macro").Range("A1")
End If
End With
End Sub
Loop through he header dates in the Macro worksheet. If any can be found in the header row of the Database worksheet, copy that column to the Macro worksheet under the header.
sub getDateData()
dim h as long, wsdb as worksheet, m as variant, arr as variant
set wsdb = worksheets("database")
with worksheets("macro")
for h=1 to .cells(1, .columns.count).end(xltoleft).column
m = application.match(.cells(1, h).value2, wsdb.rows(1), 0)
if not iserror(m) then
arr = wsdb.range(wsdb.cells(2, m), wsdb.cells(rows.count, m).end(xlup)).value
.cells(2, h).resize(ubound(arr, 1), ubound(arr, 2)) = arr
end if
next h
end with
end sub
Microsoft Excel 2010:
From month to month, the number of lines of data can be variable. When I paste new data into the ILS_IMPORT tab, there may be 3,500 records and the next month could be 2,500. When I go to import the data into Access, and extra 1,000 lines will appear unless I delete all records from line 2,501 on. I would like to have Excel VBA to do this and have made attempts, but nothing has worked thus far. I know that Column O will always have data to the end because it is the quarter indicator (ex. Q2).
However, this code keeps deleting the last row and I don't know if it is truly deleting all the way to the end. Can someone point me in the right direction?
Sub test()
Dim rng As Range
Dim lastRow As Long
With ThisWorkbook.Sheets("ILS_IMPORT")
'Find anything in the cells
Set rng = .Cells.Find(What:="*", _
After:=.Range("O1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
'if data is NOT found - exit from sub
If rng Is Nothing Then Exit Sub
'find last row
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lastRow = .Cells.Find(What:="*", _
After:=.Range("O1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
lastRow = 1
End If
'I use lastRow + 1 to prevent deletion data above when it is on lastrow
.Range(rng.Row + 2 & ":" & lastRow + 2).Delete Shift:=xlUp
End With
End Sub
Could you clear/delete the blank range before you paste data in?
range(cells(2,1),cells(2,1).end(xldown)).EntireRow.Clear