How can I select a cell, given its row and column number? - excel

I am trying to select a cell by giving which row and column to use.
It is giving me an error:
"Unable to get the select property of the range class."
when I get to this line:
Sheets("Ticker").Cells(currRow, etfCol).Select.Paste
Here is a short snippet of my really long code:
Dim etfCol As Integer, etfCount As Integer, currRow As Integer, currRowValue As String
etfCol = 1 'Just select the first column
etfCount = Sheets("Automated Table").Cells(Rows.Count, etfCol).End(xlUp).Row
'Repeat for every row.
For currRow = 5 To etfCount
''''''''''''''''''''''''''''''''''Copy and paste the ticker
Cells(currRow, etfCol).Copy
Sheets("Ticker").Cells(currRow, etfCol).Select.Paste
Next
Am I getting this error because "etfCount" is the value I got from "Automated Table" sheet, and I am trying to use that for "Ticker" sheet?
This is the only reason I could think of, but that doesn't wholly explain this error.
I tried debugging the code.

Replace:
Sheets("Ticker").Cells(currRow, etfCol).Select.Paste
with:
Sheets("Ticker").Cells(currRow, etfCol).Paste
This assumes that Sheets("Automated Table") is active.

If you are using .Select (which is not a good practice in VBA), you may profit a lot by the Macro Recorder. Just record the copy and the paste and examine the code:
Sub Makro4()
Range("B4").Select
Selection.Copy
Range("G8").Select
ActiveSheet.Paste
Application.CutCopyMode = False
End Sub
As you see, the .Select and the .Paste are on various lines and so they should stay. In your code it should be:
Sheets("Ticker").Cells(currRow, etfCol).Paste
Sheets("Ticker").Cells(currRow, etfCol).Paste
Or you may do it a bit better:
With Sheets("Ticker").Cells(currRow, etfCol)
.Select
.Paste
End With
Anyway, as pointed out in the link, the usage of Select is not to be encouraged. (Although it works).

Related

Assigned macro to control button that works on its own worksheet

I have several worksheets that have a Control Button that is assigned the same macro. I need the macro to only work on the worksheet that it is on. It is currently sending me back to the first worksheet when I click on these buttons, regardless of which worksheet I am on. I am new to VBA so I am having a hard time understanding all of the macro, but mainly I don't understand the Application.Goto line and think that is where my trouble is. This code is written by someone else, but I am only trying to reverse-engineer / fix it for my own use. I have no idea why it is using the reference of "FirstTime". It is not one of the names of the worksheets or excel filename.
Sub Break()
Application.Goto Reference:="FirstTime"
Do Until ActiveCell = ""
If ActiveCell <> "" Then
ActiveCell.Offset(1, 0).Select
End If
Loop
If ActiveCell.Offset(0, -1) = "" Then
ActiveCell.Offset(0, -4).Select
ActiveCell.FormulaR1C1 = InputBox("Enter client engagement")
ActiveCell.Offset(0, 3).Select
ActiveCell.FormulaR1C1 = Now()
Else
ActiveCell.FormulaR1C1 = Now()
ActiveCell.Offset(0, -2).Select
ActiveCell.FormulaR1C1 = InputBox("Work performed/tasks completed")
End If
Range("A1").Select
End Sub
I've tried using other strings or removing any Reference from Application.GoTo, but it only gives me a 1004 error. It also seems to need this line, otherwise it also causes an error. The rest of the code/macro works as intended as far as I can, it's just a matter of going to the wrong worksheet when the Control Button is clicked.
I think you exactly understood your own problem by yourself.
When you execute Application.Goto Reference:="FirstTime", it goes to the range that was named FirstTime, which most likely in what you call "the first worksheet".
On the left of the formula bar, as shown in the screenshow below, you have a dropdown, you can use it to check the name.
If I am right so far, follow this procedure:
In the sheet where you want your macro to apply, select the range you want to call FirstTime.This range should most likely cover as many rows/columns as the one you should have spotted with my instructions above (it may even be the very same address).
Go to menu Formula > Name manager.
Click New.
Fill the window with:
Name = FirstTime
Scope = The worksheet you are currently on.
Refers to = The range you have selected (the worksheet on that range is expected to be the same as for field Scope).
This will make it so the new name you are defining has higher priority when executing Application.Goto.

Referencing formula for row number in Excel Macro

I'm attempting to make a macro which will autofill a number of pages based on how many is actually needed. Each item, imported from another workbook, would receive its own 'page'. These pages are on one sheet, separated by print area. Currently I have a counter which counts the number of items that need pages (11 in my example), then I have a value for number of rows per page (34). Those are multiplied together to determine how many rows to autofill to (374). The issue is getting the macro to replace the range variable with the number (374).
I've tried to use the Indirect function but receive a compile error: "Expected: List separator or )"
I've also attempted the Offset function but receive the same error.
This is my Macro so far:
Sub Sheet_Fill()
Sheet_Fill Macro
ActiveCell.Range("A1:I34").Select
Selection.AutoFill Destination:=ActiveCell.Range("A1:I68"), Type:= _
xlFillDefault
ActiveCell.Range("A1:I68").Select
End Sub
Essentially, I want to replace the "I68" with something that will autofill the row number of the I column with my formula mentioned earlier. In the example case of 11 parts, the number would be autofilled with "374"
The raw version of your macro should be something like this:
Sub Sheet_Fill()
'Sheet_Fill Macro
Dim rownum As Long
rownum = 374 'Or a range? Where is this number located?
ActiveCell.Range("A1:I34").Select
Selection.AutoFill Destination:=ActiveCell.Range("A1:I" & rownum), Type:= _
xlFillDefault
ActiveCell.Range("A1:I" & rownum).Select
End Sub
Cleaned up a bit (this should work):
Sub Sheet_Fill()
Dim rownum As Long
rownum = 374 'Or a range? Where is this number located?
Range("A1:I34").AutoFill Destination:=ActiveCell.Range("A1:I" & rownum), Type:=xlFillDefault
End Sub
Need some more details from you on where you're storing this 374 - is it in a cell? Can it be calculated from your table setup? Until those answers are given, this is the best I can do.
Try:
Selection.AutoFill Destination:=ActiveCell.Range("A1:I" & lr), Type:= xlFillDefault
Where lr is last row... you would either want to determine this dynamically, or you could assign the to pull a value from a cell, e.g.:
'dynamic
lr = sheets(1).cells(sheets(1).rows.count,1).end(xlup).row
'from a cell
lr = sheets(1).range("A1").value
General comment... avoid using select/activate!

Loop with two table and last row

I'm trying to build a formula:
=BDS(Bonds!J2& " ISIN","ISSUE_UNDERWRITER","Headers","Y")
In one sheet that takes a unique identifier from another table.
These formula builds me a table. After it builds me the table, I need to take the next row in the other sheet:
=BDS(Bonds!J3& " ISIN","ISSUE_UNDERWRITER","Headers","Y")
Then insert that formula a the end of the previous table built by the previous formula.
What I tried was getting the last row and then offsetting it by one, but I'm trying to figure out how to loop through it.
This is what i have tried:
Sub Formula2()Formula2 Macro
Range("A1").Select
ActiveCell.FormulaR1C1 = _
"=BDS(Bonds!R[1]C[9]& "" ISIN"",""ISSUE_UNDERWRITER"",""Headers"",""Y"")"
lRow = Cells(Rows.Count, 1).End(xlUp).Select
Selection.Offset(1, 0).Select
ActiveCell.FormulaR1C1 = _
"=BDS(Bonds!R[-53]C10& "" ISIN"",""ISSUE_UNDERWRITER"",""Headers"",""Y"")"
Range("A57").Select
End Sub
Image of Table, Im trying to iterate through the ISIN Column. It is column "J"
Although selection and .select are used by the macro recorder, they cause big problems when developing code. It's worth your time to learn how to replace them with range objects. So, while I'm not directly answering your question, I'm trying to give you the tools to do so.
I've shown an example below to illustrate (although I do not work with the BDS() function so I'm undoubtedly getting the details wrong). The main point is that if you learn to move around using the range object you'll be much better off.
Sub formula()
Dim r As Range, sh As Worksheet, bondR As Range, bondSh as Worksheet
set sh = ActiveSheet
set r = sh.range("A1")
Set bondSh = Worksheets("Bonds")
Set bondR = bondSh.Range("J1")
For i = 1 To 10
r.formula = "=BDS(bondR.offset(i,0) & "" ISIN"",""ISSUE_UNDERWRITER"",""Headers"",""Y"")"
Set r = r.Offset(i, 0)
Next i
End Sub
Here I'm defining one range object, r, to track the location on the active sheet, and another, bondR, for the location on the "Bonds" sheet. Once the initial locations of these ranges are defined, you can manipulate them using the .offset(row,col) function as I've done with the simple for-loop, moving down 1 row (but 0 columns) in each loop.
Feel free to ask questions.

How to select clear table contents without destroying the table?

I have a vba function in excel 2010 that I built using help from people on here. This function copies the contents of a table/form, sorts them, and sends them to the appropriate tables.
Now after running this function I want the original table to be cleared. I can achieve this with the following code, assuming ACell has been defined as the first cell in the table.
ACell.ListObject.Range.ClearContents works fine, the only problem is it deletes the table as well as the data values.
Is there any way around this? I would rather not have to set the table up every time I enter some data.
How about:
ACell.ListObject.DataBodyRange.Rows.Delete
That will keep your table structure and headings, but clear all the data and rows.
EDIT: I'm going to just modify a section of my answer from your previous post, as it does mostly what you want. This leaves just one row:
With loSource
.Range.AutoFilter
.DataBodyRange.Offset(1).Resize(.DataBodyRange.Rows.Count - 1, .DataBodyRange.Columns.Count).Rows.Delete
.DataBodyRange.Rows(1).Specialcells(xlCellTypeConstants).ClearContents
End With
If you want to leave all the rows intact with their formulas and whatnot, just do:
With loSource
.Range.AutoFilter
.DataBodyRange.Specialcells(xlCellTypeConstants).ClearContents
End With
Which is close to what #Readify suggested, except it won't clear formulas.
Try just clearing the data (not the entire table including headers):
ACell.ListObject.DataBodyRange.ClearContents
I reworked Doug Glancy's solution to avoid rows deletion, which can lead to #Ref issue in formulae.
Sub ListReset(lst As ListObject)
'clears a listObject while leaving row 1 empty, with formulae
With lst
If .ShowAutoFilter Then .AutoFilter.ShowAllData
On Error Resume Next
With .DataBodyRange
.Offset(1).Rows.Clear
.Rows(1).SpecialCells(xlCellTypeConstants).ClearContents
End With
On Error GoTo 0
.Resize .Range.Rows("1:2")
End With
End Sub
There is a condition that most of these solutions do not address. I revised Patrick Honorez's solution to handle it. I felt I had to share this because I was pulling my hair out when the original function was occasionally clearing more data that I expected.
The situation happens when the table only has one column and the .SpecialCells(xlCellTypeConstants).ClearContents attempts to clear the contents of the top row. In this situation, only one cell is selected (the top row of the table that only has one column) and the SpecialCells command applies to the entire sheet instead of the selected range. What was happening to me was other cells on the sheet that were outside of my table were also getting cleared.
I did some digging and found this advice from Mathieu Guindon:
Range SpecialCells ClearContents clears whole sheet
Range({any single cell}).SpecialCells({whatever}) seems to work off the entire sheet.
Range({more than one cell}).SpecialCells({whatever}) seems to work off the specified cells.
If the list/table only has one column (in row 1), this revision will check to see if the cell has a formula and if not, it will only clear the contents of that one cell.
Public Sub ClearList(lst As ListObject)
'Clears a listObject while leaving 1 empty row + formula
' https://stackoverflow.com/a/53856079/1898524
'
'With special help from this post to handle a single column table.
' Range({any single cell}).SpecialCells({whatever}) seems to work off the entire sheet.
' Range({more than one cell}).SpecialCells({whatever}) seems to work off the specified cells.
' https://stackoverflow.com/questions/40537537/range-specialcells-clearcontents-clears-whole-sheet-instead
On Error Resume Next
With lst
'.Range.Worksheet.Activate ' Enable this if you are debugging
If .ShowAutoFilter Then .AutoFilter.ShowAllData
If .DataBodyRange.Rows.Count = 1 Then Exit Sub ' Table is already clear
.DataBodyRange.Offset(1).Rows.Clear
If .DataBodyRange.Columns.Count > 1 Then ' Check to see if SpecialCells is going to evaluate just one cell.
.DataBodyRange.Rows(1).SpecialCells(xlCellTypeConstants).ClearContents
ElseIf Not .Range.HasFormula Then
' Only one cell in range and it does not contain a formula.
.DataBodyRange.Rows(1).ClearContents
End If
.Resize .Range.Rows("1:2")
.HeaderRowRange.Offset(1).Select
' Reset used range on the sheet
Dim X
X = .Range.Worksheet.UsedRange.Rows.Count 'see J-Walkenbach tip 73
End With
End Sub
A final step I included is a tip that is attributed to John Walkenbach, sometimes noted as J-Walkenbach tip 73 Automatically Resetting The Last Cell
I use this code to remove my data but leave the formulas in the top row. It also removes all rows except for the top row and scrolls the page up to the top.
Sub CleanTheTable()
Application.ScreenUpdating = False
Sheets("Data").Select
ActiveSheet.ListObjects("TestTable").HeaderRowRange.Select
'Remove the filters if one exists.
If ActiveSheet.FilterMode Then
Selection.AutoFilter
End If
'Clear all lines but the first one in the table leaving formulas for the next go round.
With Worksheets("Data").ListObjects("TestTable")
.Range.AutoFilter
On Error Resume Next
.DataBodyRange.Offset(1).Resize(.DataBodyRange.Rows.Count - 1, .DataBodyRange.Columns.Count).Rows.Delete
.DataBodyRange.Rows(1).SpecialCells(xlCellTypeConstants).ClearContents
ActiveWindow.SmallScroll Down:=-10000
End With
Application.ScreenUpdating = True
End Sub
I usually use something very simple if you just want to clear table contents.
Sub Clear_table()
Range("Table1").ClearContents
End Sub
Obviously if you have a workbook with multiple pages you might want to change the code to accommodate that.
Sub Clear_table()
Worksheets("Sheet1").Range("Table1").ClearContents
End Sub
If you want to delete the entire table except your headers, and your formula, you can try this:
Sub DeteteTableExceptFormula()
Dim tb As ListObject
Set tb = activeworksheet.ListObjects("MyTable")
tb.DataBodyRange.Delete
End Sub

Excel Macro: conditional cut and paste between workbooks

So I want a macro running in an Excel file ("input.xls") that is searching a column in another Excel file ("data.xls") for the value "1" (the only values in that columns are 1s and 0s). When it finds a "1," it should copy and paste the entire row from that file into "input.xls".
Here is the code that I have
Sub NonErrorDataParse()
Dim intEnd As Integer
Workbooks("data.xls").Sheets("Raw").Activate
intEnd = 65000
Range("F").Select
Do Until ActiveCell.Row = intEnd
If Int(ActiveCell.Value) = 1 Then
Range(ActiveCell.Row & ":" & ActiveCell.Row).Cut
intEnd = intEnd - 1
Workbooks("input.xls").Sheets("Non-errors").Activate
Range("A1").Select
ActiveSheet.Paste
Else
ActiveCell.Offset(1, 0).Select
End If
Loop
End Sub
However, when I run it, it gives me a "subscript out of range" error on "data.xls." No matter how I fiddle with the code I can't seem to get past that error (even though I have OTHER macros that are accessing that sheet that work fine).
Any ideas as to how to fix it? Or better code that will do the same thing?
Thanks in advance
You don't have to Select or Activate each time you do a command.
You can also find the last used cell with Range("A65536").End(xlup) instead of parsing every cell (that probably caused your error).
The code would then look like:
Sub NonErrorDataParse()
Dim intEnd As Integer
Dim c As Range
intEnd = Workbooks("data.xls").Sheets("Raw").Range("A65536").End(xlUp).Row
For Each c In Workbooks("data.xls").Sheets("Raw").Range("F1:F" & intEnd)
If CStr(c.Value) = "1" Then
c.EntireRow.Cut
Workbooks("input.xls").Sheets("Non-errors").Rows("1:1").Insert Shift:=xlDown
End If
Next c
End Sub
Yet, if you have many rows, it would be faster to use the autofilter method or use a dictionary.

Resources