在Excel VBA中,如何将求和函数转换为其显式形式?
excel单元格的公式形式为在Excel VBA中,如何将求和函数转换为其显式形式?,excel,vba,excel-formula,Excel,Vba,Excel Formula,excel单元格的公式形式为=SUM(I1:I5)。我们如何将其转换为显式形式: =I1+I2+I3+I4+I5 我编写了一个函数,通过字符串操作来实现这一点 我试过了 前=SUM(C2:C4,E2:G2,D7:E8) =$C$2+$C$3+$C$4+$E$2+$F$2+$G$2+$D$7+$E$7+$D$8+$E$8之后 用法,使用目标单元格作为参数调用ExpandSum() Public Sub ExpandSum(ByVal r_target As Range) Dim f
=SUM(I1:I5)
。我们如何将其转换为显式形式:
=I1+I2+I3+I4+I5
我编写了一个函数,通过字符串操作来实现这一点 我试过了
- 前
=SUM(C2:C4,E2:G2,D7:E8)
=$C$2+$C$3+$C$4+$E$2+$F$2+$G$2+$D$7+$E$7+$D$8+$E$8之后
ExpandSum()
Public Sub ExpandSum(ByVal r_target As Range)
Dim f As String
f = Mid(r_target.Formula, 2)
' Is it a SUM function
If Left(f, 3) = "SUM" Then
' Take the arguments of SUM
f = Mid(f, 5, Len(f) - 5)
' make an array of string with each
' arument
Dim parts() As String
parts = Split(f, ",")
Dim i As Long, n As Long
n = UBound(parts) + 1
Dim rng As Range, cl As Range
Dim col As New Collection
For i = 1 To n
' for each argument find the range of cells
Set rng = Range(parts(i - 1))
For Each cl In rng
' Add each cell in range into a list
col.Add cl.Address
Next
Next i
' Transfer list to array
ReDim parts(0 To col.Count - 1)
For i = 1 To col.Count
parts(i - 1) = col(i)
Next i
' Combine parts into one expression
' ["A1","A2","A3"] => "A1+A2+A3"
f = Join(parts, "+")
r_target.Formula = "=" & f
End If
End Sub
使用当前选择调用的示例
Public Sub ThisExpandSum()
Call ExpandSum(Selection)
End Sub
注意事项我不知道如果总和包含文字值或来自不同工作表的单元格,它将如何运行。这是以后添加的功能。请使用下一个功能:
Function SUMbyItems(strFormula As String) As String
If strFormula = "" Then Exit Function
Dim rng As Range, Ar As Range, c As Range, strF As String
Set rng = Range(left(Split(strFormula, "(")(1), Len(Split(strFormula, "(")(1)) - 1))
For Each Ar In rng.Areas
For Each c In Ar.cells
strF = strF & c.Address(0, 0) & "+"
Next c
Next
strF = left(strF, Len(strF) - 1)
SUMbyItems = "=SUM(" & strF & ")"
End Function
可以使用它,选择具有包含范围的求和公式的单元格,然后运行下一个子单元格:
Sub testSumByItems()
Debug.Print SUMbyItems(ActiveCell.Formula)
End Sub
如果它返回您想要的结果,并且您需要使用其扩展版本更改范围公式,您可以使用(在上面的测试子部分中):
这感觉就像是一篇关于代码高尔夫的帖子。这是我的函数版本,可以实现这一点
函数显式(ByVal表达式作为字符串)作为字符串
暗淡的strStart和长的一样,强壮的和长的一样
strStart=InStr(1,UCase(表达式),“和(“)+4
如果strStart=0,则
“找不到金额
ExplicitSum=表达式
退出功能
如果结束
strEnd=InStr(strStart+1,表达式“)”)
如果strEnd=0,则
'未找到右括号
ExplicitSum=表达式
退出功能
如果结束
调暗LeftText作为字符串,RightText作为字符串,AddressText作为字符串
LeftText=Replace(左(表达式,strStart-1),“sum”(“,”,Compare:=vbTextCompare)
AddressText=Mid(表达式、strStart、strEnd-strStart)
RightText=Right(表达式,Len(表达式)-强度+1)
如果InStr(1,UCase(rightext),“SUM”()0,则
'递归将处理同一公式中的多个和
RightText=明确(RightText)
如果结束
模糊范围作为范围
出错时继续下一步
设置SumRange=范围(AddressText)
错误转到0
如果SumRange什么都不是,那么
'无效的AddressText-命名范围或间接引用
ExplicitSum=左文本&地址文本&右文本
退出功能
如果结束
Dim Addresses()作为字符串
ReDim地址(1到SumRange.Cells.Count)
变暗单元格作为范围,i作为长度:i=1
对于SumRange中的每个单元格
地址(i)=单元格地址(假,假)
i=i+1
下一个细胞
ExplicitSum=LeftText&Join(地址“+”)&rightext
端函数
如何使用该功能的示例:
子测试()
MsgBox明确(“=5+和(A1:D1)/20”)
'显示“=5+(A1+B1+C1+D1)/20”
端接头
子示例用法()
'转换后将公式放回单元格中
范围(“E1”)。公式=明确(范围(“E1”)。公式)
端接头
私有子工作表_更改(ByVal目标作为范围)
'在公式中包含SUM的每个单元格上运行
如果LCase(Target.Cells(1,1).Formula)像“*sum(*”,那么Target.Cells(1,1).Formula=ExplicitSum(Target.Cells(1,1).Formula)
端接头
有先例的另一种方法:
Sub expandSUM()
Range("A1").Formula = "=SUM(I1:I5)" 'the formula must be in the cell
Output = "=SUM("
For Each cl In Range("A1").Precedents
Output = Output & "+" & cl.Address(False, False)
Next
Debug.Print Replace(Output, "(+", "(") & ")"
End Sub
没有内置的方法可以做到这一点。你想自己操纵字符串来完成这一点吗?要正确地做到这一点,你需要能够解析Excel公式语法;然后你的代码能够理解
I1:I5
如何代表5个单独单元格的范围。其他任何东西都是一种黑客行为(可能有用!)这就引出了一个问题……为什么?另外,=SUM(I1:I5)
和=I1+I2+I3+I4+I5
不是一回事。@DarrenBartrup Cook将'1
、2
和TRUE
输入三个单元格,比较SUM和+。然后将其中一个单元格更改为hello
,看看会发生什么。:)@MathieuGuindon为了回答您的原因,扩展的公式将保存在csv中,然后由另一个与excel函数无关的应用程序读取。tnxy您的函数不检查公式是否有求和。并在找到的第一个括号上拆分。任何输入,如=Count(A1:B5)/SUM(A1:B5)
不会被正确转换。@Cubbleson:当然不会!这不是我的功能。这是OP问题的答案。他问过这样一个公式吗?我错过了?你希望它也在你的帐户里存一些钱吗…?是的,请!我非常希望。@Cubbleson:那么,请稍等一下…)大约一个小时后检查您的帐户。如果公式中的和前面有任何项,那么您的函数将不起作用。任何输入,如=1+Sum(A1:B1)
都不起作用。@cubbleson-true,但这不是op问题中的要求。我正在等待有人发布表达式树解析器并使用它。
Sub expandSUM()
Range("A1").Formula = "=SUM(I1:I5)" 'the formula must be in the cell
Output = "=SUM("
For Each cl In Range("A1").Precedents
Output = Output & "+" & cl.Address(False, False)
Next
Debug.Print Replace(Output, "(+", "(") & ")"
End Sub