Select all data in sheet - excel

I am writing a macro that opens a New Workbook and copies all data to a different Workbook.
The data always starts on C12 but we dont always know how many rows of data there are
The following code is giving an error:
Workbooks("Somesheet.xls").Activate
Sheets("Sheet1").Activate
With Range("C12").Select
End (xlDown)
End With
How do I select all rows from C12?

dim rng as range
with Workbooks("Somesheet.xls").Sheets("Sheet1").range("C12")
set rng = range(.cells(0,0), .end(xldown))
end with
You could also use
set rng = Workbooks("Somesheet.xls").range("C12").CurrentRegion

I use Find to detect the true last used cell as UsedRange can be unreliable with over- estimating the extent of the true used range unless it is forced to recalc in the code before being used. UsedRange can also be problematic unless it start from A1 (I had this issue with Rachel's code when testing data only in C12:C40, the answer provided was G34:G60)
From your question sample code it appears you only wanted column C data from C12 down (which is what this code does). It can readily be extended accross the true used range of columns, or as entire rows if needed
Sub GetData()
Dim wb As Workbook
Dim ws As Worksheet
Dim rng1 As Range
Dim rng2 As Range
Set wb = Workbooks("SomeSheet.xlsm")
Set ws = wb.Sheets("Sheet1")
Set rng1 = ws.Columns("C").Find("*", ws.[c1], xlFormulas, , , xlPrevious)
If rng1.Row > 12 Then
Set rng2 = ws.Range(ws.[c12], rng1)
MsgBox "Your range is " & rng2.Address(0, 0)
Else
MsgBox "Last row in " & ws.Name & " was only " & rng1.Row
End If
End Sub

In order to select all data from cell C12 down, use the UsedRange property to find the absolute last row used. Other methods will stop before the true end of the sheet if there is a blank cell in Column C. This snippet sets a Range variable that spans from C12 to the last used cell in the sheet:
Dim rng As Range
Dim lRowLast As Long, lColLast As Long
With ActiveWorkbook.Worksheets("Sheet1")
lRowLast = .UsedRange.Row + .UsedRange.Rows.Count - 1
lColLast = .UsedRange.Column + .UsedRange.Columns.Count - 1
Set rng = .Range(.Range("C12"), .Cells(lRowLast, lColLast))
End With
Note: use .Row + .Rows.Count - 1 to handle cases where the used range starts after the first row.
Edit: Updated example to fix the bug that #brettdj pointed out.

Related

Auto fill a formula down a column but skipping already populated cells

After numerous failed attempts I am really hoping someone can with my problem. It theory what I am trying to do sounds easy enough but I have spent hours on it today with no success.
I have tried all the possible solutions from this thread but to no avail: Excel vba Autofill only empty cells
Also looked here : https://www.mrexcel.com/board/threads/macro-to-copy-cell-value-down-until-next-non-blank-cell.660608/
I am looking to autofill a formula down a column(a vlookup from another sheet) but if there is already populated cells then to skip and continue the formula in the next available blank cell. For example, in rows A2:A10, row A5 has a value in it, so the formula gets into in A2, then fills to A4, then skips A5, then continues in A6 to A10.
This below code works the first time you use it but then on the second run it debugs with a "Run-time error '1004' - No cells were found". I noticed it it putting the formula into the first cell (B2) and then debugging out.
Sub FillDownFormulaOnlyBlankCells()
Dim wb As Workbook
Dim ws1, ws2 As Worksheet
Dim rDest As Range
Set wb = ThisWorkbook
Set ws1 = Sheets("Copy From")
Set ws2 = Sheets("Copy To")
ws2.Range("A1").Formula = "=IFERROR(IF(VLOOKUP(A2,'Copy From'!A:B,2,FALSE)=0,"""",VLOOKUP(A2,'Copy From'!A:B,2,FALSE)),"""")"
Set rDest = Intersect(ActiveSheet.UsedRange, Range("B2:B300").Cells.SpecialCells(xlCellTypeBlanks))
ws2.Range("B2").Copy rDest
End Sub
Please, try the next code:
Sub FillDownFormulaOnlyBlankCells()
Dim wb As Workbook, ws1 As Worksheet, rngBlanc As Range
Set wb = ThisWorkbook
Set ws1 = wb.Sheets("Copy From")
On Error Resume Next
Set rngBlanc = ws1.Range("B2:B" & ws1.rows.count.End(xlUp).row).SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If Not rngBlanc Is Nothing Then
rngBlanc.Formula = "=IFERROR(IF(VLOOKUP(A2,'Copy From'!A:B,2,FALSE)=0,"""",VLOOKUP(A2,'Copy From'!A:B,2,FALSE)),"""")"
Else
MsgBox "No blanc rows exist in B:B column..."
End If
End Sub
After running it once and do not create any empty cell, of course there will not be any blanc cells, anymore, at a second run...
Thanks to FaneDuru for his suggestion but I actually came up with an alternative solution to my problem which I though I would post as it might help others with a similar issue.
On a separate sheet, I created 3 columns, first column is names I already have, 2nd column are the new names and the 3rd column is there to combine the first 2 columns together, then use this code to combine first 2 columns :
Sub MergeColumns()
Dim wb As Workbook
Dim ws1 As Worksheet
Dim LastRow As Long, i As Long
Set ws1 = Sheets("Your Sheet Name")
LastRow = ws1.Range("F" & Rows.Count).End(xlUp).Row
For i = 2 To LastRow
If ws1.Range("G" & i) <> "" Then
ws1.Range("I" & i) = ws1.Range("H" & i).Text & "" & ws1.Range("G" & i).Text
Else: ws1.Range("I" & i) = ws1.Range("H" & i)
End If
Next i
End Sub
Obviously changing the sheet name and columns letter to suit your requirements.

Formula auditing - error checking for a specific region

I would like to ask whether it is possible to check inconsistent formula for a specific region.
In my case, col D and col E contain different sets of formula.
I just want to ensure that all formula in col E are consistent.
Is it possible to do so??
Here is one way.
Let's say your worksheet looks like this
Now Paste this code in a module and run it. It will tell you which cells have inconsistent formulas. See below screenshot
I have commented the code so that you will not have any problem understanding it. If you do simply ask :)
Option Explicit
Sub GetInConsCells()
Dim ws As Worksheet
Dim rng As Range, cl As Range, errCells As Range
Dim ErrorCells As String
Dim lRow As Long
'~~> Create a temp copy of the sheet
ThisWorkbook.Sheets("Sheet1").Copy After:=Sheets(ThisWorkbook.Sheets.Count)
Set ws = ActiveSheet
With ws
'~~> Clear Col D and Col F Contents
.Range("D:D,F:F").ClearContents
'~~> Find the last row of col E
lRow = .Range("E" & .Rows.Count).End(xlUp).Row
'~~> Set your range
Set rng = Range("E1:E" & lRow)
'~~> Check if the cells have inconsistent formulas
For Each cl In rng
If cl.Errors(xlInconsistentFormula).Value Then
If errCells Is Nothing Then
Set errCells = cl
Else
Set errCells = Union(cl, errCells)
End If
End If
Next cl
'~~> Display relevant message
If Not errCells Is Nothing Then
ErrorCells = errCells.Address
MsgBox "Formulas in cells " & ErrorCells & " are inconsitent"
Else
MsgBox "All Formulas are consistent"
End If
End With
'~~> Delete temp sheet
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End Sub
A quick and pragmatic way would be to use another column (temporarily):
Assuming you want to check that each cell in column E has the formula =SUM(A1:D1), simply enter the formula =(SUM(A1:D1)-E1 in another column. Then select the column and filter for FALSE- this will give you all the formulas that have different results!

Count number of rows in worksheet

I want to count number of rows in Sheet1, from the Sheet2 code module.
In the sheet1 code module, the following code works fine
ctr = Range("B2", Range("B2").End(xlDown)).Count
I tried the same code in the Sheet2 code module
recct = ThisWorkbook.Sheets("Sheet1").Range("B2", Range("B2").End(xlDown)).Count
I am getting run time error 1004 Application -Defined or Defined error
Thanks
The error occurs in the 2nd range reference in recct. Because you are referencing a different sheet, you need to tell VBA the sheet name in both range references.
Try this instead:
With ThisWorkbook.Sheets("Sheet1")
recct = .Range("B2", .Range("B2").End(xlDown)).Rows.Count
End With
Alternatively, this will work as well (though a bit sloppier).
recct = ThisWorkbook.Sheets("Sheet1").Range("B2", ThisWorkbook.Sheets("Sheet1").Range("B2").End(xlDown)).Rows.Count
Update
Since there is a lot of discussion around what you actually mean by number of rows on the sheet, use the above code to literally start at B2 and count the number of contiguous cells directly underneath
However, if you want to find the last "real" used cell in column B (by real, I mean with data in it) do this:
With ThisWorkbook.Sheets("Sheet1")
recct = .Range("B2", .Range("B" & .Rows.Count).End(xlUp)).Rows.Count
End With
You can use this for example:
rowsInThere = Sheets("Sheet1").UsedRange.Rows.Count
This works without ranges. Also you might use ActiveSheet as a sheet to check, in case you would need to change current sheet and check its rows count.
Two things
When working off sheet you need to fully qualify your range
Always measure the last cell bottom up rather than top down - you may have gaps
code
Sub GetB()
Dim ws As Worksheet
Set ws = Sheets(1)
Dim lngCnt As Long
lngCnt = ws.Range(ws.[b2], ws.Cells(Rows.Count, "b").End(xlUp)).Count
End Sub
more robust
To handle all situations cleanly then Find is easier
Sub GetB()
Dim ws As Worksheet
Dim rng1 As Range
Set ws = Sheets(1)
Set rng1 = ws.Range("B:B").Find("*", ws.[b1], xlValues, , , xlPrevious)
If Not rng1 Is Nothing Then
Select Case rng1.Row
Case 1
MsgBox "Only B1 has data", vbCritical
Case 2
MsgBox "No used cells past B2"
Case Else
MsgBox rng1.Row - 1 & " cells between B2 and B" & rng1.Row
End Select
Else
MsgBox ws.Name & " column B Is blank", vbCritical
End If
End Sub
Don't know if this will help but I use this in my modules all the time:
Dim TR as long, TC as long
TR = [Sheet1!A1].CurrentRegion.Rows.count
TC = [Sheet1!A1].CurrentRegion.Columns.count
If I know that if the dataset I'm dealing with doesn't have an empty row or column, like an extract from another program or something, then it's quick and works great!
From this I can specify a range select or perform a vlookup.
TR = [Sheet1!A1].CurrentRegion.Rows.count
[I2] = "=vlookup($C2,'sheet1'!A$2:B$" & TR & ",2,FALSE)"

Last Row in Range

Having an issue finding information and/or solutions that produce the desired result, so here it goes.
Right now, and potentially at production time, i will have a "template" named-range on a worksheet. On first use this NamedRange is only rngNamed1 but after the first use there could be more Named Ranges similar to this one, say up to rngNamed30.
Lets say on the 2nd run after building up to rngNamed30, that i need to add 3 more of the NamedRange, which results in rngNamed33.
What i need to do is basically find the last row & column of the last Named Range, so i know where to start the copying of data to and declare the next Named Range.
What i have tried so far:
Dim rng As range
Set rng = range("rngNamed1")
'Set rng = rng.Find("*", rng.Cells(1, 1), xlFormulas, xlPart, xlByRows, xlPrevious, False)
Debug.Print rng.Find("*", rng.Cells(1, 1), , , , xlPrevious).Address
The problem with most of the solutions out there is they are based on finding the last cell WITH DATA. I just need to know the Last Cell of the Range, irregardless of whether it contains data or not.
You can do this easily using the Row and Rows.Count of the range:
Sub NextRowAfterRange()
Dim ws As Worksheet
Dim rangeNom As String
Dim nextRow As Long
' Enter desired name here
rangeNom = "rngName1"
Set ws = ActiveSheet
nextRow = ws.Range(rangeNom).Row + ws.Range(rangeNom).Rows.Count
MsgBox nextRow
End Sub

Skip empty rows in Excel column

In a scenario where the user selects a whole column in Excel and I must act on cells inside the column, how do I efficiently ignore rows that are empty. A whole column has over 1 million cells! Please help!
The range comes from
var range = Application.ActiveWindow.RangeSelection;
Ultimately I want to do something using
for (int i = 0; i < range.Rows.Count; i++)
where Rows.Count should be the non-empty Row count... maybe there is a way of locating the last cell with something in it?
Several options depending on whether you have blanks inside your range (use method 1), or more simply if you want to find the last used cell (use method 3)
These options using column A of the activesheet as an example
1. SpecialCells
If the empty cells are truly empty then you can use SpecialCells to work with the formulae cells (that start with =) and/or constant cells
Sub GetNonEmtpy()
Dim rng1 As Range
Dim rng2 As Range
On Error Resume Next
Set rng1 = Columns("A").SpecialCells(xlConstants)
Set rng2 = Columns("A").SpecialCells(xlFormulas)
On Error GoTo 0
If Not rng1 Is Nothing Then MsgBox "Constants in " & rng1.Address(0, 0)
If Not rng2 Is Nothing Then MsgBox "formula in " & rng2.Address(0, 0)
'then work with these ranges
End Sub
2. Last cell look up
Sub LastCellLookup()
Dim rng1 As Range
Set rng1 = Cells(Rows.Count, "A").End(xlUp)
If rng1.Row <> 1 Then
MsgBox "last cell is " & rng1.Address(0, 0)
Else
'check first cell is not empty
If Len(rng1.Value) > 0 Then
MsgBox "last cell is " & rng1.Address(0, 0)
Else
MsgBox "row is blank"
End If
End If
End Sub
3. Find
Sub LastCellFind()
Dim rng1 As Range
Set rng1 = Columns("A").Find("*", [a1], xlValues, , xlByRows, xlPrevious)
If Not rng1 Is Nothing Then MsgBox "Last cell is " & rng1.Address(0, 0)
End Sub
It sounds to me like you want a good idea on what the upper bound on the number of rows is so you don't end up looping all the way to the bottom of the workbook.
If that's the case, then you may be looking for Worksheet.UsedRange property, which contains the range of all cells that have ever been used (this includes cells where a value was entered and then deleted).
For example,
Dim MaxUsedRow As Integer
MaxUsedRows = ActiveSheet.UsedRange.Row + ActiveSheet.UsedRange.Rows.Count - 1
MsgBox MaxUsedRows
will show the index of the last used row in entire workbook.

Resources