So I created a macro that muliplies a cell value with 100 (10^2). If the cell is simply a value it justs multiplies the cell value with 100, however if it's a formula it puts the formula in brackets and adds a 100* to the beginning
As you can't undo a macro easily but I need it, I tried to create an "undo" macro.
The Cell Value-Undo is quite easy, however for the formulas I struggle to delete the outer brackets.
An example process would be:
Original: =1+1 becomes =100*(1+1) and the undo should return to =1+1 (without brackets).
This is my code for the multiplication:
Private Sub MultiplySelectionBy100(Control As IRibbonControl)
Dim Cell As Range
For Each Cell In Selection
If Len(Cell.Value) > 0 And Application.IsNumber(Cell.Value) Then
If Cell.HasFormula Then
Cell.Formula = Replace(Cell.Formula, "=", "=100*(") & ")"
Else
Cell.Value = 100 * Cell.Value
End If
End If
Next
Application.OnUndo "Undo something", "UnDoSomething"
End Sub
For the UNDO, this is what I have so far:
Public Sub UnDoSomething()
Dim Cell As Range
Dim bet As String
For Each Cell In Selection
If Len(Cell.Value) > 0 And Application.IsNumber(Cell.Value) Then
If Cell.HasFormula Then
Cell.Formula = Replace(Cell.Formula, "=100*(", "=") 'This is not running
Cell.Formula = Replace(Cell.Formula, Chr(41), Chr(0))
Else
Cell.Value = 100 / Cell.Value
End If
End If
Next
End Sub
I don't know how to attach multiple replace functions but it gives me an error every time (mostly because I delete a opening bracket but the closing bracket remains).
I also can't delete all brackets as there may be more brackets inside the formula.
Maybe you have an idea...
Your main problem is that the first replace command will set the formula invalid because the closing ")" is still there, and Excel (not VBA) doesn't allow an invalid formula, so you get a runtime error (1004).
You should use an intermediate variable to handle the string manipulation of the formula, and only if that is done completely, assign the formula back to the cell. Using intermediate variables is always a good idea if you are dealing with formulas in VBA - you can check with the debugger if the formula looks really as expected before you write it back to the cell.
You need to be careful with your second replace-statement: This will remove all closing parenthesis characters, even if it has nothing to do with your "Undo". You should (a) check if you really want to remove it and (b) remove only the last closing parenthesis.
Dim f As String
f = cell.Formula
If Left(f, 6) = "=100*(" Then
f = Replace(cell.Formula, "=100*(", "=")
f = Left(f, Len(f) - 1)
cell.Formula = f
End If
Or, maybe easier
If Left(f, 6) = "=100*(" Then
f = "=" & Mid(f, 7, Len(f) - 7)
cell.Formula = f
End If
Related
I do have a cell in excel that contains Σh. Not sure how to check for it in vba. I have tried with .Value and .Text, but the check is never true.
If (tRange.Value = (ChrW(931) + "h")) Then
Exit Sub
End if
When testing (Debug) I get this result for ActiveCell.Value = Sh
(a) You have to use .Value to get the content of the cell.
(b) You should use the ampersand character (&) to concatenate strings in VBA. The plus-sign works also, but only if all operands are strings.
(c) ChrW(931) & "h" (or ChrW(931) + "h") should work. VBA is able to handle characters even if the VBA-environment cannot show them.
Seems to me that either the Sigma-character is composed with a different character, or your cell contains invisible characters like space, newline, tabs...
You can dump the content of the cell with the following code to get an idea why your If-statement fails:
Sub DumpString(s As String)
Dim i As Long
For i = 1 To Len(s)
Dim c As String
c = Mid(s, i, 1)
Debug.Print i, AscW(c), c
Next
End Sub
When you enter the following command into the immediate window, you will see output like that:
DumpString activecell.Value
1 931 S
2 104 h
This should check if cell value contains the sub-string 'Σh'
If tRange.Value Like "*" & ChrW(931) & "h*" Then
Exit Sub
End If
Another maybe simpler way for some folks
If InStr(1, tRange.Value, ChrW(931) & "h") <> 0 Then
Exit Sub
End If
You have to use an ampersand to join the two characters:
If (tRange.Value = ChrW(931) & "h") Then
Exit Sub
End if
I´m developing an Excel Makro right now.
Wanted to know, how I can repeat some lines of code using different data, without copy and paste.
Looking forward for your answers : )
This is my current code:
Sub deleteredundant()
Windows("Test1.xlsm").Activate
If Range("A6") = Range("A7") And Range("B6") = Range("B7") Then
Range("A7:B7").Select
Selection.ClearContents
End If
End Sub
It sounds like #BruceWayne has pointed in you in the right direction for what you need - removing duplicates.
As #Apurv Pawar shows you can use a loop, but he's selecting cells (if any code says select or activate a cell just don't.... you can reference a cell without selecting).
Another way is to have a procedure to remove the cells, and another procedure to tell it which workbook, worksheet and cell to look at.
Sub DeleteRedundant(CheckRange As Range)
If CheckRange = CheckRange.Offset(1) And CheckRange.Offset(, 1) = CheckRange.Offset(1, 1) Then
CheckRange.Offset(1).Resize(, 2).ClearContents
End If
End Sub
The code above will accept a range that is passed to it.
It will check if the passed cell is equal to the cell below itself:
CheckRange = CheckRange.Offset(1)
It will then check if the cell to the right of the passed cell is equal to the value below that:
CheckRange.Offset(, 1) = CheckRange.Offset(1, 1)
If the values match it will look at the cell below the passed cell, resize that to two cells wide and clear the contents of those two cells:
CheckRange.Offset(1).Resize(, 2).ClearContents
With this procedure in place we can pass it various range references to operate on:
Sub Test()
DeleteRedundant Workbooks("Excel Worksheet1.xlsx").Worksheets("Sheet1").Range("A6")
DeleteRedundant Workbooks("Excel Worksheet2.xlsx").Worksheets("Sheet2").Range("D5")
'Pass every other cell to the procedure in a loop.
'So will pass A2, A4, A6 - Cells(2,1), Cells(4,1) and Cells(6,1)
Dim x As Long
For x = 2 To 20 Step 2
DeleteRedundant Workbooks("Excel Worksheet1.xlsx").Worksheets("Sheet1").Cells(x, 1)
Next x
End Sub
But, as #BruceWayne says - you probably just need the Delete Duplicates button on the data ribbon.
try the below.
Sub deleteredundant()
Windows("Test1.xlsm").Activate
x = 1
Do While Range("a" & x).Formula <> ""
If Range("A" & x) = Range("A" & (x + 1)) And Range("B6" & x) = Range("B7" & (x + 1)) Then
Rows(x & ":" & x).Select
With Selection
.Delete EntireRow
End With
End If
x = x + 1
Loop
End Sub
Seeking help!
Hi,
I am almost done on a project and there's a part I don't understand
I have a + and a - button to add amounts from it's left cell to a total cell on the right (reads 54 in the example) (shown in the link down below)
Also, the amount of times the + is pressed is also calculated on the far most cell (2 for this example)
From the following code I made:
Range("L8").FormulaLocal = "=" & Replace(Range("L8").FormulaLocal, "=", "") & "+" & Range("G8")
The problem is that with the same code, using subtraction, I don't want to see it in the formula bar as it ends up as:
=29+29+29-29-29+29... (2nd image)
I only want to keep the positives. Is there something in the above mentioned code that I can change that will not show the subtraction though and not erase the whole formula that is there already
Thanks!
Part of my excel sheet for better understanding:
What I don't want to see in my formula bar:
First, shouldn't the value in your screenshot be 58, not 54?
Next, does the cell really need to contain a formula? As #teylyn mentioned, just do the calculation in VBA and set the cell's value. E.g. for the + button:
Range("L8").Value = Range("L8").Value + Range("G8").Value
Finally, if you really need to keep the formula, and you know that the value in cell G8 (the value being added or subtracted) never changes between clicks of the + and - buttons, you could first increment the counter (which I assume is cell M8), and then use its value to build the formula.
That might look something like the following, although you'd want to add some error trapping. Also, if you can ensure the counter will never be negative, you could eliminate the ElseIf portion:
Public Sub MinusButton_Click()
Range("M8").Value = Range("M8").Value - 1
Range("L8").FormulaLocal = GetCellFormula
End Sub
Public Sub PlusButton_Click()
Range("M8").Value = Range("M8").Value + 1
Range("L8").FormulaLocal = GetCellFormula
End Sub
Private Function GetCellFormula()
Dim strFormula As String
Dim intNum As Integer
strFormula = "="
If Range("M8").Value > 0 Then
For intNum = 1 To Range("M8").Value
strFormula = strFormula & Range("G8").Value & "+"
Next intNum
ElseIf Range("M8").Value < 0 Then
For intNum = Range("M8").Value To 1 Step -1
strFormula = strFormula & Range("G8").Value & "-"
Next intNum
End If
strFormula = Left(strFormula, Len(strFormula) - 1) 'strip trailing symbol
GetCellFormula = strFormula
End Function
Otherwise, if the value in cell G8 may change, your only option may be to do some (potentially) complicated parsing of the existing formula. If that's the case, please give it a try first, and post a new SO Question if you have any issues.
I'm trying to get all the content between multiple parenthesis and comma delimiting them. So for example
A1 contains
thisfile.jpg (/path/to/file.jpg), thisfile2.jpg (/path/to/file2.jpg)
and B1 should look like
/path/to/file.jpg, /path/to/file2.jpg
If it's just one entry I can get what I need with this:
MID(A1,FIND("(",A1)+1,FIND(")",A1)-FIND("(",A1)-1)
But that only returns the first one, I need to be for each parenthesis. The amount of parenthesis in each row will vary.
I am sure there are better solutions out there with formulas only. Yet, I cannot help you there. But the following UDF is surely also a feasible solution. Just copy this code into an empty module:
Option Explicit
Public Function GetPaths(strTMP As String)
Dim i As Long
Dim varArray As Variant
varArray = Split(strTMP, "(")
For i = LBound(varArray) To UBound(varArray)
If InStr(1, varArray(i), ")") > 0 Then
GetPaths = GetPaths & ", " & Mid(varArray(i), 1, InStr(1, varArray(i), ")") - 1)
End If
Next i
GetPaths = Mid(GetPaths, 3)
End Function
Afterwards, you can use this formula in column B as follows: =GetPaths(A1).
can i do this =(For i=1 to 100, print i)
is there a way to put a FOR statement inside a cell WITHOUT USING VBA?
You can use an array to get the numbers 1 through 100, but you're limited on what you can do with them. You can't, for instance, concatenate in an array formula (which your pseudo code suggests). But you could SUM, AVERAGE or many other operations.
{=SUM(ROW(1:100))}
{=AVERAGE(ROW(1:100))}
{=MAX(ROW(1:100))}
The braces means enter with control+shift+enter, not just enter.
The VBA for this isn't fancy at all :-)
Option Explicit
Sub SimpleForLoop()
Dim i As Integer
For i = 1 To 100 Step 1
With ActiveWorkbook.Sheets(1).Cells(1, 1)
.Value = .Value + i
End With
Next
End Sub
The simple code above puts the value 5050 in cell A1.
If you want to concatenate a string instead, slap this code into your for-loop:
With ActiveWorkbook.Sheets(1).Cells(2, 1)
If .Value = "" Then
.Value = CStr(i)
Else
.Value = .Value & "," & CStr(i)
End If
End With
Which will print the following into cell A2:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100