2012-04-15 6 views
7

Gibt es einen cleveren Weg mit VBA oder eine Formel zu finden "k" und "m" Variablen in einem kx+m string?Excel: Finden Sie k und m in "kx + m" Textzeichenfolge

Es gibt verschiedene Szenarien, wie der kx + m Zeichenfolge aussehen kann, z.B .:

312*x+12 
12+x*2 
-4-x 

und so weiter. Ich bin mir ziemlich sicher, dass ich das lösen kann, indem ich sehr komplizierte Formeln in Excel schreibe, aber ich denke, dass jemand diese und ähnliche Probleme bereits gelöst hat. Hier ist mein Bestes so weit, aber es behandelt nicht alle Situationen noch (wie wenn es zwei Nachteile in der kx + m string:

=TRIM(IF(NOT(ISERROR(SEARCH("~+";F5))); IF(SEARCH("~+";F5)>SEARCH("~*";F5);RIGHT(F5;LEN(F5)-SEARCH("~+";F5));LEFT(F5;SEARCH("~+";F5)-1)); IF(NOT(ISERROR(SEARCH("~-";F5))); IF(SEARCH("~-";F5)>SEARCH("~*";F5);RIGHT(F5;LEN(F5)-SEARCH("~-";F5)+1);LEFT(F5;SEARCH("~*";F5)-1));"")))

+2

+! für eine interessante Frage :) –

Antwort

4

Ich bin mir sicher, das wird Ihnen helfen :)

Setzen Sie diese Funktion in ein Modul:

Function FindKXPlusM(ByVal str As String) As String 
    Dim K As String, M As String 
    Dim regex As Object, matches As Object, sm As Object 

    '' remove unwanted spaces from input string (if any) 
    str = Replace(str, " ", "") 

    '' create an instance of RegEx object. 
    '' I'm using late binding here, but you can use early binding too. 
    Set regex = CreateObject("VBScript.RegExp") 
    regex.IgnoreCase = True 
    regex.Global = True 

    '' test for kx+m or xk+m types 
    regex.Pattern = "^(-?\d*)\*?x([\+-]?\d+)?$|^x\*(-?\d+)([\+-]?\d+)?$" 
    Set matches = regex.Execute(str) 
    If matches.Count >= 1 Then 
     Set sm = matches(0).SubMatches 
     K = sm(0) 
     M = sm(1) 
     If K = "" Then K = sm(2) 
     If M = "" Then M = sm(3) 
     If K = "-" Or K = "+" Or K = "" Then K = K & "1" 
     If M = "" Then M = "0" 
    Else 
     '' test for m+kx or m+xk types 
     regex.Pattern = "^(-?\d+)[\+-]x\*([\+-]?\d+)$|^(-?\d+)([\+-]\d*)\*?x$" 
     Set matches = regex.Execute(str) 
     If matches.Count >= 1 Then 
      Set sm = matches(0).SubMatches 
      M = sm(0) 
      K = sm(1) 
      If M = "" Then M = sm(2) 
      If K = "" Then K = sm(3) 
      If K = "-" Or K = "+" Or K = "" Then K = K & "1" 
      If M = "" Then M = "0" 
     End If 
    End If 
    K = Replace(K, "+", "") 
    M = Replace(M, "+", "") 

    '' the values found are in K & M. 
    '' I output here in this format only for showing sample. 
    FindKXPlusM = " K = " & K & "   M = " & M 
End Function 

Dann können Sie es entweder von einem Makro z. wie folgt:

Sub Test() 
    Debug.Print FindKXPlusM("x*312+12") 
End Sub 

Oder verwenden Sie es wie eine Formel. z.B. indem sie diese in einer Zelle:

=FindKXPlusM(B1) 

mag ich die zweite Möglichkeit (weniger Arbeit: P)

ich es mit verschiedenen Werten getestet und hier ist ein Screenshot von dem, was ich bekommen:

Screenshot of Find KX+M Formula

this helps :)

+2

+1 Schöne. Ich mag die Art, wie Sie umgehen, wenn es umgekehrt ist :) –

+1

Regexp ist der beste Weg, um die Zeichenfolge zu analysieren, aber die Analyse ist für diese Anwendung arbeitsintensiv. – brettdj

3

ich einen regulären Ausdruck für verwenden würde suchen eine oder mehrere Ziffern, nach "* x" für m und nach "+" für k.

Ihr Beispiel zeigt Integer-Werte Was ist, wenn die Steigung und Schnittpunkt sind Gleitkommazahlen? Signed Werte? Es ist komplizierter als Ihr Beispiel würde vorschlagen

Ich würde vorschlagen, dass die allgemeinste Lösung einen Lexer/Parser mit einem einfachen gra schreiben würde mmar, um es für Sie zu handhaben. Ich weiß nicht, was VB oder .NET für Sie bieten. ANTLR würde eine Lösung in Java-Land; Es gibt eine ANTLR.NET.

Ich bin mir nicht sicher, was all diese Bemühungen Sie kaufen. Was machen Sie mit den extrahierten Inhalten? Ich würde denken, es wäre genauso einfach für Benutzer, numerische Zellen für k und m einzugeben und y = m*x + k aus diesen zu berechnen, anstatt einen String einzufügen und sie zu extrahieren.

Wenn Ihr Ziel ist einfach ein String zu bewerten, vielleicht eval() ist Ihre Antwort:

