selection of multiple columns with end(xlDown).End(xlUp).Row - excel

I'm doing debug for a VBA template.
The Macro let users choose a excel file to import, then it will check each columns whether they correpond the requirements.
When I try to import a file, I alway get error "oveeflow" with the following line:
'maxRow = ws.Range(Cells(StartRow, AdditionalInfoColumns.OtherInfo).Address).End(xlDown).Row
My colleague tells me that I just need to add end(xlDown).End(xlup) like this:
maxRow = ws.Range(Cells(StartRow, AdditionalInfoColumns.OtherInfo).Address).End(xlDown).End(xlDown).End(xlUp).Row
And it does work! I don't know why. So I try to do it in a simpler way as following:
maxRow = ws.Range(Cells(StartRow, 1).Address, Cells(StartRow, 3).Address).End(xlDown).End(xlUp).Row
It works as well.
Can someone please explain why does it work? Thank you for your answer.
PS: The value of xlDown and xlUp are -4121 and -4162.
Best Regards
Kai

First of all End(xlDown) and End(xlUp) is nothing more than …
End(xlDown) = Pressing Ctrl + Arrow down
End(xlUp) = Pressing Ctrl + Arrow up
you can test this manually by selecting a range/cell and press the combination to see the effect on your actual worksheet.
The overflow error just comes because if you eg. select cell A1 in an empty worksheet and do .End(xlDown) it selects the very last cell of the worksheet. And if you now insert something it fails because the maximum rows of Excel are exceeded.
To find the last used row of a column it's better to use End(xlUp) instead of End(xlDown) eg:
LastUsedRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
'finds the last used row in column A

