I need to iterate the "condition" in the formula "sumif". The variable type is "string" but my code doesn´t work. I can´t keep the condition of the string of the variable. The code is an example if i can solve the problem with the "variable". I just need to simply iterate that variable. The code is:
Private Sub cmd_psps_Click()
Dim prueba As Integer
Dim var As String
prueba = Sheets("PRUEBAS").Index
var = "a"
Sheets(prueba).Cells(5, 16).Formula = "=sumif(" & Range(Cells(4, 13),
Cells(8, 13)).Address() & "," & var & "," & Range(Cells(4, 14), Cells(8,
14)).Address() & ")"
End Sub
The problem is in ," & var & ", with that code the cell in worksheet looks like:
=SUMAR.SI($M$4:$M$8;a;$N$4:$N$8)
But I need:
=SUMAR.SI($M$4:$M$8;"a";$N$4:$N$8)
I can use the condition with a simpletext for example "a". But I need to iterate the condition with a variable.
Not strictly an answer, but for the code readability, when using manual Excel's formula construction, it's good to have handy function to concatenate strings:
Function FormatString(s As String, ParamArray args() As Variant)
Dim x%
For x = LBound(args) To UBound(args)
s = Replace$(s, "{" & x & "}", args(x))
Next
FormatString = s
End Function
The usage:
Sub G()
MsgBox FormatString("I have {0} apples and {1} oranges", 10, 20)
End Sub
You use placeholders {0}, {1} etc. for parameters. This is like what C#'s String.Format does.
Thus, your formula will look like this:
Sub G()
Dim sFormula$
Dim var$
var = "A1"
sFormula = FormatString( _
"=SUM({0},{1},{2})", _
Range(Cells(4, 13), Cells(8, 13)).Address(), _
var, _
Range(Cells(4, 14), Cells(8, 14)).Address())
End Sub
Now the code looks more readable.
Related
How do I return a result from a function?
For example:vba: i want function
Function xy2cell(i, f)
xy2cell = "=" & "?????????????????????????????"
End Function
Sub aaa_main()
ActiveSheet.Cells.Clear
f = "5^4*x-2^4*y-1"
For i = 1 To 2
Cells(i, 3) = xy2cell(i, f)
Next
End Sub
'I want
'Cells(1, 3) = "=5^4*" & Cells(1, 1).Address & "-2^4*" & Cells(1, 2).Address & "-1"
'Cells(2, 3) = "=5^4*" & Cells(2, 1).Address & "-2^4*" & Cells(2, 2).Address & "-1"
(20220328)
original
Japanese below ↓↓↓↓↓↓-------------------------------------------
2022 Mathematics 1A Q4 < The Common Test for University Admissions is a common entrance examination for Japanese universities
https://cdn.mainichi.jp/item/jp/etc/kyotsu-2022/pdf/MTAP.pdf#page=20
I try (vba & vba solver)
https://qiita.com/mrrclb48z/items/af08059157cfbce8f0fe
Japanese up ↑↑↑↑↑-------------------------------------------
A simpler approach is to use the formual2R1C1 property of a range. This allows you to specify a formula using notation that refers to cells as offsets from the destination cell. This way, a single expression can be used to create different formulas in each target cell of the range.
Sub aaa_main_2()
Dim f As String
f = "=5^4*x-2^4*y-1"
f = Replace(f, "x", "RC[-2]")
f = Replace(f, "y", "RC[-1]")
ActiveSheet.Cells.Clear
Range("C1:C2").Formula2R1C1 = f
End Sub
or, more directly
Sub aaa_main_3()
ActiveSheet.Cells.Clear
Range("C1:C2").Formula2R1C1 = "=5^4*RC[-2]-2^4*RC[-1]-1"
End Sub
It seems unusual to clear all the cells from the active sheet, as this would remove any inputs on which the function would operate. Nonetheless, here is your code converted to do as you ask. I've added Dim statements to declare the variables your code uses.
Function xy2cell(i As Long, f As String)
Dim formula As String
formula = Replace(f, "x", Cells(i, 1).Address(False, False))
formula = Replace(formula, "y", Cells(i, 2).Address(False, False))
xy2cell = "=" & formula
End Function
Sub aaa_main()
Dim f As String
Dim i As Long
ActiveSheet.Cells.Clear
f = "5^4*x-2^4*y-1"
For i = 1 To 2
Cells(i, 3).Formula = xy2cell(i, f)
Next
End Sub
This code uses the "replace" function to find "x" in your formula string (f) and replace it with the appropriate cell reference. The result is stored in a variable named "formula" which is then used as the input to replace y with the appropriate cell reference.
However, there is a much simpler approach using the formula2R1C1 property. I'll post a separate solution on that technique.
I am new to Macros below is what I wrote to be able to do a lookup through a function. When I debug all the values seem to work well except that at the end it gives error about circular reference.
I am making a call to below like: = GetCost("abc")
Public Function GetCost(arg1 As String)
'
' GetCost Macro
'
Dim fName As String
Dim searchItem As String
Dim result As Integer
fName = Range("B4").Value
searchItem = Chr(34) & arg1 & Chr(34)
expression = "=VLOOKUP(" & searchItem & "," & fName & ", 2, FALSE)"
ActiveCell.Value = ActiveSheet.Evaluate(expression)
result = Evaluate(expression)
GetBOMCOst = result
End Function
The circular reference is because you are trying to change the value of the cell containing the function:
remove ActiveCell.Value = ...
change result= Evaluate to result =application.caller.parent.Evaluate(expression)
Also fName=Range("B4").value should use a fully qualified reference (Sheet.Range)
And this function should be made volatile otherwise it will not recalculate whenever the value in Range("B4") changes
You need to remove your active cell reference as suggested by other.
Also, its looks like, your lookup range is incorrect. Change the lookup expression as below, in case, if you have your value in A and B column.
expression = "=VLOOKUP(" & searchItem & "," & "A:B" & ", 2, FALSE)"
And, it looks like you trying to return the value to your calling function. In VBA, to return a variable, you need to assign the variable to a function name. i.e. change your last line GetBOMCOst = result to GetCost = result
Try the below updated version of the code.
Public Function GetCost(arg1 As String) ' ' GetCost Macro ' Dim fName As String Dim searchItem As String Dim result As Integer
searchItem = Chr(34) & arg1 & Chr(34)
expression = "=VLOOKUP(" & searchItem & "," & "A:B" & ", 2, FALSE)"
result = Evaluate(expression)
GetCost = result
End Function
How do I calculate the value of a text box and print it to a cell in Microsoft Excel VBA?
For example: I enter 2*2 into my textbox, and I want it to print 4 to a cell.
the textbox is in a userform this is what i have so far, although it works it doesn't look nice. I'm new to excel so help is appreciated.
Private Sub Submit_Click()
Dim str As String
Dim bracket As String
lastrow = Cells(Rows.Count, 1).End(xlUp).Row + 1
str = "=SUM("
bracket = ")"
Application.ScreenUpdating = False
Sheets("Value").Activate
Cells(lastrow, 1) = str & txtbox.Value & bracket
Application.ScreenUpdating = True
Fully Qualify your Objects.
Currently, you are writing Cells(lastrow, 1) = str & txtbox.Value & bracket
Excel is implictly treating this as ActiveSheet.Cells(lastrow, 1).Value = str & txtbox.Value & bracket - because you only provide half the information, it has to guess. It assumes you want the ActiveSheet, and it assumes you want to change the Value. But, you don't.
To put a Formula into a Cell in VBA, don't use Value - use Formula, like so: ActiveSheet.Cells(lastrow,1).Formula = str & txtbox.Value & bracket
Alternatively, if you want the Value, but not the Formula, then there are 2 methods. Either convert the result, like so:
With ActiveSheet.Cells(lastrow, 1)
.Formula = str & txtbox.Value & bracket
.Calculate
.Value = .Value
End With
Or use the Application.Evaluate method:
ActiveSheet.Cells(lastrow, 1).Value = EVALUATE(str & txtbox.Value & bracket)
Private Sub Submit_Click()
With Sheets("Value")
.Cells(Rows.Count, 1).End(xlUp).offset(1 ,0).formula = "=" & me.txtbox
End With
End Sub
I assume that the textbox is called txtbox and that the routine is being run from a button on the same userform
So currently in column B, there are cells that have no spaces before them but there are also cells that do.
For example: cell B1 would just be "Market:" but then cell B4, B5,B6,B10, B14, etc would have "_____Total:" ( __ meaning blank space)
What would I have to write to delete the 5 spaces before "Total:"?
I currently have:
mos = Range("B:B")
For Each x In mos
xv = x.Value
If Left(xv, 1) = "" Then xv = Right(xv, Len(xv) - 1)
Next xv
which gives me an error.
Please let me know what I should do.
Thanks!
Use Trim$ function. Trim function removes excess trailing and leading white space. Trim$ is a typed function and is faster.
Using Intersect, as below, means only processing the necessary number of rows and not the entire column B.
Be explicit. Put Option Explicit at the top of your code to force variable declaration and declare your variables. And fully qualify which sheet you are working with.
As noted in another answer, there are variants such as LTrim$ just to remove from left (Start of string) and RTrim$, just to remove from right (end of string).
Code:
Option Explicit
Public Sub test()
Dim mos As Range
Dim x As Range
With ActiveSheet 'change to appropriate worksheetname
Set mos = .Range("B:B")
For Each x In Intersect(mos, .UsedRange)
x = Trim$(x)
Next x
End With
End Sub
Bonus:
There are a lot of existing functions written to "clean" strings removing all "extra" white space characters i.e. leaving only single internal white spaces.
Here is one by Henry Habermacher
Public Function removeObsoleteWhiteSpace _
(FromString As Variant) As Variant
If IsNull(FromString) Then 'handle Null values
removeObsoleteWhiteSpace = Null
Exit Function
End If
Dim strTemp As String
strTemp = Replace(FromString, vbCr, " ")
strTemp = Replace(strTemp, vbLf, " ")
strTemp = Replace(strTemp, vbTab, " ")
strTemp = Replace(strTemp, vbVerticalTab, " ")
strTemp = Replace(strTemp, vbBack, " ")
strTemp = Replace(strTemp, vbNullChar, " ")
While InStr(strTemp, " ") > 0
strTemp = Replace(strTemp, " ", " ")
Wend
strTemp = Trim(strTemp)
removeObsoleteWhiteSpace = strTemp
End Function
Example call:
Public Sub testing()
Debug.Print removeObsoleteWhiteSpace(" my string with a few spaces ")
End Sub
To avoid looping you can use:
Dim myAddress As String
myAddress = "B1:B" & Cells(Rows.Count, 2).End(xlUp).Row
Range(myAddress) = Evaluate("IF(" & myAddress & "="""","""",TRIM(" & myAddress & "))")
which can be also written as:
With Range("B1", Cells(Rows.Count, 2).End(xlUp))
.Value = Evaluate("IF(" & .Address & "="""","""",TRIM(" & .Address & "))")
End With
or Replace() method:
Range("B1", Cells(Rows.Count, 2).End(xlUp)).Replace what:=" ", replacement:="", lookat:=xlPart
of course all above solutions assume that you only have extra spaces at the beginning of each cell content, or they will trim (first two solutions) or eliminate (3rd solution) other spaces also
if you actually have the need to eliminate the leading spaces (the ones preceding the first not blank character) leaving all other ones in place, then you have to loop and use LTrim() VBA function:
Dim cell As Range
For Each cell In Range("B1", Cells(Rows.Count, 2).End(xlUp))
cell.Value = LTrim(cell.Value)
Next
Sorry, didn't realize your loop was only to remove spaces.
This is how I trim my spaces:
Sub trim()
Dim mos As Range
Set mos = Range("B:B")
mos.Value = Application.trim(mos)
End Sub
1. I was trying to answer VBA UDF to split string array and got an unpleasant results during computing my UDF.
Public Function mytest(src, dest)
dest.Parent.Evaluate "test(" & src.Address(False, False) & ", " & dest.Address(False, False) & ")"
mytest = "wut"
End Function
Sub test(src As Range, dest As Range)
Dim chr, rows, cols
rows = 0
cols = 0
For chr = 1 To Len(src.Value)
Select Case Mid(src.Value, chr, 1)
Case ","
rows = rows + 1
Case ";"
cols = cols + 1
rows = 0
Case Else
Cells(dest.Row + rows, dest.Column + cols).Value = Cells(dest.Row + rows, dest.Column + cols).Value & Mid(src.Value, chr, 1) '
End Select
Next chr
End Sub
Expected results:
Formula results:
Can someone explain why does it double Value of the cell?
When I debugged test using
Sub ffs()
Call test(Cells(1, 1), Cells(3, 1))
End Sub
I got expected results, so I guess the problem is not in the test Sub?..
2. Whenever I try to add more parameters to Function and Sub (for example delimiters) Function doesn't Evaluate Sub at all
Public Function CellToRange(src, dest, DelimL, DelimC)
dest.Parent.Evaluate "test(" & src.Address(False, False) & ", " & dest.Address(False, False) & ", " & DelimL & ", " & DelimC & ")"
CellToRange = "wut"
End Function
Sub CTR(src As Range, dest As Range, Delim1, Delim2)
Dim chr, rows, cols
rows = 0
cols = 0
For chr = 1 To Len(src.Value)
Select Case Mid(src.Value, chr, 1)
Case Delim1
rows = rows + 1
Case Delim2
cols = cols + 1
rows = 0
Case Else
Cells(dest.Row + rows, dest.Column + cols).Value = Cells(dest.Row + rows, dest.Column + cols).Value & Mid(src.Value, chr, 1) '
End Select
Next chr
End Sub
Please help ._. and thanks in advance.
Solution:
Thanks Billy and Charles Williams.
Change
dest.Parent.Evaluate "CTR(" & src.Address(False, False) & ", " & dest.Address(False, False) & ", " & DelimL & ", " & DelimC & ")"
To
dest.Parent.Evaluate "0+CTR(" & src.Address(False, False) & ", " & dest.Address(False, False) & ", " & DelimL & ", " & DelimC & ")"
Thanks everyone!
The problem lies with the Worksheet.Evaluate method which is being used to get round the restriction that a UDF is not allowed to modify the worksheet structure.
Consider this code
Option Explicit
Public Function dummyudf() As String
Debug.Print "Calling Evaluate method"
ActiveSheet.Evaluate "testsub()"
Debug.Print "Returning From Evaluate method"
dummyudf = "done"
End Function
Sub testsub()
Debug.Print "testsub running"
End Sub
Sub testmacro()
Dim s As String
Debug.Print "testmacro running"
s = dummyudf
End Sub
The UDF dummyudf() uses the Evaluate method to invoke the Sub called testsub(). These are analagous to mytest and test in part 1. of the OP and to CellToRange and CTR in part 2 but are stripped down to the bare minimum.
testsub() can also be invoked directly as a macro. A second macro testmacro invokes dummyudf as a function in VBA.
The following output was obtained from the Immediate Window:
As can be seen
when invoked as a macro: testsub() behaves as expected
when dummyudf() is invoked as a UDF on the worksheet (for example by adding the formula =dummyudf() to cell A1 the Evaluate method appears to call testsub() twice
when dummyudf() is invoked as a function in VBA by running testmacro() as a macro the Evaluate method appears to call testsub() twice.
The documentation here suggests that the Name argument of the Worksheet.Evaluate method should be the name of an object, so it is a bit surprising that it is possible supply the name of a Sub. That it also seems to call any such Sub twice, is even more surprising but does underline the advice given in YowE3K's answer about not using this hack in a UDF. I'd go further: don't use Worksheet.Evaluate with any Sub.
1) It evaluates once when the formula is triggered, and again when cell A3 is updated by the function (as it is one of the cells the formula is dependent on).
2a) You are calling the wrong subroutine (test instead of CTR)
2b) You need to call your second function using something like
=CellToRange(A1;A3;""",""";""";""")
or else change the line in your code calling CTR to be
dest.Parent.Evaluate "CTR(" & src.Address(False, False) & ", " & dest.Address(False, False) & ", """ & DelimL & """, """ & DelimC & """)"
3) I strongly recommend that you do not use this sort of hack to get a UDF to update cells other than the one containing the function.