Using a formula from another column in Excel - excel-formula

I'll simplify this for example sake
I have a formula in column B which is Ax + 2,
e.g. in B1, it's A1 + 2
in B2, it's A2 + 2
I want to make a formula in column Y which mirrors whatever formula is in column B at all times but replaces the A in the formula with a X.
e.g. in Y1, it's X1 + 2
in Y2, it's X2 + 2
No matter what happens to the formula in column B, I want the formula in Y to reflect those changes.
Effectively, if I could do something akin to =B1.formula.replace("A","X") then that would do the job.
Can this be done in the formula bar at the top or will it need to be done via a macro?
Thanks

Here is the solution
Sub Button1_Click()
Dim s As String
s = Range("b2").Formula
Dim res As String
res = Replace(s, "A", "x")
MsgBox res
End Sub

Select B, copy the column, select Y and "paste special" choosing formula only should do the job
Following your comment:
Private Sub Workbook_Open()
Range("Y:Y").FormulaR1C1 = Range("B:B").FormulaR1C1
End Sub
will do the job (macro to put in ThisWorkbook)
Following your second comment:
Sub Workbook_Open()
On Error GoTo errLbl
xlCalc = Application.Calculation
Application.Calculation = xlCalculationManual ' stop calculation '
Application.ScreenUpdating = False ' disable screen update '
For Each c In Range("B:B")
Range("Y" & c.Row).Formula = Replace(c.Formula, "A", "D")
If c.Formula = vbNullString Then Exit For ' stop if "B" has no formula '
Next
errLbl:
Application.ScreenUpdating = True ' enable screen update '
Application.Calculation = xlCalc ' enable calculation back to where it was '
End Sub

Related

Excel VBA - How to extract numbers from String in each row of a specific column

