VBA使Excel公式更具可读性

我在网站上浏览过一些东西,但是让Excel公式(公式?)更具可读性的build议往往是针对“使用命名范围”“使用助手列” 。 我不是在使公式更容易阅读的技术之后,我想创build一个macros以更可读的方式显示公式。 您可以跳到最后查看缩短的问题描述。 我这样说,是因为虽然我通常喜欢解释我的做法,但我觉得这次我的做法可能是从问题本质上分心。 另外,我认为这个问题可以在没有前面的背景的情况下很好地完成

问题的背景

我有很多讨厌的巢内复杂的公式,这里是我今天写的(见Excel示例文档 )

![Excel代码示例

或作为代码:

=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") 

尽pipe可能丑陋,海事组织实际上构build得非常好, IFSSUMIFS在可能的情况下避免公式的嵌套,存储在表中的所有命名范围,适用时使用的助手列。 然而,在某些情况下,它会返回一个错误的结果,而且该公式便于阅读。 (这也不是最长的,我已经编译了几个A4页面的代码,虽然这是当我不能使用VBA来构build帮助列)

我想要一个macros,它采用这个公式,并将其分割成一个分支函数树,其中每个嵌套函数是另一个树枝 – 也许公式的组成部分跨工作簿中的单元格

目前的做法

我到目前为止尝试了以下方法:列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列find的最后一个分量,并将其从长=SUBSTITUTE(A2,B3,"",1)公式中=SUBSTITUTE(A2,B3,"",1)使用=SUBSTITUTE(A2,B3,"",1) 。 因此,对于A2(作为文本)中的原始公式,B2是它的第一个分量(例如IF(在我的例子中),A3是A2中的公式减去 B2中的第一个分量),我拖下来迭代。

macros

这给了我B列的每个单元格中的公式组件的列表。然后,我的macros决定每个组件的级别 ,并缩减该组件的许多单元格。 该级别定义为在我的代码中的公式* 或“段”的组件之前未打开的括号。 macros观评论解释了这一点。

 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 

如何改进

这到目前为止我已经有多远了。 我真正想要的是,用缩进列表树replace缩进树。 对于一个公式=IF(MAX(arg1,arg2)=1,arg3,MIN(arg1,arg2))我想分成几个片段: IF(MAX(ARG1,ARG2) =1,ARG3,MIN(ARG1,ARG2)) htn显示它们。 不是这样的:(就像我现在)

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

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

 IF(◀ 

当你点击就会变成这样:

 IF(▼ MAX(◀ =1, ARG3, MIN(◀ 

然后把Min扩展到

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

缩短问题描述


总结:

  • 我在Excel中有一个公式 Excel中的公式具有通用formsFUNCTION(argument1, arg2, arg3...)
  • 每个参数可能很简单(一个常量,一个文本string,一个单元格引用)或复杂的(另一个具有自己的函数和参数的公式)
  • 我想要一个macros,它接受一个input公式,并创build某种forms的用户界面(像我的例子中那样是特定位置的单元格,或者其他方法),以便像树
  • 这意味着在用户界面的第一层,我显示function,第2层有函数的参数,如果参数是复杂的,他们将有进一步的子层
  • 要访问子图层,可以用下拉箭头或其他方法展开每个函数,以显示其参数(下面的“图层”)。 就像一个Reddit的post,你可以点击[+]获得更深的1层。

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

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

Excel公式美化

Interesting Posts