VBA使Excel公式更具可读性

时间:2017-01-25 09:31:31

标签: excel vba excel-vba excel-formula readability

我已经浏览了网站,但是关于使Excel公式(公式?)更具可读性的建议倾向于指向使用命名区域' '使用帮助列' 。我不是在使公式更容易阅读的技术之后,我想创建一个宏来以更易读的方式显示公式。 您可以跳到最后以获得缩短的问题说明。我这样说是因为虽然我喜欢解释我的方法,但我觉得这次我的方法可能会分散问题的本质。此外,我认为如果没有前面提到的背景,问题可以很好地提炼出来

问题背景

我有很多令人讨厌的窝窝复杂的公式,这是我今天写的一个(见Excel sample document

![Excel Code sample

或代码:

=IFERROR(IF(Latest[Weekday Num]=5,0,M13+MAX(Table3[Lunchtime],Latest[Lunchtime])-INDEX(Table4[Out],Latest[Weekday Num]))+Table3[Time remaining]-SUMIFS(Table4[Work time],Table4[Weekday Num],">"&Latest[Weekday Num],Table4[Weekday Num],"<5")+Latest[Clocked In]-S13,"Refresh csv")

虽然它很丑陋,IMO实际上构造得很好; IFSSUMIFS尽可能避免公式的嵌套,存储在表中的所有命名范围,适用时使用的辅助列。然而,在某些情况下,它会返回错误的结果,并且公式 令人愉快。 (它不是最长的,我编译了几个a4页的代码,代码,虽然那是我无法使用vba构建帮助列的时候)

我想要一个宏,它采用这个公式并将其拆分为一种分支函数树,其中每个嵌套函数是另一个树枝 - 可能在工作簿中的单元格中拆分公式的组件

目前的方法

到目前为止,我尝试了以下方法:列A和B用于将公式拆分为更小的部分。 我将这些部分定义为Excel公式的功能和参数,因此公式IF(A1=1,A2,B1)分为IF(A1=1,A2,B1)。我在B栏中使用以下公式执行此操作:

=LEFT(A2,IFERROR(MAX(1,MIN(IFERROR(FIND("(",A2),LEN(A2)+1),IFERROR(FIND(")",A2),LEN(A2)+1),FIND(",",A2))),LEN(A2)))

同时,A列查看B列找到的最后一个组件,并将其从长公式(使用=SUBSTITUTE(A2,B3,"",1)中删除。 因此,对于A2中的原始公式(作为文本),B2是它的第一个组成部分(例如我的例子中的IF(),A3是A2 中的公式减去的第一个组成部分在B2。我拖下来迭代。

这给了我列B中每个单元格中公式的组件列表。然后,我的宏决定每个组件的级别,并通过那么多单元格缩进组件。 级别定义为公式* 或&#39;段&#39;的组件前面的开放括号数。在我的代码中尚未关闭。宏评论解释了这一点。

Sub DispFormula()
'takes a split-up formula and indents lines appropriately

Dim CurrLev As Integer, OBrac As Integer, CBrac As Integer
Dim Segment As Range 'each part of the split up formula
LastRow = Sheets("sheet1").Cells(Rows.Count, 2).End(xlUp).Row

Set orange = Range("B2:B" & LastRow) 'all the segments make an orange

CurrLev = 0 'the "level" of the "segment" - it's level is a measure of how many layers deep the formula is nested
            'if(a=1,b,c) is split into 4 components: `if(`, `a=1,`, `b,` & `c)` where `if(` is level 0 and all the other segments are level 1

OBrac = 0 'how many open brackets have happened/ precede a segment of the formula
CBrac = 0 'how many closed brackets have happened
On Error Resume Next
For Each Segment In orange
    If InStr(Segment, "(") <> 0 Then
        OBrac = OBrac + 1
    ElseIf InStr(Segment, ")") <> 0 Then
        CBrac = CBrac + 1
    End If
    Cells(Segment.Row, CurrLev + 3) = Segment 'copies the segment value into a column indented by a number of cells equal to the order of the segment
    CurrLev = OBrac - CBrac 'current level is how many brackets have been opened - how many have been closed,
                            'ie. the number of brackets preceding a segment which are currently open
Next Segment


End Sub

如何改进

到目前为止我已经走了多远。我真正想要的是将缩进树替换为下拉列表树。对于公式=IF(MAX(arg1,arg2)=1,arg3,MIN(arg1,arg2)),我想分成若干段:IF(MAX(ARG1,ARG2)=1,,{{1} },ARG3,MIN(&amp; ARG1, htn显示它们。不像这样:(就像我现在一样)

ARG2))

但是像这样:(或类似的)

IF(     
    MAX(    
        ARG1,
        ARG2)
    =1, 
    ARG3,   
    MIN(    
        ARG1,
        ARG2))

当您点击IF(◀ 时会变成这样:

然后将IF(▼ MAX(◀ =1, ARG3, MIN(◀ 扩展为

Min

缩短问题描述

总结:

  • 我在Excel中有一个公式; Excel中的公式具有一般形式IF(▼ MAX(◀ =1, ARG3, MIN(▼ ARG1, ARG2))
  • 每个参数可以是简单的(常量,文本字符串,单元格引用)或复杂(另一个具有自己的函数和参数的公式)
  • 我想要一个带有输入公式的宏,并创建某种形式的用户界面(无论是在我的例子中特别定位的单元格,还是其他一些方法),以像时尚一样的树形式显示函数
  • 这意味着在UI的第一层,我显示了函数,第2层有函数的参数,如果参数很复杂,它们将有更多的子图层
  • 要访问子图层,可以使用下拉箭头或其他方法展开每个函数以显示其参数(其下面的&#39;层)。就像Reddit帖子一样,你可以点击[+]来获得更深的1层。

1 个答案:

答案 0 :(得分:1)

我使用这个网站来处理长公式,它帮助了我很多。

它没有你提到的UI组件,但它在“美化”输出方面做得很好。

Excel Formula Beautifier