I ran into an issue, I dont usually code in VBA so im having difficulties.
I'm trying to extract numbers from cells that contains a String(text).
The code that I currently have is working on a specific column, Column A in this case.
It loops over each row of that column.
It then puts the last number it found in the cell into the same row of column "B".
For Example:
A2: "123will", B2: 3.
A3: "12 Strawberries", B3: 2
What I am trying to get is the following(only the first 2 numbers):
For Example :
A2 : "123will", B2 : 12
A3: "12 Strawberries", B3: 12
A4: "15225 Street", B4: 15
A5: "Dog", B5: ""(empty)
What do I have to change in this code in order for it to work as I stated?
Thanks in advance! :)
Sub seperateNumbers()
checkRange (Worksheets("Sheet1").Range("A2:A9999"))
End Sub
Private Sub checkRange(objRange As Range)
Dim myAccessary As Variant
Dim i As Long
Dim iRow As Long
iRow = 2
For Each myAccessory In objRange ' LOOP THROUGH ELEMENTS OR VALUES IN EACH ROW.
For i = 1 To Len(myAccessory.Value) ' LOOP THROUGH EACH CHARACTER OF THE STRING (CELL VALUE).
' CHECK IF THE CHARACTER IS A NUMBER.
If IsNumeric(Mid(myAccessory.Value, i, 2)) Then
' SHOW THE NUMBER IN THE 2ND COLUMN OF THE SAME ROW.
If Trim(objRange.Cells(objRange.Row - 1, 2)) <> "" Then
objRange.Cells(iRow - 1, 2) = objRange.Cells(iRow - 1, 2) & Mid(myAccessory.Text, i, 2)
Else
objRange.Cells(iRow - 1, 2) = Mid(myAccessory.Text, i, 2)
End If
End If
Next i
iRow = iRow + 1
Next myAccessory
End Sub
Why not just a simple formula instead of overcomplicating things with VBA; here is a thought:
Formula in C1:
=IFERROR(-LOOKUP(1,-LEFT(A1,ROW($1:$2))),"")
You can use regexp in UDF:
Function ExtractNumber(str As String) As String
' set a reference to 'Microsoft VBScript Regular Expression 5.5' in Tools->References VBE menu
Dim res As IMatchCollection2, m As IMatch2
Static re As RegExp
If re Is Nothing Then
Set re = New RegExp
re.Global = False
re.PATTERN = "\d+"
End If
Set res = re.Execute(str)
If res.Count > 0 Then ExtractNumber = res(0)
End Function
Note. If the numbers are always at the beginning, you can use n = Val(str)
Try this option:
Sub seperateNumbers()
With ThisWorkbook.Sheets("Sheet1")
With .Range("B2", "B" & .Cells(.Rows.Count, 1).End(xlUp).Row)
.Formula2 = "=IFERROR(LEFT(A2,2)*1,IFERROR(LEFT(A2,1)*1,""""))"
.Value2 = .Value2
End With
End With
End Sub

Put timestamp when a checkbox is ticked or unticked

I have a worksheet with 3 rows and 7 columns (A1:G3).
A and B columns have 6 checkboxes (A1:B3). Boxes in columns A & B are linked to columns C & D respectively. Cells in columns E & F are just replicating columns C & D respectively (live E1 cell is =C1 and F3 cell is =D3).
I want to put a timestamp in cell G for each row when a checkbox is ticked or unticked by using Worksheet_Calculate event in VBA for that sheet.
My code works when used for just 1 row.
Private Sub Worksheet_calculate()
Dim cbX1 As Range
Set cbX1 = Range("A1:F1")
If Not Intersect(cbX1, Range("A1:F1")) Is Nothing Then
Range("G1").Value = Now()
End If
End Sub
I want to combine the code for 3 rows.
Here are 2 variations:
1st one:
Private Sub Worksheet_calculate()
Dim cbX1 As Range
Dim cbX2 As Range
Dim cbX3 As Range
Set cbX1 = Range("A1:F1")
Set cbX2 = Range("A2:F2")
Set cbX3 = Range("A3:F2")
If Not Intersect(cbX1, Range("A1:F1")) Is Nothing Then
Range("G1").Value = Now()
ElseIf Intersect(cbX2, Range("A2:F2")) Is Nothing Then
Range("G2").Value = Now()
ElseIf Intersect(cbX3, Range("A3:F3")) Is Nothing Then
Range("G3").Value = Now()
End If
End Sub
When I combine them with ElseIf like in the code above, a timestamp gets put in only G1, no matter if I tick B1 or C2.
2nd one:
Private Sub Worksheet_calculate()
Dim cbX1 As Range
Dim cbX2 As Range
Dim cbX3 As Range
Set cbX1 = Range("A1:F1")
If Not Intersect(cbX1, Range("A1:F1")) Is Nothing Then
Range("G1").Value = Now()
End If
Set cbX2 = Range("A2:F2")
If Not Intersect(cbX2, Range("A2:F2")) Is Nothing Then
Range("G2").Value = Now()
End If
Set cbX3 = Range("A3:F2")
If Not Intersect(cbX3, Range("A3:F3")) Is Nothing Then
Range("G3").Value = Now()
End If
End Sub
When I combine them by ending each one with End If and start a new If, timestamp gets put in all of the G1, G2 and G3 cells, even if I tick just one of the boxes.
You seem to be confusing Worksheet_Calculate with Worksheet_Change and using Intersect as if one of the arguments was Target (which Worksheet_Calculate does not have).
Intersect(cbX1, Range("A1:F1")) is always not nothing because you are comparing six apples to the same six apples. You might as well ask 'Is 1,2,3,4,5,6 the same as 1,2,3,4,5,6?'.
You need a method of recording the values of your range of formulas from one calculation cycle to the next. Some use a public variable declared outside the Worksheet_calculate sub procedure; personally I prefer a Static variant array declared within the Worksheet_calculate sub.
The problem with these is initial values but this can be accomplished since workbooks undergo a calculation cycle when opened. However, it is not going to register Now in column G the first time you run through a calculation cycle; you already have the workbook open when you paste in the code and it needs one calculation cycle to 'seed' the array containing the previous calculation cycle's values.
Option Explicit
Private Sub Worksheet_Calculate()
Static vals As Variant
If IsEmpty(vals) Then 'could also be IsArray(vals)
vals = Range(Cells(1, "A"), Cells(3, "F")).Value2
Else
Dim i As Long, j As Long
With Range(Cells(1, "A"), Cells(3, "F"))
For i = LBound(vals, 1) To UBound(vals, 1)
For j = LBound(vals, 2) To UBound(vals, 2)
If .Cells(i, j).Value2 <> vals(i, j) Then
Application.EnableEvents = False
.Cells(i, "G") = Now
Application.EnableEvents = True
vals(i, j) = .Cells(i, j).Value2
End If
Next j
Next i
End With
End If
End Sub

Removing Blank Cell

In column A, we have numbers of 1 to 10 respectively
And in column B we hold letters a to j which do not have order
We removed 4 letters
I do not want to change column A but column B removes her empty cells and letters writing following
The following code removes rows with empty cells:
Sub DeleteEmptyRows()
' Deletes the entire row within the selection if the ENTIRE row contains no data.
Dim i As Long
ActiveSheet.UsedRange.Select
With Application
' Turn off calculation and screenupdating to speed up the macro.
.Calculation = xlCalculationManual
.ScreenUpdating = False
For i = Selection.Rows.Count To 2 Step -1
If WorksheetFunction.CountA(Selection.Rows(i)) = 0 Then Selection.Rows(i).EntireRow.Delete
Next i
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub
This solution will loop through the rangeAreas, copy the contents in Column B of that area, remove the blanks, and but the results back in column b, I requires column Z as a helper column
Sub Button1_Click()
Dim RangeArea As Range, x
For Each RangeArea In Columns("A").SpecialCells(xlCellTypeConstants, 1).Areas
x = RangeArea.Rows.Count
RangeArea.Offset(, 1).Copy [z1]
Columns("Z:Z").SpecialCells(xlCellTypeBlanks).Delete Shift:=xlUp
RangeArea.Offset(, 1).Value = Range("Z1:Z" & x).Value
Range("Z:Z").Delete
Next RangeArea
End Sub
I don't understand how you get from your first picture to the second, but if you start from the second, this will get you to the third.
Sub x()
On Error Resume Next 'avoid error if no blank cells
Columns("B").SpecialCells(xlCellTypeBlanks).Delete shift:=xlUp
On Error GoTo 0
End Sub

Visual Basic Excel Macro

I want to have a little Macro in excel. The Macro should take a double number from A1 and multiply this number by 5 and return it back into A1 but i always get error messages etc.
My code up to now:
Function multiply()
Dim a As Long
For a = 1 To 65563
cell(a,3) = cell(a,3).Value * 5
next a
End Function
I have not worked with VBA before.
That does what you ask, but it's a sub as you can't edit worksheet values using a function
Public Sub multiply()
On Error GoTo err
Dim val As Long
val = ActiveSheet.Cells(1, 1).Value
ActiveSheet.Cells(1, 1).Value = val * 5
Exit Sub
err:
End Sub
you dont need to use function just use these subs:
bellow you can multiplay all of *column A * values:
Sub example()
For a = 1 To 65563
Cells(a, 1).Value = Cells(a, 1).Value * 5
Next a
End Sub
considering 65563 CELLS isn't a good idea, i suggest you to use the sub bellow to count rows and reduce memory usage.
Sub example2()
Dim countrows As Long
countrows = Range("A" & Rows.Count).End(xlUp).Row
For a = 1 To countrows
Cells(a, 1).Value = Cells(a, 1).Value * 5
Next a
End Sub
You don't actually need a macro for this - although if you do want to use VBA you can avoid time consuming loops altogether
1 Manual Method using Paste Special - Multiply
from walkenbach
To increase a range of values by 5 times:
Enter 5 into any blank cell.
Select the cell and choose Edit, Copy.
Select the range of values (Column A in your example) and choose Edit, Paste Special.
Choose the Multiply option and click OK.
Delete the cell that contains the 5
2 Code using Paste Special - Multiply
Using Zack Barresse's code from vbax - with minor amendments
This code updates the selected range with a user-entered multiplier
Sub psMultiply()
' http://www.vbaexpress.com/kb/getarticle.php?kb_id=47
Dim y As Long 'The multiplier value, user-defined
Dim x As Range 'Just a blank cell for variable
Dim z As Range 'Selection to work with
Set z = Selection
y = Application.InputBox("Enter selection multiplier:", _
Title:="Selection multiplier", Default:=10, Type:=1)
Set x = Cells(Rows.Count, "A").End(xlUp).Offset(1)
If y = 0 Then Exit Sub 'Cancel button will = 0, hence cancel
If x <> "" Then
Exit Sub
Else: x.Value = y
x.Copy
z.PasteSpecial Paste:=xlPasteAll, Operation:=xlMultiply
Application.CutCopyMode = False 'Kill copy mode
End If
x.ClearContents 'Back to normal
End Sub
Why not make it a little more generic by only multiplying the numbers you select:
Sub MultiplyByFive()
Dim cl As Range
For Each cl In Selection
cl = cl * 5
Next cl
End Sub
This way you avoid the 65536 hard coding.

How to highlight a row if three conditions are met?

If the following conditions are met:
For any given row between row 10 and row 100 inclusively:
The cell in column A is not empty
The cell in column B is not empty
The cell in column O is empty
I would like to highlight a specific cell (let's say A1).
Example:
I populate A10 and E10 while leaving O10 empty, then cell A1 gets highlighted. If I then populate cell O10, the highlight in cell A1 disappears.
I can proceed to the next row. Any row at any time should generate these actions.
Thanks!
This will do the highlights based on the conditions you specified. When you run it, it'll stop at the first row you need to input something in column O. If you want it to keep running until row 101 and highlight all the rows, then remove then Exit Do command that's between the 2 End If statements.
Sub Highlight()
Dim TheRow As Integer
TheRow = 9
Application.ScreenUpdating = False 'This hides the visual process and speeds up
'the execution
Do
TheRow = TheRow + 1
If TheRow = 101 Then Exit Do
Cells(TheRow, 1).Select
Selection.Interior.Pattern = 0
Cells(TheRow, 2).Select
Selection.Interior.Pattern = 0
If Not Cells(TheRow, 1).Value = "" And Not Cells(TheRow, 2).Value = "" And Cells(TheRow, 15).Value = "" Then
If Cells(TheRow, 1).Value = "" Then
Cells(TheRow, 1).Select
Selection.Interior.Color = 656
End If
If Cells(TheRow, 2).Value = "" Then
Cells(TheRow, 2).Select
Selection.Interior.Color = 656
End If
Exit Do 'this is the line to remove if you want to highlight all cells
End If
Loop
Application.ScreenUpdating = True
End Sub
And then, create an event handler that triggers when a cell in column 15 changes. Put the following code in the module of the actual worksheet (in the VBA project explorer, double click on the sheet you want have this functionality for; don't put this in a different module!)
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 15 Then
If Target.Row > 9 And Target.Row < 101 Then Call Highlight
End Sub
Let me know if this solution works and remember to click "accept solution" and to vote for it!
Happy coding.
You don't need VBA: just use conditional formatting on cell A10 with the following formula:
=AND(NOT(ISBLANK($A10)),NOT(ISBLANK($B10)),ISBLANK($O10))
OK - I misunderstood what you wanted. Here is a VBA UDF to do the checking.
Enter =Checker($A$10:$B$100,$O$10:$O$100) in cell A1, then use conditional formatting on cell A1 that is triggered when it becomes True.
Public Function Checker(theRangeAB As Range, theRangeO As Variant) As Boolean
Dim varAB As Variant
Dim varO As Variant
Dim j As Long
varAB = theRangeAB.Value2
varO = theRangeO.Value2
Checker = False
For j = 1 To UBound(varAB)
If Not IsEmpty(varAB(j, 1)) And Not IsEmpty(varAB(j, 2)) Then
If IsEmpty(varO(j, 1)) Then
Checker = True
Exit For
End If
End If
Next j
End Function

Resources