2017-03-22 70 views
1

我想遞歸查找範圍對象的公式,直到找到它構成的每個單個值。 由於我對前面句子的語法正確性不太確定(無論如何,我對我的英語表示歉意),我會試着用一個例子來解釋我想完成的事情(希望這可能是最簡單的一個) :遞歸地從VBA中提取公式的值

mysheet = "Sheet1" 
    Sheets(mysheet).Range("A1").Formula = "=+B1" 
    Sheets(mysheet).Range("B1").Formula = "=+C1-C2" 
    Sheets(mysheet).Range("C1").Value = "value:val1" 
    Sheets(mysheet).Range("C2").Formula = "=+D1-D2" 
    Sheets(mysheet).Range("D1").Value = "value:val2" 
    Sheets(mysheet).Range("D2").Value = "value:val3" 

你能不能給我一個提示(或更好的代碼草案)什麼樣的功能(?遞歸一個,也許)可以返回一個字符串(我們稱之爲my_formula),使得命令

MsgBox(my_formula) 

將返回以下:

A1 = +value:val1 - value:val2 + value:val3 

?請幫我

謝謝

更新後不到一小時

喜一切,非常感謝您的回答。我會指出單元格中的值實際上是字符串+我只有簡單的操作(+和 - )+所有依賴項都在同一張表中+我沒有範圍,如$ X $ 1。然而,我知道你們中的一些人發佈的方法/屬性(先例,NavigateArrow ...),但是我問的是如何以最好的方式使用這種方法/屬性而不會感到頭疼的想法。

再次

+0

除非有一個範圍對象的內置屬性來做到這一點,我只能想象由於命名範圍,工作表引用,工作簿引用,連接等引起的頭痛。但是,你是否假設你所有的單元格值只是表格A1或$ A $ 1? –

+0

https://msdn.microsoft.com/en-us/library/office/ff197707.aspx也許? –

+1

咳嗽 - 你不是指https://msdn.microsoft.com/zh-cn/library/office/ff196936.aspx –

回答

2

謝謝你這段代碼會爲你的工作,例如 - 但情況因人而異它是如何將擴展到在現實生活中更復雜的公式。然而,它會讓你開始 - 然後是一些 - 如何緩存集合Range。我已經評論了代碼,但理解它的最簡單方法是使用F8在調試模式下進行。

Option Explicit 

Sub Test() 
    Dim ws As Worksheet 
    Dim rng As Range 
    Dim strOutput As String 

    'your test case from the original question  
    Set ws = ThisWorkbook.Sheets("Sheet1") 
    With ws 
     .Range("A1").Formula = "=+B1" 
     .Range("B1").Formula = "=+C1-C2" 
     .Range("C1").Value = "10" 
     .Range("C2").Formula = "=+D1-D2" 
     .Range("D1").Value = "20" 
     .Range("D2").Value = "30" 
    End With 

    'the cell you want to start from 
    Set rng = Sheet1.Range("A1") 

    'get the output from calling the recursive function 
    'note we pass the original formula in to kick off the function 
    strOutput = rng.Address(0, 0) & GetFullFormula(rng, rng.Formula) 

    'show user 
    MsgBox strOutput 

End Sub 

Function GetFullFormula(rng As Range, strFormula As String) As String 

    Dim rngPrecedents As Range 
    Dim rngPrecedent As Range 
    Dim strPrecedentAddress As String 
    Dim strPrecedentFormula As String 

    If rng.HasFormula Then 
     Set rngPrecedents = rng.Precedents 
     For Each rngPrecedent In rngPrecedents 
      'get the precedent cell address to check if in current formula (without $) 
      strPrecedentAddress = rngPrecedent.Address(0, 0) 
      'Debug.Print strFormula 
      'substiute into formula if matching a range address 
      If rngPrecedent.HasFormula Then 
       If InStr(1, strFormula, strPrecedentAddress, vbBinaryCompare) Then 
        'strip = from formula and put in brackets to preserve ordering 
        strPrecedentFormula = "(" & Mid(rngPrecedent.Formula, 2, Len(rngPrecedent.Formula) - 1) & ")" 
        'replace our formula with precedent formula 
        strFormula = Replace(strFormula, strPrecedentAddress, strPrecedentFormula) 
       End If 
       'carry on with recursion - passes formula back into function for expansion 
       GetFullFormula rngPrecedent, strFormula 
      Else 
       'just a value 
       If InStr(1, strFormula, strPrecedentAddress, vbBinaryCompare) Then 
        'replace the address with the value 
        strFormula = Replace(strFormula, strPrecedentAddress, rngPrecedent.Value) 
       End If 
      End If 
     Next rngPrecedent 
    End If 

    GetFullFormula = strFormula 

End Function 

輸出:

=+(+10-(+20-30)) 

會有這段代碼有問題,如果你使用的是像$A$1單元格引用,因爲函數需要普通的單元格引用。代碼可以擴展來處理這些情況,也可以命名範圍,但這只是一個基本的例子。