I am looking to have a macro to run for a specific worksheet only. The purpose of the macro would be to look for a specified range and find negative values and if there is any to extract the whole row into a new worksheet and at the same time transform those negatives to positives. I came up with some but i know for sure that this is totally wrong...missing a lot of stuff. Still trying to learn, new to this vba stuff. Thanks in advance for any help that you can provide. fyi ntp stands for negativestopositives. Not sure if that will help, just thought i can write all the details to my small "code"
Sub ntp()
Dim ws As Worksheet
If ws.Name <> "originalNeg" Then
For Each Cell In Range("I2:I1048576")
If Cell.Value < 0 Then
Cell.Value = Abs(Cell.Value)
End If
Next Cell
End Sub
Sub ntp()
Dim ws As Worksheet
Dim cel As Range
With Activeworkbook.Worksheets("originalNeg")
For Each cel In .Range("I2:I" & .Range("I" & Rows.Count).End(xlUp).row)
If cel.Value < 0 Then cel.Value = Abs(cel.Value)
Next cel
End With
End Sub
This uses the worksheet, and note the . before Range() which links the range to that specific sheet.
Also, only rarely would you want to use all cells in a column. I used the .End(xlUp).Row to get the last used row in Column I for you to loop through.
Set ws = ThisWorkbook.Worksheets("originalNeg")
instead of the if on the name.
Related
I am trying to do a loop with Excel VBA, I have a data range in a1:a1000, I want to loop through them and copy one by one to single cell of C1, but below code not working, any idea what went wrong?
Dim I As Integer
For I = 1 To lastrow - 1
Sheets("display").Range("w1").Value = Sheets("data").Range("c1").Offset(I, 0).Value
msgbox Sheets("data").Range("c1").Value
Next I
You're setting the value in cell "W1" instead of "C1".
Updated After Author's Clarification of Question:
Below are two ways you can loop through cells and copy/paste. Neither one is "better". I would like to emphasize that there are probably more efficient methods than these to accomplish your task, but hopefully this answer gets you a resolution.
Sub LoopExampleUsingRange()
Dim aCell As Range
For Each aCell In Range("A1:A1000").Cells
aCell.Copy Range("C1")
Next aCell
End Sub
Sub LoopExampleUsingIntegerReference()
Dim i As Integer
For i = 1 To 1000
Range("A" & i).Copy Range("C1")
'I prefer to use offset, but they both work:
'Range("A1").Offset(i - 1, 0).Copy Range("C1")
Next i
End Sub
I'm trying to update the conditional formatting range for about 30 rows of data on a worksheet. Every month I update the data and I want to run a macro to adjust the ranges to incorporate the new month. I've already done this for my charts by updating the end of the series ranges by looping through the ChartObjects and SeriesCollection.
To do this on conditional formatting, everything I've found requires hardcoding a range (either a cell reference or a named range), e.g.:
With Worksheets(1).Range("e1:e10").FormatConditions(1)
I'd prefer to just loop through the collection of conditional formatting for the worksheet, but I can't find any evidence of this collection existing in the Excel VBA Object Model. Am I missing something here?
This is a little convoluted since there isn't really any great way to loop through formatconditions in a sheet. But, you can loop through specialcells and then loop through their formatconditions and dig in from there:
Sub test()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Dim rngCell As Range
Dim lng As Long
For Each rngCell In ws.Cells.SpecialCells(xlCellTypeAllFormatConditions).Cells
For lng = 1 To rngCell.FormatConditions.Count
On Error Resume Next
Debug.Print rngCell.FormatConditions(lng).Formula1, rngCell.FormatConditions(lng).AppliesTo.Address
Next lng
Next rngCell
End Sub
I poached the specialcells() idea from Dick Kusleika's excellent post on this very subject at dailydoseofexcel.com blog.
You can use code as below: Here Based on condition Highlighted the row in yellow color. You can use your formatting
LastColumnARows = WB_Source.Sheets(SheetName.Name).range("A" & Rows.Count).End(xlUp).Row
With WB_Source.Sheets(SheetName.Name)
For i = 2 To LastColumnARows
If .range("A" & i).Value > [Condition] Then
With .range("A" & i & ":E" & i)
.Interior.Color = vbYellow
.Font.Color = vbBlack
End With
End If
Next i
End With
I'm new to vba programming and I would like to work on a function to fix salutations in an excel file.
To start, I would just like to append a Dear " to a name in the first column, and put this value in the next column, so that I would end up with the name in the first column and "Dear name" in the next column.
The function I have so far, is putting "Dear " in the next column, but it is not appending that to the text in the first column. Could someone help me correct my code?
Sub letterSalutationFixer()
Dim letterSalutationColumn As Range
Set letterSalutationColumn = Columns(1)
For Each Cell In letterSalutationColumn
Cell.Offset(, 1).Value = "Dear " & Cell.Text
Next
End Sub
PS. I do realise that I don't necessarily need to do this programmatically since it doesn't take that long to do with the functions already available, but I eventually want to expand this to fix other data with more complexity - and just thought I could start with something simple.
Many thanks in advance!
The reason it's blank is that Cell is equivalent to the whole column. You're close though. If you did...
For Each Cell In letterSalutationColumn.Cells
..l it would cycle through each cell.
However, the way it's written, it would cycle through each cell in the whole column, which could crash Excel, or at least slow things way down.
Here's a reworked version of what you're trying to do. It only acts on the cells in column A with content:
Sub Salutation()
Dim ws As Excel.Worksheet
Dim LastRow As Long
Dim NameRange As Excel.Range
Dim cell As Excel.Range
Set ws = ActiveSheet
With ws
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set NameRange = .Range("A2:A" & LastRow)
For Each cell In NameRange
cell.Offset(, 1) = "Dear " & cell.Text
Next cell
End With
End Sub
It also declares all variables, something you want to get in the habit of doing. Do a search on Option Explicit to learn how to force yourself to.
It also uses a With statement to fully qualify Object references, so that instead of just referring to Column(1) or Range(something) you're specifying that it's in ws, which has been set to the ActiveSheet.
Another way is the VBA alternative of
Using a formula in column B that runs the concatenation against the used part of column A (ie in B1 ="Dear " &A1 etc)
The formula then is copied over itself as a value to remove the formula
code
Sub QuickCon()
Dim rng1 As Range
Set rng1 = Range([a1], Cells(Rows.Count, "A").End(xlUp))
With rng1.Offset(0, 1)
.FormulaR1C1 = "=""Dear "" &RC[-1]"
.Value = .Value
End With
End Sub
So i've searched for hours now, and can't seem to find a solution to my problem.
I have a list of 13000+ rows, but I have auto filtered it down to about 200, now what I want is that, lets assume, the top of the list now shows as A1 then straight to A28 because of the filter.
I want the text in cell A28 and B28 to be concatenated and put in cell J28.
I am able to do this manually easily, but when I record the actions for a macro this code comes up
Sub concat()
'
' concat Macro
'
'
ActiveCell.FormulaR1C1 = "=RC[-9]&RC[-8]"
Range("J28").Select
Selection.FillDown
End Sub
Now I'm not sure what
"=RC[-9]&RC[-8]"
means but when I run the macro it does not result in what I want.
If I am unclear on this problem, I apologize in advance but I really do need help.
Thanks!
Varun
This will work, but you have to turn off the filter first:
Sub FillDown()
Dim ws As Excel.Worksheet
Dim LastRow As Long
Set ws = ActiveSheet
With ws
LastRow = ws.Range("A" & .Rows.Count).End(xlUp).Row
.Range("J2:J" & LastRow).FormulaR1C1 = "=RC[-9]&RC[-8]"
End With
End Sub
I'm not clear why you don't just turn off the filter and manually copy down the formula as far as necessary.
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)"