Hi I have dynamically changing Column numbers. I need to select 2 cells using that column number. As I cannot use cells command to select more than one cell and i cannot use Range as i don't know the column with respect to letters, Please help me find a solution for the same.
Thanks in advance
for example my code is :
Dim Row_num as integer
for x=1 to 100
Thisworkbook.Sheets("Sheet1").range((Row_num,x),(Row_num,x+1)).select
selection.merge
next
Correct Usage is:
<WorkBook>.<WorkSheet>.Range(<CornerCell>, <OpositeCornerCell>)
There are several other issues in your code fragment. See comments in this code
Dim Row_num as Long ' Use Long as there may be more than 32767 rows, and its faster
Dim x as Long ' Dim all your variables
With Thisworkbook.Worksheets("Sheet1") ' Use With so you can refer to this part repeatedly
For x = 1 to 100 Step 2 ' Maybe you meant every second cell, otherwise ranges will overlap
' Refer to two corners of the required Range
' Don't use Select
Range(.Cells(Row_num, x), .Cells(Row_num, x + 1)).Merge
Next
End With
In addition to chris' excellent answer, let me add two small but really helpful methods of the Range object: .Offset and .Resize:
With Range.Offset you can "move" a cell, i.e. Range("A1").Offset(3, 2) will result in B3. And .Resize will will do as the name says, resize the range, i.e. Range("A1").Resize(3, 2) will result in A1:B3.
Both elements can be combined, e.g. Range("A1").Offset(1, 1).Resize(3, 2) results in B2:C4.
In your case, you could use:
Option Explicit 'always use Option Explicit, as it forces you to declare variables
Sub MergeFields
Dim lngRow As Long
Dim rngTopLeft As Range
Set rngTopLeft = Thisworkbook.Worksheets("Sheet1").Range("A1") 'change A1 accordingly!
For lngRow = 1 To 100
rngTopLeft.Offset(lngRow).Resize(1, 2).Merge
Next lngRow
End Sub
Related
I have to divide all the cell values of sheet -"Databook" with a number 1000000 only if the cell contains numeric value. It means I have to divide only those cells in the sheet which contains numbers like 17577.2 , 2123, 13979123.22, 239812098321.1, and 9798.
Sub i()
'declare variables
Dim ws As Worksheet
Dim rng As Range
Dim myVal As Range
Set ws = Worksheets("Sheet1")
Set rng = ws.Range("A:Z")
For Each myVal In rng
If IsNumeric(myVal) = True Then
myVal = myVal.Value / 1000000
Else
Next myVal
End Sub
You currently suffer from a missing End If, thus your current code won't run at all. Properly indenting your code would have revealed the issue. I would also recommend not trying to loop all cells in your current range. Note that these are (for Excel 2019 at least) 27.262.976 cells to go through (you might want to first find your range of interest first; last used row, last used column). This many calls will be terribly slow. Limit that numbers by just using the actual numeric values at least.
Try to uitilize SpecialCells. The way it works > <YourRange>.SpecialCells(XlCellType, [XlSpecialCellsValue]). For example:
Sub Test()
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Sheet1")
For Each cl In ws.Range("A:Z").SpecialCells(2, 1)
cl.Value = cl.Value / 1000000
Next
End Sub
Where: .SpecialCells(2, 1) can also be read as .SpecialCells(xlCellTypeConstants, xlNumbers)
Note: If you have big chunks of cells that contain numeric values it might be beneficial to loop Areas property instead of Cells since you can load these into an array and perform calculations in memory before pasting back these values. This could also save you some valuable runtime.
I tried to copy a set of filtered data from the worksheet "PEP" (Filter: Emetteurs, in column 18) and paste it in the next empty row in the worksheet"Sanctions". I found this text code online and add the section NextRow in order to paste it on the next Empty Row in the "Sanctions" Worksheet. I just started using VBA not long ago, so I tried to use codes online however in this case, I think the problem here is that I cannot define the value of range. I tried to look it up online but no result. Thank you in advance for all your help!
Dim k,j,i As Interger
ActiveWorkbook.Sheets("Sanctions").Select
NextRow=Cells(Range("A"&Rows.Count).End(xlUp).Row+1,1
k=1
With sheets("PEP")
T=.Range("A1:AS"&.Cells(Rows.Count,1).End(xlUp).Row)
.Rows(1).Copy Sheets("Sanctions").Range("NextRow")
End With
For i=2 To UBound(T,1)
If T(i,18)="Emetteurs" Then
k=k+1
For j =1 to UBound(T,2)
T(k,j)=T(i,j)
Next j
End If
Next i
With Sheets("Sanctions")
Application.ScreenUpdating=False
.Range("NextRow").Resiwe(k,UBound(T,2))=T.Offset(1)
.Columns.AutoFit
Application.ScreenUpdating=True
End With
End Sub
And if possible I would also like to find a solution to remove the header once I do the Copy-Paste process.
Read the code's comments and adjust it to fit your needs.
Some things to begin:
Use option explicit so you don't have unexpected behavior with undefined variables
Always indent your code (see www.rubberduckvba.com a free tool that helps you with that)
Try to separate your logic defining variables and the reusing them
EDIT: Some reviews to your code:
As mentioned by #Pᴇʜ you need to declare each of your variables types.
This:
Dim k,j,i As Interger
is the same as declaring:
Dim k As Variant
Dim j As Variant
Dim i As Integer
Side note. You had a typo in Interger
Which is not what you really want, knowing that all of them are going to store numbers
Declare the objects that you're going to work with. For example, you refer to the sheet Sanctions three times in your code:
ActiveWorkbook.Sheets("Sanctions")
This can be set once like this:
Set targetSheet = ThisWorkbook.Worksheets("Sanctions")
And then reused in lines like this:
With Sheets("Sanctions")
or this:
Sheets("Sanctions").Range("NextRow")
by writing this:
With targetSheet
in this way, if you ever need to change it (the person working with your code, or your future you will be really thankful)
Declaring your variables to just letters, makes your code really hard to understand.
Dim j,k,l
is different when you have:
Dim lastRow As Long
Dim lastColumn As Long
etc.
I suggest that you use the key F8 and step through the code, and see the logic behind it. That way you can learn more.
Code:
Public Sub ConditionalRowCopy()
' Declare object variables
Dim sourceSheet As Worksheet
Dim targetSheet As Worksheet
Dim cell As Range
' Declare other variables
Dim sourceLastRow As Long
Dim targetLastRow As Long
' Set a reference to the sheets so you can access them later
Set sourceSheet = ThisWorkbook.Worksheets("PEP")
Set targetSheet = ThisWorkbook.Worksheets("Sanctions")
' Find last row in source sheet based on column "R"
sourceLastRow = sourceSheet.Cells(sourceSheet.Rows.Count, "R").End(xlUp).Row
' Find cell with word "Emetteurs", search in column R)
For Each cell In sourceSheet.Range("R1:R" & sourceLastRow).Cells
' If match
If cell.Value = "Emetteurs" Then
' Find last row in target sheet based on column "A"
targetLastRow = targetSheet.Cells(targetSheet.Rows.Count, "A").End(xlUp).Row
' Copy entire row to next empty row in target sheet
cell.EntireRow.Copy Destination:=targetSheet.Range("A" & targetLastRow).Offset(RowOffset:=1)
End If
Next cell
End Sub
Let me know if it works!
Task: I need to copy a cell value from E12 to the range E23:E25. I achieved this easily using a simple copy and paste statement in the editor. But the range isn't always fixed. I have managed to capture the start point of this range as: Set rangeStart = Range("E12").End(xlDown).Offset(6, 0). I am unable to use this as a starting point for a range selection statement as follows:
Range("E23:E" & Range("A23").End(xlDown).Row).Select
That is how I'm selecting the range to be filled with data in the next step via a paste statement. How do I edit the first half of that range call to something more dynamic? Using rangeStart instead of E23:E.
I have just started working with Excel VBA, so this might be a very basic question to ask. Any help would be appreciated.
First I'd like to address the point that using Select is in most cases highly discouraged. Since you're only looking to paste a value into other cells, you can simply use a line like the following example:
Range("A1:A10").Value = Range("C2:C11").Value
or
Range("A1:A10").Value = 1
This would fill the A1:A10 range with either the values from C2:C11 or the integer 1, respectively. Note the two ranges in the first line are of the same size.
Now, a dynamic approach to your problem could be something along the following example
'Initialise two range variables
Dim SourceRange As Range, TargetRange As Range
'And integers for target rows
Dim fRow As Long, lRow As Long
With ThisWorkbook 'Assuming the code needs to be performed on the Workbook that hosts the macro
'Determine target rows
fRow = 23 'You have not specified how the first row should be determined
lRow = .Cells(fRow, "E").End(xlDown).Row
'Populate range vars
Set SourceRange = .Range("E12")
Set TargetRange = .Range(.Cells(fRow, "E"),.Cells(lRow, "E"))
'Paste values to target range
TargetRange.Value = SourceRange.Value
End With
Note that, since you haven't specified how this should be determined instead, the code above is hard-coded to have a target range in column E that starts at row 23.
If you have
Set rangeStart = Range("E12").End(xlDown).Offset(6, 0)
You can also have
Set rangeEnd = Range(rangeStart, Range("E" & Range("A23").End(xlDown).Row)
which will form a range from the first cell to the second cell.
But read the link posted by Vitaliy.
I am trying to set my array equal to all column headers of tables in a worksheet.
If I were doing this in Excel, I would click on A1 and do Control+Shift+Right Arrow. I've found some 15 year old code attempting to simulate this, shown below, but it doesn't recognize the last Column.
Sub Ls_List_Click()
'variables used in for each loops
Dim Column_Array() As Variant
Dim EndRange As Range
ThisWorkbook.Worksheets(Me.Ls_List.Value).Select
Range("A1", Range("A1").End(xlRight)).Select
EndRange = Range("A1").End(xlRight).Offset(2, 0)
Range(EndRange, EndRange.End(xlRight)).Select
EndRange = EndRange.End(xlRight).Offset(2, 0)
Column_Array() = EndRange
'... couple of for each loops
End Sub
I get error 1004 on the following line:
Range("A1", Range("A1").End(xlRight)).Select
If you replace xlRight with xlToRight you should be good
I believe you're looking for something more like:
Sub Ls_List_Click()
'variables used in for each loops
Dim Column_Array() As Variant
Column_Array() = Range(Cells(1,1),Cells(1, Cells(1, 1).End(xlToRight).Column)).value
'... couple of for each loops
End Sub
There didn't appear to be rhyme or reason for the .select components beyond stepping through to see where things were (nice for testing... i guess?).
Just one line of code gets your array generated for all the contiguous headers in your first row.
Edit:
Checking back, because EndRange is used for looping, you may want to write:
Sub Ls_List_Click()
'variables used in for each loops
Dim Column_Array() As Variant, EndRange as Long 'reference to column number, not a range, so watch referencing
EndRange = Cells(1, 1).End(xlToRight).Column
Column_Array() = Range(Cells(1,1),Cells(1, EndRange)).value
'... couple of for each loops
End Sub
Two main issues with your code:
You misspelled xlRight - the correct value is xlToRight. That's why it is recommended to use Option Explicit, so such errors are detected at compile time.
You shouldn't use Select - what for? If you want to reference particular cells/range, just use Cells(row, column) (row and column are integers) or Range("A1:B3") (just example).
Having said that, to get values into an array, you should use:
firstRowArray = Range(Cells(1, 1), Cells(1, 1).End(xlToRight)).Value2
Expalnation:
I used Range overload, accepting two cells as top-left and bottom-right cells to define the range. Top left is Cell(1, 1), i.e. A1 and bottom left is Cells(1, 1).End(xlToRight), which you are already familiar with :)
Then I use Value2 property, which return array of values (you could use Value but it's slower).
Note that, the result will be two-diensional array with number of rows and number of columns same as in the range.
I'm having some trouble trying to find VBA code to delete multiple specific cells if a certain cell contains a specific text. This spreadsheet can run close to 100k rows as well, but will vary depending on the data pull.
The specific VBA would be able to do the following:
If Cell J3 equals #N/A, Blank, or 0, then clear contents of cells J3:K3 and P3:X3, and then repeat til it reaches the bottom of column J.
Thanks in advance
How to clear contents for specified cells when another cell contains specific text or string
Dim cellToClear As Range
Dim cellToCheck As Range
Dim specificText As String
If cellToCheck.Value = specificText Then cellToClear.ClearContents
"I'm having some trouble trying to find VBA code "
These links contain VBA code that you can use when you no longer have trouble trying. They contain examples you can paste into your project and modify for your needs.
This link has examples of how to read the contents of a cell.
A range is a group of one or more cells in a worksheet. You can perform an operation on a range and it will affect all the cells inside the range. This link has examples of how to work with a range.
A loop is when the program repeats the same sequence of steps, usually until a specific condition is met. You can find examples of different loops here.
I prefer placing values into an array if you are going to be changing a bunch of cells in a routine. This generally makes the process much quicker.
Start out by setting your worksheet and range objects. Please take note that the below code is currently using index 1 for the worksheet here: Set ws = ThisWorkbook.Worksheets(1). If this is not the worksheet you are personally needing, then you will need to change this.
Then place the cell contents of the entire range into an array. As I mentioned earlier, this process is quicker than making adjustments to individual cells 1 at a time.
Loop the array, checking for either the specific error value #N/A or the other criteria. If this criteria is a match, you will enter another loop that quickly loops through the 'columns' in the row that will delete the values from only the columns you specified.
Once finished, rewrite the array back to the worksheet.
Sub main()
Dim ws As Worksheet, rng As Range, dataArr() As Variant
Set ws = ThisWorkbook.Worksheets(1)
Set rng = ws.Range("J3:X" & ws.Cells(ws.Rows.Count, "J").End(xlUp).Row)
' Place the entire contents of worksheet range into an array
dataArr = rng.Value
Dim i As Long, x As Long, clearRow As Boolean
For i = LBound(dataArr) To UBound(dataArr)
If IsError(dataArr(i, 1)) Then
If dataArr(i, 1) = CVErr(xlErrNA) Then clearRow = True
ElseIf dataArr(i, 1) = vbNullString Or dataArr(i, 1) = 0 Then
clearRow = True
End If
' Loop thru the columns (x) of the current row (i)
If clearRow Then
For x = 1 To 15
Select Case x
Case 1, 2, 7 To 15
dataArr(i, x) = ""
End Select
Next x
clearRow = False
End If
Next i
' Re-write the entire array back to the worksheet in one step
rng.Value = dataArr
End Sub