How to turn a string formula into a "real" formula

+0

+1 Ich stimme dir zu :) Es ist komplexer als es scheint. Ein 'kx + m' kann Max 7 Operatoren und min 1 Operator haben, wenn ich nicht falsch liege. Und in einem solchen Szenario wird es sehr komplex, die "K" - und "M" -Werte zu erhalten. –

4

Es ist komplexer als es scheint. Ein kx + m kann Max 7 Operatoren und min 1 Operator haben, wenn ich nicht falsch liege. Und in einem solchen Szenario wird es sehr komplex, die "K" - und "M" -Werte zu erhalten. - Siddharth Rout 33 Minuten vor

Aufbauend auf meinen Kommentar in duffymo der Post

Dieser Schnappschuss die verschiedenen Kombinationen zeigt, dass „kx + m“ haben

enter image description here

Und wie bereits erwähnt, ist es sehr komplex zu erreichen, was Sie wollen. Hier ist mein Schwachversuch um gerade "K" zu extrahieren. Dieser Code ist in keiner Weise classy :(Auch habe ich den Code mit verschiedenen Szenarien nicht getestet, so dass es mit anderen fehlschlagen kann. Allerdings gibt es Ihnen eine faire Idee, wie Sie dieses Problem anzugehen. Sie müssen zwicken Sie es mehr, um die genauen Ergebnisse zu erhalten, die Sie wollen.

CODE (ich bin für 7 mögliche Kombinationen in diesem Code testen.Es funktioniert für diese 7 aber könnte/wird für andere scheitern)

Option Explicit 

Sub Sample() 
    Dim StrCheck As String 
    Dim posStar As Long, posBrk As Long, pos As Long, i As Long 
    Dim strK As String, strM As String 
    Dim MyArray(6) As String 

    MyArray(0) = "-k*(-x)+(-m)*(-2)" 
    MyArray(1) = "-k*x+(-m)*(-2)" 
    MyArray(2) = "-k(x)+(-m)*(-2)" 
    MyArray(3) = "-k(x)+(-m)(-2)" 
    MyArray(4) = "-kx+m" 
    MyArray(5) = "kx+m" 
    MyArray(6) = "k(x)+m" 

    For i = 0 To 6 
     StrCheck = MyArray(i) 
     Select Case Left(Trim(StrCheck), 1) 

     Case "+", "-" 
      posBrk = InStr(2, StrCheck, "(") 
      posStar = InStr(2, StrCheck, "*") 

      If posBrk > posStar Then   '<~~ "-k*(-x)+(-m)*(-2)" 
       pos = InStr(2, StrCheck, "*") 
       If pos <> 0 Then 
        strK = Mid(StrCheck, 1, pos - 1) 
       Else 
        strK = Mid(StrCheck, 1, posBrk - 1) 
       End If 
      ElseIf posBrk < posStar Then  '<~~ "-k(-x)+(-m)*(-2)" 
       pos = InStr(2, StrCheck, "(") 
       strK = Mid(StrCheck, 1, pos - 1) 
      Else        '<~~ "-kx+m" 
       '~~> In such a case I am assuming that you will never use 
       '~~> a >=2 letter variable 
       strK = Mid(StrCheck, 1, 2) 
      End If 
     Case Else 
      posBrk = InStr(1, StrCheck, "(") 
      posStar = InStr(1, StrCheck, "*") 

      If posBrk > posStar Then   '<~~ "k*(-x)+(-m)*(-2)" 
       pos = InStr(1, StrCheck, "*") 
       If pos <> 0 Then 
        strK = Mid(StrCheck, 1, pos - 2) 
       Else 
        strK = Mid(StrCheck, 1, posBrk - 1) 
       End If 
      ElseIf posBrk < posStar Then  '<~~ "k(-x)+(-m)*(-2)" 
       pos = InStr(1, StrCheck, "(") 
       strK = Mid(StrCheck, 1, pos - 2) 
      Else        '<~~ "kx+m" 
       '~~> In such a case I am assuming that you will never use 
       '~~> a >=2 letter variable 
       strK = Mid(StrCheck, 1, 1) 
      End If 
     End Select 

     Debug.Print "Found " & strK & " in " & MyArray(i) 
    Next i 
End Sub 

SCHNAPPSCHUSS

enter image description here

Es ist nicht viel, aber ich hoffe, dass diese Sie in dem richtigen Weg bekommt ...

+0

+1 gut überlegt – brettdj

+0

+1 schöne ohne Regexp –

5

Anstatt die Mühe mit Parsing eine einfache LINEST in VBA laufen.

ersetzen StrFunc nach Bedarf

Sub Extract() 
Dim strFunc As String 
Dim X(1 To 2) As Variant 
Dim Y(1 To 2) As Variant 
Dim C As Variant 

X(1) = 0 
X(2) = 100 

strFunc = "312*x+12" 
'strFunc = "12+x*2 " 
'strFunc = "-4-X" 

Y(1) = Evaluate(Replace(LCase$(strFunc), "x", X(1))) 
Y(2) = Evaluate(Replace(LCase$(strFunc), "x", X(2))) 
C = Application.WorksheetFunction.LinEst(Y, X) 

MsgBox "K is " & C(1) & vbNewLine & "M is " & C(2) 

End Sub 
+1

+1 Sehr kreativ! – Excellll