End(xldown) has the same effect as pressing control and the down arrow (and End(xlright) is control and right arrow. If you try those key presses in a cell you will see it jumps to the next intersection of filled and empty cells (or the edge of the spreadsheet if there's no filled cells in the way)

Related

Excel VBA Index Match Only Blank Row [duplicate]

So I have a column with blanks randomly throughout...I need a macro that would select only the blanks, and then in those blank cells paste in the value of the cell above it. The select part is obviously easy, but I keep getting errors about 'too many continuations' when trying to fill the formula down into the blanks. I included a picture, the first column is a 'before' and the second is how I want the column to look after the application of the macro.
If the macro needs to create a second column or something that's fine too, as long as the end result looks like it does in the picture. Thanks!
Picture to illustrate.
try,
sub fillblankfromabove()
dim blnks as range
with worksheets("Sheet1").Columns("E").Cells
set blnks = .specialcells(xlcelltypeblanks)
if not blnks is nothing then
blnks.formular1c1 = "=r[-1]c"
end if
.value = .value
end with
end sub
Another way to do this is to select all cells that you want included in this process, press CTRL + G, select Special, then select 'Blank Cells'. This will select all blank cells within your selected range. Then enter =[cell above] and press CTRL + ENTER and it will enter that formula into all selected cells.

Excel cells from Access export look empty but are not (=isblank=FALSE)

My problem is that an Excel spreadsheet (exported from Access as .xls) has cells that look empty, but are not. This is mucking up my calculations & navigation shortcuts.
There are no formulae or contents in the cells (the answers already posted on this topic don't fix my problem). I've attached an image of my problem (see bottom)
Troubleshooting shows:
If I test these cells e.g. =isblank(a1), it's FALSE.
The cell lengnth is 0, according to =LEN(a1)
If I try 'Go to (special) highlight "Blanks" (or any other go to special combination like formula/text,numbers, etc) it will NOT highlight these empty looking cells
YET if I filter the column, I can select these non-empty "blanks" from the filter list (this is the only way to identify these tricky cells I've found so far) -
So my column has entries in some cells, "blank" non-empty cells. I only want the cells with entries, the rest I need cleared. This also annoyingly means the shortcut to skip to the next empty or nonempty cell wont work (it reads all as nonblank) - making it super painful to navigate the large dataset.
Once I click within an individual 'non-empty' blank cell & press enter, this seems to clear the cell contents ('=isblank' formula's that were saying "FALSE" now switch to 'TRUE') - this is not feasible to fix individual cells in such a large dataset though.
Can ANYONE help?!
I have found 2 basic workarounds that fix this, but I really want to know how & why this happens & how to avoid it in future.
Workaround 1
In excel, filter the column, show only "blank", then highlight the filtered column & press delete. Unfilter the list & the problems solved.
Workaround 2
save the excel spreadsheet from 'file.xlsx' & save as '.csv'.
Close it all, open the csv & it seems the non-empty blank cells are fixed, show =isblank= TRUE & can be skipped with [CNTL arrow key] shortcuts now.
This is so frustrating & I haven't seen any similar questions nor answers on why this is?
Why is this happening & are there any other fixes around for this?
Thanks hive-mind!
excel sheet shows non-blank empty cells - working
Sometimes it's nice to have the ctrl+up/down stop at the edge of the data set other times it's not; here's the macro I use to clear the selected range's "blank" cells for when it's not:
'clears cells with error or empty string values
Public Sub clearJunk()
Dim scrn As Boolean: scrn = Application.ScreenUpdating: Application.ScreenUpdating = False
Dim i As Long, rowCount As Long, FirstRow As Long
Dim col As Range
rowCount = Selection.Columns(1).Cells.count
FirstRow = Selection.Cells(1).Row - 1
For Each col In Selection.Columns
For i = 1 To rowCount
If IsEmpty(col.Cells(i)) Then i = col.Cells(i).End(xlDown).Row - FirstRow
If i > rowCount Then Exit For
If IsError(col.Cells(i).Value) Then
col.Cells(i).ClearContents
ElseIf col.Cells(i).Value = "" Then
col.Cells(i).ClearContents
ElseIf Trim(col.Cells(i).Value) = "" Then
col.Cells(i).ClearContents
End If
Next i
Next col
Application.ScreenUpdating = scrn
End Sub
Also if you're copying and pasting from MS-Access you might find this one useful too:
Public Sub UnWrapText(): Selection.WrapText = False: End Sub
I've bound both to buttons on my Ribbon/QAT and it's made my life more hassle free.
You can also try the below:
Select your region.
In the "Find & Replace" dialog box, leave the "Find what:" box empty.
Enter any value that doesn't exist yet in your data, e.g. a pipe ("|") in the "Replace with:" box.
Check the "Match entire cell contents" option.
"Replace All"
Now, enter the pipe in the "Find what:" box, and clear the "Replace with:" box.
"Replace All", and you're done!
Source: https://www.mrexcel.com/board/threads/how-to-remove-null-string-from-cells.565955/ (A bit updated by me)
Just save you excel file as an csv file. Then create in Access a linked table to the csv file. When you create a query to import your data then values which look empty in excel will have a NULL value in Access.

Conceptual understanding of xlDown

We find last row using code line
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
I am refreshing my conceptual understanding of xlDown. I refer to data in column B in Sheet1 as appended below.
My understaqnding of End(xlDown) has been that it searches from the top down finding the last used cell before a blank cell.Its concept can be simulated by pressing ctrl down. If we highlight a column that contains data intermixed with blanks and then press ctrl down - it will go to the cell before the first blank cell. Pressing ctrl down in Column B Sheet 1 takes to B2 and then to B18. But if I use the following code snippet I get the last row as 1048576.
What logic this code snippet follows?
Can anyone explain it please to clarify this trivial issue.
You will get the same result if you remove .End():
lastRow = .Cells(.Rows.Count, "B").Row
This is because ws.Cells(ws.Rows.Count, "B") is already the last possible cell of the B column. Calling .End() on it is allowed, but does nothing because there is nowhere to go.
Otherwise your understanding is correct.

how to select the cell below on a different sheet to populate a cell next to one on your worksheet

I am tasked with creating A map of our warehouse.
In the data I have to have model, description and location.
What I am having trouble with is, I am using data from a second sheet to populate the "map"
i.e. ='1'!F2
when I try to drag and use it to fill an entire line it changes to ='1'!g2. I would like it to go to ='1'!F3
I see the logic in what it is doing...but I dont want it to use that logic..I want it to use the next cell below it to populate that cell.
The simplest thing might be to Copy and then Paste Special > Transpose the data on "1" to a new sheet. Then you could drag formulas that refer to the new sheet and they'd behave as expected.
EDIT: Based on your original question, this will fill in the results of columns to the right as you drag it down and vice-versa. This literally does what your original question asked:
=INDEX(Sheet1!$F$2:$Z$8000,COLUMN(),ROW())
Start in A1 and drag in either direction. To add a header line or rows to left just insert rows or columns to top or left (to keep the formula sound).
EDIT: Here's the Transpose function, per #brettdj's suggestion. I find it difficult to work with, but it certainly makes it clearer what's going on:
In cells F2:8000 of your target sheet enter:
=TRANSPOSE(Sheet1!$F2:$Z8000)
Then, with all those cells selected, go into edit mode in one of the cells and do Ctrl Shft Enter to array-enter it. If you have to resize the source range I believe you have to repeat these steps with the correct ranges. I'm an Index fan myself, so would stick with that. Offset is volatile, so I'd avoid it. If I've got any of this last edit wrong, #brettdj will help us.
Since what you want is non-native behaviour, it might be worth writing a small VBA macro to do the copy, and assign it to a keyboard shortcut.
Here's a simple example to copy a formula one cell to right, updating reference one cell down (preserves Absolute/Relative settings in formula).
It assumes A1 style address, work only if the active cell contains a formula referencing a single cell (ends silently if not). Will silently overwrite anything in the destination cell.
Sub CopyToRight()
Dim clFrom As Range
Dim clAddr As Range
Dim addr As String
On Error GoTo EH
Set clFrom = ActiveCell
If clFrom.Formula Like "=*!*" Then
Set clAddr = Range(Mid(clFrom.Formula, 2))
If clAddr.Count = 1 Then
If clFrom.Formula Like "=*!$*$*" Then
addr = clAddr.Offset(1, 0).Address(True, True)
ElseIf clFrom.Formula Like "=*!$**" Then
addr = clAddr.Offset(1, 0).Address(False, True)
ElseIf clFrom.Formula Like "=*!*$*" Then
addr = clAddr.Offset(1, 0).Address(True, False)
Else
addr = clAddr.Offset(1, 0).Address(False, False)
End If
clFrom.Offset(0, 1).Formula = "='" & clAddr.Worksheet.Name & "'!" & addr
End If
End If
clFrom.Offset(0, 1).Select
EH:
End Sub

.End(xlToRight) within a range

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.

Resources