Can anybody help me out in making all values of my selected range values Absolute (or applying absolute formula on each cell in a range) by single button using Excel VBA?
A B C
5.119999886 -13.06999969 -13.14000034
-5.76999998 -12.52000046 -12.78999996
-5.88000011 -13.69999981 -14.13000011
5.46999979 -12.61999989 -12.48999977
Consider:
Sub dural()
Dim rng As Range
Set rng = Range("A1:F10")
rng.Replace what:="-", lookat:=xlPart, replacement:=""
End Sub
Not exactly VBA, but if required can be recorded.
Select your Data Range, press Ctrl H (Replace), in Find what add " - " sign and replace all. This will remove the negative sign from all numbers and it will become absolute.
Note: As mentioned in comment that OP agrees that this works for him, hence posting as an answer.
You can do something like this:
Sub MakeAbsolute()
Dim c As Range
Dim rngToAbs As Range
'Set the worksheet name and range appropriately
Set rngToAbs = Worksheets("Sheet1").Range("A1:C2")
For Each c In rngToAbs
c.Value = Abs(c.Value)
Next c
End Sub
You need to change Sheet1 to your worksheet name and A1:C2 to whatever range of cells you want to take the absolute value of.
Hopefully the code is simple enough to understand, but the basic idea is that we will declare a specific range, loop through each cell in that range, and change the value of that cell to be the absolute value by applying the Abs function.
Related
I would like to be able to Check for criteria "owners" In column A and SUM cell from the same row column E with the cell above and repeat through the spread sheet where owner is found.
I have tried to use Function =SUMIF(A3,"*owner*",E2:E3) This returns the Value above the cell in the row with owner but does not SUM them.
I have also tried this VBA CODE and it does the same thing.
Sub vba_sumif()
Dim gRange As Range
Dim sRange As Range
Set gRange = Range("A3")
Set sRange = Range("E2:E3")
Range("G2") = _
WorksheetFunction.SumIf(gRange,"*Owner*", sRange)
End Sub
Ideally it would return the summed cells in the above cell. using VBA
Thanks again,
Aaron
Well first of all, I would suggest just using the formula unless you have a reason not to:
Formula:: Your first error with the formula is both ranges need to be the same size.
VBA:: Same thing here with range sizes, then you also need to remember to make sure Excel knows what sheet you're referring to. I like to do this with a With My_Worksheet_Namestatement, then include a . before any range from that sheet. Just make sure to change the sheet name to your sheet name
Option Explicit
Sub vba_sumif()
Dim TableSheet As Worksheet
Dim gRange As Range
Dim sRange As Range
Set TableSheet = Worksheets("TableSheet")
With TableSheet
Set gRange = .Range("A2:A13")
Set sRange = .Range("E2:E13")
.Range("G2").Value = _
WorksheetFunction.SumIf(gRange, "*Owner*", sRange)
End With
End Sub
I have multiple sheets that should have references to another sheet.
For example cell B3,sheet AC: =Inlife!G4. Now I create two new sheets AC (2) and Inlife (2), the reference for B3,sheet AC (2) should be:
=Inlife (2)!G4
I have tried many variations of the replace option but so far all that I managed to do was remove the formula and leave a value or blank cell.
Dim rng As Range, cell As Range
Set rng = Sheets("AC (2)").Range("B3:B10")
For Each cell In rng
cell = WorksheetFunction.Substitute(cell, "Inlife", "Inlife (2)")
Next
Does anyone know a way to update all the references/formulas in one go?
(I have tried to just use the search and replace function of excel but that gave me an error about the formula)
Please, try:
For Each cell In rng
cell.Formula = Replace(cell.Formula, "Inlife", "'Inlife (2)'")
Next
I would also like to suggest replacing of cell variable with cel. Cell is a range property and it is good to avoid creating such variables. It may create confusions on a complex code...
In the end this worked well.
Dim rng As Range, cel As Range
Set rng = Sheets("AC (2)").Range("B3:B10")
For Each cel In rng
cel.Formula = Replace(cel.Formula, "Inlife", "'Inlife (2)'")
Next
I have the following code right now:
Sub ClearTimeline()
Dim wsTimeline As Worksheet
Set wsTimeline = ThisWorkbook.Sheets(1)
wsTimeline.Range("B8, F25, F26, F28, F30, M17, M31, L17, L24:L25, L26, L28, L29:L30, J24:J25, J26, J28, J29:J30, K25, K26, K28, K30").ClearContents
End Sub
I want to replace the fixed cell reference by something more dynamic. The rows won't change, so I want to change how I reference the columns. I have a "reference cell", i.e. a cell I can always find/know the column of.
Sub ClearTimeline()
Dim wsTimeline As Worksheet
Dim referenceDay As Long
Set wsTimeline = ThisWorkbook.Sheets(1)
referenceDay = 10
'what works:
wsTimeline.Range(wsTimeline.Cells(referenceDay - 9, 1)).ClearContents 'clears single cell
wsTimeline.Range(wsTimeline.Cells(referenceDay - 9, 1), wsTimeline.Cells(referenceDay - 1, 1)).ClearContents 'clears range
End Sub
My goal is to refer to every column as 'referenceDay +/- X' because the distance to this day will stay the same even if the sheet is altered in some other way. But how do I tell Excel to do the same action for non-contiguous cells? I'm not sure how to reference them and what to put into the parentheses after wsTimeline.Range
If I understand correctly, the whole range of hardcoded cells should be moved to the right or to the left, depending on the column. Offset() is pretty good for this.
The "red" cells are the cells of the initial range, and the selected cells are the cells with the Offset(columnoffset:=2). I have used .Select to illustrate the difference, because there is overlapping and colors would not have been ok:
Sub ClearTimeline()
Dim wsTimeline As Worksheet
Set wsTimeline = ThisWorkbook.Worksheets(1)
Dim timelineRange As Range
Set timelineRange = wsTimeline.Range("B8, F25, F26, F28, F30, M17, M31, L17, L24:L25, L26, L28, L29:L30, J24:J25, J26, J28, J29:J30, K25, K26, K28, K30")
timelineRange.ClearContents
timelineRange.Interior.Color = vbRed
timelineRange.Offset(columnoffset:=2).Select 'But in general, do not use .Select
End Sub
I'll start by making my objective clear, and then explaining it fully.
My goal is to check for non-blank values in a range, but only in the hidden cells of that range, and then use conditional formatting in a different cell, depending on whether the cells in the range are empty or not.
I have a named range called Location_Address_RangeCheck that covers the cells directly to the right of the location numbers, like this (location numbers are not part of the range).
When the Number of Locations is changed, the rows that go beyond that number (up to 25) are automatically hidden on worksheet_change to reduce clutter and reduce scrolling to see the stuff below it. That code works fine, so I'm not posting it here so as to not confuse anyone with what I'm trying to accomplish.
I want to provide a safeguard to ensure that there aren't values in the hidden rows that could affect outputs (i.e., if someone selects "3" for Number of Locations, but there is data in cells that might be on the row of the 8th location).
My goal is to check for non-blank values in the range, but only in the hidden cells, and then use conditional formatting in the cell next to the number of locations chosen, depending on whether the cells in the range are empty or not.
So if there is data in the hidden cells, then it would cause the sheet to look like this
.
I've tried so many different things so far, but I'm not making any progress. I've scoured the internet trying to find a solution, but everything I've found is about finding things in visible cells, which is the opposite of what I'm trying to achieve.
Here is the code I have written so far, which I know does not achieve my objective:
Sub testhiddencells()
Dim myRange As Range
Set myRange = Range("Location_Address_RangeCheck")
NumRows = Application.WorksheetFunction.CountA(myRange)
If Range("Location_Address_RangeCheck").Hidden = True Then
If Application.WorksheetFunction.CountA(Range("Location_Address_RangeCheck")) <> 0 Then
MsgBox "There's something there"
End If
End If
End Sub
Here is a minimal example to check with a cell is both hidden and is non-empty:
Option Explicit
Sub Test()
Dim ws As Worksheet
Dim rngToCheck As Range
'test range - all cells populated with 'a' and 3 are hidden
Set ws = ThisWorkbook.Worksheets("Sheet1")
Set rngToCheck = ws.Range("A1:A7")
If TestForNonBlankCellsInHiddenRange(rngToCheck) Then
'do you conditional format stuff here
End If
End Sub
Function TestForNonBlankCellsInHiddenRange(rngToCheck As Range) As Boolean
Dim rngCell As Range
Dim blnCheck As Boolean
'assume that hidden cells are blank
blnCheck = False
'iterate range
For Each rngCell In rngToCheck
If rngCell.EntireRow.Hidden And Not IsEmpty(rngCell.Value) Then
'found a hidden and non-empty cell
blnCheck = True
'debug address of this cell
Debug.Print rngCell.Address
End If
Next rngCell
'return check
TestForNonBlankCellsInHiddenRange = blnCheck
End Function
Looking at the code you used already, you should be able to adapt this to the particular use case of your worksheet.
The following VBA function counts the number of cells containing formulas in a given range. It works correctly when called from a VBA sub. When called from Excel, it returns the total number of cells in the range.
The call from Excel is =CountFormulas(A1:C7), which returns 21 even though only two cells with formulas are in the range.
What is causing this discrepancy?
Public Function CountFormulas(ByRef rng As Range) As Long
CountFormulas = rng.SpecialCells(xlCellTypeFormulas).Count
End Function
Public Sub CountFormulasFromSub()
Dim rng As Range
Dim res As Integer
Set rng = Sheet1.Range("a1:c7")
res = CountFormulas(rng)
End Sub
This isn't possible. The following link has the things that won't work inside of a UDF.
Here - http://support.microsoft.com/kb/170787
EDIT: A manual way of counting works though.
Public Function CountFormulas(rng As Range) As Integer
Dim i As Integer
Dim cell As Range
For Each cell In rng
If cell.HasFormula Then
i = i + 1
End If
Next
CountFormulas = i
End Function
Change Integer to Long if you think it will exceed 32767.
If I were to send worksheet.cells to the function, it would check all cells in the entire worksheet, quite many and quite slow. Although Excel 2007+ supports 16384*1048576 rows, only cells which have actually been used are loaded to memory. There would be no need to go through all the other 17 billion cells to check. The closest I could get to identifying these was using Worksheet.UsedRange to restrict an arbitrary range input. It is not perfect though, in cases when cells far apart have been used. E.g. if cells A1 and XFD1048576 contain data, the entire worksheet would be included in UsedRange. Any tips on how to restrict the range to actually used cells (merely two cells in the above example) would be greatly appreciated.
Utilizing UsedRange I built a function which I'll share in case anyone else can make use of it:
Public Function CountIfFormula(ByRef rng As Range, Optional ByVal matchStr As String) As Long
'Counts the number of cells containing a formula and optionally a specific string (matchStr) in the formula itself.
Dim i As Long
Dim isect As Range
'Restricts the range to used cells (checks only cells in memory)
Set isect = Application.Intersect(rng, rng.Parent.UsedRange)
For Each cell In isect
If cell.HasFormula Then
If InStr(1, cell.Formula, matchStr) Then i = i + 1
End If
Next
CountIfFormula = i
End Function
Use of the function:
Sub GetNrOfCells()
Dim i As Long
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
i = i + CountIfFormula(ws.Cells, "=SUM(")
Next
'i will now contain the number of cells using the SUM function
End Sub
Best regards, and thank you for your reply.
Fossie